{"version":3,"file":"asyncUtils.mjs","sources":["../../../src/lib/utils/asyncUtils.ts"],"sourcesContent":["/**\n * @file Async Utilities\n * @description Common async/promise utilities for the application\n */\n\n/**\n * Deferred promise interface\n */\nexport interface Deferred<T> {\n  promise: Promise<T>;\n  resolve: (value: T | PromiseLike<T>) => void;\n  reject: (reason?: unknown) => void;\n}\n\n/**\n * Create a deferred promise\n */\nexport function defer<T = void>(): 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/**\n * Delay execution for a specified time\n */\nexport async function delay(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Wait for a condition to be true\n */\nexport async function waitFor(\n  condition: () => boolean | Promise<boolean>,\n  options: { timeout?: number; interval?: number } = {}\n): Promise<void> {\n  const { timeout = 5000, interval = 100 } = options;\n  const startTime = Date.now();\n\n  while (!(await condition())) {\n    if (Date.now() - startTime > timeout) {\n      throw new Error('waitFor timeout exceeded');\n    }\n    await delay(interval);\n  }\n}\n\n/**\n * Retry a function with exponential backoff\n */\nexport async function retry<T>(\n  fn: () => Promise<T>,\n  options: {\n    maxAttempts?: number;\n    delayMs?: number;\n    maxDelayMs?: number;\n    backoffMultiplier?: number;\n    onRetry?: (error: Error, attempt: number) => void;\n  } = {}\n): Promise<T> {\n  const {\n    maxAttempts = 3,\n    delayMs = 1000,\n    maxDelayMs = 30000,\n    backoffMultiplier = 2,\n    onRetry,\n  } = options;\n\n  let lastError: Error | undefined;\n  let currentDelay = delayMs;\n\n  for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n    try {\n      return await fn();\n    } catch (error) {\n      lastError = error instanceof Error ? error : new Error(String(error));\n\n      if (attempt === maxAttempts) {\n        throw lastError;\n      }\n\n      onRetry?.(lastError, attempt);\n      await delay(currentDelay);\n      currentDelay = Math.min(currentDelay * backoffMultiplier, maxDelayMs);\n    }\n  }\n\n  if (lastError !== undefined) {\n    throw lastError;\n  }\n  throw new Error('Operation failed without error details');\n}\n\n/**\n * Run promises with a concurrency limit\n */\nexport async function concurrent<T, R>(\n  items: T[],\n  fn: (item: T, index: number) => Promise<R>,\n  concurrency: number = 5\n): Promise<R[]> {\n  const results: R[] = [];\n  const executing: Promise<void>[] = [];\n\n  for (let i = 0; i < items.length; i++) {\n    const item = items[i];\n    if (item === undefined) continue;\n    const promise = fn(item, i).then((result) => {\n      results[i] = result;\n    });\n\n    const e: Promise<void> = promise.then(() => {\n      const index = executing.indexOf(e);\n      if (index !== -1) {\n        void executing.splice(index, 1);\n      }\n    });\n    void executing.push(e);\n\n    if (executing.length >= concurrency) {\n      await Promise.race(executing);\n    }\n  }\n\n  await Promise.all(executing);\n  return results;\n}\n\n/**\n * Timeout wrapper for promises\n */\nexport async function withTimeout<T>(\n  promise: Promise<T>,\n  timeoutMs: number,\n  message = 'Operation timed out'\n): Promise<T> {\n  let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n  const timeoutPromise = new Promise<never>((_, reject) => {\n    timeoutId = setTimeout(() => {\n      reject(new Error(message));\n    }, timeoutMs);\n  });\n\n  try {\n    return await Promise.race([promise, timeoutPromise]);\n  } finally {\n    if (timeoutId !== undefined) {\n      clearTimeout(timeoutId);\n    }\n  }\n}\n\n/**\n * Create a debounced async function\n */\nexport function debounceAsync<T extends (...args: unknown[]) => Promise<unknown>>(\n  fn: T,\n  delayMs: number\n): T {\n  let timeoutId: ReturnType<typeof setTimeout> | null = null;\n  let pendingPromise: Promise<unknown> | null = null;\n\n  return (async (...args: unknown[]) => {\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n    }\n\n    return new Promise((resolve, reject) => {\n      timeoutId = setTimeout(() => {\n        void (async () => {\n          try {\n            pendingPromise = fn(...args);\n            const result = await pendingPromise;\n            resolve(result);\n          } catch (error) {\n            reject(error instanceof Error ? error : new Error(String(error)));\n          } finally {\n            pendingPromise = null;\n          }\n        })();\n      }, delayMs);\n    });\n  }) as T;\n}\n\n/**\n * Create a throttled async function\n */\nexport function throttleAsync<T extends (...args: unknown[]) => Promise<unknown>>(\n  fn: T,\n  intervalMs: number\n): T {\n  let lastExecution = 0;\n  let pendingPromise: Promise<unknown> | null = null;\n\n  return (async (...args: unknown[]) => {\n    const now = Date.now();\n    const timeSinceLast = now - lastExecution;\n\n    if (timeSinceLast >= intervalMs) {\n      lastExecution = now;\n      pendingPromise = fn(...args);\n      return pendingPromise;\n    }\n\n    if (pendingPromise) {\n      return pendingPromise;\n    }\n\n    return new Promise((resolve, reject) => {\n      setTimeout(() => {\n        void (async () => {\n          lastExecution = Date.now();\n          try {\n            pendingPromise = fn(...args);\n            const result = await pendingPromise;\n            resolve(result);\n          } catch (error) {\n            reject(error instanceof Error ? error : new Error(String(error)));\n          } finally {\n            pendingPromise = null;\n          }\n        })();\n      }, intervalMs - timeSinceLast);\n    });\n  }) as T;\n}\n\n/**\n * Execute a function and return a tuple of [error, result]\n */\nexport async function tryCatch<T>(fn: () => Promise<T>): Promise<[Error, null] | [null, T]> {\n  try {\n    const result = await fn();\n    return [null, result];\n  } catch (error) {\n    return [error instanceof Error ? error : new Error(String(error)), null];\n  }\n}\n\n/**\n * Create a cancelable promise\n */\nexport interface CancelablePromise<T> {\n  promise: Promise<T>;\n  cancel: () => void;\n  isCanceled: () => boolean;\n}\n\nexport function makeCancelable<T>(promise: Promise<T>): CancelablePromise<T> {\n  let isCanceled = false;\n\n  const wrappedPromise = new Promise<T>((resolve, reject) => {\n    promise\n      .then((val) => {\n        if (!isCanceled) {\n          resolve(val);\n        }\n      })\n      .catch((error) => {\n        if (!isCanceled) {\n          reject(error instanceof Error ? error : new Error(String(error)));\n        }\n      });\n  });\n\n  return {\n    promise: wrappedPromise,\n    cancel: () => {\n      isCanceled = true;\n    },\n    isCanceled: () => isCanceled,\n  };\n}\n\n/**\n * Run async functions in sequence\n */\nexport async function sequence<T>(fns: Array<() => Promise<T>>): Promise<T[]> {\n  const results: T[] = [];\n  for (const fn of fns) {\n    results.push(await fn());\n  }\n  return results;\n}\n\n/**\n * Create a semaphore for limiting concurrent operations\n */\nexport function createSemaphore(limit: number): {\n  acquire: () => Promise<void>;\n  release: () => void;\n  available: number;\n  waiting: number;\n} {\n  let currentCount = 0;\n  const waitingQueue: Array<() => void> = [];\n\n  return {\n    async acquire(): Promise<void> {\n      if (currentCount < limit) {\n        currentCount++;\n        return;\n      }\n\n      await new Promise<void>((resolve) => {\n        waitingQueue.push(resolve);\n      });\n      currentCount++;\n    },\n\n    release(): void {\n      currentCount--;\n      const next = waitingQueue.shift();\n      if (next) {\n        next();\n      }\n    },\n\n    get available(): number {\n      return limit - currentCount;\n    },\n\n    get waiting(): number {\n      return waitingQueue.length;\n    },\n  };\n}\n"],"names":["defer","resolve","reject","res","rej"],"mappings":"AAiBO,SAASA,IAA+B;AAC7C,MAAIC,GACAC;AAOJ,SAAO,EAAE,SALO,IAAI,QAAW,CAACC,GAAKC,MAAQ;AAC3C,IAAAH,IAAUE,GACVD,IAASE;AAAA,EACX,CAAC,GAEiB,SAAAH,GAAS,QAAAC,EAAA;AAC7B;"}