{"version":3,"file":"cached-provider.mjs","sources":["../../../../src/lib/flags/providers/cached-provider.ts"],"sourcesContent":["/**\n * @fileoverview Caching layer provider for feature flags.\n *\n * Provides caching functionality with:\n * - TTL-based expiration\n * - Stale-while-revalidate pattern\n * - Multiple storage backends\n * - Cache statistics\n *\n * @module flags/providers/cached-provider\n *\n * @example\n * ```typescript\n * const remoteProvider = new RemoteProvider({ endpoint: '...' });\n * const cachedProvider = new CachedProvider({\n *   provider: remoteProvider,\n *   ttl: 60000, // 1 minute\n *   staleWhileRevalidate: 300000, // 5 minutes\n * });\n *\n * await cachedProvider.initialize();\n * const flags = await cachedProvider.getFlags(); // Returns cached or fresh\n * ```\n */\n\nimport type { FeatureFlag, Segment, SegmentId } from '@/lib/flags';\nimport type {\n  FlagProvider,\n  CachedProviderConfig,\n  FlagChangeListener,\n  FlagChangeEvent,\n  ProviderStats,\n} from './types';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes\nconst DEFAULT_STALE_WHILE_REVALIDATE = 60 * 60 * 1000; // 1 hour\nconst DEFAULT_MAX_SIZE = 1000;\n\n// ============================================================================\n// Types\n// ============================================================================\n\ninterface CacheEntry<T> {\n  value: T;\n  timestamp: number;\n  expiresAt: number;\n  staleAt: number;\n}\n\n// ============================================================================\n// Cached Provider\n// ============================================================================\n\n/**\n * Caching wrapper for flag providers.\n */\nexport class CachedProvider implements FlagProvider {\n  readonly name: string;\n  readonly priority: number;\n\n  private provider: FlagProvider;\n  private flagsCache: CacheEntry<FeatureFlag[]> | null = null;\n  private flagCache = new Map<string, CacheEntry<FeatureFlag | null>>();\n  private segmentsCache: CacheEntry<Segment[]> | null = null;\n  private listeners = new Set<FlagChangeListener>();\n  private ready = false;\n  private config: Required<Omit<CachedProviderConfig, 'provider'>> & {\n    provider: FlagProvider;\n  };\n  private cacheHits = 0;\n  private cacheMisses = 0;\n  private revalidating = false;\n  private readonly storageKey: string;\n\n  constructor(config: CachedProviderConfig) {\n    this.name = config.name ?? `cached-${config.provider.name}`;\n    this.priority = config.priority ?? config.provider.priority;\n\n    this.config = {\n      name: this.name,\n      priority: this.priority,\n      debug: config.debug ?? false,\n      provider: config.provider,\n      ttl: config.ttl ?? DEFAULT_TTL,\n      staleWhileRevalidate: config.staleWhileRevalidate ?? DEFAULT_STALE_WHILE_REVALIDATE,\n      maxSize: config.maxSize ?? DEFAULT_MAX_SIZE,\n      storage: config.storage ?? 'memory',\n    };\n\n    this.provider = config.provider;\n    this.storageKey = `flag-cache-${this.name}`;\n\n    // Subscribe to underlying provider changes\n    if (this.provider.subscribe) {\n      this.provider.subscribe(this.handleProviderChange.bind(this));\n    }\n  }\n\n  // ==========================================================================\n  // Initialization\n  // ==========================================================================\n\n  /**\n   * Initialize the provider.\n   */\n  async initialize(): Promise<void> {\n    this.log('Initializing cached provider');\n\n    // Load from persistent storage if configured\n    if (this.config.storage !== 'memory') {\n      this.loadFromStorage();\n    }\n\n    // Initialize underlying provider\n    await this.provider.initialize();\n    this.ready = true;\n\n    // Pre-warm cache\n    try {\n      await this.getFlags();\n    } catch (error) {\n      this.log('Failed to pre-warm cache:', error);\n    }\n\n    this.log('Cached provider initialized');\n  }\n\n  // ==========================================================================\n  // Flag Operations\n  // ==========================================================================\n\n  /**\n   * Get all flags with caching.\n   */\n  async getFlags(): Promise<readonly FeatureFlag[]> {\n    const now = Date.now();\n\n    // Check cache\n    if (this.flagsCache) {\n      const { value, expiresAt, staleAt } = this.flagsCache;\n\n      // Fresh cache hit\n      if (now < expiresAt) {\n        this.cacheHits++;\n        this.log('Cache hit (fresh)');\n        return value;\n      }\n\n      // Stale-while-revalidate\n      if (now < staleAt) {\n        this.cacheHits++;\n        this.log('Cache hit (stale, revalidating in background)');\n        void this.revalidateInBackground('flags');\n        return value;\n      }\n    }\n\n    // Cache miss - fetch fresh data\n    this.cacheMisses++;\n    this.log('Cache miss');\n    return this.fetchAndCacheFlags(now);\n  }\n\n  /**\n   * Get a specific flag with caching.\n   */\n  async getFlag(key: string): Promise<FeatureFlag | null> {\n    const now = Date.now();\n\n    // Check individual flag cache\n    const cached = this.flagCache.get(key);\n    if (cached) {\n      const { value, expiresAt, staleAt } = cached;\n\n      if (now < expiresAt) {\n        this.cacheHits++;\n        return value;\n      }\n\n      if (now < staleAt) {\n        this.cacheHits++;\n        void this.revalidateInBackground('flag', key);\n        return value;\n      }\n    }\n\n    // Check flags cache\n    if (this.flagsCache && now < this.flagsCache.staleAt) {\n      const flag = this.flagsCache.value.find((f) => f.key === key) ?? null;\n      this.cacheFlag(key, flag, now);\n      this.cacheHits++;\n      return flag;\n    }\n\n    // Cache miss\n    this.cacheMisses++;\n    const flag = await this.provider.getFlag(key);\n    this.cacheFlag(key, flag, now);\n    return flag;\n  }\n\n  /**\n   * Get all segments with caching.\n   */\n  async getSegments(): Promise<readonly Segment[]> {\n    if (!this.provider.getSegments) {\n      return [];\n    }\n\n    const now = Date.now();\n\n    if (this.segmentsCache) {\n      const { value, expiresAt, staleAt } = this.segmentsCache;\n\n      if (now < expiresAt) {\n        this.cacheHits++;\n        return value;\n      }\n\n      if (now < staleAt) {\n        this.cacheHits++;\n        void this.revalidateInBackground('segments');\n        return value;\n      }\n    }\n\n    this.cacheMisses++;\n    const segments = await this.provider.getSegments();\n    const segmentArray = [...segments];\n\n    this.segmentsCache = {\n      value: segmentArray,\n      timestamp: now,\n      expiresAt: now + this.config.ttl,\n      staleAt: now + this.config.staleWhileRevalidate,\n    };\n\n    return segmentArray;\n  }\n\n  /**\n   * Get a segment by ID.\n   */\n  async getSegment(id: SegmentId): Promise<Segment | null> {\n    if (!this.provider.getSegment) {\n      return null;\n    }\n\n    // Check segments cache\n    if (this.segmentsCache && Date.now() < this.segmentsCache.staleAt) {\n      return this.segmentsCache.value.find((s) => s.id === id) ?? null;\n    }\n\n    return this.provider.getSegment(id);\n  }\n\n  /**\n   * Invalidate all cached data.\n   */\n  invalidate(): void {\n    this.flagsCache = null;\n    this.flagCache.clear();\n    this.segmentsCache = null;\n    this.log('Cache invalidated');\n  }\n\n  // ==========================================================================\n  // Segment Operations\n  // ==========================================================================\n\n  /**\n   * Invalidate a specific flag.\n   */\n  invalidateFlag(key: string): void {\n    this.flagCache.delete(key);\n    this.flagsCache = null; // Also invalidate the full list\n    this.log(`Cache invalidated for flag: ${key}`);\n  }\n\n  /**\n   * Force refresh the cache.\n   */\n  async refresh(): Promise<void> {\n    this.invalidate();\n    await this.getFlags();\n    this.log('Cache refreshed');\n  }\n\n  // ==========================================================================\n  // Background Revalidation\n  // ==========================================================================\n\n  /**\n   * Check if the provider is ready.\n   */\n  isReady(): boolean {\n    return this.ready && this.provider.isReady();\n  }\n\n  // ==========================================================================\n  // Storage Operations\n  // ==========================================================================\n\n  /**\n   * Check if the provider is healthy.\n   */\n  async isHealthy(): Promise<boolean> {\n    return this.provider.isHealthy();\n  }\n\n  /**\n   * Get cache statistics.\n   */\n  getCacheStats(): {\n    hits: number;\n    misses: number;\n    hitRate: number;\n    size: number;\n    flagsCached: boolean;\n    segmentsCached: boolean;\n  } {\n    const total = this.cacheHits + this.cacheMisses;\n    return {\n      hits: this.cacheHits,\n      misses: this.cacheMisses,\n      hitRate: total > 0 ? this.cacheHits / total : 0,\n      size: this.flagCache.size,\n      flagsCached: this.flagsCache !== null,\n      segmentsCached: this.segmentsCache !== null,\n    };\n  }\n\n  /**\n   * Get provider statistics.\n   */\n  getStats(): ProviderStats {\n    const cacheStats = this.getCacheStats();\n    return {\n      flagCount: this.flagsCache?.value.length ?? 0,\n      segmentCount: this.segmentsCache?.value.length ?? 0,\n      requestCount: this.cacheHits + this.cacheMisses,\n      errorCount: 0,\n      cacheHitRate: cacheStats.hitRate,\n      lastRefresh: this.flagsCache ? new Date(this.flagsCache.timestamp) : undefined,\n    };\n  }\n\n  // ==========================================================================\n  // Cache Management\n  // ==========================================================================\n\n  /**\n   * Subscribe to flag changes.\n   */\n  subscribe(listener: FlagChangeListener): () => void {\n    this.listeners.add(listener);\n    return () => {\n      this.listeners.delete(listener);\n    };\n  }\n\n  /**\n   * Shutdown the provider.\n   */\n  async shutdown(): Promise<void> {\n    await this.provider.shutdown();\n    this.ready = false;\n    this.listeners.clear();\n    this.log('Cached provider shutdown');\n  }\n\n  private async fetchAndCacheFlags(now: number): Promise<FeatureFlag[]> {\n    const flags = await this.provider.getFlags();\n    const flagArray = [...flags];\n\n    this.flagsCache = {\n      value: flagArray,\n      timestamp: now,\n      expiresAt: now + this.config.ttl,\n      staleAt: now + this.config.staleWhileRevalidate,\n    };\n\n    // Update individual flag cache\n    for (const flag of flagArray) {\n      this.cacheFlag(flag.key, flag, now);\n    }\n\n    // Persist to storage\n    if (this.config.storage !== 'memory') {\n      this.saveToStorage();\n    }\n\n    return flagArray;\n  }\n\n  // ==========================================================================\n  // Provider Change Handling\n  // ==========================================================================\n\n  private cacheFlag(key: string, flag: FeatureFlag | null, now: number): void {\n    // Enforce max size\n    if (this.flagCache.size >= this.config.maxSize) {\n      const oldest = this.findOldestEntry();\n      if (oldest != null && oldest !== '') {\n        this.flagCache.delete(oldest);\n      }\n    }\n\n    this.flagCache.set(key, {\n      value: flag,\n      timestamp: now,\n      expiresAt: now + this.config.ttl,\n      staleAt: now + this.config.staleWhileRevalidate,\n    });\n  }\n\n  // ==========================================================================\n  // Status and Health\n  // ==========================================================================\n\n  private findOldestEntry(): string | null {\n    let oldest: string | null = null;\n    let oldestTime = Infinity;\n\n    for (const [key, entry] of this.flagCache) {\n      if (entry.timestamp < oldestTime) {\n        oldestTime = entry.timestamp;\n        oldest = key;\n      }\n    }\n\n    return oldest;\n  }\n\n  private async revalidateInBackground(\n    type: 'flags' | 'segments' | 'flag',\n    key?: string\n  ): Promise<void> {\n    if (this.revalidating) {\n      return;\n    }\n\n    this.revalidating = true;\n    this.log(\n      `Background revalidation: ${type}${key !== null && key !== undefined ? ` (${key})` : ''}`\n    );\n\n    try {\n      const now = Date.now();\n\n      switch (type) {\n        case 'flags':\n          await this.fetchAndCacheFlags(now);\n          break;\n        case 'segments':\n          if (this.provider.getSegments) {\n            const segments = await this.provider.getSegments();\n            this.segmentsCache = {\n              value: [...segments],\n              timestamp: now,\n              expiresAt: now + this.config.ttl,\n              staleAt: now + this.config.staleWhileRevalidate,\n            };\n          }\n          break;\n        case 'flag':\n          if (key !== null && key !== undefined) {\n            const flag = await this.provider.getFlag(key);\n            this.cacheFlag(key, flag, now);\n          }\n          break;\n      }\n\n      this.log('Background revalidation complete');\n    } catch (error) {\n      this.log('Background revalidation failed:', error);\n    } finally {\n      this.revalidating = false;\n    }\n  }\n\n  private getStorage(): Storage | null {\n    if (typeof window === 'undefined') {\n      return null;\n    }\n\n    switch (this.config.storage) {\n      case 'localStorage':\n        return window.localStorage;\n      case 'sessionStorage':\n        return window.sessionStorage;\n      default:\n        return null;\n    }\n  }\n\n  private loadFromStorage(): void {\n    const storage = this.getStorage();\n    if (!storage) {\n      return;\n    }\n\n    try {\n      const data = storage.getItem(this.storageKey);\n      if (data !== null && data !== '') {\n        const parsed = JSON.parse(data) as Record<string, unknown>;\n        if (\n          parsed.flags !== null &&\n          parsed.flags !== undefined &&\n          typeof parsed.flags === 'object'\n        ) {\n          const flags = parsed.flags as Record<string, unknown>;\n          this.flagsCache = {\n            ...flags,\n            timestamp: new Date(flags.timestamp as string | number | Date).getTime(),\n            expiresAt: new Date(flags.expiresAt as string | number | Date).getTime(),\n            staleAt: new Date(flags.staleAt as string | number | Date).getTime(),\n          } as CacheEntry<FeatureFlag[]>;\n        }\n        this.log('Loaded cache from storage');\n      }\n    } catch (error) {\n      this.log('Failed to load from storage:', error);\n    }\n  }\n\n  // ==========================================================================\n  // Subscription\n  // ==========================================================================\n\n  private saveToStorage(): void {\n    const storage = this.getStorage();\n    if (!storage) {\n      return;\n    }\n\n    try {\n      const data = {\n        flags: this.flagsCache,\n        segments: this.segmentsCache,\n      };\n      storage.setItem(this.storageKey, JSON.stringify(data));\n    } catch (error) {\n      this.log('Failed to save to storage:', error);\n    }\n  }\n\n  private handleProviderChange(event: FlagChangeEvent): void {\n    // Invalidate affected cache entries\n    if (event.flagKey !== null && event.flagKey !== undefined) {\n      this.invalidateFlag(event.flagKey);\n    } else {\n      this.invalidate();\n    }\n\n    // Forward the event\n    this.emitChange(event);\n  }\n\n  // ==========================================================================\n  // Shutdown\n  // ==========================================================================\n\n  private emitChange(event: FlagChangeEvent): void {\n    for (const listener of this.listeners) {\n      try {\n        listener(event);\n      } catch (error) {\n        this.log('Error in change listener:', error);\n      }\n    }\n  }\n\n  // ==========================================================================\n  // Utilities\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(`[CachedProvider] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a cached provider instance.\n */\nexport function createCachedProvider(config: CachedProviderConfig): CachedProvider {\n  return new CachedProvider(config);\n}\n"],"names":["CachedProvider","config","error","now","value","expiresAt","staleAt","key","cached","flag","f","segmentArray","id","s","total","cacheStats","listener","flagArray","oldest","oldestTime","entry","type","segments","storage","data","parsed","flags","event","message","args","createCachedProvider"],"mappings":"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"}