{"version":3,"sources":["../src/core/errors.ts","../src/core/retry.ts","../src/core/http.ts","../src/core/rate-limiter.ts","../src/core/logger.ts","../src/utils/assert.ts","../src/utils/crypto.ts","../src/utils/phone.ts"],"names":[],"mappings":"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","file":"chunk-UOHLFIOO.cjs","sourcesContent":["// ---------------------------------------------------------------------------\n// Custom error class hierarchy — typed, serializable, provider-aware\n// ---------------------------------------------------------------------------\n\nimport type { WhatsAppErrorCode } from '../types/errors.js'\n\n/**\n * Base error class for all waflow errors.\n * Extends native Error with structured code, provider, and status info.\n */\nexport class WhatsAppError extends Error {\n  readonly code: WhatsAppErrorCode\n  readonly provider: string\n  readonly statusCode: number | undefined\n  readonly raw: unknown\n\n  constructor(opts: {\n    code: WhatsAppErrorCode\n    message: string\n    provider?: string\n    statusCode?: number\n    raw?: unknown\n    cause?: unknown\n  }) {\n    super(opts.message, { cause: opts.cause })\n    this.name = 'WhatsAppError'\n    this.code = opts.code\n    this.provider = opts.provider ?? 'unknown'\n    this.statusCode = opts.statusCode\n    this.raw = opts.raw\n  }\n}\n\nexport class AuthenticationError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'AUTH_FAILED' })\n    this.name = 'AuthenticationError'\n  }\n}\n\nexport class RateLimitError extends WhatsAppError {\n  readonly retryAfter: number | undefined\n\n  constructor(\n    opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'> & {\n      retryAfter?: number\n    },\n  ) {\n    super({ ...opts, code: 'RATE_LIMITED' })\n    this.name = 'RateLimitError'\n    this.retryAfter = opts.retryAfter\n  }\n}\n\nexport class ValidationError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'VALIDATION_FAILED' })\n    this.name = 'ValidationError'\n  }\n}\n\nexport class MediaError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'MEDIA_ERROR' })\n    this.name = 'MediaError'\n  }\n}\n\nexport class TemplateError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'TEMPLATE_ERROR' })\n    this.name = 'TemplateError'\n  }\n}\n\nexport class ProviderError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'PROVIDER_ERROR' })\n    this.name = 'ProviderError'\n  }\n}\n\nexport class UnsupportedFeatureError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'UNSUPPORTED_FEATURE' })\n    this.name = 'UnsupportedFeatureError'\n  }\n}\n\nexport class NetworkError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'NETWORK_ERROR' })\n    this.name = 'NetworkError'\n  }\n}\n\nexport class TimeoutError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'TIMEOUT' })\n    this.name = 'TimeoutError'\n  }\n}\n\nexport class WebhookVerificationError extends WhatsAppError {\n  constructor(opts: Omit<ConstructorParameters<typeof WhatsAppError>[0], 'code'>) {\n    super({ ...opts, code: 'WEBHOOK_VERIFICATION_FAILED' })\n    this.name = 'WebhookVerificationError'\n  }\n}\n","// ---------------------------------------------------------------------------\n// Exponential backoff retry logic\n// ---------------------------------------------------------------------------\n\nimport type { RetryConfig } from '../types/config.js'\nimport type { Logger } from './logger.js'\nimport { RateLimitError, NetworkError, TimeoutError, ProviderError } from './errors.js'\n\nconst DEFAULT_RETRY_CONFIG = {\n  maxRetries: 3,\n  baseDelay: 1000,\n  maxDelay: 30_000,\n  retryNonIdempotent: false,\n} as const satisfies Required<RetryConfig>\n\n/** Merge user config with defaults, validating numeric ranges */\nexport function resolveRetryConfig(config?: RetryConfig): Required<RetryConfig> {\n  const maxRetries = config?.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries\n  const baseDelay = config?.baseDelay ?? DEFAULT_RETRY_CONFIG.baseDelay\n  const maxDelay = config?.maxDelay ?? DEFAULT_RETRY_CONFIG.maxDelay\n\n  if (!Number.isInteger(maxRetries) || maxRetries < 0) {\n    throw new RangeError(`retry.maxRetries must be a non-negative integer, got ${maxRetries}`)\n  }\n  if (!Number.isFinite(baseDelay) || baseDelay < 0) {\n    throw new RangeError(`retry.baseDelay must be a non-negative number, got ${baseDelay}`)\n  }\n  if (!Number.isFinite(maxDelay) || maxDelay < 0) {\n    throw new RangeError(`retry.maxDelay must be a non-negative number, got ${maxDelay}`)\n  }\n\n  return {\n    maxRetries,\n    baseDelay,\n    maxDelay,\n    retryNonIdempotent: config?.retryNonIdempotent ?? DEFAULT_RETRY_CONFIG.retryNonIdempotent,\n  }\n}\n\n/** Retry policy for a single operation */\nexport interface RetryPolicy {\n  /**\n   * Whether the operation is safe to retry after an *ambiguous* failure —\n   * a network error, timeout, or 5xx, where the request may already have\n   * been processed by the provider. Idempotent reads/deletes set this true;\n   * sends/creates set it false to avoid duplicate side effects.\n   */\n  idempotent: boolean\n}\n\n/**\n * Determine if an error is retryable.\n *\n * - `429` is always retryable: the request was rejected before processing, so\n *   there is no duplicate risk.\n * - Network errors, timeouts, and `5xx` are *ambiguous* (the request may have\n *   landed). They are only retried when the operation is idempotent.\n */\nfunction isRetryable(error: unknown, canRetryAmbiguous: boolean): boolean {\n  if (error instanceof RateLimitError) return true\n  if (error instanceof NetworkError) return canRetryAmbiguous\n  if (error instanceof TimeoutError) return canRetryAmbiguous\n  if (error instanceof ProviderError) {\n    return canRetryAmbiguous && (error.statusCode ?? 0) >= 500\n  }\n  return false\n}\n\n/** Calculate delay with jitter for the given attempt */\nfunction calculateDelay(attempt: number, config: Required<RetryConfig>): number {\n  const exponential = config.baseDelay * Math.pow(2, attempt)\n  const capped = Math.min(exponential, config.maxDelay)\n  // Add ±25% jitter to prevent thundering herd\n  const jitter = capped * (0.75 + Math.random() * 0.5)\n  return Math.round(jitter)\n}\n\n/**\n * Execute a function with exponential backoff retry.\n *\n * Retries on rate limits (429) always, and on network errors / timeouts /\n * 5xx only when `policy.idempotent` is set (or `retryNonIdempotent` is\n * enabled in config). This prevents duplicate sends for non-idempotent POSTs.\n */\nexport async function withRetry<T>(\n  fn: () => Promise<T>,\n  config: Required<RetryConfig>,\n  logger: Logger,\n  policy: RetryPolicy,\n): Promise<T> {\n  const canRetryAmbiguous = policy.idempotent || config.retryNonIdempotent\n  let lastError: unknown\n\n  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {\n    try {\n      return await fn()\n    } catch (error) {\n      lastError = error\n\n      if (attempt >= config.maxRetries || !isRetryable(error, canRetryAmbiguous)) {\n        throw error\n      }\n\n      // Respect Retry-After header from rate limit responses, but never wait\n      // longer than maxDelay — a huge Retry-After must not park an edge\n      // function past its wall-clock budget.\n      let delay: number\n      if (error instanceof RateLimitError && error.retryAfter) {\n        delay = Math.min(error.retryAfter * 1000, config.maxDelay)\n      } else {\n        delay = calculateDelay(attempt, config)\n      }\n\n      logger.warn(`Retrying request (attempt ${attempt + 1}/${config.maxRetries})`, {\n        delay,\n        errorMessage: error instanceof Error ? error.message : String(error),\n      })\n\n      await sleep(delay)\n    }\n  }\n\n  throw lastError\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise(resolve => setTimeout(resolve, ms))\n}\n","// ---------------------------------------------------------------------------\n// HTTP client wrapper — fetch-based, with retry + rate limiting\n// ---------------------------------------------------------------------------\n\nimport type { ClientHooks } from '../types/config.js'\nimport type { ProviderName } from '../types/common.js'\nimport type { Logger } from './logger.js'\nimport type { RateLimiter } from './rate-limiter.js'\nimport type { RetryConfig } from '../types/config.js'\nimport {\n  AuthenticationError,\n  NetworkError,\n  ProviderError,\n  RateLimitError,\n  TimeoutError,\n  ValidationError,\n} from './errors.js'\nimport { resolveRetryConfig, withRetry } from './retry.js'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface HttpClientConfig {\n  /** Default base URL for requests */\n  baseUrl: string\n  /** Default headers applied to every request */\n  defaultHeaders: Record<string, string>\n  /** Request timeout in ms */\n  timeout: number\n  /** Provider name for error context */\n  provider: ProviderName\n  /** Logger instance */\n  logger: Logger\n  /** Rate limiter instance */\n  rateLimiter: RateLimiter\n  /** Retry config */\n  retry: RetryConfig\n  /** Lifecycle hooks */\n  hooks?: ClientHooks\n}\n\nexport interface RequestOptions {\n  /** HTTP method */\n  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'\n  /** Path appended to baseUrl */\n  path: string\n  /** JSON body (will be serialized) */\n  body?: unknown\n  /** Additional headers (merged with defaults) */\n  headers?: Record<string, string>\n  /** Query string parameters */\n  query?: Record<string, string | number | boolean | undefined>\n  /** Override timeout for this request */\n  timeout?: number\n  /** Skip retry for this request */\n  skipRetry?: boolean\n  /**\n   * Override idempotency for retry purposes. By default GET/PUT/DELETE are\n   * treated as idempotent (safe to retry after ambiguous failures) and\n   * POST/PATCH are not. Set explicitly when the default is wrong.\n   */\n  idempotent?: boolean\n}\n\nexport interface HttpResponse<T = unknown> {\n  status: number\n  data: T\n  headers: Headers\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\nexport class HttpClient {\n  private readonly config: HttpClientConfig\n  private readonly retryConfig: Required<RetryConfig>\n\n  constructor(config: HttpClientConfig) {\n    this.config = config\n    this.retryConfig = resolveRetryConfig(config.retry)\n  }\n\n  /**\n   * Make a JSON request. Handles rate limiting, retry, timeout, and\n   * error classification.\n   */\n  async request<T = unknown>(opts: RequestOptions): Promise<HttpResponse<T>> {\n    const execute = async (): Promise<HttpResponse<T>> => {\n      await this.config.rateLimiter.acquire()\n\n      const url = this.buildUrl(opts.path, opts.query)\n      const timeout = opts.timeout ?? this.config.timeout\n      const headers: Record<string, string> = {\n        ...this.config.defaultHeaders,\n        ...opts.headers,\n      }\n\n      // Only set Content-Type for JSON bodies\n      if (opts.body !== undefined && !headers['Content-Type']) {\n        headers['Content-Type'] = 'application/json'\n      }\n\n      const startTime = Date.now()\n\n      this.config.hooks?.onRequest?.({\n        url,\n        method: opts.method,\n        body: opts.body,\n      })\n\n      this.config.logger.debug(`${opts.method} ${url}`)\n\n      const response = await this.doFetch(url, {\n        method: opts.method,\n        headers,\n        body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n        timeout,\n      })\n\n      const durationMs = Date.now() - startTime\n\n      this.config.hooks?.onResponse?.({\n        url,\n        status: response.status,\n        durationMs,\n      })\n\n      if (!response.ok) {\n        await this.handleErrorResponse(response, opts)\n      }\n\n      const data = await this.parseJsonBody<T>(response, opts)\n\n      this.config.logger.debug(`${opts.method} ${url} → ${response.status} (${durationMs}ms)`)\n\n      return {\n        status: response.status,\n        data,\n        headers: response.headers,\n      }\n    }\n\n    return this.run(execute, opts.method, opts.skipRetry, opts.idempotent)\n  }\n\n  /**\n   * Make a raw fetch request (for media downloads that return streams).\n   * Returns the raw Response so the caller can access .body as a stream.\n   * Supports retry for transient failures.\n   */\n  async rawRequest(opts: RequestOptions): Promise<Response> {\n    const execute = async (): Promise<Response> => {\n      await this.config.rateLimiter.acquire()\n\n      const url = this.buildUrl(opts.path, opts.query)\n      const timeout = opts.timeout ?? this.config.timeout\n      const headers: Record<string, string> = {\n        ...this.config.defaultHeaders,\n        ...opts.headers,\n      }\n\n      const startTime = Date.now()\n      this.config.hooks?.onRequest?.({ url, method: opts.method, body: opts.body })\n\n      const response = await this.doFetch(url, {\n        method: opts.method,\n        headers,\n        body: opts.body !== undefined ? JSON.stringify(opts.body) : undefined,\n        timeout,\n      })\n\n      this.config.hooks?.onResponse?.({\n        url,\n        status: response.status,\n        durationMs: Date.now() - startTime,\n      })\n\n      if (!response.ok) {\n        await this.handleErrorResponse(response, opts)\n      }\n\n      return response\n    }\n\n    return this.run(execute, opts.method, opts.skipRetry, opts.idempotent)\n  }\n\n  /**\n   * Make a multipart/form-data request (for media uploads).\n   *\n   * Uploads are POSTs and therefore treated as non-idempotent: they are not\n   * retried after ambiguous failures (to avoid duplicate uploads), though a\n   * `429` is still retried. Pass `skipRetry: true` to disable retry entirely.\n   */\n  async uploadRequest<T = unknown>(\n    path: string,\n    formData: FormData,\n    extraHeaders?: Record<string, string>,\n    skipRetry?: boolean,\n  ): Promise<HttpResponse<T>> {\n    const execute = async (): Promise<HttpResponse<T>> => {\n      await this.config.rateLimiter.acquire()\n\n      const url = this.buildUrl(path)\n      const timeout = this.config.timeout\n      const headers: Record<string, string> = {\n        ...this.config.defaultHeaders,\n        ...extraHeaders,\n      }\n      // Do NOT set Content-Type — fetch sets it with boundary for FormData\n\n      const startTime = Date.now()\n      this.config.hooks?.onRequest?.({ url, method: 'POST' })\n\n      const response = await this.doFetch(url, { method: 'POST', headers, body: formData, timeout })\n\n      this.config.hooks?.onResponse?.({\n        url,\n        status: response.status,\n        durationMs: Date.now() - startTime,\n      })\n\n      if (!response.ok) {\n        await this.handleErrorResponse(response, { method: 'POST', path })\n      }\n\n      const data = await this.parseJsonBody<T>(response, { method: 'POST', path })\n\n      return { status: response.status, data, headers: response.headers }\n    }\n\n    return this.run(execute, 'POST', skipRetry, false)\n  }\n\n  /**\n   * Release resources held by this client (the rate limiter's pending timer\n   * and queued waiters). Call when you're done with the client.\n   */\n  destroy(): void {\n    this.config.rateLimiter.destroy()\n  }\n\n  // -----------------------------------------------------------------------\n  // Private helpers\n  // -----------------------------------------------------------------------\n\n  /** Run `execute` with retry + a single onError hook on terminal failure. */\n  private async run<T>(\n    execute: () => Promise<T>,\n    method: RequestOptions['method'],\n    skipRetry: boolean | undefined,\n    idempotentOverride: boolean | undefined,\n  ): Promise<T> {\n    try {\n      if (skipRetry) return await execute()\n      const idempotent = idempotentOverride ?? isIdempotentMethod(method)\n      return await withRetry(execute, this.retryConfig, this.config.logger, { idempotent })\n    } catch (error) {\n      // Fire once, after retries are exhausted, with the actual thrown error\n      // (covers network/timeout errors, not just HTTP error responses).\n      this.config.hooks?.onError?.(error)\n      throw error\n    }\n  }\n\n  /** Perform a single fetch, translating low-level failures to typed errors. */\n  private async doFetch(\n    url: string,\n    init: { method: string; headers: Record<string, string>; body?: BodyInit; timeout: number },\n  ): Promise<Response> {\n    try {\n      return await fetch(url, {\n        method: init.method,\n        headers: init.headers,\n        body: init.body,\n        signal: AbortSignal.timeout(init.timeout),\n      })\n    } catch (error) {\n      if (error instanceof DOMException && error.name === 'TimeoutError') {\n        throw new TimeoutError({\n          message: `Request timed out after ${init.timeout}ms: ${init.method} ${url}`,\n          provider: this.config.provider,\n        })\n      }\n      if (error instanceof DOMException && error.name === 'AbortError') {\n        throw new TimeoutError({\n          message: `Request aborted: ${init.method} ${url}`,\n          provider: this.config.provider,\n        })\n      }\n      throw new NetworkError({\n        message: `Network error: ${error instanceof Error ? error.message : String(error)}`,\n        provider: this.config.provider,\n        cause: error,\n      })\n    }\n  }\n\n  /**\n   * Parse a JSON response body, tolerating empty bodies (204, no content) and\n   * surfacing non-JSON bodies as a typed ProviderError instead of an\n   * unhandled SyntaxError.\n   */\n  private async parseJsonBody<T>(\n    response: Response,\n    opts: Pick<RequestOptions, 'method' | 'path'>,\n  ): Promise<T> {\n    if (response.status === 204) return undefined as T\n    const text = await response.text()\n    if (!text) return undefined as T\n    try {\n      return JSON.parse(text) as T\n    } catch {\n      throw new ProviderError({\n        message: `Provider returned a non-JSON response: ${opts.method} ${opts.path}`,\n        provider: this.config.provider,\n        statusCode: response.status,\n        raw: text,\n      })\n    }\n  }\n\n  private buildUrl(path: string, query?: Record<string, string | number | boolean | undefined>): string {\n    // If path is already a full URL (e.g., media download URLs), use as-is\n    if (path.startsWith('http://') || path.startsWith('https://')) {\n      return path\n    }\n\n    const base = this.config.baseUrl.replace(/\\/$/, '')\n    const cleanPath = path.startsWith('/') ? path : `/${path}`\n    const url = new URL(`${base}${cleanPath}`)\n\n    if (query) {\n      for (const [key, value] of Object.entries(query)) {\n        if (value !== undefined) {\n          url.searchParams.set(key, String(value))\n        }\n      }\n    }\n\n    return url.toString()\n  }\n\n  private async handleErrorResponse(response: Response, opts: Pick<RequestOptions, 'method' | 'path'>): Promise<never> {\n    // Read as text first, then try to parse as JSON.\n    // This avoids double-consuming the body stream (response.json() + response.text()\n    // would fail because Response.body is a one-shot ReadableStream).\n    let errorBody: unknown\n    try {\n      const text = await response.text()\n      try {\n        errorBody = JSON.parse(text)\n      } catch {\n        errorBody = text || null\n      }\n    } catch {\n      errorBody = null\n    }\n\n    const context = {\n      provider: this.config.provider,\n      statusCode: response.status,\n      raw: errorBody,\n    } as const\n\n    // Classify by HTTP status\n    switch (response.status) {\n      case 401:\n        throw new AuthenticationError({\n          message: `Authentication failed: ${opts.method} ${opts.path}`,\n          ...context,\n        })\n      case 403:\n        throw new AuthenticationError({\n          message: `Access forbidden: ${opts.method} ${opts.path}`,\n          ...context,\n        })\n      case 429: {\n        const retryAfter = response.headers.get('Retry-After')\n        const parsed = retryAfter ? parseInt(retryAfter, 10) : NaN\n        throw new RateLimitError({\n          message: `Rate limited: ${opts.method} ${opts.path}`,\n          ...context,\n          retryAfter: Number.isNaN(parsed) ? undefined : parsed,\n        })\n      }\n      case 400:\n        throw new ValidationError({\n          message: `Validation failed: ${opts.method} ${opts.path}`,\n          ...context,\n        })\n      default:\n        throw new ProviderError({\n          message: `Provider error (${response.status}): ${opts.method} ${opts.path}`,\n          ...context,\n        })\n    }\n  }\n}\n\n/** GET/PUT/DELETE are idempotent and safe to retry after ambiguous failures. */\nfunction isIdempotentMethod(method: RequestOptions['method']): boolean {\n  return method === 'GET' || method === 'PUT' || method === 'DELETE'\n}\n","// ---------------------------------------------------------------------------\n// Token bucket rate limiter — no dependencies\n// ---------------------------------------------------------------------------\n\nimport type { RateLimitConfig } from '../types/config.js'\nimport { RateLimitError, TimeoutError } from './errors.js'\n\nconst DEFAULT_MAX_RPS = 80 // WhatsApp Cloud API default\nconst DEFAULT_MAX_QUEUE = 10_000 // overload protection — bounds memory\nconst DEFAULT_QUEUE_TIMEOUT_MS = 30_000 // a request never waits forever for a token\n\n/** A parked caller waiting for a token. */\ninterface Waiter {\n  grant: () => void\n  settled: boolean\n}\n\n/**\n * Token bucket rate limiter.\n *\n * Ensures we don't exceed the provider's per-second request limit.\n * When the bucket is empty, callers wait FIFO until a token is available.\n *\n * NOTE: state lives in this instance's memory. It only limits the requests\n * flowing through a single client instance in a single isolate/process — it is\n * NOT a distributed limiter. On multi-isolate platforms (e.g. Cloudflare\n * Workers) construct ONE client and reuse it; for a true cross-isolate limit,\n * front it with Durable Objects / Upstash. Also note Workers freezes\n * `Date.now()` during synchronous execution, so token refill only advances\n * across `await`/I/O boundaries. See the README.\n */\nexport class RateLimiter {\n  private tokens: number\n  private readonly maxTokens: number\n  private lastRefill: number\n  private readonly refillRate: number // tokens per ms\n  private readonly maxQueue: number\n  private readonly queueTimeoutMs: number\n  private readonly waitQueue: Waiter[] = []\n  private drainTimerId: ReturnType<typeof setTimeout> | null = null\n\n  constructor(config?: RateLimitConfig) {\n    const maxRps = config?.maxRequestsPerSecond ?? DEFAULT_MAX_RPS\n    if (!Number.isFinite(maxRps) || maxRps <= 0) {\n      throw new RangeError(`rateLimit.maxRequestsPerSecond must be a positive number, got ${maxRps}`)\n    }\n\n    const maxQueue = config?.maxQueueSize ?? DEFAULT_MAX_QUEUE\n    if (!Number.isInteger(maxQueue) || maxQueue < 1) {\n      throw new RangeError(`rateLimit.maxQueueSize must be a positive integer, got ${maxQueue}`)\n    }\n\n    const queueTimeoutMs = config?.queueTimeoutMs ?? DEFAULT_QUEUE_TIMEOUT_MS\n    if (!Number.isFinite(queueTimeoutMs) || queueTimeoutMs <= 0) {\n      throw new RangeError(`rateLimit.queueTimeoutMs must be a positive number, got ${queueTimeoutMs}`)\n    }\n\n    this.maxTokens = maxRps\n    this.tokens = maxRps\n    this.lastRefill = Date.now()\n    this.refillRate = maxRps / 1000 // tokens per millisecond\n    this.maxQueue = maxQueue\n    this.queueTimeoutMs = queueTimeoutMs\n  }\n\n  /** Refill tokens based on elapsed time */\n  private refill(): void {\n    const now = Date.now()\n    const elapsed = now - this.lastRefill\n    const newTokens = elapsed * this.refillRate\n    this.tokens = Math.min(this.maxTokens, this.tokens + newTokens)\n    this.lastRefill = now\n  }\n\n  /** Drain queued waiters if tokens are available */\n  private drain(): void {\n    while (this.waitQueue.length > 0 && this.tokens >= 1) {\n      const waiter = this.waitQueue.shift()\n      if (!waiter || waiter.settled) continue // timed out already — don't waste a token\n      this.tokens -= 1\n      waiter.grant()\n    }\n  }\n\n  /**\n   * Acquire a token. Resolves immediately if tokens are available AND no one\n   * is already waiting (FIFO fairness — newcomers never jump the queue),\n   * otherwise waits until a token is refilled.\n   *\n   * - Rejects with a `RateLimitError` if the wait queue is already at capacity\n   *   (bounds memory under sustained overload).\n   * - Rejects with a `TimeoutError` if it waits longer than `queueTimeoutMs`,\n   *   so a request never hangs forever before its fetch even starts.\n   */\n  async acquire(): Promise<void> {\n    this.refill()\n    // Serve already-queued waiters first (FIFO) with any tokens that refilled —\n    // don't make them wait for the next drain-timer tick when a token is free now.\n    this.drain()\n\n    if (this.tokens >= 1 && this.waitQueue.length === 0) {\n      this.tokens -= 1\n      return\n    }\n\n    if (this.waitQueue.length >= this.maxQueue) {\n      throw new RateLimitError({\n        message: `Local rate limiter queue is full (${this.maxQueue}) — too many concurrent requests`,\n      })\n    }\n\n    return new Promise<void>((resolve, reject) => {\n      const waiter: Waiter = { settled: false, grant: () => {} }\n\n      const timer = setTimeout(() => {\n        if (waiter.settled) return\n        waiter.settled = true\n        const idx = this.waitQueue.indexOf(waiter)\n        if (idx >= 0) this.waitQueue.splice(idx, 1)\n        reject(\n          new TimeoutError({\n            message: `Timed out after ${this.queueTimeoutMs}ms waiting for a rate-limit token`,\n          }),\n        )\n      }, this.queueTimeoutMs)\n\n      waiter.grant = () => {\n        if (waiter.settled) return\n        waiter.settled = true\n        clearTimeout(timer)\n        resolve()\n      }\n\n      this.waitQueue.push(waiter)\n      this.scheduleDrain()\n    })\n  }\n\n  /** Schedule a drain check if not already scheduled */\n  private drainScheduled = false\n  private scheduleDrain(): void {\n    if (this.drainScheduled) return\n    this.drainScheduled = true\n\n    const waitMs = Math.max(1, Math.ceil(1 / this.refillRate))\n    this.drainTimerId = setTimeout(() => {\n      this.drainTimerId = null\n      this.drainScheduled = false\n      this.refill()\n      this.drain()\n      // If there are still waiters, schedule another drain\n      if (this.waitQueue.length > 0) {\n        this.scheduleDrain()\n      }\n    }, waitMs)\n    // Unref so the timer doesn't hold the event loop open in serverless/edge\n    if (typeof this.drainTimerId === 'object' && this.drainTimerId !== null && 'unref' in this.drainTimerId) {\n      (this.drainTimerId as { unref: () => void }).unref()\n    }\n  }\n\n  /**\n   * Clean up pending timers and resolve queued waiters.\n   * Call this when you're done with the client to allow clean shutdown\n   * in serverless/edge environments.\n   */\n  destroy(): void {\n    if (this.drainTimerId !== null) {\n      clearTimeout(this.drainTimerId)\n      this.drainTimerId = null\n    }\n    this.drainScheduled = false\n    // Resolve all pending waiters (grant() clears each one's timeout) so\n    // nothing hangs after shutdown.\n    while (this.waitQueue.length > 0) {\n      this.waitQueue.shift()?.grant()\n    }\n  }\n}\n","// ---------------------------------------------------------------------------\n// Pluggable logger interface — consumers bring their own\n// ---------------------------------------------------------------------------\n\nexport interface Logger {\n  debug(msg: string, meta?: Record<string, unknown>): void\n  info(msg: string, meta?: Record<string, unknown>): void\n  warn(msg: string, meta?: Record<string, unknown>): void\n  error(msg: string, meta?: Record<string, unknown>): void\n}\n\n/** No-op logger used when no logger is provided */\nexport const noopLogger: Logger = {\n  debug() {},\n  info() {},\n  warn() {},\n  error() {},\n}\n","// ---------------------------------------------------------------------------\n// Type guard utilities\n// ---------------------------------------------------------------------------\n\n/** Exhaustive check utility — causes compile error if a case is missed */\nexport function assertNever(x: never): never {\n  throw new Error(`Unhandled case: ${JSON.stringify(x)}`)\n}\n\n/** Type guard: checks if value is a non-null object */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/** Type guard: checks if value has a specific string property */\nexport function hasStringProp<K extends string>(\n  value: unknown,\n  key: K,\n): value is Record<K, string> {\n  return isRecord(value) && typeof value[key] === 'string'\n}\n\n/** Type guard: checks if value has a specific property */\nexport function hasProp<K extends string>(\n  value: unknown,\n  key: K,\n): value is Record<K, unknown> {\n  return isRecord(value) && key in value\n}\n","// ---------------------------------------------------------------------------\n// Web Crypto API helpers — no node:crypto imports\n// ---------------------------------------------------------------------------\n\n/**\n * Compute HMAC SHA-256 and compare with a signature string.\n * Uses the Web Crypto API (crypto.subtle) for Cloudflare Workers compatibility.\n *\n * @param body - The raw request body string\n * @param signature - The signature to verify (with or without \"sha256=\" prefix)\n * @param secret - The shared secret key\n * @returns true if signatures match\n */\nexport async function verifyHmacSha256(\n  body: string,\n  signature: string,\n  secret: string,\n): Promise<boolean> {\n  const encoder = new TextEncoder()\n\n  const key = await crypto.subtle.importKey(\n    'raw',\n    encoder.encode(secret),\n    { name: 'HMAC', hash: 'SHA-256' },\n    false,\n    ['sign'],\n  )\n\n  const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(body))\n  const computed = arrayBufferToHex(sig)\n\n  // Strip \"sha256=\" prefix if present\n  const expected = signature.startsWith('sha256=')\n    ? signature.slice(7)\n    : signature\n\n  return timingSafeEqual(computed, expected)\n}\n\n/** Precomputed byte → 2-char hex lookup (avoids per-byte toString/padStart) */\nconst HEX_TABLE: readonly string[] = Array.from({ length: 256 }, (_, i) =>\n  i.toString(16).padStart(2, '0'),\n)\n\n/** Convert an ArrayBuffer to a lowercase hex string. Runs on every webhook\n *  signature verification, so it uses a lookup table and a single join. */\nfunction arrayBufferToHex(buffer: ArrayBuffer): string {\n  const bytes = new Uint8Array(buffer)\n  const out = new Array<string>(bytes.length)\n  for (let i = 0; i < bytes.length; i++) {\n    out[i] = HEX_TABLE[bytes[i] ?? 0] as string\n  }\n  return out.join('')\n}\n\n/**\n * Constant-time string comparison to prevent timing attacks.\n * Compares both length and content without early exit to avoid\n * leaking information through timing side-channels.\n *\n * Uses charCodeAt (not codePointAt) since we only compare ASCII hex digests.\n * charCodeAt returns NaN for out-of-bounds, which becomes 0 via bitwise OR.\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n  const maxLen = Math.max(a.length, b.length)\n  // XOR lengths — non-zero if different, contributing to final result\n  let result = a.length ^ b.length\n  for (let i = 0; i < maxLen; i++) {\n    result |= (a.charCodeAt(i) | 0) ^ (b.charCodeAt(i) | 0)\n  }\n  return result === 0\n}\n","// ---------------------------------------------------------------------------\n// Phone number normalization utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize a phone number to E.164-like format for WhatsApp API calls.\n *\n * WhatsApp APIs expect numbers without the \"+\" prefix\n * (e.g. \"966501234567\" not \"+966501234567\").\n *\n * This function:\n * - Strips \"+\", spaces, dashes, parentheses\n * - Validates that the result is digits only\n * - Returns the cleaned number\n */\n// Hoisted to module scope so they aren't reallocated on every send.\nconst STRIP_CHARS = /[\\s\\-()+]/g\nconst E164_DIGITS = /^\\d{7,15}$/\n\nexport function normalizePhoneNumber(phone: string): string {\n  const cleaned = phone.replace(STRIP_CHARS, '')\n\n  if (!E164_DIGITS.test(cleaned)) {\n    throw new Error(\n      `Invalid phone number: \"${phone}\". Expected 7-15 digits in E.164 format (e.g. \"+966501234567\").`,\n    )\n  }\n\n  return cleaned\n}\n"]}