{"version":3,"file":"error-recovery-ux.mjs","sources":["../../../src/lib/ux/error-recovery-ux.ts"],"sourcesContent":["/**\n * @file Smart Error Recovery UX\n * @description PhD-level intelligent error recovery with automatic retry strategies,\n * user-friendly progress indication, and circuit breaker integration.\n *\n * Features:\n * - Automatic recovery strategies\n * - Intelligent retry logic with exponential backoff\n * - User-friendly progress indication\n * - Circuit breaker UX integration\n * - Network-aware recovery\n * - Graceful degradation messaging\n */\n\nimport { useCallback, useEffect, useState, useRef } from 'react';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Error severity levels\n */\nexport type RecoveryErrorSeverity = 'info' | 'warning' | 'error' | 'critical';\n\n/**\n * Recovery strategy types\n */\nexport type RecoveryStrategy = 'retry' | 'refresh' | 'fallback' | 'redirect' | 'manual' | 'none';\n\n/**\n * Recovery state\n */\nexport type RecoveryState = 'idle' | 'recovering' | 'recovered' | 'failed' | 'circuit-open';\n\n/**\n * Recovery progress info\n */\nexport interface RecoveryProgress {\n  /** Current state */\n  state: RecoveryState;\n  /** Current attempt number */\n  attempt: number;\n  /** Maximum attempts */\n  maxAttempts: number;\n  /** Progress percentage (0-100) */\n  percentage: number;\n  /** Time until next retry in ms */\n  nextRetryIn: number;\n  /** Error message */\n  message: string;\n  /** User-friendly suggestion */\n  suggestion: string;\n}\n\n/**\n * Error classification result\n */\nexport interface ErrorClassification {\n  /** Error severity */\n  severity: RecoveryErrorSeverity;\n  /** Is recoverable */\n  recoverable: boolean;\n  /** Recommended strategy */\n  strategy: RecoveryStrategy;\n  /** Is network related */\n  isNetworkError: boolean;\n  /** Is rate limited */\n  isRateLimited: boolean;\n  /** Is authentication error */\n  isAuthError: boolean;\n  /** Is validation error */\n  isValidationError: boolean;\n  /** Retry delay suggestion in ms */\n  suggestedRetryDelay: number;\n}\n\n/**\n * Recovery options\n */\nexport interface RecoveryOptions {\n  /** Maximum retry attempts */\n  maxAttempts?: number;\n  /** Base delay between retries in ms */\n  baseDelay?: number;\n  /** Maximum delay between retries in ms */\n  maxDelay?: number;\n  /** Backoff multiplier */\n  backoffMultiplier?: number;\n  /** Add jitter to delays */\n  jitter?: boolean;\n  /** Retry only on specific errors */\n  retryOn?: (error: Error) => boolean;\n  /** Custom error classifier */\n  classifier?: (error: Error) => ErrorClassification;\n  /** On recovery attempt */\n  onAttempt?: (attempt: number, error: Error) => void;\n  /** On recovery success */\n  onSuccess?: () => void;\n  /** On recovery failure */\n  onFailure?: (error: Error, attempts: number) => void;\n  /** Respect circuit breaker state */\n  respectCircuitBreaker?: boolean;\n}\n\n/**\n * Circuit breaker state\n */\nexport interface CircuitBreakerState {\n  /** Is circuit open */\n  isOpen: boolean;\n  /** Failures count */\n  failures: number;\n  /** Last failure timestamp */\n  lastFailure: number | null;\n  /** Time until half-open in ms */\n  resetIn: number;\n}\n\n// ============================================================================\n// Error Classification\n// ============================================================================\n\n/**\n * Default error classifier\n */\nexport function classifyRecoveryError(error: Error): ErrorClassification {\n  const message = error.message.toLowerCase();\n  const name = error.name.toLowerCase();\n\n  // Network errors\n  if (\n    name.includes('network') ||\n    name.includes('fetch') ||\n    message.includes('network') ||\n    message.includes('failed to fetch') ||\n    message.includes('connection') ||\n    message.includes('timeout') ||\n    message.includes('offline')\n  ) {\n    return {\n      severity: 'warning',\n      recoverable: true,\n      strategy: 'retry',\n      isNetworkError: true,\n      isRateLimited: false,\n      isAuthError: false,\n      isValidationError: false,\n      suggestedRetryDelay: 2000,\n    };\n  }\n\n  // Rate limiting\n  if (\n    message.includes('rate limit') ||\n    message.includes('too many requests') ||\n    message.includes('429')\n  ) {\n    return {\n      severity: 'warning',\n      recoverable: true,\n      strategy: 'retry',\n      isNetworkError: false,\n      isRateLimited: true,\n      isAuthError: false,\n      isValidationError: false,\n      suggestedRetryDelay: 60000, // 1 minute\n    };\n  }\n\n  // Authentication errors\n  if (\n    message.includes('unauthorized') ||\n    message.includes('unauthenticated') ||\n    message.includes('401') ||\n    message.includes('403') ||\n    message.includes('forbidden')\n  ) {\n    return {\n      severity: 'error',\n      recoverable: false,\n      strategy: 'redirect',\n      isNetworkError: false,\n      isRateLimited: false,\n      isAuthError: true,\n      isValidationError: false,\n      suggestedRetryDelay: 0,\n    };\n  }\n\n  // Validation errors\n  if (\n    message.includes('validation') ||\n    message.includes('invalid') ||\n    message.includes('400')\n  ) {\n    return {\n      severity: 'warning',\n      recoverable: false,\n      strategy: 'manual',\n      isNetworkError: false,\n      isRateLimited: false,\n      isAuthError: false,\n      isValidationError: true,\n      suggestedRetryDelay: 0,\n    };\n  }\n\n  // Server errors\n  if (\n    message.includes('500') ||\n    message.includes('502') ||\n    message.includes('503') ||\n    message.includes('504') ||\n    message.includes('server error')\n  ) {\n    return {\n      severity: 'error',\n      recoverable: true,\n      strategy: 'retry',\n      isNetworkError: false,\n      isRateLimited: false,\n      isAuthError: false,\n      isValidationError: false,\n      suggestedRetryDelay: 5000,\n    };\n  }\n\n  // Default: unknown error\n  return {\n    severity: 'error',\n    recoverable: false,\n    strategy: 'fallback',\n    isNetworkError: false,\n    isRateLimited: false,\n    isAuthError: false,\n    isValidationError: false,\n    suggestedRetryDelay: 3000,\n  };\n}\n\n/**\n * Get user-friendly error message\n */\nexport function getUserFriendlyErrorMessage(\n  classification: ErrorClassification\n): { message: string; suggestion: string } {\n  if (classification.isNetworkError) {\n    return {\n      message: 'Connection issue detected',\n      suggestion: 'Please check your internet connection. We\\'ll retry automatically.',\n    };\n  }\n\n  if (classification.isRateLimited) {\n    return {\n      message: 'Too many requests',\n      suggestion: 'Please wait a moment. The system will retry automatically.',\n    };\n  }\n\n  if (classification.isAuthError) {\n    return {\n      message: 'Session expired',\n      suggestion: 'Please sign in again to continue.',\n    };\n  }\n\n  if (classification.isValidationError) {\n    return {\n      message: 'Invalid input',\n      suggestion: 'Please check your input and try again.',\n    };\n  }\n\n  return {\n    message: 'Something went wrong',\n    suggestion: 'We\\'re working on it. Please try again shortly.',\n  };\n}\n\n// ============================================================================\n// Recovery Engine\n// ============================================================================\n\n/**\n * Smart recovery engine\n */\nexport class RecoveryEngine {\n  private options: Required<RecoveryOptions>;\n  private circuitBreaker: CircuitBreakerState = {\n    isOpen: false,\n    failures: 0,\n    lastFailure: null,\n    resetIn: 0,\n  };\n  private circuitBreakerThreshold = 5;\n  private circuitBreakerTimeout = 30000;\n\n  constructor(options: RecoveryOptions = {}) {\n    this.options = {\n      maxAttempts: options.maxAttempts ?? 3,\n      baseDelay: options.baseDelay ?? 1000,\n      maxDelay: options.maxDelay ?? 30000,\n      backoffMultiplier: options.backoffMultiplier ?? 2,\n      jitter: options.jitter ?? true,\n      retryOn: options.retryOn ?? (() => true),\n      classifier: options.classifier ?? classifyRecoveryError,\n      onAttempt: options.onAttempt ?? (() => {}),\n      onSuccess: options.onSuccess ?? (() => {}),\n      onFailure: options.onFailure ?? (() => {}),\n      respectCircuitBreaker: options.respectCircuitBreaker ?? true,\n    };\n  }\n\n  /**\n   * Execute with automatic recovery\n   */\n  async execute<T>(\n    operation: () => Promise<T>,\n    onProgress?: (progress: RecoveryProgress) => void\n  ): Promise<T> {\n    // Check circuit breaker\n    if (this.options.respectCircuitBreaker && this.circuitBreaker.isOpen) {\n      const now = Date.now();\n      const timeSinceFailure = now - (this.circuitBreaker.lastFailure ?? 0);\n\n      if (timeSinceFailure < this.circuitBreakerTimeout) {\n        const resetIn = this.circuitBreakerTimeout - timeSinceFailure;\n        onProgress?.({\n          state: 'circuit-open',\n          attempt: 0,\n          maxAttempts: this.options.maxAttempts,\n          percentage: 0,\n          nextRetryIn: resetIn,\n          message: 'Service temporarily unavailable',\n          suggestion: `Please wait ${Math.ceil(resetIn / 1000)} seconds`,\n        });\n        throw new Error('Circuit breaker is open');\n      } else {\n        // Half-open: allow one attempt\n        this.circuitBreaker.isOpen = false;\n      }\n    }\n\n    let lastError: Error = new Error('Unknown error');\n    let attempt = 0;\n\n    while (attempt < this.options.maxAttempts) {\n      attempt++;\n\n      try {\n        onProgress?.({\n          state: 'recovering',\n          attempt,\n          maxAttempts: this.options.maxAttempts,\n          percentage: (attempt / this.options.maxAttempts) * 100,\n          nextRetryIn: 0,\n          message: `Attempt ${attempt} of ${this.options.maxAttempts}`,\n          suggestion: 'Please wait...',\n        });\n\n        const result = await operation();\n\n        // Success - reset circuit breaker\n        this.circuitBreaker.failures = 0;\n        this.circuitBreaker.isOpen = false;\n        this.options.onSuccess();\n\n        onProgress?.({\n          state: 'recovered',\n          attempt,\n          maxAttempts: this.options.maxAttempts,\n          percentage: 100,\n          nextRetryIn: 0,\n          message: 'Success',\n          suggestion: '',\n        });\n\n        return result;\n      } catch (error) {\n        lastError = error instanceof Error ? error : new Error(String(error));\n        this.options.onAttempt(attempt, lastError);\n\n        // Classify error\n        const classification = this.options.classifier(lastError);\n\n        // Check if we should retry\n        if (!classification.recoverable || !this.options.retryOn(lastError)) {\n          break;\n        }\n\n        // Update circuit breaker\n        this.circuitBreaker.failures++;\n        this.circuitBreaker.lastFailure = Date.now();\n\n        if (this.circuitBreaker.failures >= this.circuitBreakerThreshold) {\n          this.circuitBreaker.isOpen = true;\n        }\n\n        // Calculate delay\n        if (attempt < this.options.maxAttempts) {\n          const delay = this.calculateDelay(attempt, classification.suggestedRetryDelay);\n          const { message, suggestion } = getUserFriendlyErrorMessage(classification);\n\n          onProgress?.({\n            state: 'recovering',\n            attempt,\n            maxAttempts: this.options.maxAttempts,\n            percentage: (attempt / this.options.maxAttempts) * 100,\n            nextRetryIn: delay,\n            message,\n            suggestion: `${suggestion} Retrying in ${Math.ceil(delay / 1000)}s...`,\n          });\n\n          await this.delay(delay);\n        }\n      }\n    }\n\n    // All attempts failed\n    this.options.onFailure(lastError, attempt);\n\n    const classification = this.options.classifier(lastError);\n    const { message, suggestion } = getUserFriendlyErrorMessage(classification);\n\n    onProgress?.({\n      state: 'failed',\n      attempt,\n      maxAttempts: this.options.maxAttempts,\n      percentage: 100,\n      nextRetryIn: 0,\n      message,\n      suggestion,\n    });\n\n    throw lastError;\n  }\n\n  /**\n   * Get circuit breaker state\n   */\n  getCircuitBreakerState(): CircuitBreakerState {\n    const now = Date.now();\n    const timeSinceFailure = now - (this.circuitBreaker.lastFailure ?? 0);\n    const resetIn = this.circuitBreaker.isOpen\n      ? Math.max(0, this.circuitBreakerTimeout - timeSinceFailure)\n      : 0;\n\n    return { ...this.circuitBreaker, resetIn };\n  }\n\n  /**\n   * Reset circuit breaker\n   */\n  resetCircuitBreaker(): void {\n    this.circuitBreaker = {\n      isOpen: false,\n      failures: 0,\n      lastFailure: null,\n      resetIn: 0,\n    };\n  }\n\n  /**\n   * Calculate retry delay with exponential backoff and jitter\n   */\n  private calculateDelay(attempt: number, suggestedDelay: number): number {\n    let delay = Math.max(\n      this.options.baseDelay * Math.pow(this.options.backoffMultiplier, attempt - 1),\n      suggestedDelay\n    );\n\n    // Cap at max delay\n    delay = Math.min(delay, this.options.maxDelay);\n\n    // Add jitter\n    if (this.options.jitter) {\n      const jitter = delay * 0.2 * Math.random();\n      delay = delay + jitter - delay * 0.1;\n    }\n\n    return Math.round(delay);\n  }\n\n  /**\n   * Delay helper\n   */\n  private async delay(ms: number): Promise<void> {\n    return new Promise((resolve) => setTimeout(resolve, ms));\n  }\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * Hook for automatic error recovery\n */\nexport function useRecovery<T>(\n  operation: () => Promise<T>,\n  options: RecoveryOptions & { enabled?: boolean } = {}\n): {\n  execute: () => Promise<T>;\n  progress: RecoveryProgress;\n  isRecovering: boolean;\n  error: Error | null;\n  reset: () => void;\n} {\n  const { enabled = true, ...recoveryOptions } = options;\n  const engineRef = useRef<RecoveryEngine | null>(null);\n  engineRef.current ??= new RecoveryEngine(recoveryOptions);\n  const engine = engineRef.current;\n  const [progress, setProgress] = useState<RecoveryProgress>({\n    state: 'idle',\n    attempt: 0,\n    maxAttempts: recoveryOptions.maxAttempts ?? 3,\n    percentage: 0,\n    nextRetryIn: 0,\n    message: '',\n    suggestion: '',\n  });\n  const [error, setError] = useState<Error | null>(null);\n\n  const execute = useCallback(async (): Promise<T> => {\n    if (!enabled) {\n      return operation();\n    }\n\n    setError(null);\n    try {\n      return await engine.execute(operation, setProgress);\n    } catch (err) {\n      const e = err instanceof Error ? err : new Error(String(err));\n      setError(e);\n      throw e;\n    }\n  }, [enabled, engine, operation]);\n\n  const reset = useCallback(() => {\n    setProgress({\n      state: 'idle',\n      attempt: 0,\n      maxAttempts: recoveryOptions.maxAttempts ?? 3,\n      percentage: 0,\n      nextRetryIn: 0,\n      message: '',\n      suggestion: '',\n    });\n    setError(null);\n    engine.resetCircuitBreaker();\n  }, [engine, recoveryOptions.maxAttempts]);\n\n  return {\n    execute,\n    progress,\n    isRecovering: progress.state === 'recovering',\n    error,\n    reset,\n  };\n}\n\n/**\n * Hook for circuit breaker awareness\n */\nexport function useCircuitBreaker(options: RecoveryOptions = {}): {\n  state: CircuitBreakerState;\n  isOpen: boolean;\n  reset: () => void;\n} {\n  const engineRef = useRef<RecoveryEngine | null>(null);\n  engineRef.current ??= new RecoveryEngine(options);\n  const engine = engineRef.current;\n  const [state, setState] = useState<CircuitBreakerState>(() => engine.getCircuitBreakerState());\n\n  useEffect(() => {\n    const interval = setInterval(() => {\n      setState(engine.getCircuitBreakerState());\n    }, 1000);\n    return () => {\n      clearInterval(interval);\n    };\n  }, [engine]);\n\n  const reset = useCallback(() => {\n    engine.resetCircuitBreaker();\n    setState(engine.getCircuitBreakerState());\n  }, [engine]);\n\n  return {\n    state,\n    isOpen: state.isOpen,\n    reset,\n  };\n}\n\n/**\n * Hook for network-aware recovery\n */\nexport function useNetworkAwareRecovery<T>(\n  operation: () => Promise<T>,\n  options: RecoveryOptions = {}\n): {\n  execute: () => Promise<T>;\n  isOnline: boolean;\n  isRecovering: boolean;\n  progress: RecoveryProgress;\n  error: Error | null;\n} {\n  const [isOnline, setIsOnline] = useState(\n    typeof navigator !== 'undefined' ? navigator.onLine : true\n  );\n\n  useEffect(() => {\n    const handleOnline = (): void => setIsOnline(true);\n    const handleOffline = (): void => setIsOnline(false);\n\n    window.addEventListener('online', handleOnline);\n    window.addEventListener('offline', handleOffline);\n\n    return () => {\n      window.removeEventListener('online', handleOnline);\n      window.removeEventListener('offline', handleOffline);\n    };\n  }, []);\n\n  const { execute, progress, isRecovering, error } = useRecovery(operation, {\n    ...options,\n    enabled: isOnline,\n  });\n\n  return { execute, isOnline, isRecovering, progress, error };\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Create recovery engine\n */\nexport function createRecoveryEngine(options?: RecoveryOptions): RecoveryEngine {\n  return new RecoveryEngine(options);\n}\n\n/**\n * Execute with recovery\n */\nexport async function executeWithRecovery<T>(\n  operation: () => Promise<T>,\n  options?: RecoveryOptions\n): Promise<T> {\n  return new RecoveryEngine(options).execute(operation);\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport default {\n  RecoveryEngine,\n  classifyRecoveryError,\n  getUserFriendlyErrorMessage,\n  createRecoveryEngine,\n  executeWithRecovery,\n  useRecovery,\n  useCircuitBreaker,\n  useNetworkAwareRecovery,\n};\n"],"names":["classifyRecoveryError","error","message","name","getUserFriendlyErrorMessage","classification","RecoveryEngine","options","operation","onProgress","timeSinceFailure","resetIn","lastError","attempt","result","delay","suggestion","suggestedDelay","jitter","ms","resolve","useRecovery","enabled","recoveryOptions","engineRef","useRef","engine","progress","setProgress","useState","setError","execute","useCallback","err","e","reset","useCircuitBreaker","state","setState","useEffect","interval","useNetworkAwareRecovery","isOnline","setIsOnline","handleOnline","handleOffline","isRecovering","createRecoveryEngine","executeWithRecovery"],"mappings":"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"}