{"version":3,"file":"network-performance.mjs","sources":["../../../src/lib/performance/network-performance.ts"],"sourcesContent":["/**\n * @file Network Performance Module\n * @description Comprehensive network performance analysis and optimization with:\n * - Request timing analysis (DNS, TCP, TLS, TTFB, download)\n * - Bandwidth detection and estimation\n * - Request prioritization hints\n * - Connection quality metrics\n * - Adaptive loading strategies\n *\n * This module provides deep insights into network performance and enables\n * intelligent adaptation based on network conditions.\n *\n * @example\n * ```typescript\n * import { NetworkPerformanceAnalyzer, getNetworkQuality } from '@/lib/performance';\n *\n * const analyzer = NetworkPerformanceAnalyzer.getInstance();\n *\n * // Get current network quality\n * const quality = analyzer.getQuality();\n * if (quality.effectiveType === 'slow-2g') {\n *   // Load low-quality images\n * }\n *\n * // Analyze a specific request\n * const timing = analyzer.analyzeRequest('https://api.example.com/data');\n * console.info(`TTFB: ${timing.ttfb}ms, Download: ${timing.downloadTime}ms`);\n * ```\n */\n\nimport { formatBytes, formatDuration, getNetworkTier, type NetworkTierConfig, } from '../../config/performance.config';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Network connection type\n */\nexport type ConnectionType =\n  | 'bluetooth'\n  | 'cellular'\n  | 'ethernet'\n  | 'wifi'\n  | 'wimax'\n  | 'other'\n  | 'none'\n  | 'unknown';\n\n/**\n * Effective connection type (Network Information API)\n */\nexport type EffectiveConnectionType = 'slow-2g' | '2g' | '3g' | '4g';\n\n/**\n * Request timing breakdown\n */\nexport interface RequestTiming {\n  readonly name: string;\n  readonly url: string;\n  readonly startTime: number;\n  readonly duration: number;\n  /** DNS lookup time */\n  readonly dnsLookup: number;\n  /** TCP connection time */\n  readonly tcpConnect: number;\n  /** TLS negotiation time (HTTPS only) */\n  readonly tlsNegotiation: number;\n  /** Time to first byte */\n  readonly ttfb: number;\n  /** Content download time */\n  readonly downloadTime: number;\n  /** Transfer size in bytes */\n  readonly transferSize: number;\n  /** Encoded body size */\n  readonly encodedBodySize: number;\n  /** Decoded body size */\n  readonly decodedBodySize: number;\n  /** Resource type */\n  readonly initiatorType: string;\n  /** Effective bandwidth during this request (bytes/sec) */\n  readonly effectiveBandwidth: number;\n  /** Server timing entries */\n  readonly serverTiming: ServerTimingEntry[];\n  /** Timestamp */\n  readonly timestamp: number;\n}\n\n/**\n * Server timing entry\n */\nexport interface ServerTimingEntry {\n  readonly name: string;\n  readonly duration: number;\n  readonly description: string;\n}\n\n/**\n * Network quality metrics\n */\nexport interface NetworkQuality {\n  /** Effective connection type */\n  readonly effectiveType: EffectiveConnectionType;\n  /** Estimated downlink speed in Mbps */\n  readonly downlink: number;\n  /** Estimated round-trip time in ms */\n  readonly rtt: number;\n  /** Data saver enabled */\n  readonly saveData: boolean;\n  /** Connection type */\n  readonly type: ConnectionType;\n  /** Network tier configuration */\n  readonly tier: NetworkTierConfig;\n  /** Overall quality score (0-100) */\n  readonly score: number;\n  /** Is connection metered */\n  readonly isMetered: boolean;\n  /** Timestamp */\n  readonly timestamp: number;\n}\n\n/**\n * Bandwidth measurement\n */\nexport interface BandwidthMeasurement {\n  readonly timestamp: number;\n  /** Estimated bandwidth in bytes/sec */\n  readonly bandwidth: number;\n  /** Number of samples used */\n  readonly sampleCount: number;\n  /** Confidence level (0-1) */\n  readonly confidence: number;\n  /** Trend direction */\n  readonly trend: 'improving' | 'stable' | 'degrading';\n}\n\n/**\n * Request priority hint\n */\nexport type RequestPriority = 'highest' | 'high' | 'normal' | 'low' | 'lowest';\n\n/**\n * Priority recommendation\n */\nexport interface PriorityRecommendation {\n  readonly url: string;\n  readonly resourceType: string;\n  readonly recommendedPriority: RequestPriority;\n  readonly reason: string;\n  readonly fetchPriority?: 'high' | 'low' | 'auto';\n  readonly shouldPreload: boolean;\n  readonly shouldPreconnect: boolean;\n  readonly shouldDefer: boolean;\n}\n\n/**\n * Network statistics\n */\nexport interface NetworkStats {\n  readonly totalRequests: number;\n  readonly totalTransferSize: number;\n  readonly averageTtfb: number;\n  readonly averageDownloadTime: number;\n  readonly averageBandwidth: number;\n  readonly p50Ttfb: number;\n  readonly p95Ttfb: number;\n  readonly slowRequests: number;\n  readonly failedRequests: number;\n  readonly requestsByType: Record<string, number>;\n  readonly sizeByType: Record<string, number>;\n}\n\n/**\n * Analyzer configuration\n */\nexport interface NetworkAnalyzerConfig {\n  /** Slow request threshold (ms) */\n  readonly slowThreshold?: number;\n  /** Maximum request history */\n  readonly maxHistorySize?: number;\n  /** Enable auto-monitoring */\n  readonly autoMonitor?: boolean;\n  /** Bandwidth measurement interval (ms) */\n  readonly bandwidthInterval?: number;\n  /** Callback on slow request */\n  readonly onSlowRequest?: (timing: RequestTiming) => void;\n  /** Callback on network quality change */\n  readonly onQualityChange?: (quality: NetworkQuality) => void;\n  /** Enable debug logging */\n  readonly debug?: boolean;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<NetworkAnalyzerConfig> = {\n  slowThreshold: 1000,\n  maxHistorySize: 500,\n  autoMonitor: true,\n  bandwidthInterval: 10000,\n  onSlowRequest: () => {},\n  onQualityChange: () => {},\n  debug: false,\n};\n\n/**\n * Resource type priorities\n */\nconst RESOURCE_PRIORITIES: Record<string, RequestPriority> = {\n  document: 'highest',\n  script: 'high',\n  css: 'high',\n  font: 'high',\n  img: 'normal',\n  fetch: 'normal',\n  xmlhttprequest: 'normal',\n  media: 'low',\n  video: 'low',\n  audio: 'low',\n  beacon: 'lowest',\n  other: 'low',\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Get navigator connection object\n */\nfunction getNavigatorConnection(): {\n  effectiveType?: EffectiveConnectionType;\n  downlink?: number;\n  rtt?: number;\n  saveData?: boolean;\n  type?: ConnectionType;\n  addEventListener?: (type: string, listener: () => void) => void;\n  removeEventListener?: (type: string, listener: () => void) => void;\n} | null {\n  const nav = navigator as Navigator & {\n    connection?: {\n      effectiveType?: EffectiveConnectionType;\n      downlink?: number;\n      rtt?: number;\n      saveData?: boolean;\n      type?: ConnectionType;\n      addEventListener?: (type: string, listener: () => void) => void;\n      removeEventListener?: (type: string, listener: () => void) => void;\n    };\n    mozConnection?: typeof nav.connection;\n    webkitConnection?: typeof nav.connection;\n  };\n\n  return nav.connection ?? nav.mozConnection ?? nav.webkitConnection ?? null;\n}\n\n/**\n * Calculate percentile from sorted array\n */\nfunction percentile(sortedArr: number[], p: number): number {\n  if (sortedArr.length === 0) return 0;\n  const index = Math.ceil((p / 100) * sortedArr.length) - 1;\n  return sortedArr[Math.max(0, Math.min(index, sortedArr.length - 1))] ?? 0;\n}\n\n/**\n * Generate unique ID\n */\n\n\n// ============================================================================\n// Network Performance Analyzer\n// ============================================================================\n\n/**\n * Comprehensive network performance analyzer\n */\nexport class NetworkPerformanceAnalyzer {\n  private static instance: NetworkPerformanceAnalyzer | null = null;\n\n  private readonly config: Required<NetworkAnalyzerConfig>;\n  private readonly requestHistory: RequestTiming[] = [];\n  private readonly bandwidthHistory: BandwidthMeasurement[] = [];\n\n  private resourceObserver: PerformanceObserver | null = null;\n  private bandwidthIntervalId: ReturnType<typeof setInterval> | null = null;\n  private lastQuality: NetworkQuality | null = null;\n  private connectionChangeHandler: (() => void) | null = null;\n\n  /**\n   * Private constructor for singleton pattern\n   */\n  private constructor(config: NetworkAnalyzerConfig = {}) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n\n    if (this.config.autoMonitor) {\n      this.startMonitoring();\n    }\n  }\n\n  /**\n   * Get singleton instance\n   */\n  public static getInstance(config?: NetworkAnalyzerConfig): NetworkPerformanceAnalyzer {\n    NetworkPerformanceAnalyzer.instance ??= new NetworkPerformanceAnalyzer(config);\n    return NetworkPerformanceAnalyzer.instance;\n  }\n\n  /**\n   * Reset singleton instance (for testing)\n   */\n  public static resetInstance(): void {\n    if (NetworkPerformanceAnalyzer.instance !== null) {\n      NetworkPerformanceAnalyzer.instance.stopMonitoring();\n      NetworkPerformanceAnalyzer.instance = null;\n    }\n  }\n\n  // ==========================================================================\n  // Monitoring Control\n  // ==========================================================================\n\n  /**\n   * Start monitoring network performance\n   */\n  public startMonitoring(): void {\n    this.startResourceObserver();\n    this.startBandwidthMeasurement();\n    this.startConnectionListener();\n    this.log('Network monitoring started');\n  }\n\n  /**\n   * Stop monitoring\n   */\n  public stopMonitoring(): void {\n    this.stopResourceObserver();\n    this.stopBandwidthMeasurement();\n    this.stopConnectionListener();\n    this.log('Network monitoring stopped');\n  }\n\n  /**\n   * Analyze a specific request by URL\n   */\n  public analyzeRequest(url: string): RequestTiming | null {\n    const entries = performance.getEntriesByName(url, 'resource') as PerformanceResourceTiming[];\n    if (entries.length === 0) return null;\n\n    // Get the most recent entry\n    const entry = entries[entries.length - 1];\n    if (entry === undefined) return null;\n    return this.processResourceEntry(entry);\n  }\n\n  /**\n   * Analyze all requests matching a pattern\n   */\n  public analyzeRequestsMatching(pattern: RegExp): RequestTiming[] {\n    const entries = performance.getEntriesByType('resource');\n    return entries\n      .filter((e) => pattern.test(e.name))\n      .map((e) => this.processResourceEntry(e))\n      .filter((t): t is RequestTiming => t !== null);\n  }\n\n  /**\n   * Get current network quality\n   */\n  public getQuality(): NetworkQuality {\n    const connection = getNavigatorConnection();\n\n    const effectiveType: EffectiveConnectionType = connection?.effectiveType ?? '4g';\n    const downlink = connection?.downlink ?? 10;\n    const rtt = connection?.rtt ?? 50;\n    const saveData = connection?.saveData ?? false;\n    const type: ConnectionType = connection?.type ?? 'unknown';\n\n    // Get tier configuration\n    const tier = getNetworkTier(rtt, downlink);\n\n    // Calculate quality score (0-100)\n    const rttScore = Math.max(0, 100 - (rtt / 10));\n    const downlinkScore = Math.min(100, downlink * 10);\n    const score = Math.round((rttScore + downlinkScore) / 2);\n\n    // Determine if metered\n    const isMetered = type === 'cellular' || saveData;\n\n    return {\n      effectiveType,\n      downlink,\n      rtt,\n      saveData,\n      type,\n      tier,\n      score,\n      isMetered,\n      timestamp: Date.now(),\n    };\n  }\n\n  /**\n   * Get quality-based loading strategy\n   */\n  public getLoadingStrategy(): {\n    imageQuality: 'high' | 'medium' | 'low' | 'placeholder';\n    prefetchStrategy: 'aggressive' | 'moderate' | 'conservative' | 'none';\n    shouldReduceMotion: boolean;\n    shouldDeferNonCritical: boolean;\n    maxConcurrentRequests: number;\n  } {\n    const quality = this.getQuality();\n\n    return {\n      imageQuality: quality.tier.imageQuality,\n      prefetchStrategy: quality.tier.prefetchStrategy,\n      shouldReduceMotion: quality.score < 50 || quality.saveData,\n      shouldDeferNonCritical: quality.score < 30,\n      maxConcurrentRequests: (() => {\n        if (quality.score >= 70) return 6;\n        if (quality.score >= 40) return 4;\n        return 2;\n      })(),\n    };\n  }\n\n  /**\n   * Measure current bandwidth from recent requests\n   */\n  public measureBandwidth(): BandwidthMeasurement | null {\n    const recentRequests = this.requestHistory\n      .filter((r) => Date.now() - r.timestamp < 60000) // Last minute\n      .filter((r) => r.transferSize > 0 && r.downloadTime > 0);\n\n    if (recentRequests.length === 0) return null;\n\n    // Calculate weighted bandwidth (larger transfers are more accurate)\n    let totalWeight = 0;\n    let weightedBandwidth = 0;\n\n    recentRequests.forEach((r) => {\n      const weight = Math.log(r.transferSize + 1);\n      weightedBandwidth += r.effectiveBandwidth * weight;\n      totalWeight += weight;\n    });\n\n    const bandwidth = totalWeight > 0 ? weightedBandwidth / totalWeight : 0;\n\n    // Calculate trend\n    const trend = this.calculateBandwidthTrend();\n\n    // Calculate confidence based on sample count and variability\n    const confidence = Math.min(1, recentRequests.length / 10);\n\n    return {\n      timestamp: Date.now(),\n      bandwidth,\n      sampleCount: recentRequests.length,\n      confidence,\n      trend,\n    };\n  }\n\n  /**\n   * Get estimated bandwidth\n   */\n  public getEstimatedBandwidth(): number {\n    const measurement = this.measureBandwidth();\n    if (measurement !== null && measurement.confidence > 0.5) {\n      return measurement.bandwidth;\n    }\n\n    // Fall back to Network Information API\n    const connection = getNavigatorConnection();\n    return ((connection?.downlink ?? 10) * 1024 * 1024) / 8; // Convert Mbps to bytes/sec\n  }\n\n  /**\n   * Get priority recommendation for a resource\n   */\n  public getPriorityRecommendation(\n    url: string,\n    resourceType: string,\n    options: {\n      isAboveFold?: boolean;\n      isLCP?: boolean;\n      isInteractive?: boolean;\n    } = {}\n  ): PriorityRecommendation {\n    const quality = this.getQuality();\n\n\n    let recommendedPriority: RequestPriority = RESOURCE_PRIORITIES[resourceType] ?? 'normal';\n    let fetchPriority: 'high' | 'low' | 'auto' = 'auto';\n    let shouldPreload = false;\n    let shouldPreconnect = false;\n    let shouldDefer = false;\n    let reason = 'Standard priority for resource type';\n\n    // Boost priority for critical resources\n    if (options.isLCP === true) {\n      recommendedPriority = 'highest';\n      fetchPriority = 'high';\n      shouldPreload = true;\n      reason = 'LCP candidate - highest priority';\n    } else if (options.isAboveFold === true && resourceType === 'img') {\n      recommendedPriority = 'high';\n      fetchPriority = 'high';\n      shouldPreload = true;\n      reason = 'Above-fold image - preload recommended';\n    } else if (options.isInteractive === true) {\n      recommendedPriority = 'high';\n      reason = 'Interactive element - high priority';\n    }\n\n    // Reduce priority on slow connections\n    if (quality.score < 30) {\n      if (options.isLCP !== true && options.isAboveFold !== true) {\n        recommendedPriority = 'low';\n        fetchPriority = 'low';\n        shouldDefer = true;\n        reason = 'Slow connection - defer non-critical resources';\n      }\n    }\n\n    // Check if preconnect would help\n    try {\n      const urlObj = new URL(url);\n      const {origin} = urlObj;\n      const isCrossOrigin = origin !== window.location.origin;\n      if (isCrossOrigin && (recommendedPriority === 'highest' || recommendedPriority === 'high')) {\n        shouldPreconnect = true;\n      }\n    } catch {\n      // Invalid URL, skip preconnect recommendation\n    }\n\n    return {\n      url,\n      resourceType,\n      recommendedPriority,\n      reason,\n      fetchPriority,\n      shouldPreload,\n      shouldPreconnect,\n      shouldDefer,\n    };\n  }\n\n  // ==========================================================================\n  // Request Analysis\n  // ==========================================================================\n\n  /**\n   * Get network statistics\n   */\n  public getStats(): NetworkStats {\n    const requests = this.requestHistory;\n\n    if (requests.length === 0) {\n      return {\n        totalRequests: 0,\n        totalTransferSize: 0,\n        averageTtfb: 0,\n        averageDownloadTime: 0,\n        averageBandwidth: 0,\n        p50Ttfb: 0,\n        p95Ttfb: 0,\n        slowRequests: 0,\n        failedRequests: 0,\n        requestsByType: {},\n        sizeByType: {},\n      };\n    }\n\n    const ttfbs = requests.map((r) => r.ttfb).sort((a, b) => a - b);\n    const totalSize = requests.reduce((s, r) => s + r.transferSize, 0);\n    const totalTtfb = ttfbs.reduce((s, t) => s + t, 0);\n    const totalDownload = requests.reduce((s, r) => s + r.downloadTime, 0);\n    const totalBandwidth = requests.reduce((s, r) => s + r.effectiveBandwidth, 0);\n    const slowCount = requests.filter((r) => r.ttfb > this.config.slowThreshold).length;\n\n    const requestsByType: Record<string, number> = {};\n    const sizeByType: Record<string, number> = {};\n\n    requests.forEach((r) => {\n      const type = r.initiatorType ?? 'other';\n      requestsByType[type] = (requestsByType[type] ?? 0) + 1;\n      sizeByType[type] = (sizeByType[type] ?? 0) + r.transferSize;\n    });\n\n    return {\n      totalRequests: requests.length,\n      totalTransferSize: totalSize,\n      averageTtfb: totalTtfb / requests.length,\n      averageDownloadTime: totalDownload / requests.length,\n      averageBandwidth: totalBandwidth / requests.length,\n      p50Ttfb: percentile(ttfbs, 50),\n      p95Ttfb: percentile(ttfbs, 95),\n      slowRequests: slowCount,\n      failedRequests: 0, // Resource timing doesn't capture failures\n      requestsByType,\n      sizeByType,\n    };\n  }\n\n  /**\n   * Get request history\n   */\n  public getHistory(): RequestTiming[] {\n    return [...this.requestHistory];\n  }\n\n  /**\n   * Get slow requests\n   */\n  public getSlowRequests(): RequestTiming[] {\n    return this.requestHistory.filter((r) => r.ttfb > this.config.slowThreshold);\n  }\n\n  // ==========================================================================\n  // Network Quality\n  // ==========================================================================\n\n  /**\n   * Clear history\n   */\n  public clearHistory(): void {\n    this.requestHistory.length = 0;\n    this.bandwidthHistory.length = 0;\n    this.log('History cleared');\n  }\n\n  /**\n   * Generate network performance report\n   */\n  public generateReport(): string {\n    const stats = this.getStats();\n    const quality = this.getQuality();\n    const bandwidth = this.measureBandwidth();\n    const slowRequests = this.getSlowRequests();\n\n    const lines = [\n      '='.repeat(60),\n      'NETWORK PERFORMANCE REPORT',\n      '='.repeat(60),\n      '',\n      `Generated: ${new Date().toISOString()}`,\n      '',\n      '--- Network Quality ---',\n      `Effective Type: ${quality.effectiveType}`,\n      `RTT: ${quality.rtt}ms`,\n      `Downlink: ${quality.downlink} Mbps`,\n      `Quality Score: ${quality.score}/100`,\n      `Data Saver: ${quality.saveData ? 'Enabled' : 'Disabled'}`,\n      '',\n      '--- Bandwidth ---',\n      `Estimated: ${bandwidth !== null ? `${formatBytes(bandwidth.bandwidth)  }/s` : 'N/A'}`,\n      `Confidence: ${bandwidth !== null ? `${(bandwidth.confidence * 100).toFixed(0)  }%` : 'N/A'}`,\n      `Trend: ${bandwidth?.trend ?? 'N/A'}`,\n      '',\n      '--- Request Statistics ---',\n      `Total Requests: ${stats.totalRequests}`,\n      `Total Transfer: ${formatBytes(stats.totalTransferSize)}`,\n      `Average TTFB: ${formatDuration(stats.averageTtfb)}`,\n      `P50 TTFB: ${formatDuration(stats.p50Ttfb)}`,\n      `P95 TTFB: ${formatDuration(stats.p95Ttfb)}`,\n      `Slow Requests: ${stats.slowRequests}`,\n      '',\n      '--- Requests by Type ---',\n    ];\n\n    Object.entries(stats.requestsByType)\n      .sort(([, a], [, b]) => b - a)\n      .forEach(([type, count]) => {\n        const size = stats.sizeByType[type] ?? 0;\n        lines.push(`  ${type}: ${count} requests, ${formatBytes(size)}`);\n      });\n\n    if (slowRequests.length > 0) {\n      lines.push('');\n      lines.push('--- Slow Requests (Top 5) ---');\n      slowRequests.slice(0, 5).forEach((r) => {\n        lines.push(`  - ${r.name}: TTFB ${formatDuration(r.ttfb)}`);\n      });\n    }\n\n    lines.push('');\n    lines.push('='.repeat(60));\n\n    return lines.join('\\n');\n  }\n\n  // ==========================================================================\n  // Bandwidth Measurement\n  // ==========================================================================\n\n  /**\n   * Start resource timing observer\n   */\n  private startResourceObserver(): void {\n    if (typeof PerformanceObserver === 'undefined') return;\n\n    try {\n      this.resourceObserver = new PerformanceObserver((list) => {\n        const entries = list.getEntries() as PerformanceResourceTiming[];\n        entries.forEach((entry) => {\n          const timing = this.processResourceEntry(entry);\n          if (timing !== null) {\n            this.requestHistory.push(timing);\n            this.trimHistory();\n\n            if (timing.ttfb > this.config.slowThreshold) {\n              this.config.onSlowRequest(timing);\n              this.log(`Slow request: ${timing.url} (TTFB: ${formatDuration(timing.ttfb)})`);\n            }\n          }\n        });\n      });\n\n      this.resourceObserver.observe({ entryTypes: ['resource'] });\n    } catch (error) {\n      this.log('Failed to start resource observer:', error);\n    }\n  }\n\n  /**\n   * Stop resource observer\n   */\n  private stopResourceObserver(): void {\n    if (this.resourceObserver !== null) {\n      this.resourceObserver.disconnect();\n      this.resourceObserver = null;\n    }\n  }\n\n  /**\n   * Start bandwidth measurement\n   */\n  private startBandwidthMeasurement(): void {\n    this.bandwidthIntervalId = setInterval(() => {\n      const measurement = this.measureBandwidth();\n      if (measurement !== null) {\n        this.bandwidthHistory.push(measurement);\n        if (this.bandwidthHistory.length > 100) {\n          this.bandwidthHistory.shift();\n        }\n      }\n    }, this.config.bandwidthInterval);\n  }\n\n  // ==========================================================================\n  // Priority Recommendations\n  // ==========================================================================\n\n  /**\n   * Stop bandwidth measurement\n   */\n  private stopBandwidthMeasurement(): void {\n    if (this.bandwidthIntervalId !== null) {\n      clearInterval(this.bandwidthIntervalId);\n      this.bandwidthIntervalId = null;\n    }\n  }\n\n  // ==========================================================================\n  // Statistics\n  // ==========================================================================\n\n  /**\n   * Start connection change listener\n   */\n  private startConnectionListener(): void {\n    const connection = getNavigatorConnection();\n    if (connection?.addEventListener === undefined || connection?.addEventListener === null) return;\n\n    this.connectionChangeHandler = () => {\n      const quality = this.getQuality();\n      if (this.hasQualityChanged(quality)) {\n        this.config.onQualityChange(quality);\n        this.lastQuality = quality;\n        this.log('Network quality changed:', quality.effectiveType);\n      }\n    };\n\n    connection.addEventListener('change', this.connectionChangeHandler);\n  }\n\n  /**\n   * Stop connection listener\n   */\n  private stopConnectionListener(): void {\n    if (this.connectionChangeHandler === null) return;\n\n    const connection = getNavigatorConnection();\n    if (connection?.removeEventListener !== undefined && connection?.removeEventListener !== null) {\n      connection.removeEventListener('change', this.connectionChangeHandler);\n    }\n    this.connectionChangeHandler = null;\n  }\n\n  /**\n   * Check if network quality has changed significantly\n   */\n  private hasQualityChanged(newQuality: NetworkQuality): boolean {\n    if (this.lastQuality === null) return true;\n    return newQuality.effectiveType !== this.lastQuality.effectiveType ||\n           Math.abs(newQuality.score - this.lastQuality.score) > 10;\n  }\n\n  /**\n   * Process a resource timing entry\n   */\n  private processResourceEntry(entry: PerformanceResourceTiming): RequestTiming | null {\n    // Skip entries with no timing data\n    if (entry.duration === 0) return null;\n\n    const dnsLookup = entry.domainLookupEnd - entry.domainLookupStart;\n    const tcpConnect = entry.connectEnd - entry.connectStart;\n    const tlsNegotiation = entry.secureConnectionStart > 0\n      ? entry.connectEnd - entry.secureConnectionStart\n      : 0;\n    const ttfb = entry.responseStart - entry.requestStart;\n    const downloadTime = entry.responseEnd - entry.responseStart;\n\n    // Calculate effective bandwidth\n    const effectiveBandwidth = downloadTime > 0\n      ? (entry.transferSize / downloadTime) * 1000\n      : 0;\n\n    // Extract server timing\n    const serverTiming: ServerTimingEntry[] = [];\n    if ('serverTiming' in entry && Array.isArray(entry.serverTiming)) {\n      entry.serverTiming.forEach((st: { name: string; duration: number; description: string }) => {\n        serverTiming.push({\n          name: st.name,\n          duration: st.duration,\n          description: st.description,\n        });\n      });\n    }\n\n    return {\n      name: entry.name.split('/').pop() ?? entry.name,\n      url: entry.name,\n      startTime: entry.startTime,\n      duration: entry.duration,\n      dnsLookup: Math.max(0, dnsLookup),\n      tcpConnect: Math.max(0, tcpConnect),\n      tlsNegotiation: Math.max(0, tlsNegotiation),\n      ttfb: Math.max(0, ttfb),\n      downloadTime: Math.max(0, downloadTime),\n      transferSize: entry.transferSize,\n      encodedBodySize: entry.encodedBodySize,\n      decodedBodySize: entry.decodedBodySize,\n      initiatorType: entry.initiatorType,\n      effectiveBandwidth,\n      serverTiming,\n      timestamp: Date.now(),\n    };\n  }\n\n  // ==========================================================================\n  // Reporting\n  // ==========================================================================\n\n  /**\n   * Calculate bandwidth trend\n   */\n  private calculateBandwidthTrend(): 'improving' | 'stable' | 'degrading' {\n    if (this.bandwidthHistory.length < 2) return 'stable';\n\n    const recent = this.bandwidthHistory.slice(-5);\n    const older = this.bandwidthHistory.slice(-10, -5);\n\n    if (older.length === 0) return 'stable';\n\n    const recentAvg = recent.reduce((s, m) => s + m.bandwidth, 0) / recent.length;\n    const olderAvg = older.reduce((s, m) => s + m.bandwidth, 0) / older.length;\n\n    const change = ((recentAvg - olderAvg) / olderAvg) * 100;\n\n    if (change > 10) return 'improving';\n    if (change < -10) return 'degrading';\n    return 'stable';\n  }\n\n  // ==========================================================================\n  // Utilities\n  // ==========================================================================\n\n  /**\n   * Trim history to max size\n   */\n  private trimHistory(): void {\n    if (this.requestHistory.length > this.config.maxHistorySize) {\n      this.requestHistory.splice(0, this.requestHistory.length - this.config.maxHistorySize);\n    }\n  }\n\n  /**\n   * Debug logging\n   */\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      console.info(`[NetworkAnalyzer] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Get the singleton NetworkPerformanceAnalyzer instance\n */\nexport function getNetworkAnalyzer(\n  config?: NetworkAnalyzerConfig\n): NetworkPerformanceAnalyzer {\n  return NetworkPerformanceAnalyzer.getInstance(config);\n}\n\n/**\n * Get current network quality (convenience function)\n */\nexport function getNetworkQuality(): NetworkQuality {\n  return getNetworkAnalyzer().getQuality();\n}\n\n/**\n * Check if on slow connection\n */\nexport function isSlowConnection(): boolean {\n  const quality = getNetworkQuality();\n  return quality.score < 50 || quality.effectiveType === 'slow-2g' || quality.effectiveType === '2g';\n}\n\n/**\n * Check if data saver is enabled\n */\nexport function isDataSaverEnabled(): boolean {\n  return getNetworkQuality().saveData;\n}\n\n/**\n * Get loading strategy based on network\n */\nexport function getAdaptiveLoadingStrategy(): ReturnType<NetworkPerformanceAnalyzer['getLoadingStrategy']> {\n  return getNetworkAnalyzer().getLoadingStrategy();\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n"],"names":["DEFAULT_CONFIG","RESOURCE_PRIORITIES","getNavigatorConnection","nav","percentile","sortedArr","p","index","NetworkPerformanceAnalyzer","config","url","entries","entry","pattern","e","t","connection","effectiveType","downlink","rtt","saveData","type","tier","getNetworkTier","rttScore","downlinkScore","score","quality","recentRequests","totalWeight","weightedBandwidth","weight","bandwidth","trend","confidence","measurement","resourceType","options","recommendedPriority","fetchPriority","shouldPreload","shouldPreconnect","shouldDefer","reason","urlObj","origin","requests","ttfbs","r","b","totalSize","s","totalTtfb","totalDownload","totalBandwidth","slowCount","requestsByType","sizeByType","stats","slowRequests","lines","formatBytes","formatDuration","a","count","size","list","timing","error","newQuality","dnsLookup","tcpConnect","tlsNegotiation","ttfb","downloadTime","effectiveBandwidth","serverTiming","st","recent","older","recentAvg","m","olderAvg","change","message","args","getNetworkAnalyzer","getNetworkQuality","isSlowConnection","isDataSaverEnabled","getAdaptiveLoadingStrategy"],"mappings":"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"}