{"version":3,"file":"useStream.mjs","sources":["../../../../src/lib/streaming/hooks/useStream.ts"],"sourcesContent":["/**\n * @file useStream Hook\n * @description Core hook for accessing streaming context and controlling streams.\n *\n * The useStream hook provides a comprehensive interface for interacting with\n * stream boundaries, including state monitoring, lifecycle control, and\n * progress tracking.\n *\n * @module streaming/hooks/useStream\n * @version 1.0.0\n * @author Harbor Framework Team\n *\n * @example\n * ```tsx\n * function StreamingContent() {\n *   const { state, isStreaming, start, pause, resume, abort } = useStream('content');\n *\n *   return (\n *     <div>\n *       <p>State: {state}</p>\n *       <button onClick={start} disabled={isStreaming}>Start</button>\n *       <button onClick={pause} disabled={!isStreaming}>Pause</button>\n *       <button onClick={resume}>Resume</button>\n *       <button onClick={() => abort('User cancelled')}>Cancel</button>\n *     </div>\n *   );\n * }\n * ```\n */\n\nimport { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\n\nimport { useOptionalStreamContext, useStreamContext } from '../StreamProvider';\n\nimport {\n  type StreamConfig,\n  type StreamError,\n  StreamEventType,\n  StreamState,\n  type UseStreamResult,\n} from '../types';\n\n// ============================================================================\n// Hook Options\n// ============================================================================\n\n/**\n * Options for the useStream hook.\n */\nexport interface UseStreamOptions {\n  /**\n   * Boundary ID to monitor/control.\n   * If not provided, creates an unregistered stream interface.\n   */\n  boundaryId?: string;\n\n  /**\n   * Stream configuration for auto-registration.\n   * If provided with boundaryId, the boundary will be automatically registered.\n   */\n  config?: StreamConfig;\n\n  /**\n   * Auto-start streaming when the hook mounts.\n   * @default false\n   */\n  autoStart?: boolean;\n\n  /**\n   * Callback when stream state changes.\n   */\n  onStateChange?: (state: StreamState) => void;\n\n  /**\n   * Callback when stream completes.\n   */\n  onComplete?: () => void;\n\n  /**\n   * Callback when stream errors.\n   */\n  onError?: (error: StreamError) => void;\n}\n\n// ============================================================================\n// Default Result for No Context\n// ============================================================================\n\nconst DEFAULT_RESULT: UseStreamResult = {\n  state: StreamState.Idle,\n  isStreaming: false,\n  isComplete: false,\n  hasError: false,\n  error: null,\n  progress: null,\n  start: () => {},\n  pause: () => {},\n  resume: () => {},\n  abort: () => {},\n  reset: () => {},\n};\n\n// ============================================================================\n// Main Hook Implementation\n// ============================================================================\n\n/**\n * Core hook for stream control and monitoring.\n *\n * @description\n * Provides a complete interface for interacting with a stream boundary,\n * including state observation, lifecycle control, and progress tracking.\n *\n * Features:\n * - Real-time state monitoring\n * - Lifecycle control (start, pause, resume, abort)\n * - Progress tracking (when determinable)\n * - Error handling\n * - Automatic cleanup on unmount\n *\n * @param boundaryIdOrOptions - Boundary ID string or options object\n * @returns Stream control interface\n *\n * @example\n * ```tsx\n * // Simple usage with just boundary ID\n * const stream = useStream('my-boundary');\n *\n * // Usage with options\n * const stream = useStream({\n *   boundaryId: 'my-boundary',\n *   config: { priority: StreamPriority.High },\n *   autoStart: true,\n *   onComplete: () => console.log('Done!'),\n * });\n *\n * // Control stream lifecycle\n * stream.start();\n * stream.pause();\n * stream.resume();\n * stream.abort('User cancelled');\n * stream.reset();\n * ```\n */\nexport function useStream(boundaryIdOrOptions?: string | UseStreamOptions): UseStreamResult {\n  // Normalize arguments\n  const options: UseStreamOptions = useMemo(() => {\n    if (typeof boundaryIdOrOptions === 'string') {\n      return { boundaryId: boundaryIdOrOptions };\n    }\n    return boundaryIdOrOptions ?? {};\n  }, [boundaryIdOrOptions]);\n\n  const { boundaryId, config, autoStart = false, onStateChange, onComplete, onError } = options;\n\n  // Get streaming context (optional to support usage outside provider)\n  const context = useOptionalStreamContext();\n\n  // State\n  const [state, setState] = useState<StreamState>(StreamState.Idle);\n  const [error, setError] = useState<StreamError | null>(null);\n  const [progress, setProgress] = useState<number | null>(null);\n\n  // Refs\n  const isRegistered = useRef(false);\n  const mountedRef = useRef(true);\n  const bytesTotal = useRef<number | null>(null);\n  const bytesReceived = useRef(0);\n\n  // ==========================================================================\n  // Registration & Cleanup\n  // ==========================================================================\n\n  useEffect(() => {\n    mountedRef.current = true;\n\n    // Skip if no context or no boundary ID\n    if (\n      context === null ||\n      context === undefined ||\n      boundaryId === undefined ||\n      boundaryId === null ||\n      boundaryId === ''\n    ) {\n      return;\n    }\n\n    // Register if config provided\n    if (config && !isRegistered.current) {\n      try {\n        context.registerBoundary(boundaryId, {\n          ...config,\n          onStreamStart: () => {\n            config.onStreamStart?.();\n          },\n          onStreamComplete: () => {\n            config.onStreamComplete?.();\n            onComplete?.();\n          },\n          onStreamError: (err) => {\n            config.onStreamError?.(err);\n            onError?.(err);\n          },\n        });\n        isRegistered.current = true;\n      } catch {\n        // Boundary might already exist\n        isRegistered.current = true;\n      }\n    }\n\n    // Subscribe to events\n    const unsubscribe = context.subscribe((event) => {\n      if (event.boundaryId !== boundaryId || !mountedRef.current) return;\n\n      switch (event.type) {\n        case StreamEventType.StateChange: {\n          const payload = event.payload as { from: StreamState; to: StreamState };\n          setState(payload.to);\n          onStateChange?.(payload.to);\n          break;\n        }\n        case StreamEventType.Error: {\n          const streamError = event.payload as StreamError;\n          setError(streamError);\n          onError?.(streamError);\n          break;\n        }\n        case StreamEventType.Complete: {\n          setState(StreamState.Completed);\n          setProgress(1);\n          onComplete?.();\n          break;\n        }\n        case StreamEventType.Chunk: {\n          // Update progress if we can determine it\n          const chunk = event.payload as { size: number };\n          bytesReceived.current += chunk.size;\n          if (bytesTotal.current !== null && bytesTotal.current > 0) {\n            setProgress(bytesReceived.current / bytesTotal.current);\n          }\n          break;\n        }\n      }\n    });\n\n    // Auto-start if configured\n    if (autoStart) {\n      context.startStream(boundaryId);\n    }\n\n    return () => {\n      mountedRef.current = false;\n      unsubscribe();\n    };\n  }, [boundaryId, config, context, autoStart, onStateChange, onComplete, onError]);\n\n  // ==========================================================================\n  // Actions\n  // ==========================================================================\n\n  const start = useCallback(() => {\n    if (\n      context === null ||\n      context === undefined ||\n      boundaryId === undefined ||\n      boundaryId === null ||\n      boundaryId === ''\n    )\n      return;\n    context.startStream(boundaryId);\n  }, [context, boundaryId]);\n\n  const pause = useCallback(() => {\n    if (\n      context === null ||\n      context === undefined ||\n      boundaryId === undefined ||\n      boundaryId === null ||\n      boundaryId === ''\n    )\n      return;\n    context.pauseStream(boundaryId);\n  }, [context, boundaryId]);\n\n  const resume = useCallback(() => {\n    if (\n      context === null ||\n      context === undefined ||\n      boundaryId === undefined ||\n      boundaryId === null ||\n      boundaryId === ''\n    )\n      return;\n    context.resumeStream(boundaryId);\n  }, [context, boundaryId]);\n\n  const abort = useCallback(\n    (reason?: string) => {\n      if (\n        context === null ||\n        context === undefined ||\n        boundaryId === undefined ||\n        boundaryId === null ||\n        boundaryId === ''\n      )\n        return;\n      context.abortStream(boundaryId, reason);\n    },\n    [context, boundaryId]\n  );\n\n  const reset = useCallback(() => {\n    setState(StreamState.Idle);\n    setError(null);\n    setProgress(null);\n    bytesReceived.current = 0;\n  }, []);\n\n  // ==========================================================================\n  // Computed Values\n  // ==========================================================================\n\n  const isStreaming = state === StreamState.Streaming;\n  const isComplete = state === StreamState.Completed;\n  const hasError = state === StreamState.Error;\n\n  // Return memoized result to prevent unnecessary re-renders\n  // This is critical for performance - returning a new object every render\n  // would cause all consumers to re-render even when values haven't changed.\n  return useMemo<UseStreamResult>(() => {\n    // Return default result if no context\n    if (!context) {\n      return DEFAULT_RESULT;\n    }\n\n    return {\n      state,\n      isStreaming,\n      isComplete,\n      hasError,\n      error,\n      progress,\n      start,\n      pause,\n      resume,\n      abort,\n      reset,\n    };\n  }, [\n    context,\n    state,\n    isStreaming,\n    isComplete,\n    hasError,\n    error,\n    progress,\n    start,\n    pause,\n    resume,\n    abort,\n    reset,\n  ]);\n}\n\n// ============================================================================\n// Specialized Hooks\n// ============================================================================\n\n/**\n * Hook for monitoring multiple streams.\n *\n * @description\n * Provides aggregated state for multiple stream boundaries,\n * useful for tracking overall page streaming progress.\n *\n * @param boundaryIds - Array of boundary IDs to monitor\n * @returns Aggregated stream information\n *\n * @example\n * ```tsx\n * function PageLoader() {\n *   const { allComplete, progress, states } = useMultipleStreams([\n *     'header',\n *     'main',\n *     'sidebar',\n *     'footer',\n *   ]);\n *\n *   if (!allComplete) {\n *     return <ProgressBar value={progress} />;\n *   }\n *\n *   return <Page />;\n * }\n * ```\n */\nexport interface UseMultipleStreamsResult {\n  /** States for each boundary */\n  states: Map<string, StreamState>;\n  /** Whether all streams are complete */\n  allComplete: boolean;\n  /** Whether any stream has an error */\n  hasErrors: boolean;\n  /** Aggregate progress (0-1) */\n  progress: number;\n  /** Number of active streams */\n  activeCount: number;\n  /** Number of completed streams */\n  completedCount: number;\n  /** Start all streams */\n  startAll: () => void;\n  /** Abort all streams */\n  abortAll: (reason?: string) => void;\n}\n\nexport function useMultipleStreams(boundaryIds: string[]): UseMultipleStreamsResult {\n  const context = useOptionalStreamContext();\n  const [states, setStates] = useState<Map<string, StreamState>>(new Map());\n\n  useLayoutEffect(() => {\n    if (!context) return;\n\n    // Initialize states\n    const initialStates = new Map<string, StreamState>();\n    for (const id of boundaryIds) {\n      const state = context.getBoundaryState(id);\n      initialStates.set(id, state ?? StreamState.Idle);\n    }\n    // eslint-disable-next-line react-hooks/set-state-in-effect\n    setStates(initialStates);\n\n    // Subscribe to updates\n\n    return context.subscribe((event) => {\n      if (!boundaryIds.includes(event.boundaryId)) return;\n\n      if (event.type === StreamEventType.StateChange) {\n        const payload = event.payload as { to: StreamState };\n        setStates((prev) => {\n          const next = new Map(prev);\n          next.set(event.boundaryId, payload.to);\n          return next;\n        });\n      }\n    });\n  }, [context, boundaryIds]);\n\n  const allComplete = useMemo(() => {\n    if (states.size === 0) return false;\n    return Array.from(states.values()).every((s) => s === StreamState.Completed);\n  }, [states]);\n\n  const hasErrors = useMemo(() => {\n    return Array.from(states.values()).some((s) => s === StreamState.Error);\n  }, [states]);\n\n  const activeCount = useMemo(() => {\n    return Array.from(states.values()).filter(\n      (s) => s === StreamState.Streaming || s === StreamState.Paused\n    ).length;\n  }, [states]);\n\n  const completedCount = useMemo(() => {\n    return Array.from(states.values()).filter((s) => s === StreamState.Completed).length;\n  }, [states]);\n\n  const progress = useMemo(() => {\n    if (boundaryIds.length === 0) return 0;\n    return completedCount / boundaryIds.length;\n  }, [boundaryIds.length, completedCount]);\n\n  const startAll = useCallback(() => {\n    if (!context) return;\n    for (const id of boundaryIds) {\n      context.startStream(id);\n    }\n  }, [context, boundaryIds]);\n\n  const abortAll = useCallback(\n    (reason?: string) => {\n      if (!context) return;\n      for (const id of boundaryIds) {\n        context.abortStream(id, reason);\n      }\n    },\n    [context, boundaryIds]\n  );\n\n  return {\n    states,\n    allComplete,\n    hasErrors,\n    progress,\n    activeCount,\n    completedCount,\n    startAll,\n    abortAll,\n  };\n}\n\n/**\n * Hook for awaiting stream completion.\n *\n * @description\n * Returns a promise that resolves when the stream completes\n * or rejects when the stream errors.\n *\n * @param boundaryId - Boundary ID to await\n * @returns Promise that resolves/rejects with stream result\n *\n * @example\n * ```tsx\n * function DataProcessor() {\n *   const awaitStream = useAwaitStream('data-stream');\n *\n *   const handleProcess = async () => {\n *     try {\n *       await awaitStream();\n *       console.log('Stream completed, processing data...');\n *     } catch (error) {\n *       console.error('Stream failed:', error);\n *     }\n *   };\n *\n *   return <button onClick={handleProcess}>Process Data</button>;\n * }\n * ```\n */\nexport function useAwaitStream(boundaryId: string): () => Promise<void> {\n  const context = useStreamContext();\n\n  return useCallback(async () => {\n    return new Promise<void>((resolve, reject) => {\n      // Check if already complete\n      const currentState = context.getBoundaryState(boundaryId);\n      if (currentState === StreamState.Completed) {\n        resolve();\n        return;\n      }\n      if (currentState === StreamState.Error) {\n        reject(new Error('Stream already in error state'));\n        return;\n      }\n\n      const unsubscribe = context.subscribe((event) => {\n        if (event.boundaryId !== boundaryId) return;\n\n        if (event.type === StreamEventType.Complete) {\n          unsubscribe();\n          resolve();\n        } else if (event.type === StreamEventType.Error) {\n          unsubscribe();\n          reject(event.payload instanceof Error ? event.payload : new Error(String(event.payload)));\n        } else if (event.type === StreamEventType.Abort) {\n          unsubscribe();\n          reject(new Error('Stream aborted'));\n        }\n      });\n    });\n  }, [context, boundaryId]);\n}\n"],"names":["DEFAULT_RESULT","StreamState","useStream","boundaryIdOrOptions","options","useMemo","boundaryId","config","autoStart","onStateChange","onComplete","onError","context","useOptionalStreamContext","state","setState","useState","error","setError","progress","setProgress","isRegistered","useRef","mountedRef","bytesTotal","bytesReceived","useEffect","err","unsubscribe","event","StreamEventType","payload","streamError","chunk","start","useCallback","pause","resume","abort","reason","reset","isStreaming","isComplete","hasError","useMultipleStreams","boundaryIds","states","setStates","useLayoutEffect","initialStates","id","prev","next","allComplete","s","hasErrors","activeCount","completedCount","startAll","abortAll","useAwaitStream","useStreamContext","resolve","reject","currentState"],"mappings":"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"}