{"version":3,"file":"websocket-provider.mjs","sources":["../../../../src/lib/flags/providers/websocket-provider.ts"],"sourcesContent":["/**\n * @fileoverview WebSocket provider for real-time flag updates.\n *\n * Provides real-time flag synchronization with:\n * - Automatic reconnection\n * - Heartbeat/ping-pong\n * - Message queuing during disconnection\n * - Authentication support\n *\n * @module flags/providers/websocket-provider\n *\n * @example\n * ```typescript\n * const provider = new WebSocketProvider({\n *   url: 'wss://api.example.com/flags/ws',\n *   authToken: 'your-token',\n *   reconnect: {\n *     enabled: true,\n *     maxAttempts: 10,\n *   },\n * });\n *\n * await provider.initialize();\n * provider.connect();\n * ```\n */\n\nimport type {\n  FeatureFlag,\n  Segment,\n  SegmentId,\n} from '../advanced/types';\nimport type {\n  FlagProvider,\n  WebSocketProviderConfig,\n  FlagChangeListener,\n  FlagChangeEvent,\n  ProviderStats,\n  ReconnectConfig,\n} from './types';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst DEFAULT_PING_INTERVAL = 30000; // 30 seconds\nconst DEFAULT_RECONNECT_CONFIG: Required<ReconnectConfig> = {\n  enabled: true,\n  maxAttempts: 10,\n  baseDelay: 1000,\n  maxDelay: 30000,\n  backoffMultiplier: 2,\n};\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * WebSocket message types.\n */\ntype WSMessageType =\n  | 'flags'\n  | 'flag_update'\n  | 'flag_delete'\n  | 'segments'\n  | 'segment_update'\n  | 'ping'\n  | 'pong'\n  | 'subscribe'\n  | 'unsubscribe'\n  | 'error';\n\n/**\n * WebSocket message structure.\n */\ninterface WSMessage {\n  type: WSMessageType;\n  payload?: unknown;\n  timestamp?: string;\n}\n\n/**\n * Connection state.\n */\ntype ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';\n\n// ============================================================================\n// WebSocket Provider\n// ============================================================================\n\n/**\n * WebSocket provider for real-time flag updates.\n */\nexport class WebSocketProvider implements FlagProvider {\n  readonly name: string;\n  readonly priority: number;\n\n  private socket: WebSocket | null = null;\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 config: Required<Omit<WebSocketProviderConfig, 'initialFlags' | 'authToken' | 'channel'>> & {\n    initialFlags?: WebSocketProviderConfig['initialFlags'];\n    authToken?: WebSocketProviderConfig['authToken'];\n    channel?: WebSocketProviderConfig['channel'];\n  };\n  private connectionState: ConnectionState = 'disconnected';\n  private reconnectAttempts = 0;\n  private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n  private pingTimer: ReturnType<typeof setInterval> | null = null;\n  private messageQueue: WSMessage[] = [];\n  private lastMessageTime: Date | null = null;\n\n  constructor(config: WebSocketProviderConfig) {\n    this.name = config.name ?? 'websocket';\n    this.priority = config.priority ?? 10; // High priority for real-time\n\n    this.config = {\n      name: this.name,\n      priority: this.priority,\n      debug: config.debug ?? false,\n      url: config.url,\n      initialFlags: config.initialFlags,\n      reconnect: { ...DEFAULT_RECONNECT_CONFIG, ...config.reconnect },\n      pingInterval: config.pingInterval ?? DEFAULT_PING_INTERVAL,\n      authToken: config.authToken,\n      channel: config.channel,\n    };\n\n    // Load initial flags\n    if (config.initialFlags) {\n      for (const flag of config.initialFlags) {\n        this.flags.set(flag.key, flag);\n      }\n    }\n  }\n\n  // ==========================================================================\n  // Initialization\n  // ==========================================================================\n\n  /**\n   * Initialize the provider.\n   */\n  async initialize(): Promise<void> {\n    this.log('Initializing WebSocket provider');\n    this.ready = true;\n    this.log('WebSocket provider initialized');\n    return Promise.resolve();\n  }\n\n  // ==========================================================================\n  // Connection Management\n  // ==========================================================================\n\n  /**\n   * Connect to the WebSocket server.\n   */\n  connect(): void {\n    if (this.connectionState === 'connected' || this.connectionState === 'connecting') {\n      return;\n    }\n\n    this.connectionState = 'connecting';\n    this.log('Connecting to WebSocket server');\n\n    try {\n      const url = new URL(this.config.url);\n\n      // Add auth token as query param if provided\n      if (this.config.authToken !== null && this.config.authToken !== undefined && this.config.authToken !== '') {\n        url.searchParams.set('token', this.config.authToken);\n      }\n\n      this.socket = new WebSocket(url.toString());\n      this.setupSocketHandlers();\n    } catch (error) {\n      this.log('Failed to create WebSocket:', error);\n      this.handleDisconnect();\n    }\n  }\n\n  /**\n   * Disconnect from the WebSocket server.\n   */\n  disconnect(): void {\n    this.stopPing();\n    this.stopReconnect();\n\n    if (this.socket) {\n      this.socket.close(1000, 'Client disconnect');\n      this.socket = null;\n    }\n\n    this.connectionState = 'disconnected';\n    this.log('Disconnected from WebSocket server');\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    return Promise.resolve(this.flags.get(key) ?? null);\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   * 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.connectionState === 'connected');\n  }\n\n  /**\n   * Get connection state.\n   */\n  getConnectionState(): ConnectionState {\n    return this.connectionState;\n  }\n\n  /**\n   * Get connection status.\n   */\n  getConnectionStatus(): {\n    state: ConnectionState;\n    reconnectAttempts: number;\n    lastMessageTime: Date | null;\n    queuedMessages: number;\n  } {\n    return {\n      state: this.connectionState,\n      reconnectAttempts: this.reconnectAttempts,\n      lastMessageTime: this.lastMessageTime,\n      queuedMessages: this.messageQueue.length,\n    };\n  }\n\n  // ==========================================================================\n  // Reconnection\n  // ==========================================================================\n\n  /**\n   * Get provider statistics.\n   */\n  getStats(): ProviderStats {\n    return {\n      flagCount: this.flags.size,\n      segmentCount: this.segments.size,\n      requestCount: 0,\n      errorCount: 0,\n      lastRefresh: this.lastMessageTime ?? undefined,\n    };\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  // Heartbeat\n  // ==========================================================================\n\n  /**\n   * Shutdown the provider.\n   */\n  async shutdown(): Promise<void> {\n    this.disconnect();\n    this.ready = false;\n    this.listeners.clear();\n    this.log('WebSocket provider shutdown');\n    return Promise.resolve();\n  }\n\n  private setupSocketHandlers(): void {\n    if (!this.socket) {\n      return;\n    }\n\n    this.socket.onopen = (): void => {\n      this.log('WebSocket connected');\n      this.connectionState = 'connected';\n      this.reconnectAttempts = 0;\n\n      // Start ping\n      this.startPing();\n\n      // Subscribe to channel if specified\n      if (this.config.channel !== null && this.config.channel !== undefined && this.config.channel !== '') {\n        this.send({\n          type: 'subscribe',\n          payload: { channel: this.config.channel },\n        });\n      }\n\n      // Request initial flags\n      this.send({ type: 'flags' });\n\n      // Flush message queue\n      this.flushMessageQueue();\n    };\n\n    this.socket.onmessage = (event) => {\n      this.handleMessage(event);\n    };\n\n    this.socket.onclose = (event) => {\n      this.log(`WebSocket closed: ${event.code} ${event.reason}`);\n      this.handleDisconnect();\n    };\n\n    this.socket.onerror = (error) => {\n      this.log('WebSocket error:', error);\n    };\n  }\n\n  // ==========================================================================\n  // Message Sending\n  // ==========================================================================\n\n  private handleMessage(event: MessageEvent): void {\n    try {\n      const message = JSON.parse(event.data as string) as WSMessage;\n      this.lastMessageTime = new Date();\n\n      this.log('Received message:', message.type);\n\n      switch (message.type) {\n        case 'flags':\n          this.handleFlagsMessage(message.payload as FeatureFlag[]);\n          break;\n        case 'flag_update':\n          this.handleFlagUpdate(message.payload as FeatureFlag);\n          break;\n        case 'flag_delete':\n          this.handleFlagDelete(message.payload as { key: string });\n          break;\n        case 'segments':\n          this.handleSegmentsMessage(message.payload as Segment[]);\n          break;\n        case 'segment_update':\n          this.handleSegmentUpdate(message.payload as Segment);\n          break;\n        case 'pong':\n          // Heartbeat response received\n          break;\n        case 'error':\n          this.log('Server error:', message.payload);\n          break;\n      }\n    } catch (error) {\n      this.log('Failed to parse message:', error);\n    }\n  }\n\n  private handleFlagsMessage(flags: FeatureFlag[]): void {\n    this.flags.clear();\n    for (const flag of flags) {\n      this.flags.set(flag.key, this.deserializeFlag(flag));\n    }\n\n    this.emitChange({\n      type: 'refreshed',\n      timestamp: new Date(),\n      source: this.name,\n    });\n\n    this.log(`Received ${flags.length} flags`);\n  }\n\n  // ==========================================================================\n  // Flag Operations\n  // ==========================================================================\n\n  private handleFlagUpdate(flag: FeatureFlag): void {\n    const existing = this.flags.get(flag.key);\n    const deserializedFlag = this.deserializeFlag(flag);\n    this.flags.set(flag.key, deserializedFlag);\n\n    this.emitChange({\n      type: existing ? 'updated' : 'added',\n      flagKey: flag.key,\n      previousFlag: existing,\n      newFlag: deserializedFlag,\n      timestamp: new Date(),\n      source: this.name,\n    });\n\n    this.log(`Flag ${existing ? 'updated' : 'added'}: ${flag.key}`);\n  }\n\n  private handleFlagDelete(payload: { key: string }): void {\n    const existing = this.flags.get(payload.key);\n    if (existing) {\n      this.flags.delete(payload.key);\n\n      this.emitChange({\n        type: 'deleted',\n        flagKey: payload.key,\n        previousFlag: existing,\n        timestamp: new Date(),\n        source: this.name,\n      });\n\n      this.log(`Flag deleted: ${payload.key}`);\n    }\n  }\n\n  // ==========================================================================\n  // Segment Operations\n  // ==========================================================================\n\n  private handleSegmentsMessage(segments: Segment[]): void {\n    this.segments.clear();\n    for (const segment of segments) {\n      this.segments.set(segment.id, this.deserializeSegment(segment));\n    }\n    this.log(`Received ${segments.length} segments`);\n  }\n\n  private handleSegmentUpdate(segment: Segment): void {\n    this.segments.set(segment.id, this.deserializeSegment(segment));\n    this.log(`Segment updated: ${segment.id}`);\n  }\n\n  // ==========================================================================\n  // Deserialization\n  // ==========================================================================\n\n  private handleDisconnect(): void {\n    this.stopPing();\n    this.connectionState = 'disconnected';\n\n    if (this.config.reconnect.enabled === true) {\n      this.scheduleReconnect();\n    }\n  }\n\n  private scheduleReconnect(): void {\n    const maxAttempts = this.config.reconnect?.maxAttempts ?? 5;\n    if (this.reconnectAttempts >= maxAttempts) {\n      this.log('Max reconnection attempts reached');\n      return;\n    }\n\n    this.connectionState = 'reconnecting';\n    this.reconnectAttempts++;\n\n    const baseDelay = this.config.reconnect?.baseDelay ?? 1000;\n    const backoffMultiplier = this.config.reconnect?.backoffMultiplier ?? 2;\n    const maxDelay = this.config.reconnect?.maxDelay ?? 30000;\n\n    const delay = Math.min(\n      baseDelay * Math.pow(backoffMultiplier, this.reconnectAttempts - 1),\n      maxDelay\n    );\n\n    this.log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\n\n    this.reconnectTimer = setTimeout(() => {\n      this.connect();\n    }, delay);\n  }\n\n  // ==========================================================================\n  // Status and Health\n  // ==========================================================================\n\n  private stopReconnect(): void {\n    if (this.reconnectTimer) {\n      clearTimeout(this.reconnectTimer);\n      this.reconnectTimer = null;\n    }\n    this.reconnectAttempts = 0;\n  }\n\n  private startPing(): void {\n    if (this.pingTimer) {\n      return;\n    }\n\n    this.pingTimer = setInterval(() => {\n      this.send({ type: 'ping' });\n    }, this.config.pingInterval);\n  }\n\n  private stopPing(): void {\n    if (this.pingTimer) {\n      clearInterval(this.pingTimer);\n      this.pingTimer = null;\n    }\n  }\n\n  private send(message: WSMessage): void {\n    if (this.socket?.readyState === WebSocket.OPEN) {\n      this.socket.send(JSON.stringify(message));\n    } else {\n      // Queue message for later\n      this.messageQueue.push(message);\n    }\n  }\n\n  private flushMessageQueue(): void {\n    while (this.messageQueue.length > 0) {\n      const message = this.messageQueue.shift();\n      if (message) {\n        this.send(message);\n      }\n    }\n  }\n\n  // ==========================================================================\n  // Subscription\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\n          ? new Date(flag.lifecycle.activatedAt)\n          : undefined,\n        deprecationDate: flag.lifecycle.deprecationDate\n          ? new Date(flag.lifecycle.deprecationDate)\n          : undefined,\n        removalDate: flag.lifecycle.removalDate\n          ? new Date(flag.lifecycle.removalDate)\n          : undefined,\n        reviewDate: flag.lifecycle.reviewDate\n          ? new Date(flag.lifecycle.reviewDate)\n          : undefined,\n      },\n    };\n  }\n\n  private deserializeSegment(segment: Segment): Segment {\n    return {\n      ...segment,\n      updatedAt: new Date(segment.updatedAt),\n    };\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(`[WebSocketProvider] ${message}`, ...args);\n    }\n  }\n}\n\n// ============================================================================\n// Factory Function\n// ============================================================================\n\n/**\n * Create a WebSocket provider instance.\n */\nexport function createWebSocketProvider(\n  config: WebSocketProviderConfig\n): WebSocketProvider {\n  return new WebSocketProvider(config);\n}\n"],"names":["DEFAULT_RECONNECT_CONFIG","WebSocketProvider","config","flag","url","error","key","id","listener","event","message","flags","existing","deserializedFlag","payload","segments","segment","maxAttempts","baseDelay","backoffMultiplier","maxDelay","delay","args","createWebSocketProvider"],"mappings":"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"}