import { a5 as RateLimitConfig, a4 as ProviderName, Z as Logger, a7 as RetryConfig, m as ClientHooks, W as WhatsAppProviderAdapter, o as CloudApiConfig, n as ClientOptions, O as OutboundMessage, S as SendResult, d as MediaUpload, e as MediaUploadResult, f as MediaUrlResult, g as MediaDownloadResult, h as WebhookEvent, i as Template, j as CreateTemplateInput, P as ProviderFeature } from '../../provider-C49GxNtg.cjs'; /** * Token bucket rate limiter. * * Ensures we don't exceed the provider's per-second request limit. * When the bucket is empty, callers wait FIFO until a token is available. * * NOTE: state lives in this instance's memory. It only limits the requests * flowing through a single client instance in a single isolate/process — it is * NOT a distributed limiter. On multi-isolate platforms (e.g. Cloudflare * Workers) construct ONE client and reuse it; for a true cross-isolate limit, * front it with Durable Objects / Upstash. Also note Workers freezes * `Date.now()` during synchronous execution, so token refill only advances * across `await`/I/O boundaries. See the README. */ declare class RateLimiter { private tokens; private readonly maxTokens; private lastRefill; private readonly refillRate; private readonly maxQueue; private readonly queueTimeoutMs; private readonly waitQueue; private drainTimerId; constructor(config?: RateLimitConfig); /** Refill tokens based on elapsed time */ private refill; /** Drain queued waiters if tokens are available */ private drain; /** * Acquire a token. Resolves immediately if tokens are available AND no one * is already waiting (FIFO fairness — newcomers never jump the queue), * otherwise waits until a token is refilled. * * - Rejects with a `RateLimitError` if the wait queue is already at capacity * (bounds memory under sustained overload). * - Rejects with a `TimeoutError` if it waits longer than `queueTimeoutMs`, * so a request never hangs forever before its fetch even starts. */ acquire(): Promise; /** Schedule a drain check if not already scheduled */ private drainScheduled; private scheduleDrain; /** * Clean up pending timers and resolve queued waiters. * Call this when you're done with the client to allow clean shutdown * in serverless/edge environments. */ destroy(): void; } interface HttpClientConfig { /** Default base URL for requests */ baseUrl: string; /** Default headers applied to every request */ defaultHeaders: Record; /** Request timeout in ms */ timeout: number; /** Provider name for error context */ provider: ProviderName; /** Logger instance */ logger: Logger; /** Rate limiter instance */ rateLimiter: RateLimiter; /** Retry config */ retry: RetryConfig; /** Lifecycle hooks */ hooks?: ClientHooks; } interface RequestOptions { /** HTTP method */ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'; /** Path appended to baseUrl */ path: string; /** JSON body (will be serialized) */ body?: unknown; /** Additional headers (merged with defaults) */ headers?: Record; /** Query string parameters */ query?: Record; /** Override timeout for this request */ timeout?: number; /** Skip retry for this request */ skipRetry?: boolean; /** * Override idempotency for retry purposes. By default GET/PUT/DELETE are * treated as idempotent (safe to retry after ambiguous failures) and * POST/PATCH are not. Set explicitly when the default is wrong. */ idempotent?: boolean; } interface HttpResponse { status: number; data: T; headers: Headers; } declare class HttpClient { private readonly config; private readonly retryConfig; constructor(config: HttpClientConfig); /** * Make a JSON request. Handles rate limiting, retry, timeout, and * error classification. */ request(opts: RequestOptions): Promise>; /** * Make a raw fetch request (for media downloads that return streams). * Returns the raw Response so the caller can access .body as a stream. * Supports retry for transient failures. */ rawRequest(opts: RequestOptions): Promise; /** * Make a multipart/form-data request (for media uploads). * * Uploads are POSTs and therefore treated as non-idempotent: they are not * retried after ambiguous failures (to avoid duplicate uploads), though a * `429` is still retried. Pass `skipRetry: true` to disable retry entirely. */ uploadRequest(path: string, formData: FormData, extraHeaders?: Record, skipRetry?: boolean): Promise>; /** * Release resources held by this client (the rate limiter's pending timer * and queued waiters). Call when you're done with the client. */ destroy(): void; /** Run `execute` with retry + a single onError hook on terminal failure. */ private run; /** Perform a single fetch, translating low-level failures to typed errors. */ private doFetch; /** * Parse a JSON response body, tolerating empty bodies (204, no content) and * surfacing non-JSON bodies as a typed ProviderError instead of an * unhandled SyntaxError. */ private parseJsonBody; private buildUrl; private handleErrorResponse; } declare class CloudApiProvider implements WhatsAppProviderAdapter { readonly name: "cloud-api"; protected readonly config: CloudApiConfig; protected readonly options: ClientOptions; protected readonly http: HttpClient; protected readonly logger: Logger; constructor(config: CloudApiConfig, options?: ClientOptions); sendMessage(message: OutboundMessage): Promise; markAsRead(messageId: string): Promise; uploadMedia(params: MediaUpload): Promise; getMediaUrl(mediaId: string): Promise; downloadMedia(mediaIdOrUrl: string): Promise; deleteMedia(mediaId: string): Promise; parseWebhook(body: unknown): WebhookEvent[]; verifyWebhookSignature(body: string, signature: string): Promise; handleVerificationChallenge(query: Record): string | null; /** Get the WABA ID for template operations, throwing if not configured */ private getWabaId; listTemplates(): Promise; createTemplate(input: CreateTemplateInput): Promise