{"version":3,"file":"networkStatus.mjs","sources":["../../../src/lib/utils/networkStatus.ts"],"sourcesContent":["/**\n * @file Network Status Utilities\n * @description Online/offline detection, connection quality monitoring,\n * and network-aware request handling\n */\n\nimport { globalEventBus } from './eventEmitter';\nimport { logger } from './logging';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Network connection type\n */\nexport type ConnectionType =\n  | 'wifi'\n  | '4g'\n  | '3g'\n  | '2g'\n  | 'slow-2g'\n  | 'ethernet'\n  | 'bluetooth'\n  | 'cellular'\n  | 'none'\n  | 'unknown';\n\n/**\n * Network effective type (speed-based)\n */\nexport type EffectiveType = 'slow-2g' | '2g' | '3g' | '4g';\n\n/**\n * Network status information\n */\nexport interface NetworkStatus {\n  /** Whether the browser is online */\n  online: boolean;\n  /** Connection type */\n  type: ConnectionType;\n  /** Effective connection type (based on measured speed) */\n  effectiveType: EffectiveType;\n  /** Downlink speed in Mbps */\n  downlink: number;\n  /** Round-trip time in ms */\n  rtt: number;\n  /** Whether data saver mode is enabled */\n  saveData: boolean;\n  /** Timestamp of last status update */\n  timestamp: number;\n}\n\n/**\n * Network quality tier\n */\nexport type NetworkQuality = 'excellent' | 'good' | 'fair' | 'poor' | 'offline';\n\n/**\n * Network status change callback\n */\nexport type NetworkStatusCallback = (status: NetworkStatus) => void;\n\n/**\n * Network quality change callback\n */\nexport type NetworkQualityCallback = (quality: NetworkQuality) => void;\n\n/**\n * Network monitor configuration\n */\nexport interface NetworkMonitorConfig {\n  /** Ping endpoint for connectivity check */\n  pingEndpoint?: string;\n  /** Ping interval in ms */\n  pingInterval?: number;\n  /** Ping timeout in ms */\n  pingTimeout?: number;\n  /** Enable periodic pinging */\n  enablePing?: boolean;\n  /** Downlink threshold for \"good\" quality (Mbps) */\n  goodDownlinkThreshold?: number;\n  /** RTT threshold for \"good\" quality (ms) */\n  goodRttThreshold?: number;\n}\n\n// ============================================================================\n// Network Information API Types\n// ============================================================================\n\n/**\n * Network Information API types (not yet standard)\n */\ninterface NetworkInformation extends EventTarget {\n  type?: ConnectionType;\n  effectiveType?: EffectiveType;\n  downlink?: number;\n  downlinkMax?: number;\n  rtt?: number;\n  saveData?: boolean;\n  onchange?: ((this: NetworkInformation, ev: Event) => void) | null;\n}\n\ninterface NavigatorWithConnection extends Navigator {\n  connection?: NetworkInformation;\n  mozConnection?: NetworkInformation;\n  webkitConnection?: NetworkInformation;\n}\n\n// ============================================================================\n// Network Monitor\n// ============================================================================\n\n/**\n * Network status monitor with quality detection and event handling\n */\nexport class NetworkMonitor {\n  private config: Required<NetworkMonitorConfig>;\n  private statusCallbacks = new Set<NetworkStatusCallback>();\n  private qualityCallbacks = new Set<NetworkQualityCallback>();\n  private currentStatus: NetworkStatus;\n  private currentQuality: NetworkQuality = 'unknown' as NetworkQuality;\n  private pingIntervalId: ReturnType<typeof setInterval> | null = null;\n  private disposed = false;\n\n  constructor(config: NetworkMonitorConfig = {}) {\n    this.config = {\n      pingEndpoint: config.pingEndpoint ?? '/api/health',\n      pingInterval: config.pingInterval ?? 30000,\n      pingTimeout: config.pingTimeout ?? 5000,\n      enablePing: config.enablePing ?? false,\n      goodDownlinkThreshold: config.goodDownlinkThreshold ?? 1.5,\n      goodRttThreshold: config.goodRttThreshold ?? 300,\n    };\n\n    this.currentStatus = this.getNetworkStatus();\n    this.currentQuality = this.calculateQuality(this.currentStatus);\n\n    this.setupListeners();\n  }\n\n  /**\n   * Start monitoring\n   */\n  start(): void {\n    if (this.config.enablePing && !this.pingIntervalId) {\n      this.pingIntervalId = setInterval(() => { void this.ping(); }, this.config.pingInterval);\n      // Initial ping\n      void this.ping();\n    }\n  }\n\n  /**\n   * Stop monitoring\n   */\n  stop(): void {\n    if (this.pingIntervalId) {\n      clearInterval(this.pingIntervalId);\n      this.pingIntervalId = null;\n    }\n  }\n\n  /**\n   * Perform connectivity ping\n   */\n  async ping(): Promise<boolean> {\n    if (!this.currentStatus.online) return false;\n\n    const startTime = performance.now();\n\n    try {\n      const controller = new AbortController();\n      const timeoutId = setTimeout(\n        () => controller.abort(),\n        this.config.pingTimeout\n      );\n\n      const response = await fetch(this.config.pingEndpoint, {\n        method: 'HEAD',\n        cache: 'no-store',\n        signal: controller.signal,\n      });\n\n      clearTimeout(timeoutId);\n\n      const endTime = performance.now();\n      const latency = endTime - startTime;\n\n      if (response.ok) {\n        // Update RTT estimate\n        this.currentStatus.rtt = latency;\n        this.updateStatus();\n        return true;\n      }\n\n      return false;\n    } catch (error) {\n      if (error instanceof Error && error.name === 'AbortError') {\n        logger.debug('[Network] Ping timeout');\n      }\n      return false;\n    }\n  }\n\n  /**\n   * Get current status\n   */\n  getStatus(): NetworkStatus {\n    return { ...this.currentStatus };\n  }\n\n  /**\n   * Get current quality\n   */\n  getQuality(): NetworkQuality {\n    return this.currentQuality;\n  }\n\n  /**\n   * Check if online\n   */\n  isOnline(): boolean {\n    return this.currentStatus.online;\n  }\n\n  /**\n   * Check if connection is metered/slow\n   */\n  isSlowConnection(): boolean {\n    return (\n      this.currentStatus.saveData ||\n      this.currentQuality === 'poor' ||\n      this.currentStatus.effectiveType === '2g' ||\n      this.currentStatus.effectiveType === 'slow-2g'\n    );\n  }\n\n  /**\n   * Subscribe to status changes\n   */\n  onStatusChange(callback: NetworkStatusCallback): () => void {\n    this.statusCallbacks.add(callback);\n    // Emit current status immediately\n    callback(this.currentStatus);\n    return () => this.statusCallbacks.delete(callback);\n  }\n\n  /**\n   * Subscribe to quality changes\n   */\n  onQualityChange(callback: NetworkQualityCallback): () => void {\n    this.qualityCallbacks.add(callback);\n    // Emit current quality immediately\n    callback(this.currentQuality);\n    return () => this.qualityCallbacks.delete(callback);\n  }\n\n  /**\n   * Wait for online status\n   */\n  async waitForOnline(timeout?: number): Promise<boolean> {\n    if (this.currentStatus.online) return true;\n\n    return new Promise((resolve) => {\n      let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n      const unsubscribe = this.onStatusChange((status) => {\n        if (status.online) {\n          if (timeoutId) clearTimeout(timeoutId);\n          unsubscribe();\n          resolve(true);\n        }\n      });\n\n      if (timeout !== undefined && timeout > 0) {\n        timeoutId = setTimeout(() => {\n          unsubscribe();\n          resolve(false);\n        }, timeout);\n      }\n    });\n  }\n\n  /**\n   * Dispose resources\n   */\n  dispose(): void {\n    if (this.disposed) return;\n    this.disposed = true;\n\n    this.stop();\n\n    if (typeof window !== 'undefined') {\n      window.removeEventListener('online', this.handleOnline);\n      window.removeEventListener('offline', this.handleOffline);\n\n      const connection = this.getConnection();\n      if (connection) {\n        connection.removeEventListener('change', this.handleConnectionChange);\n      }\n    }\n\n    this.statusCallbacks.clear();\n    this.qualityCallbacks.clear();\n  }\n\n  /**\n   * Get the Network Information API connection object\n   */\n  private getConnection(): NetworkInformation | undefined {\n    if (typeof navigator === 'undefined') return undefined;\n\n    const nav = navigator as NavigatorWithConnection;\n    return nav.connection ?? nav.mozConnection ?? nav.webkitConnection;\n  }\n\n  /**\n   * Get current network status\n   */\n  private getNetworkStatus(): NetworkStatus {\n    const online = typeof navigator !== 'undefined' ? navigator.onLine : true;\n    const connection = this.getConnection();\n\n    return {\n      online,\n      type: (connection?.type as ConnectionType) ?? 'unknown',\n      effectiveType: connection?.effectiveType ?? '4g',\n      downlink: connection?.downlink ?? 10,\n      rtt: connection?.rtt ?? 50,\n      saveData: connection?.saveData ?? false,\n      timestamp: Date.now(),\n    };\n  }\n\n  /**\n   * Calculate network quality tier\n   */\n  private calculateQuality(status: NetworkStatus): NetworkQuality {\n    if (!status.online) return 'offline';\n\n    const { downlink, rtt, effectiveType } = status;\n\n    // Effective type mapping\n    if (effectiveType === 'slow-2g' || effectiveType === '2g') {\n      return 'poor';\n    }\n\n    // Quality based on measured values\n    if (downlink >= 5 && rtt <= 100) return 'excellent';\n    if (downlink >= this.config.goodDownlinkThreshold && rtt <= this.config.goodRttThreshold) return 'good';\n    if (effectiveType === '3g' || downlink >= 0.5) return 'fair';\n\n    return 'poor';\n  }\n\n  /**\n   * Setup event listeners\n   */\n  private setupListeners(): void {\n    if (typeof window === 'undefined') return;\n\n    // Online/offline events\n    window.addEventListener('online', this.handleOnline);\n    window.addEventListener('offline', this.handleOffline);\n\n    // Network Information API events\n    const connection = this.getConnection();\n    if (connection) {\n      connection.addEventListener('change', this.handleConnectionChange);\n    }\n  }\n\n  /**\n   * Handle online event\n   */\n  private handleOnline = (): void => {\n    logger.info('[Network] Online');\n    this.updateStatus();\n\n    globalEventBus.emitSync('network:online', undefined);\n  };\n\n  /**\n   * Handle offline event\n   */\n  private handleOffline = (): void => {\n    logger.warn('[Network] Offline');\n    this.updateStatus();\n\n    globalEventBus.emitSync('network:offline', undefined);\n  };\n\n  /**\n   * Handle connection change event\n   */\n  private handleConnectionChange = (): void => {\n    this.updateStatus();\n  };\n\n  /**\n   * Update status and notify callbacks\n   */\n  private updateStatus(): void {\n    const newStatus = this.getNetworkStatus();\n    const newQuality = this.calculateQuality(newStatus);\n\n    const statusChanged =\n      this.currentStatus.online !== newStatus.online ||\n      this.currentStatus.effectiveType !== newStatus.effectiveType ||\n      Math.abs(this.currentStatus.downlink - newStatus.downlink) > 0.5;\n\n    const qualityChanged = this.currentQuality !== newQuality;\n\n    this.currentStatus = newStatus;\n\n    if (statusChanged) {\n      this.statusCallbacks.forEach((cb) => cb(newStatus));\n    }\n\n    if (qualityChanged) {\n      this.currentQuality = newQuality;\n      this.qualityCallbacks.forEach((cb) => cb(newQuality));\n\n      globalEventBus.emitSync('network:qualityChange', { quality: newQuality });\n      logger.debug('[Network] Quality changed', { quality: newQuality });\n    }\n  }\n}\n\n// ============================================================================\n// Network-Aware Request Handler\n// ============================================================================\n\n/**\n * Network-aware fetch options\n */\nexport interface NetworkAwareFetchOptions extends RequestInit {\n  /** Whether to queue request when offline */\n  queueOffline?: boolean;\n  /** Minimum quality required to send request */\n  minQuality?: NetworkQuality;\n  /** Timeout for waiting online */\n  onlineTimeout?: number;\n  /** Enable automatic retry on network recovery */\n  retryOnRecovery?: boolean;\n}\n\n/**\n * Queued request\n */\ninterface QueuedRequest {\n  url: string;\n  options: NetworkAwareFetchOptions;\n  resolve: (value: Response) => void;\n  reject: (error: Error) => void;\n  timestamp: number;\n}\n\n/**\n * Network-aware fetch wrapper\n */\nexport class NetworkAwareFetch {\n  private monitor: NetworkMonitor;\n  private offlineQueue: QueuedRequest[] = [];\n  private unsubscribe: (() => void) | null = null;\n\n  constructor(monitor: NetworkMonitor) {\n    this.monitor = monitor;\n    this.setupRecoveryHandler();\n  }\n\n  /**\n   * Make network-aware fetch request\n   */\n  async fetch(url: string, options: NetworkAwareFetchOptions = {}): Promise<Response> {\n    const {\n      queueOffline = false,\n      minQuality,\n      onlineTimeout = 30000,\n      retryOnRecovery = true,\n      ...fetchOptions\n    } = options;\n\n    // Check network status\n    if (!this.monitor.isOnline()) {\n      if (queueOffline) {\n        return this.queueRequest(url, options);\n      }\n\n      // Wait for online if timeout specified\n      if (onlineTimeout > 0) {\n        const online = await this.monitor.waitForOnline(onlineTimeout);\n        if (!online) {\n          throw new NetworkError('Network unavailable', 'offline');\n        }\n      } else {\n        throw new NetworkError('Network unavailable', 'offline');\n      }\n    }\n\n    // Check minimum quality\n    if (minQuality) {\n      const quality = this.monitor.getQuality();\n      const qualityOrder: NetworkQuality[] = ['offline', 'poor', 'fair', 'good', 'excellent'];\n      const currentIndex = qualityOrder.indexOf(quality);\n      const minIndex = qualityOrder.indexOf(minQuality);\n\n      if (currentIndex < minIndex) {\n        throw new NetworkError(\n          `Network quality insufficient: ${quality} < ${minQuality}`,\n          'quality'\n        );\n      }\n    }\n\n    try {\n      return await fetch(url, fetchOptions);\n    } catch (error) {\n      // If request failed due to network and retry is enabled, queue it\n      if (\n        retryOnRecovery &&\n        error instanceof TypeError &&\n        error.message.includes('fetch')\n      ) {\n        if (queueOffline) {\n          return this.queueRequest(url, options);\n        }\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Get queue size\n   */\n  getQueueSize(): number {\n    return this.offlineQueue.length;\n  }\n\n  /**\n   * Clear offline queue\n   */\n  clearQueue(): void {\n    const queue = [...this.offlineQueue];\n    this.offlineQueue = [];\n\n    queue.forEach((request) => {\n      request.reject(new Error('Queue cleared'));\n    });\n  }\n\n  /**\n   * Dispose resources\n   */\n  dispose(): void {\n    this.unsubscribe?.();\n    this.clearQueue();\n  }\n\n  /**\n   * Setup handler for network recovery\n   */\n  private setupRecoveryHandler(): void {\n    this.unsubscribe = this.monitor.onStatusChange((status) => {\n      if (status.online && this.offlineQueue.length > 0) {\n        void this.processQueue();\n      }\n    });\n  }\n\n  /**\n   * Process queued requests\n   */\n  private async processQueue(): Promise<void> {\n    const queue = [...this.offlineQueue];\n    this.offlineQueue = [];\n\n    logger.info('[Network] Processing offline queue', { count: queue.length });\n\n    for (const request of queue) {\n      // Skip requests older than 5 minutes\n      if (Date.now() - request.timestamp > 300000) {\n        request.reject(new Error('Request expired in offline queue'));\n        continue;\n      }\n\n      try {\n        const response = await fetch(request.url, request.options);\n        request.resolve(response);\n      } catch (error) {\n        request.reject(error as Error);\n      }\n    }\n  }\n\n  /**\n   * Queue request for later execution\n   */\n  private async queueRequest(url: string, options: NetworkAwareFetchOptions): Promise<Response> {\n    return new Promise((resolve, reject) => {\n      this.offlineQueue.push({\n        url,\n        options,\n        resolve,\n        reject,\n        timestamp: Date.now(),\n      });\n\n      logger.debug('[Network] Request queued', { url, queueSize: this.offlineQueue.length });\n    });\n  }\n}\n\n// ============================================================================\n// Network Error\n// ============================================================================\n\n/**\n * Network-related error\n */\nexport class NetworkError extends Error {\n  constructor(\n    message: string,\n    public readonly reason: 'offline' | 'timeout' | 'quality' | 'unknown'\n  ) {\n    super(message);\n    this.name = 'NetworkError';\n  }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Check if error is a network error\n */\nexport function isNetworkError(error: unknown): error is NetworkError {\n  return error instanceof NetworkError;\n}\n\n/**\n * Check if error is due to offline status\n */\nexport function isOfflineError(error: unknown): boolean {\n  if (error instanceof NetworkError) {\n    return error.reason === 'offline';\n  }\n  if (error instanceof TypeError) {\n    return error.message.includes('fetch') || error.message.includes('network');\n  }\n  return false;\n}\n\n/**\n * Get suggested action based on network quality\n */\nexport function getSuggestedAction(quality: NetworkQuality): {\n  loadImages: boolean;\n  prefetch: boolean;\n  useCache: boolean;\n  reducedMotion: boolean;\n} {\n  switch (quality) {\n    case 'excellent':\n      return { loadImages: true, prefetch: true, useCache: false, reducedMotion: false };\n    case 'good':\n      return { loadImages: true, prefetch: true, useCache: false, reducedMotion: false };\n    case 'fair':\n      return { loadImages: true, prefetch: false, useCache: true, reducedMotion: false };\n    case 'poor':\n      return { loadImages: false, prefetch: false, useCache: true, reducedMotion: true };\n    case 'offline':\n      return { loadImages: false, prefetch: false, useCache: true, reducedMotion: true };\n    default:\n      return { loadImages: true, prefetch: false, useCache: true, reducedMotion: false };\n  }\n}\n\n// ============================================================================\n// Default Instance\n// ============================================================================\n\n/**\n * Global network monitor instance\n */\nexport const networkMonitor = new NetworkMonitor();\n\n/**\n * Global network-aware fetch instance\n */\nexport const networkAwareFetch = new NetworkAwareFetch(networkMonitor);\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Check if browser is online\n */\nexport function isOnline(): boolean {\n  return networkMonitor.isOnline();\n}\n\n/**\n * Check if connection is slow\n */\nexport function isSlowConnection(): boolean {\n  return networkMonitor.isSlowConnection();\n}\n\n/**\n * Get current network quality\n */\nexport function getNetworkQuality(): NetworkQuality {\n  return networkMonitor.getQuality();\n}\n\n/**\n * Wait for online status\n */\nexport async function waitForOnline(timeout?: number): Promise<boolean> {\n  return networkMonitor.waitForOnline(timeout);\n}\n"],"names":["NetworkMonitor","config","startTime","controller","timeoutId","response","latency","error","logger","callback","timeout","resolve","unsubscribe","status","connection","nav","online","downlink","rtt","effectiveType","globalEventBus","newStatus","newQuality","statusChanged","qualityChanged","cb","NetworkAwareFetch","monitor","url","options","queueOffline","minQuality","onlineTimeout","retryOnRecovery","fetchOptions","NetworkError","quality","qualityOrder","currentIndex","minIndex","queue","request","reject","message","reason","isNetworkError","isOfflineError","getSuggestedAction","networkMonitor","networkAwareFetch","isOnline","isSlowConnection","getNetworkQuality","waitForOnline"],"mappings":"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"}