{"version":3,"file":"remote-provider.mjs","sources":["../../../../src/lib/flags/providers/remote-provider.ts"],"sourcesContent":["/**\n * @fileoverview Remote flag provider for fetching flags from an API.\n *\n * Provides flag fetching from remote servers with:\n * - Configurable endpoints\n * - Authentication support\n * - Retry logic with exponential backoff\n * - Context-aware requests\n * - Response transformation\n *\n * @module flags/providers/remote-provider\n *\n * @example\n * ```typescript\n * const provider = new RemoteProvider({\n *   endpoint: 'https://api.example.com/flags',\n *   apiKey: 'your-api-key',\n *   retry: {\n *     maxAttempts: 3,\n *     baseDelay: 1000,\n *   },\n * });\n *\n * await provider.initialize();\n * const flags = await provider.getFlags();\n * ```\n */\n\nimport type { FeatureFlag, Segment, SegmentId, EvaluationContext } from '../advanced/types';\nimport type {\n  FlagProvider,\n  RemoteProviderConfig,\n  FlagChangeListener,\n  FlagChangeEvent,\n  ProviderHealth,\n  ProviderStats,\n  RetryConfig,\n} from './types';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_TIMEOUT = 10000; // 10 seconds\nconst DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n  maxAttempts: 3,\n  baseDelay: 1000,\n  maxDelay: 30000,\n  backoffMultiplier: 2,\n  retryStatusCodes: [408, 429, 500, 502, 503, 504],\n};\n\n// ============================================================================\n// Remote Provider\n// ============================================================================\n\n/**\n * Remote flag provider that fetches flags from an API endpoint.\n */\nexport class RemoteProvider implements FlagProvider {\n  readonly name: string;\n  readonly priority: number;\n\n  private flags = new Map<string, FeatureFlag>();\n  private segments = new Map<SegmentId, Segment>();\n  private listeners = new Set<FlagChangeListener>();\n  private ready = false;\n  private readonly config: Required<Omit<RemoteProviderConfig, 'transform' | 'context'>> & {\n    transform?: RemoteProviderConfig['transform'];\n    context?: RemoteProviderConfig['context'];\n  };\n  private health: ProviderHealth = {\n    healthy: false,\n    consecutiveFailures: 0,\n  };\n  private stats: ProviderStats = {\n    flagCount: 0,\n    segmentCount: 0,\n    requestCount: 0,\n    errorCount: 0,\n  };\n  private abortController: AbortController | null = null;\n\n  constructor(config: RemoteProviderConfig) {\n    this.name = config.name ?? 'remote';\n    this.priority = config.priority ?? 50;\n\n    this.config = {\n      name: this.name,\n      priority: this.priority,\n      debug: config.debug ?? false,\n      endpoint: config.endpoint,\n      apiKey: config.apiKey ?? '',\n      timeout: config.timeout ?? DEFAULT_TIMEOUT,\n      headers: config.headers ?? {},\n      retry: { ...DEFAULT_RETRY_CONFIG, ...config.retry },\n      transform: config.transform,\n      context: config.context,\n    };\n  }\n\n  // ==========================================================================\n  // Initialization\n  // ==========================================================================\n\n  /**\n   * Initialize the provider by fetching initial flags.\n   */\n  async initialize(): Promise<void> {\n    this.log('Initializing remote provider');\n\n    try {\n      await this.fetchFlags();\n      this.ready = true;\n      this.log(`Initialized with ${this.flags.size} flags`);\n    } catch (error) {\n      this.log('Failed to initialize:', error);\n      // Don't throw - allow graceful degradation\n      this.ready = true;\n    }\n  }\n\n  // ==========================================================================\n  // Flag Operations\n  // ==========================================================================\n\n  /**\n   * Get all flags.\n   */\n  async getFlags(): Promise<readonly FeatureFlag[]> {\n    return Promise.resolve(Array.from(this.flags.values()));\n  }\n\n  /**\n   * Get a flag by key.\n   */\n  async getFlag(key: string): Promise<FeatureFlag | null> {\n    // Try local cache first\n    const cached = this.flags.get(key);\n    if (cached) {\n      return cached;\n    }\n\n    // Optionally fetch single flag from API\n    try {\n      const flag = await this.fetchSingleFlag(key);\n      if (flag) {\n        this.flags.set(key, flag);\n        this.updateStats();\n      }\n      return flag;\n    } catch {\n      return null;\n    }\n  }\n\n  /**\n   * Refresh flags from the remote server.\n   */\n  async refresh(): Promise<void> {\n    const previousFlags = new Map(this.flags);\n    await this.fetchFlags();\n\n    // Detect changes\n    const changes: FlagChangeEvent[] = [];\n    for (const [key, flag] of this.flags) {\n      const previous = previousFlags.get(key);\n      if (!previous) {\n        changes.push({\n          type: 'added',\n          flagKey: key,\n          newFlag: flag,\n          timestamp: new Date(),\n          source: this.name,\n        });\n      } else if (JSON.stringify(previous) !== JSON.stringify(flag)) {\n        changes.push({\n          type: 'updated',\n          flagKey: key,\n          previousFlag: previous,\n          newFlag: flag,\n          timestamp: new Date(),\n          source: this.name,\n        });\n      }\n    }\n\n    for (const [key, previous] of previousFlags) {\n      if (!this.flags.has(key)) {\n        changes.push({\n          type: 'deleted',\n          flagKey: key,\n          previousFlag: previous,\n          timestamp: new Date(),\n          source: this.name,\n        });\n      }\n    }\n\n    // Emit changes\n    for (const event of changes) {\n      this.emitChange(event);\n    }\n\n    if (changes.length > 0) {\n      this.log(`Detected ${changes.length} flag changes`);\n    }\n  }\n\n  // ==========================================================================\n  // Segment Operations\n  // ==========================================================================\n\n  /**\n   * Get all segments.\n   */\n  async getSegments(): Promise<readonly Segment[]> {\n    return Promise.resolve(Array.from(this.segments.values()));\n  }\n\n  /**\n   * Get a segment by ID.\n   */\n  async getSegment(id: SegmentId): Promise<Segment | null> {\n    return Promise.resolve(this.segments.get(id) ?? null);\n  }\n\n  // ==========================================================================\n  // HTTP Operations\n  // ==========================================================================\n\n  /**\n   * Check if the provider is ready.\n   */\n  isReady(): boolean {\n    return this.ready;\n  }\n\n  /**\n   * Check if the provider is healthy.\n   */\n  async isHealthy(): Promise<boolean> {\n    return Promise.resolve(this.health.healthy);\n  }\n\n  /**\n   * Get provider health status.\n   */\n  getHealth(): ProviderHealth {\n    return { ...this.health };\n  }\n\n  /**\n   * Get provider statistics.\n   */\n  getStats(): ProviderStats {\n    return { ...this.stats };\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    this.abortController?.abort();\n    this.ready = false;\n    this.listeners.clear();\n    this.log('Provider shutdown');\n    return Promise.resolve();\n  }\n\n  /**\n   * Update the context for subsequent requests.\n   */\n  setContext(context: EvaluationContext): void {\n    this.config.context = context;\n  }\n\n  private async fetchFlags(): Promise<void> {\n    const url = this.buildUrl('/flags');\n    const data = await this.request<unknown>(url);\n\n    let flags: FeatureFlag[];\n    if (this.config.transform) {\n      flags = this.config.transform(data);\n    } else if (Array.isArray(data)) {\n      flags = data as FeatureFlag[];\n    } else if (data !== null && data !== undefined && typeof data === 'object' && 'flags' in data) {\n      const dataWithFlags = data as { flags: FeatureFlag[] };\n      ({ flags } = dataWithFlags);\n    } else {\n      throw new Error('Invalid response format');\n    }\n\n    this.flags.clear();\n    for (const flag of flags) {\n      this.flags.set(flag.key, this.deserializeFlag(flag));\n    }\n\n    // Also fetch segments if available\n    try {\n      await this.fetchSegments();\n    } catch {\n      // Segments are optional\n    }\n\n    this.updateStats();\n  }\n\n  private async fetchSingleFlag(key: string): Promise<FeatureFlag | null> {\n    try {\n      const url = this.buildUrl(`/flags/${encodeURIComponent(key)}`);\n      const data = await this.request<FeatureFlag>(url);\n      return this.deserializeFlag(data);\n    } catch {\n      return null;\n    }\n  }\n\n  // ==========================================================================\n  // Health Tracking\n  // ==========================================================================\n\n  private async fetchSegments(): Promise<void> {\n    const url = this.buildUrl('/segments');\n    const data = await this.request<Segment[] | { segments: Segment[] }>(url);\n\n    const segments = Array.isArray(data) ? data : data.segments;\n\n    this.segments.clear();\n    for (const segment of segments) {\n      this.segments.set(segment.id, this.deserializeSegment(segment));\n    }\n  }\n\n  private async request<T>(url: string, options?: RequestInit): Promise<T> {\n    const { retry } = this.config;\n    let lastError: Error | null = null;\n\n    for (let attempt = 0; attempt < (retry.maxAttempts ?? 3); attempt++) {\n      try {\n        this.abortController = new AbortController();\n        const timeoutId = setTimeout(() => this.abortController?.abort(), this.config.timeout);\n\n        const response = await fetch(url, {\n          ...options,\n          headers: this.buildHeaders(),\n          signal: this.abortController.signal,\n        });\n\n        clearTimeout(timeoutId);\n        this.stats = { ...this.stats, requestCount: this.stats.requestCount + 1 };\n\n        if (!response.ok) {\n          if (retry.retryStatusCodes?.includes(response.status) === true) {\n            throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n          }\n          throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n        }\n\n        const data: unknown = await response.json();\n        this.recordSuccess();\n        return data as T;\n      } catch (error) {\n        lastError = error instanceof Error ? error : new Error(String(error));\n        this.recordFailure(lastError.message);\n\n        if (attempt < (retry.maxAttempts ?? 3) - 1) {\n          const delay = Math.min(\n            (retry.baseDelay ?? 1000) * Math.pow(retry.backoffMultiplier ?? 2, attempt),\n            retry.maxDelay ?? 30000\n          );\n          this.log(`Retry ${attempt + 1}/${retry.maxAttempts} in ${delay}ms`);\n          await this.sleep(delay);\n        }\n      }\n    }\n\n    throw lastError ?? new Error('Request failed');\n  }\n\n  // ==========================================================================\n  // Status and Health\n  // ==========================================================================\n\n  private buildUrl(path: string): string {\n    const base = this.config.endpoint.replace(/\\/$/, '');\n    const contextParams = this.buildContextParams();\n    const url = new URL(`${base}${path}`);\n\n    for (const [key, value] of Object.entries(contextParams)) {\n      url.searchParams.set(key, value);\n    }\n\n    return url.toString();\n  }\n\n  private buildHeaders(): HeadersInit {\n    const headers: HeadersInit = {\n      'Content-Type': 'application/json',\n      Accept: 'application/json',\n      ...this.config.headers,\n    };\n\n    if (\n      this.config.apiKey !== null &&\n      this.config.apiKey !== undefined &&\n      this.config.apiKey !== ''\n    ) {\n      headers['Authorization'] = `Bearer ${this.config.apiKey}`;\n    }\n\n    return headers;\n  }\n\n  private buildContextParams(): Record<string, string> {\n    const params: Record<string, string> = {};\n    const ctx = this.config.context;\n\n    if (ctx?.user?.id !== null && ctx?.user?.id !== undefined && ctx.user.id !== '') {\n      params['userId'] = ctx.user.id;\n    }\n    if (ctx?.application?.environment !== null && ctx?.application?.environment !== undefined) {\n      params['environment'] = String(ctx.application.environment);\n    }\n    if (\n      ctx?.application?.version !== null &&\n      ctx?.application?.version !== undefined &&\n      ctx.application.version !== ''\n    ) {\n      params['version'] = ctx.application.version;\n    }\n\n    return params;\n  }\n\n  private deserializeFlag(flag: FeatureFlag): FeatureFlag {\n    return {\n      ...flag,\n      lifecycle: {\n        ...flag.lifecycle,\n        createdAt: new Date(flag.lifecycle.createdAt),\n        updatedAt: new Date(flag.lifecycle.updatedAt),\n        activatedAt: flag.lifecycle.activatedAt ? new Date(flag.lifecycle.activatedAt) : undefined,\n        deprecationDate: flag.lifecycle.deprecationDate\n          ? new Date(flag.lifecycle.deprecationDate)\n          : undefined,\n        removalDate: flag.lifecycle.removalDate ? new Date(flag.lifecycle.removalDate) : undefined,\n        reviewDate: flag.lifecycle.reviewDate ? new Date(flag.lifecycle.reviewDate) : undefined,\n      },\n    };\n  }\n\n  // ==========================================================================\n  // Subscription\n  // ==========================================================================\n\n  private deserializeSegment(segment: Segment): Segment {\n    return {\n      ...segment,\n      updatedAt: new Date(segment.updatedAt),\n    };\n  }\n\n  private recordSuccess(): void {\n    this.health = {\n      healthy: true,\n      lastSuccess: new Date(),\n      consecutiveFailures: 0,\n    };\n  }\n\n  // ==========================================================================\n  // Shutdown\n  // ==========================================================================\n\n  private recordFailure(message: string): void {\n    this.health = {\n      healthy: false,\n      lastError: new Date(),\n      lastErrorMessage: message,\n      consecutiveFailures: this.health.consecutiveFailures + 1,\n      lastSuccess: this.health.lastSuccess,\n    };\n    this.stats = { ...this.stats, errorCount: this.stats.errorCount + 1 };\n  }\n\n  // ==========================================================================\n  // Utilities\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  private updateStats(): void {\n    this.stats = {\n      ...this.stats,\n      flagCount: this.flags.size,\n      segmentCount: this.segments.size,\n      lastRefresh: new Date(),\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      // eslint-disable-next-line no-console\n      console.log(`[RemoteProvider] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a remote provider instance.\n */\nexport function createRemoteProvider(config: RemoteProviderConfig): RemoteProvider {\n  return new RemoteProvider(config);\n}\n"],"names":["DEFAULT_RETRY_CONFIG","RemoteProvider","config","error","key","cached","flag","previousFlags","changes","previous","event","id","listener","context","url","data","flags","segments","segment","options","retry","lastError","attempt","timeoutId","response","delay","path","base","contextParams","value","headers","params","ctx","message","ms","resolve","args","createRemoteProvider"],"mappings":"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"}