{"version":3,"file":"PredictivePrefetch.mjs","sources":["../../../src/lib/performance/PredictivePrefetch.ts"],"sourcesContent":["/**\n * @file Predictive Prefetching System\n * @description AI-driven prefetching that learns user navigation patterns\n * and predictively loads resources for likely next pages.\n *\n * FEATURE 3: Predictive Navigation Prefetching\n *\n * Strategies:\n * 1. Markov Chain prediction based on navigation history\n * 2. Time-of-day patterns for recurring user behavior\n * 3. Session context awareness (recent interactions)\n * 4. Network-adaptive prefetching (respects connection quality)\n */\n\nimport type { QueryClient } from '@tanstack/react-query';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Navigation event for pattern learning\n */\nexport interface NavigationEvent {\n  from: string;\n  to: string;\n  timestamp: number;\n  sessionId: string;\n  timeOfDay: 'morning' | 'afternoon' | 'evening' | 'night';\n  dayOfWeek: number;\n}\n\n/**\n * Route configuration for prefetching\n */\nexport interface PrefetchableRoute {\n  /** Route path pattern */\n  path: string;\n  /** Module loader for code splitting */\n  loader?: () => Promise<unknown>;\n  /** Query configuration for data prefetching */\n  queries?: Array<{\n    queryKey: readonly unknown[];\n    queryFn: () => Promise<unknown>;\n    staleTime?: number;\n  }>;\n  /** Static assets to preload */\n  assets?: string[];\n  /** Estimated load priority (0-10) */\n  priority?: number;\n}\n\n/**\n * Prediction result\n */\nexport interface RoutePrediction {\n  route: string;\n  probability: number;\n  confidence: 'high' | 'medium' | 'low';\n  source: 'markov' | 'time-pattern' | 'session-context' | 'static';\n}\n\n/**\n * Transition matrix for Markov chain\n */\ntype TransitionMatrix = Map<string, Map<string, number>>;\n\n/**\n * Time pattern entry\n */\ninterface TimePattern {\n  route: string;\n  timeOfDay: string;\n  dayOfWeek: number;\n  count: number;\n}\n\n/**\n * Configuration for predictive prefetch\n */\nexport interface PredictivePrefetchConfig {\n  /** Enable learning from navigation */\n  enableLearning?: boolean;\n  /** Probability threshold for triggering prefetch (0-1) */\n  probabilityThreshold?: number;\n  /** Maximum routes to prefetch at once */\n  maxPrefetchCount?: number;\n  /** Storage key for persisting learned patterns */\n  storageKey?: string;\n  /** Static route priorities (fallback) */\n  staticRoutes?: Record<string, number>;\n  /** Network quality threshold ('4g' | '3g' | '2g' | 'slow-2g') */\n  minNetworkQuality?: string;\n  /** Respect user's data saver preference */\n  respectDataSaver?: boolean;\n  /** Debug logging */\n  debug?: boolean;\n  /** Decay factor for old transitions (0-1) */\n  decayFactor?: number;\n  /** Maximum history entries to keep */\n  maxHistorySize?: number;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_CONFIG: Required<PredictivePrefetchConfig> = {\n  enableLearning: true,\n  probabilityThreshold: 0.3,\n  maxPrefetchCount: 3,\n  storageKey: 'predictive-prefetch-patterns',\n  staticRoutes: {},\n  minNetworkQuality: '3g',\n  respectDataSaver: true,\n  debug: false,\n  decayFactor: 0.95,\n  maxHistorySize: 1000,\n};\n\nconst NETWORK_QUALITY_RANK: Record<string, number> = {\n  '4g': 4,\n  '3g': 3,\n  '2g': 2,\n  'slow-2g': 1,\n  unknown: 3,\n};\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Get time of day category\n */\nfunction getTimeOfDay(): 'morning' | 'afternoon' | 'evening' | 'night' {\n  const hour = new Date().getHours();\n  if (hour >= 5 && hour < 12) return 'morning';\n  if (hour >= 12 && hour < 17) return 'afternoon';\n  if (hour >= 17 && hour < 21) return 'evening';\n  return 'night';\n}\n\n/**\n * Normalize path for comparison\n */\nfunction normalizePath(path: string): string {\n  // Remove trailing slash and query params\n  const pathParts = path.split('?');\n  const pathWithoutQuery = pathParts[0] ?? '';\n  return (pathWithoutQuery !== '' ? pathWithoutQuery : '').replace(/\\/$/, '') || '/';\n}\n\n/**\n * Get current network quality\n */\nfunction getNetworkQuality(): string {\n  const nav = navigator as Navigator & {\n    connection?: { effectiveType?: string; saveData?: boolean };\n  };\n  return nav.connection?.effectiveType ?? 'unknown';\n}\n\n/**\n * Check if data saver is enabled\n */\nfunction isDataSaverEnabled(): boolean {\n  const nav = navigator as Navigator & {\n    connection?: { saveData?: boolean };\n  };\n  return nav.connection?.saveData ?? false;\n}\n\n// ============================================================================\n// Predictive Prefetch Engine\n// ============================================================================\n\n/**\n * Predictive prefetch engine that learns navigation patterns\n */\nexport class PredictivePrefetchEngine {\n  private config: Required<PredictivePrefetchConfig>;\n  private transitionMatrix: TransitionMatrix = new Map();\n  private timePatterns: TimePattern[] = [];\n  private sessionHistory: string[] = [];\n  // Session ID for tracking navigation patterns\n  private routeRegistry: Map<string, PrefetchableRoute> = new Map();\n  private prefetchedRoutes: Set<string> = new Set();\n  private queryClient: QueryClient | null = null;\n\n  constructor(config: PredictivePrefetchConfig = {}) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n    this.loadPersistedPatterns();\n  }\n\n  // ==========================================================================\n  // Initialization\n  // ==========================================================================\n\n  /**\n   * Initialize with query client for data prefetching\n   */\n  setQueryClient(client: QueryClient): void {\n    this.queryClient = client;\n  }\n\n  /**\n   * Register routes available for prefetching\n   */\n  registerRoutes(routes: PrefetchableRoute[]): void {\n    routes.forEach((route) => {\n      this.routeRegistry.set(normalizePath(route.path), route);\n    });\n    this.log(`Registered ${routes.length} prefetchable routes`);\n  }\n\n  // ==========================================================================\n  // Navigation Tracking\n  // ==========================================================================\n\n  /**\n   * Record a navigation event for learning\n   */\n  recordNavigation(from: string, to: string): void {\n    const normalizedFrom = normalizePath(from);\n    const normalizedTo = normalizePath(to);\n\n    // Skip if same page\n    if (normalizedFrom === normalizedTo) return;\n\n    // Record in session history\n    this.sessionHistory.push(normalizedTo);\n    if (this.sessionHistory.length > 20) {\n      this.sessionHistory.shift();\n    }\n\n    // Update transition matrix\n    if (this.config.enableLearning) {\n      this.updateTransitionMatrix(normalizedFrom, normalizedTo);\n      this.updateTimePatterns(normalizedTo);\n      this.persistPatterns();\n    }\n\n    // Clear prefetch cache for new navigation\n    this.prefetchedRoutes.clear();\n\n    this.log(`Recorded navigation: ${normalizedFrom} -> ${normalizedTo}`);\n  }\n\n  /**\n   * Get predicted next routes from current page\n   */\n  getPredictions(currentPath: string): RoutePrediction[] {\n    const normalizedPath = normalizePath(currentPath);\n    const predictions: RoutePrediction[] = [];\n\n    // 1. Markov chain predictions\n    const markovPredictions = this.getMarkovPredictions(normalizedPath);\n    predictions.push(...markovPredictions);\n\n    // 2. Time pattern predictions\n    const timePredictions = this.getTimePatternPredictions();\n    predictions.push(...timePredictions);\n\n    // 3. Session context predictions\n    const sessionPredictions = this.getSessionContextPredictions();\n    predictions.push(...sessionPredictions);\n\n    // 4. Static route priorities\n    const staticPredictions = this.getStaticPredictions(normalizedPath);\n    predictions.push(...staticPredictions);\n\n    // Deduplicate and sort by probability\n    const deduped = this.deduplicatePredictions(predictions);\n\n    // Filter by threshold\n    const filtered = deduped.filter(\n      (p) => p.probability >= this.config.probabilityThreshold\n    );\n\n    this.log(`Predictions for ${normalizedPath}:`, filtered);\n\n    return filtered.slice(0, this.config.maxPrefetchCount);\n  }\n\n  /**\n   * Execute prefetch for predicted routes\n   */\n  async prefetchPredictedRoutes(currentPath: string): Promise<void> {\n    // Check network conditions\n    if (!this.shouldPrefetch()) {\n      this.log('Skipping prefetch due to network conditions');\n      return;\n    }\n\n    const predictions = this.getPredictions(currentPath);\n\n    for (const prediction of predictions) {\n      await this.prefetchRoute(prediction.route);\n    }\n  }\n\n  // ==========================================================================\n  // Prediction\n  // ==========================================================================\n\n  /**\n   * Prefetch a specific route\n   */\n  async prefetchRoute(routePath: string): Promise<void> {\n    const normalizedPath = normalizePath(routePath);\n\n    // Skip if already prefetched\n    if (this.prefetchedRoutes.has(normalizedPath)) {\n      return;\n    }\n\n    const route = this.routeRegistry.get(normalizedPath);\n    if (!route) {\n      this.log(`Route not found in registry: ${normalizedPath}`);\n      return;\n    }\n\n    this.prefetchedRoutes.add(normalizedPath);\n    this.log(`Prefetching route: ${normalizedPath}`);\n\n    // Prefetch module (code splitting)\n    if (route.loader) {\n      try {\n        await route.loader();\n        this.log(`Module prefetched: ${normalizedPath}`);\n      } catch (error) {\n        this.log(`Module prefetch failed: ${normalizedPath}`, error);\n      }\n    }\n\n    // Prefetch data\n    if (route.queries && this.queryClient) {\n      for (const query of route.queries) {\n        try {\n          await this.queryClient.prefetchQuery({\n            queryKey: query.queryKey,\n            queryFn: query.queryFn,\n            staleTime: query.staleTime ?? 5 * 60 * 1000,\n          });\n          this.log(`Data prefetched: ${JSON.stringify(query.queryKey)}`);\n        } catch (error) {\n          this.log(`Data prefetch failed: ${JSON.stringify(query.queryKey)}`, error);\n        }\n      }\n    }\n\n    // Preload static assets\n    if (route.assets) {\n      route.assets.forEach((asset) => {\n        this.preloadAsset(asset);\n      });\n    }\n  }\n\n  /**\n   * Clear all learned patterns\n   */\n  clearPatterns(): void {\n    this.transitionMatrix.clear();\n    this.timePatterns = [];\n    this.sessionHistory = [];\n    this.prefetchedRoutes.clear();\n    localStorage.removeItem(this.config.storageKey);\n    this.log('Cleared all patterns');\n  }\n\n  /**\n   * Get analytics about learned patterns\n   */\n  getAnalytics(): {\n    totalTransitions: number;\n    uniqueRoutes: number;\n    timePatterns: number;\n    topRoutes: Array<{ route: string; visits: number }>;\n  } {\n    const routeVisits = new Map<string, number>();\n\n    this.transitionMatrix.forEach((transitions) => {\n      transitions.forEach((count, route) => {\n        routeVisits.set(route, (routeVisits.get(route) ?? 0) + count);\n      });\n    });\n\n    const topRoutes = Array.from(routeVisits.entries())\n      .sort(([, a], [, b]) => b - a)\n      .slice(0, 10)\n      .map(([route, visits]) => ({ route, visits: Math.round(visits) }));\n\n    return {\n      totalTransitions: Array.from(this.transitionMatrix.values())\n        .flatMap((t) => Array.from(t.values()))\n        .reduce((a, b) => a + b, 0),\n      uniqueRoutes: new Set([\n        ...this.transitionMatrix.keys(),\n        ...Array.from(this.transitionMatrix.values()).flatMap((t) =>\n          Array.from(t.keys())\n        ),\n      ]).size,\n      timePatterns: this.timePatterns.length,\n      topRoutes,\n    };\n  }\n\n  /**\n   * Update transition matrix with new navigation\n   */\n  private updateTransitionMatrix(from: string, to: string): void {\n    if (!this.transitionMatrix.has(from)) {\n      this.transitionMatrix.set(from, new Map());\n    }\n\n    const transitions = this.transitionMatrix.get(from);\n    if (transitions == null) return;\n    const currentCount = transitions.get(to) ?? 0;\n    transitions.set(to, currentCount + 1);\n\n    // Apply decay to all transitions from this page\n    transitions.forEach((count, route) => {\n      if (route !== to) {\n        transitions.set(route, count * this.config.decayFactor);\n      }\n    });\n\n    // Clean up near-zero transitions\n    transitions.forEach((count, route) => {\n      if (count < 0.1) {\n        transitions.delete(route);\n      }\n    });\n  }\n\n  /**\n   * Update time-based patterns\n   */\n  private updateTimePatterns(route: string): void {\n    const timeOfDay = getTimeOfDay();\n    const dayOfWeek = new Date().getDay();\n\n    const existingPattern = this.timePatterns.find(\n      (p) =>\n        p.route === route &&\n        p.timeOfDay === timeOfDay &&\n        p.dayOfWeek === dayOfWeek\n    );\n\n    if (existingPattern) {\n      existingPattern.count++;\n    } else {\n      this.timePatterns.push({\n        route,\n        timeOfDay,\n        dayOfWeek,\n        count: 1,\n      });\n    }\n\n    // Limit time patterns\n    if (this.timePatterns.length > 100) {\n      this.timePatterns = this.timePatterns\n        .sort((a, b) => b.count - a.count)\n        .slice(0, 100);\n    }\n  }\n\n  /**\n   * Get predictions from transition matrix (Markov chain)\n   */\n  private getMarkovPredictions(currentPath: string): RoutePrediction[] {\n    const transitions = this.transitionMatrix.get(currentPath);\n    if (!transitions || transitions.size === 0) return [];\n\n    const total = Array.from(transitions.values()).reduce((a, b) => a + b, 0);\n\n    return Array.from(transitions.entries())\n      .map(([route, count]) => ({\n        route,\n        probability: count / total,\n        confidence: this.getConfidence(count / total),\n        source: 'markov' as const,\n      }))\n      .filter((p) => p.probability > 0.1);\n  }\n\n  /**\n   * Get predictions based on time patterns\n   */\n  private getTimePatternPredictions(): RoutePrediction[] {\n    const timeOfDay = getTimeOfDay();\n    const dayOfWeek = new Date().getDay();\n\n    const relevantPatterns = this.timePatterns.filter(\n      (p) => p.timeOfDay === timeOfDay && p.dayOfWeek === dayOfWeek\n    );\n\n    const totalCount = relevantPatterns.reduce((sum, p) => sum + p.count, 0);\n    if (totalCount === 0) return [];\n\n    return relevantPatterns.map((pattern) => ({\n      route: pattern.route,\n      probability: (pattern.count / totalCount) * 0.7, // Discount time patterns\n      confidence: this.getConfidence((pattern.count / totalCount) * 0.7),\n      source: 'time-pattern' as const,\n    }));\n  }\n\n  // ==========================================================================\n  // Prefetching\n  // ==========================================================================\n\n  /**\n   * Get predictions based on session context\n   */\n  private getSessionContextPredictions(): RoutePrediction[] {\n    if (this.sessionHistory.length < 2) return [];\n\n    // Look for patterns in recent session\n    const recentHistory = this.sessionHistory.slice(-5);\n    const predictions: RoutePrediction[] = [];\n\n    // Check if user is following a known path\n    for (const [from, transitions] of this.transitionMatrix) {\n      if (recentHistory.includes(from)) {\n        const total = Array.from(transitions.values()).reduce((a, b) => a + b, 0);\n        for (const [to, count] of transitions) {\n          if (!recentHistory.includes(to)) {\n            predictions.push({\n              route: to,\n              probability: (count / total) * 0.5, // Discount session context\n              confidence: 'medium',\n              source: 'session-context',\n            });\n          }\n        }\n      }\n    }\n\n    return predictions;\n  }\n\n  /**\n   * Get static route predictions\n   */\n  private getStaticPredictions(currentPath: string): RoutePrediction[] {\n    return Object.entries(this.config.staticRoutes)\n      .filter(([route]) => route !== currentPath)\n      .map(([route, priority]) => ({\n        route,\n        probability: priority / 10, // Convert priority to probability\n        confidence: 'low' as const,\n        source: 'static' as const,\n      }));\n  }\n\n  /**\n   * Deduplicate predictions, keeping highest probability\n   */\n  private deduplicatePredictions(predictions: RoutePrediction[]): RoutePrediction[] {\n    const routeMap = new Map<string, RoutePrediction>();\n\n    predictions.forEach((prediction) => {\n      const existing = routeMap.get(prediction.route);\n      if (!existing || prediction.probability > existing.probability) {\n        routeMap.set(prediction.route, prediction);\n      }\n    });\n\n    return Array.from(routeMap.values()).sort(\n      (a, b) => b.probability - a.probability\n    );\n  }\n\n  /**\n   * Get confidence level from probability\n   */\n  private getConfidence(probability: number): 'high' | 'medium' | 'low' {\n    if (probability >= 0.7) return 'high';\n    if (probability >= 0.4) return 'medium';\n    return 'low';\n  }\n\n  // ==========================================================================\n  // Persistence\n  // ==========================================================================\n\n  /**\n   * Preload a static asset\n   */\n  private preloadAsset(url: string): void {\n    const link = document.createElement('link');\n    link.rel = 'prefetch';\n    link.href = url;\n\n    // Determine type from extension\n    if (url.endsWith('.js') || url.endsWith('.mjs')) {\n      link.as = 'script';\n    } else if (url.endsWith('.css')) {\n      link.as = 'style';\n    } else if (/\\.(png|jpg|jpeg|gif|webp|avif|svg)$/i.test(url)) {\n      link.as = 'image';\n    } else if (/\\.(woff2?|eot|ttf|otf)$/i.test(url)) {\n      link.as = 'font';\n      link.crossOrigin = 'anonymous';\n    }\n\n    document.head.appendChild(link);\n    this.log(`Asset prefetched: ${url}`);\n  }\n\n  /**\n   * Check if prefetching should proceed\n   */\n  private shouldPrefetch(): boolean {\n    // Check data saver\n    if (this.config.respectDataSaver && isDataSaverEnabled()) {\n      return false;\n    }\n\n    // Check network quality\n    const quality = getNetworkQuality();\n    const minQuality = this.config.minNetworkQuality;\n    const qualityRank = NETWORK_QUALITY_RANK[quality] ?? 0;\n    const minQualityRank = NETWORK_QUALITY_RANK[minQuality] ?? 0;\n    const unknownRank = NETWORK_QUALITY_RANK['unknown'] ?? 0;\n    return (\n      qualityRank >= minQualityRank ||\n      qualityRank >= unknownRank\n    );\n  }\n\n  /**\n   * Persist learned patterns to storage\n   */\n  private persistPatterns(): void {\n    try {\n      const data = {\n        transitionMatrix: Array.from(this.transitionMatrix.entries()).map(\n          ([from, transitions]) => [from, Array.from(transitions.entries())]\n        ),\n        timePatterns: this.timePatterns,\n        version: 1,\n      };\n\n      localStorage.setItem(this.config.storageKey, JSON.stringify(data));\n    } catch (error) {\n      this.log('Failed to persist patterns:', error);\n    }\n  }\n\n  // ==========================================================================\n  // Analytics\n  // ==========================================================================\n\n  /**\n   * Load persisted patterns from storage\n   */\n  private loadPersistedPatterns(): void {\n    try {\n      const stored = localStorage.getItem(this.config.storageKey);\n      if (stored == null || stored === '') return;\n\n      const data = JSON.parse(stored) as {\n        transitionMatrix?: unknown;\n        timePatterns?: unknown;\n        version?: number;\n      };\n      if (data.version !== 1) return;\n\n      // Restore transition matrix\n      if (Array.isArray(data.transitionMatrix)) {\n        this.transitionMatrix = new Map(\n          (data.transitionMatrix as Array<[string, Array<[string, number]>]>).map(([from, transitions]) => [\n            from,\n            new Map(transitions),\n          ])\n        );\n      }\n\n      // Restore time patterns\n      this.timePatterns = (Array.isArray(data.timePatterns) ? data.timePatterns : []) as TimePattern[];\n\n      this.log('Loaded persisted patterns');\n    } catch (error) {\n      this.log('Failed to load persisted patterns:', error);\n    }\n  }\n\n  // ==========================================================================\n  // Debug\n  // ==========================================================================\n\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      // eslint-disable-next-line no-console\n      console.log(`[PredictivePrefetch] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet engineInstance: PredictivePrefetchEngine | null = null;\n\n/**\n * Get or create the global PredictivePrefetchEngine instance\n */\nexport function getPredictivePrefetchEngine(\n  config?: PredictivePrefetchConfig\n): PredictivePrefetchEngine {\n  engineInstance ??= new PredictivePrefetchEngine(config);\n  return engineInstance;\n}\n\n// ============================================================================\n// React Integration\n// ============================================================================\n\n/**\n * Hook options for usePredictivePrefetch\n */\nexport interface UsePredictivePrefetchOptions {\n  /** Enable automatic prefetching on route change */\n  autoPrefetch?: boolean;\n  /** Delay before prefetching (ms) */\n  prefetchDelay?: number;\n}\n\n/**\n * Create navigation listener for automatic tracking\n */\nexport function createNavigationListener(\n  engine: PredictivePrefetchEngine,\n  options: UsePredictivePrefetchOptions = {}\n): (location: { pathname: string }) => void {\n  const { autoPrefetch = true, prefetchDelay = 500 } = options;\n  let lastPath = '';\n\n  return (location) => {\n    const currentPath = location.pathname;\n\n    if (lastPath && lastPath !== currentPath) {\n      // Record navigation\n      engine.recordNavigation(lastPath, currentPath);\n\n      // Trigger prefetch after delay\n      if (autoPrefetch) {\n        setTimeout(() => {\n          void engine.prefetchPredictedRoutes(currentPath);\n        }, prefetchDelay);\n      }\n    }\n\n    lastPath = currentPath;\n  };\n}\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport type { TransitionMatrix, TimePattern };\n"],"names":["DEFAULT_CONFIG","NETWORK_QUALITY_RANK","getTimeOfDay","hour","normalizePath","path","pathWithoutQuery","getNetworkQuality","isDataSaverEnabled","PredictivePrefetchEngine","config","client","routes","route","from","to","normalizedFrom","normalizedTo","currentPath","normalizedPath","predictions","markovPredictions","timePredictions","sessionPredictions","staticPredictions","filtered","p","prediction","routePath","error","query","asset","routeVisits","transitions","count","topRoutes","a","b","visits","t","currentCount","timeOfDay","dayOfWeek","existingPattern","total","relevantPatterns","totalCount","sum","pattern","recentHistory","priority","routeMap","existing","probability","url","link","quality","minQuality","qualityRank","minQualityRank","unknownRank","data","stored","message","args","engineInstance","getPredictivePrefetchEngine","createNavigationListener","engine","options","autoPrefetch","prefetchDelay","lastPath","location"],"mappings":"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"}