{"version":3,"file":"async-utils.mjs","sources":["../../../src/lib/shared/async-utils.ts"],"sourcesContent":["/**\n * @file Unified Async Utilities\n * @description Centralized async operation utilities including sleep, retry,\n * debounce, throttle, timeout, mutex, semaphore, and promise pools.\n *\n * This module consolidates duplicate implementations from:\n * - utils/asyncUtils.ts\n * - utils/resilience.ts\n * - services/EnhancedInterceptors.ts\n * - state/sync/broadcast-sync.ts\n *\n * @module shared/async-utils\n */\n\n// =============================================================================\n// Sleep / Delay\n// =============================================================================\n\n/**\n * Sleep for a specified duration with optional abort signal support.\n *\n * @param ms - Duration in milliseconds\n * @param signal - Optional AbortSignal for cancellation\n * @returns Promise that resolves after the delay\n * @throws Error if aborted\n *\n * @example\n * ```ts\n * // Simple delay\n * await sleep(1000);\n *\n * // With abort signal\n * const controller = new AbortController();\n * setTimeout(() => controller.abort(), 500);\n * await sleep(1000, controller.signal); // throws after 500ms\n * ```\n */\nexport async function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n  return new Promise((resolve, reject) => {\n    if (signal?.aborted === true) {\n      reject(new Error('Aborted'));\n      return;\n    }\n\n    const timeoutId = setTimeout(resolve, ms);\n\n    signal?.addEventListener(\n      'abort',\n      () => {\n        clearTimeout(timeoutId);\n        reject(new Error('Aborted'));\n      },\n      { once: true }\n    );\n  });\n}\n\n// =============================================================================\n// Retry Configuration\n// =============================================================================\n\n/**\n * Retry configuration options\n */\nexport interface RetryConfig {\n  /** Maximum retry attempts (default: 3) */\n  maxAttempts?: number;\n  /** Initial delay between retries in ms (default: 1000) */\n  initialDelayMs?: number;\n  /** Maximum delay between retries in ms (default: 30000) */\n  maxDelayMs?: number;\n  /** Delay multiplier for exponential backoff (default: 2) */\n  backoffMultiplier?: number;\n  /** Whether to add random jitter to delays (default: true) */\n  jitter?: boolean;\n  /** Predicate to determine if error is retryable */\n  shouldRetry?: (error: unknown, attempt: number) => boolean;\n  /** Callback on each retry attempt */\n  onRetry?: (error: unknown, attempt: number, delayMs: number) => void;\n  /** Abort signal for cancellation */\n  signal?: AbortSignal;\n}\n\n/**\n * Default retry configuration\n */\nconst DEFAULT_RETRY_CONFIG: Required<\n  Omit<RetryConfig, 'signal' | 'onRetry' | 'shouldRetry'>\n> & { shouldRetry: NonNullable<RetryConfig['shouldRetry']> } = {\n  maxAttempts: 3,\n  initialDelayMs: 1000,\n  maxDelayMs: 30000,\n  backoffMultiplier: 2,\n  jitter: true,\n  shouldRetry: () => true,\n};\n\n/**\n * Calculate delay with exponential backoff and optional jitter\n */\nfunction calculateRetryDelay(\n  attempt: number,\n  config: Pick<\n    Required<RetryConfig>,\n    'initialDelayMs' | 'maxDelayMs' | 'backoffMultiplier' | 'jitter'\n  >\n): number {\n  const exponentialDelay =\n    config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt - 1);\n  const boundedDelay = Math.min(exponentialDelay, config.maxDelayMs);\n\n  if (config.jitter) {\n    // Add random jitter of +/-25%\n    const jitterRange = boundedDelay * 0.25;\n    return boundedDelay + (Math.random() * 2 - 1) * jitterRange;\n  }\n\n  return boundedDelay;\n}\n\n// =============================================================================\n// Retry Functions\n// =============================================================================\n\n/**\n * Execute an async function with retry logic and exponential backoff.\n *\n * @param fn - Async function to execute\n * @param config - Retry configuration\n * @returns Result of the function\n * @throws Last error if all retries fail\n *\n * @example\n * ```ts\n * const result = await withRetry(\n *   () => fetchData(),\n *   {\n *     maxAttempts: 5,\n *     initialDelayMs: 500,\n *     shouldRetry: (error) => error instanceof NetworkError,\n *     onRetry: (error, attempt) => console.log(`Retry ${attempt}...`),\n *   }\n * );\n * ```\n */\nexport async function withRetry<T>(\n  fn: () => Promise<T>,\n  config: RetryConfig = {}\n): Promise<T> {\n  const resolvedConfig = { ...DEFAULT_RETRY_CONFIG, ...config };\n  let lastError: unknown;\n\n  for (let attempt = 1; attempt <= resolvedConfig.maxAttempts; attempt++) {\n    try {\n      // Check for abort before attempting\n      if (config.signal?.aborted === true) {\n        throw new Error('Aborted');\n      }\n\n      return await fn();\n    } catch (error) {\n      lastError = error;\n\n      // Check if we should retry\n      const shouldRetry =\n        attempt < resolvedConfig.maxAttempts &&\n        resolvedConfig.shouldRetry(error, attempt);\n\n      if (!shouldRetry) {\n        break;\n      }\n\n      // Calculate and wait for delay\n      const delayMs = calculateRetryDelay(attempt, resolvedConfig);\n      config.onRetry?.(error, attempt, delayMs);\n\n      await sleep(delayMs, config.signal);\n    }\n  }\n\n  throw lastError;\n}\n\n/**\n * Fluent retry policy builder\n *\n * @example\n * ```ts\n * const policy = new RetryPolicy()\n *   .attempts(5)\n *   .delays(500, 10000)\n *   .backoff(2)\n *   .withJitter()\n *   .retryIf((error) => error instanceof NetworkError);\n *\n * const result = await policy.execute(() => fetchData());\n * ```\n */\nexport class RetryPolicy {\n  private readonly config: RetryConfig;\n\n  constructor(config: RetryConfig = {}) {\n    this.config = config;\n  }\n\n  /** Set maximum retry attempts */\n  attempts(max: number): RetryPolicy {\n    return new RetryPolicy({ ...this.config, maxAttempts: max });\n  }\n\n  /** Set initial and maximum delay in milliseconds */\n  delays(initialMs: number, maxMs?: number): RetryPolicy {\n    return new RetryPolicy({\n      ...this.config,\n      initialDelayMs: initialMs,\n      maxDelayMs: maxMs ?? initialMs * 10,\n    });\n  }\n\n  /** Set backoff multiplier */\n  backoff(multiplier: number): RetryPolicy {\n    return new RetryPolicy({ ...this.config, backoffMultiplier: multiplier });\n  }\n\n  /** Enable or disable jitter */\n  withJitter(enabled = true): RetryPolicy {\n    return new RetryPolicy({ ...this.config, jitter: enabled });\n  }\n\n  /** Set retry condition predicate */\n  retryIf(\n    predicate: (error: unknown, attempt: number) => boolean\n  ): RetryPolicy {\n    return new RetryPolicy({ ...this.config, shouldRetry: predicate });\n  }\n\n  /** Set retry callback */\n  onRetry(\n    callback: (error: unknown, attempt: number, delayMs: number) => void\n  ): RetryPolicy {\n    return new RetryPolicy({ ...this.config, onRetry: callback });\n  }\n\n  /** Execute a function with this policy */\n  async execute<T>(fn: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n    return withRetry(fn, { ...this.config, signal });\n  }\n}\n\n/**\n * Predefined retry policies for common use cases\n */\nexport const retryPolicies = {\n  /** No retry - execute once */\n  none: new RetryPolicy().attempts(1),\n\n  /** Quick retry - 3 attempts, 100ms start, for fast operations */\n  quick: new RetryPolicy().attempts(3).delays(100, 1000),\n\n  /** Standard retry - 3 attempts, 1s start, for typical API calls */\n  standard: new RetryPolicy().attempts(3).delays(1000, 10000),\n\n  /** Extended retry - 5 attempts, 2s start, for critical operations */\n  extended: new RetryPolicy().attempts(5).delays(2000, 30000),\n\n  /** Network retry - retries on network-related errors */\n  network: new RetryPolicy()\n    .attempts(3)\n    .delays(1000, 10000)\n    .retryIf((error) => {\n      if (error instanceof Error) {\n        const message = error.message.toLowerCase();\n        return (\n          message.includes('network') ||\n          message.includes('fetch') ||\n          message.includes('econnrefused') ||\n          message.includes('timeout')\n        );\n      }\n      return false;\n    }),\n} as const;\n\n// =============================================================================\n// Timeout\n// =============================================================================\n\n/**\n * Timeout error class\n */\nexport class TimeoutError extends Error {\n  readonly isTimeout = true;\n\n  constructor(message = 'Operation timed out') {\n    super(message);\n    this.name = 'TimeoutError';\n  }\n}\n\n/**\n * Execute a function with a timeout limit.\n *\n * @param fn - Async function to execute\n * @param timeoutMs - Timeout in milliseconds\n * @param errorMessage - Optional custom error message\n * @returns Result of the function\n * @throws TimeoutError if operation exceeds timeout\n *\n * @example\n * ```ts\n * const result = await withTimeout(\n *   () => fetchData(),\n *   5000,\n *   'Data fetch timed out'\n * );\n * ```\n */\nexport async function withTimeout<T>(\n  fn: () => Promise<T>,\n  timeoutMs: number,\n  errorMessage?: string\n): Promise<T> {\n  const controller = new AbortController();\n  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n\n  try {\n\n    return await Promise.race([\n      fn(),\n      new Promise<never>((_, reject) => {\n        controller.signal.addEventListener('abort', () => {\n          reject(\n            new TimeoutError(\n              errorMessage ?? `Operation timed out after ${timeoutMs}ms`\n            )\n          );\n        });\n      }),\n    ]);\n  } finally {\n    clearTimeout(timeoutId);\n  }\n}\n\n// =============================================================================\n// Debounce\n// =============================================================================\n\n/**\n * Debounce options\n */\nexport interface DebounceOptions {\n  /** Debounce delay in milliseconds */\n  delayMs: number;\n  /** Maximum wait time in milliseconds before forced execution */\n  maxWaitMs?: number;\n  /** Execute on leading edge (default: false) */\n  leading?: boolean;\n  /** Execute on trailing edge (default: true) */\n  trailing?: boolean;\n}\n\n/**\n * Debounced function interface\n */\nexport interface DebouncedFn<Args extends unknown[], R> {\n  (...args: Args): Promise<R>;\n  /** Cancel pending execution */\n  cancel(): void;\n  /** Execute immediately and return result */\n  flush(): Promise<R | undefined>;\n  /** Check if there's a pending execution */\n  pending(): boolean;\n}\n\n/**\n * Deferred promise with external resolve/reject\n */\nexport interface Deferred<T> {\n  promise: Promise<T>;\n  resolve: (value: T | PromiseLike<T>) => void;\n  reject: (reason?: unknown) => void;\n}\n\nexport function defer<T>(): Deferred<T> {\n  let resolve!: (value: T | PromiseLike<T>) => void;\n  let reject!: (reason?: unknown) => void;\n\n  const promise = new Promise<T>((res, rej) => {\n    resolve = res;\n    reject = rej;\n  });\n\n  return { promise, resolve, reject };\n}\n\n// Alias for backward compatibility\nexport const createDeferred = defer;\n\n/**\n * Create a debounced function that delays execution until after the\n * specified delay has elapsed since the last call.\n *\n * @param fn - Function to debounce\n * @param options - Debounce options or delay in milliseconds\n * @returns Debounced function with cancel, flush, and pending methods\n *\n * @example\n * ```ts\n * const debouncedSearch = debounce(\n *   (query: string) => searchApi(query),\n *   { delayMs: 300, maxWaitMs: 1000 }\n * );\n *\n * // These calls will be debounced\n * debouncedSearch('h');\n * debouncedSearch('he');\n * debouncedSearch('hel');\n * const result = await debouncedSearch('hello'); // Only this executes\n * ```\n */\nexport function debounce<Args extends unknown[], R>(\n  fn: (...args: Args) => R | Promise<R>,\n  options: DebounceOptions | number\n): DebouncedFn<Args, R> {\n  const opts: DebounceOptions =\n    typeof options === 'number' ? { delayMs: options } : options;\n\n  const { delayMs, maxWaitMs, leading = false, trailing = true } = opts;\n\n  let timeoutId: ReturnType<typeof setTimeout> | null = null;\n  let maxWaitTimeoutId: ReturnType<typeof setTimeout> | null = null;\n  let lastArgs: Args | null = null;\n  let lastThis: unknown = null;\n  let leadingCalled = false;\n  let deferred: Deferred<R> | null = null;\n\n  function invokeFunc(): void {\n    if (lastArgs === null) return;\n\n    const args = lastArgs;\n    const thisArg = lastThis;\n    lastArgs = null;\n    lastThis = null;\n\n    try {\n      const result = fn.apply(thisArg, args);\n      if (result instanceof Promise) {\n        result.then(\n          (value) => deferred?.resolve(value),\n          (error) => deferred?.reject(error)\n        );\n      } else {\n        deferred?.resolve(result);\n      }\n    } catch (error) {\n      deferred?.reject(error);\n    }\n\n    deferred = null;\n    leadingCalled = false;\n  }\n\n  function cancel(): void {\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n      timeoutId = null;\n    }\n    if (maxWaitTimeoutId) {\n      clearTimeout(maxWaitTimeoutId);\n      maxWaitTimeoutId = null;\n    }\n    lastArgs = null;\n    lastThis = null;\n    leadingCalled = false;\n    deferred?.reject(new Error('Debounced function cancelled'));\n    deferred = null;\n  }\n\n  async function flush(): Promise<R | undefined> {\n    if (timeoutId === null && maxWaitTimeoutId === null) {\n      return Promise.resolve(undefined);\n    }\n\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n      timeoutId = null;\n    }\n    if (maxWaitTimeoutId) {\n      clearTimeout(maxWaitTimeoutId);\n      maxWaitTimeoutId = null;\n    }\n\n    invokeFunc();\n    return deferred?.promise ?? undefined;\n  }\n\n  function pending(): boolean {\n    return timeoutId !== null || maxWaitTimeoutId !== null;\n  }\n\n  async function debounced(this: unknown, ...args: Args): Promise<R> {\n    const isFirstCall = lastArgs === null && !leadingCalled;\n    lastArgs = args;\n    lastThis = this; // eslint-disable-line @typescript-eslint/no-this-alias\n\n    deferred ??= createDeferred<R>();\n\n    // Handle leading edge\n    if (leading && isFirstCall && !leadingCalled) {\n      leadingCalled = true;\n      invokeFunc();\n      return deferred.promise;\n    }\n\n    // Clear existing timeout\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n    }\n\n    // Set up trailing edge timeout\n    if (trailing) {\n      timeoutId = setTimeout(() => {\n        timeoutId = null;\n        invokeFunc();\n      }, delayMs);\n    }\n\n    // Set up max wait timeout\n    if (maxWaitMs !== undefined && maxWaitTimeoutId === null) {\n      maxWaitTimeoutId = setTimeout(() => {\n        maxWaitTimeoutId = null;\n        if (timeoutId) {\n          clearTimeout(timeoutId);\n          timeoutId = null;\n        }\n        invokeFunc();\n      }, maxWaitMs);\n    }\n\n    return deferred.promise;\n  }\n\n  debounced.cancel = cancel;\n  debounced.flush = flush;\n  debounced.pending = pending;\n\n  return debounced;\n}\n\n// =============================================================================\n// Throttle\n// =============================================================================\n\n/**\n * Throttle options\n */\nexport interface ThrottleOptions {\n  /** Throttle interval in milliseconds */\n  intervalMs: number;\n  /** Execute on leading edge (default: true) */\n  leading?: boolean;\n  /** Execute on trailing edge (default: true) */\n  trailing?: boolean;\n}\n\n/**\n * Throttled function interface\n */\nexport interface ThrottledFn<Args extends unknown[], R> {\n  (...args: Args): R | undefined;\n  /** Cancel pending trailing execution */\n  cancel(): void;\n  /** Execute immediately with last arguments */\n  flush(): R | undefined;\n}\n\n/**\n * Create a throttled function that only executes at most once per interval.\n *\n * @param fn - Function to throttle\n * @param options - Throttle options or interval in milliseconds\n * @returns Throttled function with cancel and flush methods\n *\n * @example\n * ```ts\n * const throttledScroll = throttle(\n *   (event: ScrollEvent) => handleScroll(event),\n *   { intervalMs: 100 }\n * );\n *\n * window.addEventListener('scroll', throttledScroll);\n * ```\n */\nexport function throttle<Args extends unknown[], R>(\n  fn: (...args: Args) => R,\n  options: ThrottleOptions | number\n): ThrottledFn<Args, R> {\n  const opts: ThrottleOptions =\n    typeof options === 'number' ? { intervalMs: options } : options;\n\n  const { intervalMs, leading = true, trailing = true } = opts;\n\n  let lastCallTime: number | null = null;\n  let lastResult: R | undefined;\n  let timeoutId: ReturnType<typeof setTimeout> | null = null;\n  let lastArgs: Args | null = null;\n  let lastThis: unknown = null;\n\n  function invokeFunc(): R {\n    const args = lastArgs ?? ([] as unknown as Args);\n    const thisArg = lastThis;\n    lastArgs = null;\n    lastThis = null;\n    lastResult = fn.apply(thisArg, args);\n    return lastResult;\n  }\n\n  function cancel(): void {\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n      timeoutId = null;\n    }\n    lastCallTime = null;\n    lastArgs = null;\n    lastThis = null;\n  }\n\n  function flush(): R | undefined {\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n      timeoutId = null;\n    }\n    if (lastArgs !== null) {\n      return invokeFunc();\n    }\n    return lastResult;\n  }\n\n  function throttled(this: unknown, ...args: Args): R | undefined {\n    const now = Date.now();\n    const timeSinceLastCall =\n      lastCallTime !== null ? now - lastCallTime : intervalMs;\n\n    lastArgs = args;\n    lastThis = this; // eslint-disable-line @typescript-eslint/no-this-alias\n\n    if (timeSinceLastCall >= intervalMs) {\n      lastCallTime = now;\n\n      if (leading) {\n        return invokeFunc();\n      }\n    }\n\n    if (trailing && !timeoutId) {\n      timeoutId = setTimeout(() => {\n        timeoutId = null;\n        lastCallTime = Date.now();\n        invokeFunc();\n      }, intervalMs - timeSinceLastCall);\n    }\n\n    return lastResult;\n  }\n\n  throttled.cancel = cancel;\n  throttled.flush = flush;\n\n  return throttled;\n}\n\n// =============================================================================\n// Mutex and Semaphore\n// =============================================================================\n\n/**\n * Mutex for exclusive access to a resource.\n *\n * @example\n * ```ts\n * const mutex = new Mutex();\n *\n * // Manual lock/unlock\n * const release = await mutex.acquire();\n * try {\n *   await criticalOperation();\n * } finally {\n *   release();\n * }\n *\n * // Or use runExclusive\n * const result = await mutex.runExclusive(async () => {\n *   return await criticalOperation();\n * });\n * ```\n */\nexport class Mutex {\n  private locked = false;\n  private queue: Array<() => void> = [];\n\n  /** Acquire the lock, returns a release function */\n  async acquire(): Promise<() => void> {\n    if (!this.locked) {\n      this.locked = true;\n      return () => this.release();\n    }\n\n    return new Promise((resolve) => {\n      this.queue.push(() => {\n        this.locked = true;\n        resolve(() => this.release());\n      });\n    });\n  }\n\n  /** Execute a function with exclusive lock */\n  async runExclusive<T>(fn: () => Promise<T>): Promise<T> {\n    const release = await this.acquire();\n    try {\n      return await fn();\n    } finally {\n      release();\n    }\n  }\n\n  /** Check if the mutex is currently locked */\n  isLocked(): boolean {\n    return this.locked;\n  }\n\n  /** Get the number of waiting acquires */\n  getQueueLength(): number {\n    return this.queue.length;\n  }\n\n  private release(): void {\n    const next = this.queue.shift();\n    if (next) {\n      next();\n    } else {\n      this.locked = false;\n    }\n  }\n}\n\n/**\n * Semaphore for limiting concurrent access to a resource.\n *\n * @example\n * ```ts\n * // Allow max 5 concurrent operations\n * const semaphore = new Semaphore(5);\n *\n * const results = await Promise.all(\n *   urls.map(url =>\n *     semaphore.runWithPermit(() => fetch(url))\n *   )\n * );\n * ```\n */\nexport class Semaphore {\n  private permits: number;\n  private readonly maxPermits: number;\n  private queue: Array<() => void> = [];\n\n  constructor(permits: number) {\n    this.permits = permits;\n    this.maxPermits = permits;\n  }\n\n  /** Acquire a permit, returns a release function */\n  async acquire(): Promise<() => void> {\n    if (this.permits > 0) {\n      this.permits--;\n      return () => this.release();\n    }\n\n    return new Promise((resolve) => {\n      this.queue.push(() => {\n        this.permits--;\n        resolve(() => this.release());\n      });\n    });\n  }\n\n  /** Execute a function with a permit */\n  async runWithPermit<T>(fn: () => Promise<T>): Promise<T> {\n    const release = await this.acquire();\n    try {\n      return await fn();\n    } finally {\n      release();\n    }\n  }\n\n  /** Get available permits */\n  availablePermits(): number {\n    return this.permits;\n  }\n\n  /** Get the number of waiting acquires */\n  getQueueLength(): number {\n    return this.queue.length;\n  }\n\n  /** Get max permits configured */\n  getMaxPermits(): number {\n    return this.maxPermits;\n  }\n\n  private release(): void {\n    this.permits++;\n    const next = this.queue.shift();\n    if (next) {\n      next();\n    }\n  }\n}\n\n// =============================================================================\n// Cancellation Token\n// =============================================================================\n\n/**\n * Cancellation token for aborting async operations.\n *\n * @example\n * ```ts\n * const token = new CancellationToken();\n *\n * // Start operation\n * fetchWithCancellation(url, token.signal);\n *\n * // Cancel after 5 seconds\n * setTimeout(() => token.cancel('Timeout'), 5000);\n * ```\n */\nexport class CancellationToken {\n  private controller: AbortController;\n  private reason?: Error;\n\n  constructor() {\n    this.controller = new AbortController();\n  }\n\n  /** Get the abort signal */\n  get signal(): AbortSignal {\n    return this.controller.signal;\n  }\n\n  /** Check if cancelled */\n  get isCancelled(): boolean {\n    return this.controller.signal.aborted;\n  }\n\n  /** Cancel the token with an optional reason */\n  cancel(reason?: string | Error): void {\n    this.reason =\n      reason instanceof Error ? reason : new Error(reason ?? 'Cancelled');\n    this.controller.abort(this.reason);\n  }\n\n  /** Get cancellation reason */\n  getCancellationReason(): Error | undefined {\n    return this.reason;\n  }\n\n  /** Throw if cancelled */\n  throwIfCancelled(): void {\n    if (this.isCancelled) {\n      throw this.reason ?? new Error('Cancelled');\n    }\n  }\n\n  /** Register callback for cancellation */\n  onCancel(callback: (reason?: Error) => void): () => void {\n    const handler = (): void => callback(this.reason);\n    this.controller.signal.addEventListener('abort', handler);\n    return () => this.controller.signal.removeEventListener('abort', handler);\n  }\n}\n\n// =============================================================================\n// Promise Utilities\n// =============================================================================\n\n/**\n * Map over items with controlled concurrency.\n *\n * @param items - Items to process\n * @param mapper - Async mapper function\n * @param concurrency - Max concurrent operations (default: 5)\n * @returns Array of results in same order as input\n *\n * @example\n * ```ts\n * const results = await pMap(\n *   urls,\n *   async (url) => fetch(url).then(r => r.json()),\n *   3 // Max 3 concurrent requests\n * );\n * ```\n */\nexport async function pMap<T, R>(\n  items: T[],\n  mapper: (item: T, index: number) => Promise<R>,\n  concurrency = 5\n): Promise<R[]> {\n  const results: R[] = [];\n  const semaphore = new Semaphore(concurrency);\n\n  await Promise.all(\n    items.map(async (item, index) => {\n\n      results[index] = await semaphore.runWithPermit(async () => mapper(item, index));\n    })\n  );\n\n  return results;\n}\n\n/**\n * Execute async functions sequentially.\n *\n * @param items - Items to process\n * @param mapper - Async mapper function\n * @returns Array of results in same order as input\n */\nexport async function pSeries<T, R>(\n  items: T[],\n  mapper: (item: T, index: number) => Promise<R>\n): Promise<R[]> {\n  const results: R[] = [];\n  for (let i = 0; i < items.length; i++) {\n    const item = items[i];\n    if (item !== undefined) {\n      results.push(await mapper(item, i));\n    }\n  }\n  return results;\n}\n\n/**\n * Execute with cleanup guaranteed after completion.\n *\n * @param fn - Async function to execute\n * @param cleanup - Cleanup function to run after fn completes\n * @returns Result of fn\n */\nexport async function withCleanup<T>(\n  fn: () => Promise<T>,\n  cleanup: () => void | Promise<void>\n): Promise<T> {\n  try {\n    return await fn();\n  } finally {\n    await cleanup();\n  }\n}\n\n/**\n * Safe async execution returning tuple of [result, error].\n *\n * @param fn - Async function to execute\n * @returns Tuple of [result, null] on success or [null, error] on failure\n *\n * @example\n * ```ts\n * const [data, error] = await safeAsync(() => fetchData());\n * if (error) {\n *   console.error('Failed:', error);\n * } else {\n *   console.log('Success:', data);\n * }\n * ```\n */\nexport async function safeAsync<T>(\n  fn: () => Promise<T>\n): Promise<[T, null] | [null, Error]> {\n  try {\n    const result = await fn();\n    return [result, null];\n  } catch (error) {\n    return [null, error instanceof Error ? error : new Error(String(error))];\n  }\n}\n\n/**\n * Safe sync execution returning tuple of [result, error].\n */\nexport function safeSync<T>(fn: () => T): [T, null] | [null, Error] {\n  try {\n    const result = fn();\n    return [result, null];\n  } catch (error) {\n    return [null, error instanceof Error ? error : new Error(String(error))];\n  }\n}\n"],"names":["sleep","ms","signal","resolve","reject","timeoutId","DEFAULT_RETRY_CONFIG","calculateRetryDelay","attempt","config","exponentialDelay","boundedDelay","jitterRange","withRetry","fn","resolvedConfig","lastError","error","delayMs","RetryPolicy","max","initialMs","maxMs","multiplier","enabled","predicate","callback","retryPolicies","message","TimeoutError","withTimeout","timeoutMs","errorMessage","controller","_","defer","res","rej","createDeferred","debounce","options","opts","maxWaitMs","leading","trailing","maxWaitTimeoutId","lastArgs","lastThis","leadingCalled","deferred","invokeFunc","args","thisArg","result","value","cancel","flush","pending","debounced","isFirstCall","throttle","intervalMs","lastCallTime","lastResult","throttled","now","timeSinceLastCall","Mutex","release","next","Semaphore","permits","CancellationToken","reason","handler","pMap","items","mapper","concurrency","results","semaphore","item","index","pSeries","i","withCleanup","cleanup","safeAsync","safeSync"],"mappings":"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"}