{"version":3,"file":"performance-reporter.mjs","sources":["../../../../src/lib/performance/monitoring/performance-reporter.ts"],"sourcesContent":["/**\n * @file Performance Reporter\n * @description Comprehensive performance reporting with multiple output formats,\n * destinations, and customizable reports.\n *\n * Features:\n * - Multiple report formats (JSON, console, analytics)\n * - Configurable destinations\n * - Report aggregation\n * - Threshold-based alerting\n * - Historical comparison\n * - Custom report builders\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Report format\n */\nexport type ReportFormat = 'json' | 'console' | 'analytics' | 'custom';\n\n/**\n * Report destination\n */\nexport type ReportDestination = 'console' | 'endpoint' | 'localStorage' | 'callback';\n\n/**\n * Metric data for reporting\n */\nexport interface ReportMetric {\n  name: string;\n  value: number;\n  rating: 'good' | 'needs-improvement' | 'poor';\n  target?: number;\n  delta?: number;\n  timestamp: number;\n}\n\n/**\n * Performance report\n */\nexport interface PerformanceReport {\n  id: string;\n  timestamp: number;\n  url: string;\n  metrics: ReportMetric[];\n  score: number;\n  rating: 'good' | 'needs-improvement' | 'poor';\n  summary: ReportSummary;\n  context: ReportContext;\n  recommendations: string[];\n}\n\n/**\n * Report summary\n */\nexport interface ReportSummary {\n  totalMetrics: number;\n  goodMetrics: number;\n  poorMetrics: number;\n  needsImprovementMetrics: number;\n  criticalIssues: string[];\n}\n\n/**\n * Report context\n */\nexport interface ReportContext {\n  userAgent: string;\n  connection?: {\n    effectiveType?: string;\n    downlink?: number;\n    rtt?: number;\n    saveData?: boolean;\n  };\n  viewport: {\n    width: number;\n    height: number;\n  };\n  deviceMemory?: number;\n  hardwareConcurrency?: number;\n  sessionId?: string;\n  userId?: string;\n}\n\n/**\n * Reporter configuration\n */\nexport interface PerformanceReporterConfig {\n  /** Enable reporting */\n  enabled: boolean;\n  /** Report format */\n  format: ReportFormat;\n  /** Report destination */\n  destination: ReportDestination;\n  /** Endpoint URL for endpoint destination */\n  endpointUrl?: string;\n  /** Local storage key */\n  storageKey?: string;\n  /** Custom callback */\n  callback?: (report: PerformanceReport) => void | Promise<void>;\n  /** Enable alerting */\n  alerting: boolean;\n  /** Alert threshold (score below this triggers alert) */\n  alertThreshold: number;\n  /** Alert callback */\n  onAlert?: (report: PerformanceReport, issues: string[]) => void;\n  /** Include recommendations */\n  includeRecommendations: boolean;\n  /** Session ID */\n  sessionId?: string;\n  /** User ID */\n  userId?: string;\n  /** Debug mode */\n  debug: boolean;\n}\n\n/**\n * Alert rule\n */\nexport interface AlertRule {\n  metric: string;\n  condition: 'above' | 'below';\n  threshold: number;\n  severity: 'warning' | 'critical';\n  message: string;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_CONFIG: PerformanceReporterConfig = {\n  enabled: true,\n  format: 'json',\n  destination: 'console',\n  alerting: true,\n  alertThreshold: 50,\n  includeRecommendations: true,\n  debug: false,\n};\n\n/**\n * Default alert rules\n */\nconst DEFAULT_ALERT_RULES: AlertRule[] = [\n  {\n    metric: 'LCP',\n    condition: 'above',\n    threshold: 4000,\n    severity: 'critical',\n    message: 'LCP is critically slow',\n  },\n  {\n    metric: 'CLS',\n    condition: 'above',\n    threshold: 0.25,\n    severity: 'critical',\n    message: 'CLS is causing major layout shifts',\n  },\n  {\n    metric: 'INP',\n    condition: 'above',\n    threshold: 500,\n    severity: 'critical',\n    message: 'INP indicates poor interactivity',\n  },\n  {\n    metric: 'FCP',\n    condition: 'above',\n    threshold: 3000,\n    severity: 'warning',\n    message: 'FCP is slow',\n  },\n  {\n    metric: 'TTFB',\n    condition: 'above',\n    threshold: 1800,\n    severity: 'warning',\n    message: 'TTFB indicates slow server response',\n  },\n];\n\n// ============================================================================\n// Performance Reporter\n// ============================================================================\n\n/**\n * Performance reporting manager\n */\nexport class PerformanceReporter {\n  private config: PerformanceReporterConfig;\n  private alertRules: AlertRule[];\n  private reportHistory: PerformanceReport[] = [];\n  private idCounter = 0;\n\n  constructor(config: Partial<PerformanceReporterConfig> = {}) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n    this.alertRules = [...DEFAULT_ALERT_RULES];\n  }\n\n  /**\n   * Generate and send a performance report\n   */\n  async report(metrics: ReportMetric[]): Promise<PerformanceReport> {\n    if (!this.config.enabled) {\n      return this.createEmptyReport();\n    }\n\n    const report = this.createReport(metrics);\n    this.reportHistory.push(report);\n\n    // Check alerts\n    if (this.config.alerting) {\n      this.checkAlerts(report);\n    }\n\n    // Send to destination\n    await this.sendReport(report);\n\n    return report;\n  }\n\n  /**\n   * Add custom alert rule\n   */\n  addAlertRule(rule: AlertRule): void {\n    this.alertRules.push(rule);\n  }\n\n  /**\n   * Remove alert rule\n   */\n  removeAlertRule(metric: string): void {\n    this.alertRules = this.alertRules.filter((r) => r.metric !== metric);\n  }\n\n  /**\n   * Get report history\n   */\n  getHistory(): PerformanceReport[] {\n    return [...this.reportHistory];\n  }\n\n  /**\n   * Get latest report\n   */\n  getLatestReport(): PerformanceReport | null {\n    return this.reportHistory[this.reportHistory.length - 1] ?? null;\n  }\n\n  /**\n   * Clear report history\n   */\n  clearHistory(): void {\n    this.reportHistory = [];\n  }\n\n  /**\n   * Compare two reports\n   */\n  compareReports(\n    report1: PerformanceReport,\n    report2: PerformanceReport\n  ): {\n    improved: string[];\n    regressed: string[];\n    unchanged: string[];\n    scoreDelta: number;\n  } {\n    const improved: string[] = [];\n    const regressed: string[] = [];\n    const unchanged: string[] = [];\n\n    const metrics1 = new Map(report1.metrics.map((m) => [m.name, m]));\n    const metrics2 = new Map(report2.metrics.map((m) => [m.name, m]));\n\n    for (const [name, metric1] of metrics1) {\n      const metric2 = metrics2.get(name);\n      if (!metric2) continue;\n\n      // For CLS, lower is better. For time-based metrics, also lower is better.\n      const delta = metric2.value - metric1.value;\n      const threshold = metric1.value * 0.05; // 5% threshold\n\n      if (Math.abs(delta) < threshold) {\n        unchanged.push(name);\n      } else if (delta < 0) {\n        // Value decreased = improved for most metrics\n        improved.push(name);\n      } else {\n        regressed.push(name);\n      }\n    }\n\n    return {\n      improved,\n      regressed,\n      unchanged,\n      scoreDelta: report2.score - report1.score,\n    };\n  }\n\n  /**\n   * Generate console report\n   */\n  generateConsoleReport(report: PerformanceReport): string {\n    const lines: string[] = [\n      '========================================',\n      '       PERFORMANCE REPORT',\n      '========================================',\n      '',\n      `URL: ${report.url}`,\n      `Timestamp: ${new Date(report.timestamp).toISOString()}`,\n      `Overall Score: ${report.score}/100 (${report.rating})`,\n      '',\n      'METRICS:',\n      '--------',\n    ];\n\n    for (const metric of report.metrics) {\n      let indicator: string;\n      if (metric.rating === 'good') {\n        indicator = '[OK]';\n      } else if (metric.rating === 'poor') {\n        indicator = '[!!]';\n      } else {\n        indicator = '[!]';\n      }\n      lines.push(`${indicator} ${metric.name}: ${this.formatValue(metric.name, metric.value)}`);\n    }\n\n    lines.push('');\n    lines.push('SUMMARY:');\n    lines.push('--------');\n    lines.push(`Good: ${report.summary.goodMetrics}/${report.summary.totalMetrics}`);\n    lines.push(\n      `Needs Improvement: ${report.summary.needsImprovementMetrics}/${report.summary.totalMetrics}`\n    );\n    lines.push(`Poor: ${report.summary.poorMetrics}/${report.summary.totalMetrics}`);\n\n    if (report.summary.criticalIssues.length > 0) {\n      lines.push('');\n      lines.push('CRITICAL ISSUES:');\n      lines.push('----------------');\n      report.summary.criticalIssues.forEach((issue) => {\n        lines.push(`- ${issue}`);\n      });\n    }\n\n    if (report.recommendations.length > 0) {\n      lines.push('');\n      lines.push('RECOMMENDATIONS:');\n      lines.push('----------------');\n      report.recommendations.forEach((rec) => {\n        lines.push(`- ${rec}`);\n      });\n    }\n\n    lines.push('');\n    lines.push('========================================');\n\n    return lines.join('\\n');\n  }\n\n  // ============================================================================\n  // Private Methods\n  // ============================================================================\n\n  private createReport(metrics: ReportMetric[]): PerformanceReport {\n    const score = this.calculateScore(metrics);\n    const summary = this.createSummary(metrics);\n    const recommendations = this.config.includeRecommendations\n      ? this.generateRecommendations(metrics)\n      : [];\n\n    return {\n      id: this.generateId(),\n      timestamp: Date.now(),\n      url: typeof window !== 'undefined' ? window.location.href : '',\n      metrics,\n      score,\n      rating: this.scoreToRating(score),\n      summary,\n      context: this.getContext(),\n      recommendations,\n    };\n  }\n\n  private calculateScore(metrics: ReportMetric[]): number {\n    if (metrics.length === 0) return 0;\n\n    const weights: Record<string, number> = {\n      LCP: 0.25,\n      INP: 0.3,\n      CLS: 0.25,\n      FCP: 0.1,\n      TTFB: 0.1,\n    };\n\n    let totalWeight = 0;\n    let weightedScore = 0;\n\n    for (const metric of metrics) {\n      const weight = weights[metric.name] ?? 0.1;\n      const score = this.ratingToScore(metric.rating);\n      weightedScore += score * weight;\n      totalWeight += weight;\n    }\n\n    return totalWeight > 0 ? Math.round(weightedScore / totalWeight) : 0;\n  }\n\n  private createSummary(metrics: ReportMetric[]): ReportSummary {\n    const criticalIssues: string[] = [];\n\n    for (const metric of metrics) {\n      if (metric.rating === 'poor') {\n        criticalIssues.push(\n          `${metric.name} is poor (${this.formatValue(metric.name, metric.value)})`\n        );\n      }\n    }\n\n    return {\n      totalMetrics: metrics.length,\n      goodMetrics: metrics.filter((m) => m.rating === 'good').length,\n      needsImprovementMetrics: metrics.filter((m) => m.rating === 'needs-improvement').length,\n      poorMetrics: metrics.filter((m) => m.rating === 'poor').length,\n      criticalIssues,\n    };\n  }\n\n  private generateRecommendations(metrics: ReportMetric[]): string[] {\n    const recommendations: string[] = [];\n\n    for (const metric of metrics) {\n      if (metric.rating === 'good') continue;\n\n      switch (metric.name) {\n        case 'LCP':\n          recommendations.push(\n            'Optimize Largest Contentful Paint by preloading critical resources'\n          );\n          recommendations.push('Consider using a CDN for faster asset delivery');\n          recommendations.push('Optimize and compress images');\n          break;\n        case 'CLS':\n          recommendations.push('Set explicit dimensions for images and video elements');\n          recommendations.push('Reserve space for ads and embeds');\n          recommendations.push('Avoid inserting content above existing content');\n          break;\n        case 'INP':\n          recommendations.push('Reduce JavaScript execution time');\n          recommendations.push('Break up long tasks into smaller chunks');\n          recommendations.push('Use web workers for heavy computations');\n          break;\n        case 'FCP':\n          recommendations.push('Eliminate render-blocking resources');\n          recommendations.push('Inline critical CSS');\n          recommendations.push('Minimize server response time');\n          break;\n        case 'TTFB':\n          recommendations.push('Optimize server response time');\n          recommendations.push('Use edge caching with a CDN');\n          recommendations.push('Consider server-side rendering optimizations');\n          break;\n      }\n    }\n\n    // Remove duplicates\n    return [...new Set(recommendations)];\n  }\n\n  private getContext(): ReportContext {\n    if (typeof window === 'undefined') {\n      return {\n        userAgent: '',\n        viewport: { width: 0, height: 0 },\n      };\n    }\n\n    const nav = navigator as Navigator & {\n      connection?: {\n        effectiveType?: string;\n        downlink?: number;\n        rtt?: number;\n        saveData?: boolean;\n      };\n      deviceMemory?: number;\n    };\n\n    return {\n      userAgent: navigator.userAgent,\n      connection: nav.connection\n        ? {\n            effectiveType: nav.connection.effectiveType,\n            downlink: nav.connection.downlink,\n            rtt: nav.connection.rtt,\n            saveData: nav.connection.saveData,\n          }\n        : undefined,\n      viewport: {\n        width: window.innerWidth,\n        height: window.innerHeight,\n      },\n      deviceMemory: nav.deviceMemory,\n      hardwareConcurrency: navigator.hardwareConcurrency,\n      sessionId: this.config.sessionId,\n      userId: this.config.userId,\n    };\n  }\n\n  private checkAlerts(report: PerformanceReport): void {\n    const triggeredAlerts: string[] = [];\n\n    // Check score threshold\n    if (report.score < this.config.alertThreshold) {\n      triggeredAlerts.push(\n        `Overall score (${report.score}) is below threshold (${this.config.alertThreshold})`\n      );\n    }\n\n    // Check individual metric rules\n    for (const rule of this.alertRules) {\n      const metric = report.metrics.find((m) => m.name === rule.metric);\n      if (!metric) continue;\n\n      const triggered =\n        rule.condition === 'above' ? metric.value > rule.threshold : metric.value < rule.threshold;\n\n      if (triggered) {\n        triggeredAlerts.push(`[${rule.severity.toUpperCase()}] ${rule.message}`);\n      }\n    }\n\n    if (triggeredAlerts.length > 0) {\n      this.config.onAlert?.(report, triggeredAlerts);\n      this.log(`Alerts triggered: ${triggeredAlerts.join(', ')}`);\n    }\n  }\n\n  private async sendReport(report: PerformanceReport): Promise<void> {\n    switch (this.config.destination) {\n      case 'console':\n        console.info(this.generateConsoleReport(report));\n        break;\n\n      case 'endpoint':\n        await this.sendToEndpoint(report);\n        break;\n\n      case 'localStorage':\n        this.saveToLocalStorage(report);\n        break;\n\n      case 'callback':\n        await this.config.callback?.(report);\n        break;\n    }\n  }\n\n  /**\n   * Send performance report to endpoint.\n   *\n   * Note: This method intentionally uses raw fetch/sendBeacon because:\n   * 1. Performance reporting should be independent of the main API client\n   * 2. Uses keepalive/sendBeacon for reliability when page is unloading\n   * 3. Reporting endpoints may be third-party analytics services\n   *\n   * @see {@link @/lib/api/api-client} for application API calls\n   */\n  private async sendToEndpoint(report: PerformanceReport): Promise<void> {\n    if (this.config.endpointUrl === null || this.config.endpointUrl === undefined) {\n      this.log('No endpoint URL configured');\n      return;\n    }\n\n    try {\n      const body = this.formatReport(report);\n\n      if (navigator.sendBeacon !== null && navigator.sendBeacon !== undefined) {\n        navigator.sendBeacon(this.config.endpointUrl, JSON.stringify(body));\n      } else {\n        // Raw fetch is intentional - uses keepalive for page unload reliability\n        await fetch(this.config.endpointUrl, {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify(body),\n          keepalive: true,\n        });\n      }\n\n      this.log('Report sent to endpoint');\n    } catch (e) {\n      this.log('Failed to send report', e);\n    }\n  }\n\n  private saveToLocalStorage(report: PerformanceReport): void {\n    const key = this.config.storageKey ?? 'performance-reports';\n\n    try {\n      const storedValue = localStorage.getItem(key);\n      const existing: unknown =\n        storedValue !== null && storedValue !== undefined ? JSON.parse(storedValue) : [];\n\n      if (Array.isArray(existing)) {\n        existing.push(report);\n        // Keep only last 100 reports\n        const trimmed: unknown = existing.slice(-100);\n        if (Array.isArray(trimmed)) {\n          localStorage.setItem(key, JSON.stringify(trimmed));\n        }\n      }\n\n      this.log('Report saved to localStorage');\n    } catch (e) {\n      this.log('Failed to save to localStorage', e);\n    }\n  }\n\n  private formatReport(report: PerformanceReport): unknown {\n    switch (this.config.format) {\n      case 'json':\n        return report;\n\n      case 'analytics':\n        // Format for Google Analytics or similar\n        return {\n          event: 'performance_report',\n          metrics: Object.fromEntries(report.metrics.map((m) => [m.name, m.value])),\n          score: report.score,\n          url: report.url,\n        };\n\n      default:\n        return report;\n    }\n  }\n\n  private formatValue(name: string, value: number): string {\n    if (name === 'CLS') {\n      return value.toFixed(3);\n    }\n    return `${Math.round(value)}ms`;\n  }\n\n  private ratingToScore(rating: 'good' | 'needs-improvement' | 'poor'): number {\n    switch (rating) {\n      case 'good':\n        return 100;\n      case 'needs-improvement':\n        return 50;\n      case 'poor':\n        return 0;\n    }\n  }\n\n  private scoreToRating(score: number): 'good' | 'needs-improvement' | 'poor' {\n    if (score >= 90) return 'good';\n    if (score >= 50) return 'needs-improvement';\n    return 'poor';\n  }\n\n  private createEmptyReport(): PerformanceReport {\n    return {\n      id: this.generateId(),\n      timestamp: Date.now(),\n      url: '',\n      metrics: [],\n      score: 0,\n      rating: 'poor',\n      summary: {\n        totalMetrics: 0,\n        goodMetrics: 0,\n        poorMetrics: 0,\n        needsImprovementMetrics: 0,\n        criticalIssues: [],\n      },\n      context: {\n        userAgent: '',\n        viewport: { width: 0, height: 0 },\n      },\n      recommendations: [],\n    };\n  }\n\n  private generateId(): string {\n    return `report-${Date.now()}-${++this.idCounter}`;\n  }\n\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      console.info(`[PerformanceReporter] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet reporterInstance: PerformanceReporter | null = null;\n\n/**\n * Get or create the global performance reporter\n */\nexport function getPerformanceReporter(\n  config?: Partial<PerformanceReporterConfig>\n): PerformanceReporter {\n  reporterInstance ??= new PerformanceReporter(config);\n  return reporterInstance;\n}\n\n/**\n * Reset the reporter instance\n */\nexport function resetPerformanceReporter(): void {\n  reporterInstance = null;\n}\n"],"names":["DEFAULT_CONFIG","DEFAULT_ALERT_RULES","PerformanceReporter","config","metrics","report","rule","metric","r","report1","report2","improved","regressed","unchanged","metrics1","m","metrics2","name","metric1","metric2","delta","threshold","lines","indicator","issue","rec","score","summary","recommendations","weights","totalWeight","weightedScore","weight","criticalIssues","nav","triggeredAlerts","body","e","key","storedValue","existing","trimmed","value","rating","message","args","reporterInstance","getPerformanceReporter","resetPerformanceReporter"],"mappings":"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"}