{"version":3,"file":"data-prefetch.mjs","sources":["../../../../src/lib/performance/prefetch/data-prefetch.ts"],"sourcesContent":["/**\n * @file Data Prefetching\n * @description API and data prefetching utilities with caching, deduplication,\n * and stale-while-revalidate patterns.\n *\n * Features:\n * - API response prefetching\n * - GraphQL query prefetching\n * - Stale-while-revalidate\n * - Request deduplication\n * - Cache management\n * - Prefetch on interaction\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Data prefetch configuration\n */\nexport interface DataPrefetchConfig {\n  /** Enable data prefetching */\n  enabled: boolean;\n  /** Default cache TTL in ms */\n  defaultTTL: number;\n  /** Enable stale-while-revalidate */\n  staleWhileRevalidate: boolean;\n  /** Stale time before revalidation in ms */\n  staleTime: number;\n  /** Enable request deduplication */\n  deduplicate: boolean;\n  /** Deduplication window in ms */\n  dedupeWindow: number;\n  /** Maximum cache entries */\n  maxCacheEntries: number;\n  /** Include credentials */\n  credentials: RequestCredentials;\n  /** Default headers */\n  defaultHeaders: Record<string, string>;\n  /** Retry configuration */\n  retry: {\n    attempts: number;\n    delay: number;\n    backoff: 'linear' | 'exponential';\n  };\n  /** Debug mode */\n  debug: boolean;\n}\n\n/**\n * Prefetch request options\n */\nexport interface PrefetchRequestOptions {\n  /** HTTP method */\n  method?: 'GET' | 'POST';\n  /** Request headers */\n  headers?: Record<string, string>;\n  /** Request body (for POST) */\n  body?: unknown;\n  /** Cache TTL in ms */\n  ttl?: number;\n  /** Cache key (defaults to URL) */\n  cacheKey?: string;\n  /** Priority */\n  priority?: 'high' | 'normal' | 'low';\n  /** Skip cache and force fetch */\n  force?: boolean;\n  /** Tags for cache invalidation */\n  tags?: string[];\n}\n\n/**\n * Cache entry\n */\ninterface CacheEntry<T = unknown> {\n  data: T;\n  fetchedAt: number;\n  expiresAt: number;\n  staleAt: number;\n  tags: string[];\n  isRevalidating: boolean;\n}\n\n/**\n * Prefetch result\n */\nexport interface PrefetchResult<T = unknown> {\n  data: T | null;\n  error: Error | null;\n  fromCache: boolean;\n  stale: boolean;\n  fetchedAt: number;\n}\n\n/**\n * Pending request\n */\ninterface PendingRequest<T = unknown> {\n  promise: Promise<T>;\n  timestamp: number;\n}\n\n/**\n * GraphQL query options\n */\nexport interface GraphQLPrefetchOptions {\n  query: string;\n  variables?: Record<string, unknown>;\n  operationName?: string;\n  ttl?: number;\n  tags?: string[];\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_CONFIG: DataPrefetchConfig = {\n  enabled: true,\n  defaultTTL: 5 * 60 * 1000, // 5 minutes\n  staleWhileRevalidate: true,\n  staleTime: 60 * 1000, // 1 minute\n  deduplicate: true,\n  dedupeWindow: 100, // 100ms\n  maxCacheEntries: 500,\n  credentials: 'same-origin',\n  defaultHeaders: {\n    'Content-Type': 'application/json',\n  },\n  retry: {\n    attempts: 2,\n    delay: 1000,\n    backoff: 'exponential',\n  },\n  debug: false,\n};\n\n// ============================================================================\n// Data Prefetch Manager\n// ============================================================================\n\n/**\n * Manages data prefetching with caching\n */\nexport class DataPrefetchManager {\n  private readonly config: DataPrefetchConfig;\n  private cache: Map<string, CacheEntry> = new Map();\n  private pendingRequests: Map<string, PendingRequest> = new Map();\n  private listeners: Map<string, Set<(data: unknown) => void>> = new Map();\n\n  constructor(config: Partial<DataPrefetchConfig> = {}) {\n    this.config = { ...DEFAULT_CONFIG, ...config };\n  }\n\n  /**\n   * Prefetch data from a URL\n   */\n  async prefetch<T = unknown>(\n    url: string,\n    options: PrefetchRequestOptions = {}\n  ): Promise<PrefetchResult<T>> {\n    if (!this.config.enabled) {\n      return {\n        data: null,\n        error: new Error('Data prefetch disabled'),\n        fromCache: false,\n        stale: false,\n        fetchedAt: 0,\n      };\n    }\n\n    const cacheKey = options.cacheKey ?? this.generateCacheKey(url, options);\n    const now = Date.now();\n\n    // Check cache first (unless force)\n    if (options.force !== true) {\n      const cached = this.cache.get(cacheKey);\n      if (cached) {\n        // Return fresh data immediately\n        if (cached.expiresAt > now) {\n          this.log(`Cache hit (fresh): ${cacheKey}`);\n          return {\n            data: cached.data as T,\n            error: null,\n            fromCache: true,\n            stale: false,\n            fetchedAt: cached.fetchedAt,\n          };\n        }\n\n        // Return stale data and revalidate in background\n        if (this.config.staleWhileRevalidate && cached.staleAt > now && !cached.isRevalidating) {\n          this.log(`Cache hit (stale): ${cacheKey}`);\n          void this.revalidate(url, cacheKey, options);\n          return {\n            data: cached.data as T,\n            error: null,\n            fromCache: true,\n            stale: true,\n            fetchedAt: cached.fetchedAt,\n          };\n        }\n      }\n    }\n\n    // Check for pending request (deduplication)\n    if (this.config.deduplicate) {\n      const pending = this.pendingRequests.get(cacheKey);\n      if (pending && now - pending.timestamp < this.config.dedupeWindow) {\n        this.log(`Request deduplicated: ${cacheKey}`);\n        try {\n          const data = await pending.promise;\n          return {\n            data: data as T,\n            error: null,\n            fromCache: false,\n            stale: false,\n            fetchedAt: now,\n          };\n        } catch (error) {\n          return {\n            data: null,\n            error: error instanceof Error ? error : new Error(String(error)),\n            fromCache: false,\n            stale: false,\n            fetchedAt: now,\n          };\n        }\n      }\n    }\n\n    // Execute fetch\n    return this.executeFetch<T>(url, cacheKey, options);\n  }\n\n  /**\n   * Prefetch multiple URLs\n   */\n  async prefetchMany<T = unknown>(\n    requests: Array<{ url: string; options?: PrefetchRequestOptions }>\n  ): Promise<Map<string, PrefetchResult<T>>> {\n    const results = new Map<string, PrefetchResult<T>>();\n\n    const promises = requests.map(async ({ url, options }) => {\n      const result = await this.prefetch<T>(url, options);\n      results.set(options?.cacheKey ?? url, result);\n    });\n\n    await Promise.allSettled(promises);\n    return results;\n  }\n\n  /**\n   * Prefetch a GraphQL query\n   */\n  async prefetchGraphQL<T = unknown>(\n    endpoint: string,\n    options: GraphQLPrefetchOptions\n  ): Promise<PrefetchResult<T>> {\n    const cacheKey = this.generateGraphQLCacheKey(endpoint, options);\n\n    return this.prefetch<T>(endpoint, {\n      method: 'POST',\n      body: {\n        query: options.query,\n        variables: options.variables,\n        operationName: options.operationName,\n      },\n      cacheKey,\n      ttl: options.ttl,\n      tags: options.tags,\n    });\n  }\n\n  /**\n   * Get cached data without fetching\n   */\n  getCached<T = unknown>(cacheKey: string): T | null {\n    const entry = this.cache.get(cacheKey);\n    if (!entry) return null;\n\n    if (entry.expiresAt > Date.now()) {\n      return entry.data as T;\n    }\n\n    // Return stale if within stale window\n    if (entry.staleAt > Date.now()) {\n      return entry.data as T;\n    }\n\n    return null;\n  }\n\n  /**\n   * Check if data is cached\n   */\n  isCached(cacheKey: string): boolean {\n    const entry = this.cache.get(cacheKey);\n    return entry !== undefined && entry.expiresAt > Date.now();\n  }\n\n  /**\n   * Check if cached data is stale\n   */\n  isStale(cacheKey: string): boolean {\n    const entry = this.cache.get(cacheKey);\n    if (!entry) return true;\n\n    const now = Date.now();\n    return entry.expiresAt <= now && entry.staleAt > now;\n  }\n\n  /**\n   * Invalidate cache by key\n   */\n  invalidate(cacheKey: string): boolean {\n    return this.cache.delete(cacheKey);\n  }\n\n  /**\n   * Invalidate cache by tag\n   */\n  invalidateByTag(tag: string): number {\n    let invalidated = 0;\n\n    for (const [key, entry] of this.cache.entries()) {\n      if (entry.tags.includes(tag)) {\n        this.cache.delete(key);\n        invalidated++;\n      }\n    }\n\n    this.log(`Invalidated ${invalidated} entries with tag: ${tag}`);\n    return invalidated;\n  }\n\n  /**\n   * Subscribe to cache updates\n   */\n  subscribe(cacheKey: string, callback: (data: unknown) => void): () => void {\n    const subs = this.listeners.get(cacheKey) ?? new Set();\n    subs.add(callback);\n    this.listeners.set(cacheKey, subs);\n\n    // Emit current value if cached\n    const cached = this.getCached(cacheKey);\n    if (cached !== null) {\n      callback(cached);\n    }\n\n    return () => {\n      subs.delete(callback);\n      if (subs.size === 0) {\n        this.listeners.delete(cacheKey);\n      }\n    };\n  }\n\n  /**\n   * Clear all cache\n   */\n  clearCache(): void {\n    this.cache.clear();\n    this.log('Cache cleared');\n  }\n\n  /**\n   * Get cache statistics\n   */\n  getStats(): {\n    entries: number;\n    size: number;\n    pendingRequests: number;\n  } {\n    let size = 0;\n    for (const entry of this.cache.values()) {\n      size += this.estimateSize(entry.data);\n    }\n\n    return {\n      entries: this.cache.size,\n      size,\n      pendingRequests: this.pendingRequests.size,\n    };\n  }\n\n  // ============================================================================\n  // Private Methods\n  // ============================================================================\n\n  private async executeFetch<T>(\n    url: string,\n    cacheKey: string,\n    options: PrefetchRequestOptions\n  ): Promise<PrefetchResult<T>> {\n    const fetchPromise = this.fetchWithRetry<T>(url, options);\n\n    // Store pending request for deduplication\n    this.pendingRequests.set(cacheKey, {\n      promise: fetchPromise as Promise<unknown>,\n      timestamp: Date.now(),\n    });\n\n    try {\n      const data = await fetchPromise;\n      const now = Date.now();\n      const ttl = options.ttl ?? this.config.defaultTTL;\n\n      // Cache the result\n      this.setCache(cacheKey, data, ttl, options.tags);\n\n      // Clean up pending request\n      this.pendingRequests.delete(cacheKey);\n\n      this.log(`Fetched and cached: ${cacheKey}`);\n\n      return {\n        data,\n        error: null,\n        fromCache: false,\n        stale: false,\n        fetchedAt: now,\n      };\n    } catch (error) {\n      this.pendingRequests.delete(cacheKey);\n\n      // Return stale data on error if available\n      const stale = this.cache.get(cacheKey);\n      if (stale) {\n        this.log(`Fetch failed, returning stale: ${cacheKey}`);\n        return {\n          data: stale.data as T,\n          error: error instanceof Error ? error : new Error(String(error)),\n          fromCache: true,\n          stale: true,\n          fetchedAt: stale.fetchedAt,\n        };\n      }\n\n      return {\n        data: null,\n        error: error instanceof Error ? error : new Error(String(error)),\n        fromCache: false,\n        stale: false,\n        fetchedAt: Date.now(),\n      };\n    }\n  }\n\n  private async fetchWithRetry<T>(url: string, options: PrefetchRequestOptions): Promise<T> {\n    const { retry } = this.config;\n    let lastError: Error | null = null;\n\n    for (let attempt = 0; attempt <= retry.attempts; attempt++) {\n      try {\n        const response = await fetch(url, {\n          method: options.method ?? 'GET',\n          headers: {\n            ...this.config.defaultHeaders,\n            ...options.headers,\n          },\n          body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n          credentials: this.config.credentials,\n        });\n\n        if (!response.ok) {\n          throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n        }\n\n        return (await response.json()) as T;\n      } catch (error) {\n        lastError = error instanceof Error ? error : new Error(String(error));\n\n        if (attempt < retry.attempts) {\n          const delay =\n            retry.backoff === 'exponential'\n              ? retry.delay * Math.pow(2, attempt)\n              : retry.delay * (attempt + 1);\n\n          this.log(`Retry ${attempt + 1}/${retry.attempts} for ${url} in ${delay}ms`);\n          await this.sleep(delay);\n        }\n      }\n    }\n\n    throw lastError ?? new Error('Unknown error occurred');\n  }\n\n  private async revalidate(\n    url: string,\n    cacheKey: string,\n    options: PrefetchRequestOptions\n  ): Promise<void> {\n    const entry = this.cache.get(cacheKey);\n    if (entry == null || entry.isRevalidating) {\n      return;\n    }\n\n    entry.isRevalidating = true;\n    this.log(`Revalidating: ${cacheKey}`);\n\n    try {\n      const data = await this.fetchWithRetry(url, options);\n      const ttl = options.ttl ?? this.config.defaultTTL;\n      this.setCache(cacheKey, data, ttl, options.tags);\n\n      // Notify subscribers\n      this.notifySubscribers(cacheKey, data);\n    } catch (error) {\n      this.log(`Revalidation failed: ${cacheKey}`, error);\n    } finally {\n      const currentEntry = this.cache.get(cacheKey);\n      if (currentEntry) {\n        currentEntry.isRevalidating = false;\n      }\n    }\n  }\n\n  private setCache(cacheKey: string, data: unknown, ttl: number, tags?: string[]): void {\n    const now = Date.now();\n\n    // Evict if at capacity\n    if (this.cache.size >= this.config.maxCacheEntries) {\n      this.evictOldest();\n    }\n\n    this.cache.set(cacheKey, {\n      data,\n      fetchedAt: now,\n      expiresAt: now + ttl,\n      staleAt: now + ttl + this.config.staleTime,\n      tags: tags ?? [],\n      isRevalidating: false,\n    });\n  }\n\n  private evictOldest(): void {\n    let oldestKey: string | null = null;\n    let oldestTime = Infinity;\n\n    for (const [key, entry] of this.cache.entries()) {\n      if (entry.fetchedAt < oldestTime) {\n        oldestTime = entry.fetchedAt;\n        oldestKey = key;\n      }\n    }\n\n    if (oldestKey !== null) {\n      this.cache.delete(oldestKey);\n      this.log(`Evicted oldest: ${oldestKey}`);\n    }\n  }\n\n  private notifySubscribers(cacheKey: string, data: unknown): void {\n    const subs = this.listeners.get(cacheKey);\n    if (subs !== undefined) {\n      subs.forEach((callback) => callback(data));\n    }\n  }\n\n  private generateCacheKey(url: string, options: PrefetchRequestOptions): string {\n    const parts = [url, options.method ?? 'GET'];\n\n    if (options.body !== undefined) {\n      parts.push(JSON.stringify(options.body));\n    }\n\n    return parts.join(':');\n  }\n\n  private generateGraphQLCacheKey(endpoint: string, options: GraphQLPrefetchOptions): string {\n    const parts = [\n      endpoint,\n      options.operationName ?? 'anonymous',\n      JSON.stringify(options.variables ?? {}),\n    ];\n    return `graphql:${parts.join(':')}`;\n  }\n\n  private estimateSize(data: unknown): number {\n    try {\n      return new Blob([JSON.stringify(data)]).size;\n    } catch {\n      return 0;\n    }\n  }\n\n  private async sleep(ms: number): Promise<void> {\n    return new Promise((resolve) => setTimeout(resolve, ms));\n  }\n\n  private log(message: string, ...args: unknown[]): void {\n    if (this.config.debug) {\n      console.info(`[DataPrefetch] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet managerInstance: DataPrefetchManager | null = null;\n\n/**\n * Get or create the global data prefetch manager\n */\nexport function getDataPrefetchManager(config?: Partial<DataPrefetchConfig>): DataPrefetchManager {\n  managerInstance ??= new DataPrefetchManager(config);\n  return managerInstance;\n}\n\n/**\n * Reset the manager instance\n */\nexport function resetDataPrefetchManager(): void {\n  if (managerInstance !== null) {\n    managerInstance.clearCache();\n    managerInstance = null;\n  }\n}\n\n// ============================================================================\n// Convenience Functions\n// ============================================================================\n\n/**\n * Prefetch data from a URL\n */\nexport async function prefetchData<T = unknown>(\n  url: string,\n  options?: PrefetchRequestOptions\n): Promise<PrefetchResult<T>> {\n  return getDataPrefetchManager().prefetch<T>(url, options);\n}\n\n/**\n * Prefetch a GraphQL query\n */\nexport async function prefetchGraphQL<T = unknown>(\n  endpoint: string,\n  options: GraphQLPrefetchOptions\n): Promise<PrefetchResult<T>> {\n  return getDataPrefetchManager().prefetchGraphQL<T>(endpoint, options);\n}\n\n/**\n * Get cached data\n */\nexport function getCachedData<T = unknown>(cacheKey: string): T | null {\n  return getDataPrefetchManager().getCached<T>(cacheKey);\n}\n\n/**\n * Invalidate cache by key\n */\nexport function invalidateData(cacheKey: string): boolean {\n  return getDataPrefetchManager().invalidate(cacheKey);\n}\n\n/**\n * Invalidate cache by tag\n */\nexport function invalidateDataByTag(tag: string): number {\n  return getDataPrefetchManager().invalidateByTag(tag);\n}\n"],"names":["DEFAULT_CONFIG","DataPrefetchManager","config","url","options","cacheKey","now","cached","pending","error","requests","results","promises","result","endpoint","entry","tag","invalidated","key","callback","subs","size","fetchPromise","data","ttl","stale","retry","lastError","attempt","response","delay","currentEntry","tags","oldestKey","oldestTime","parts","ms","resolve","message","args","managerInstance","getDataPrefetchManager","resetDataPrefetchManager","prefetchData","prefetchGraphQL","getCachedData","invalidateData","invalidateDataByTag"],"mappings":"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"}