{"version":3,"file":"useStreamStatus.mjs","sources":["../../../../src/lib/streaming/hooks/useStreamStatus.ts"],"sourcesContent":["/**\n * @file useStreamStatus Hook\n * @description Hook for monitoring detailed stream status and progress.\n *\n * Provides comprehensive status information about a stream boundary\n * including state, timing, transfer statistics, and human-readable\n * status messages.\n *\n * @module streaming/hooks/useStreamStatus\n * @version 1.0.0\n * @author Harbor Framework Team\n *\n * @example\n * ```tsx\n * function StreamingIndicator({ boundaryId }: { boundaryId: string }) {\n *   const status = useStreamStatus(boundaryId);\n *\n *   return (\n *     <div>\n *       <p>Status: {status.statusMessage}</p>\n *       <p>Elapsed: {status.elapsedTime}ms</p>\n *       <p>Bytes: {status.bytesTransferred}</p>\n *       {status.estimatedTimeRemaining && (\n *         <p>ETA: {status.estimatedTimeRemaining}ms</p>\n *       )}\n *     </div>\n *   );\n * }\n * ```\n */\n\nimport { useState, useEffect, useRef, useMemo } from 'react';\n\nimport { useOptionalStreamContext } from '../StreamProvider';\n\nimport { type UseStreamStatusResult, StreamState, StreamEventType } from '../types';\n\n// ============================================================================\n// Status Messages\n// ============================================================================\n\n/**\n * Human-readable status messages for each stream state.\n */\nconst STATUS_MESSAGES: Record<StreamState, string> = {\n  [StreamState.Idle]: 'Waiting to start',\n  [StreamState.Pending]: 'Preparing to stream',\n  [StreamState.Streaming]: 'Streaming content',\n  [StreamState.Paused]: 'Stream paused',\n  [StreamState.Completed]: 'Stream complete',\n  [StreamState.Error]: 'Stream error',\n  [StreamState.Aborted]: 'Stream cancelled',\n};\n\n// ============================================================================\n// Default Result\n// ============================================================================\n\nconst DEFAULT_RESULT: UseStreamStatusResult = {\n  state: StreamState.Idle,\n  statusMessage: STATUS_MESSAGES[StreamState.Idle],\n  isRegistered: false,\n  elapsedTime: null,\n  estimatedTimeRemaining: null,\n  bytesTransferred: 0,\n  chunksReceived: 0,\n};\n\n// ============================================================================\n// Hook Options\n// ============================================================================\n\n/**\n * Options for the useStreamStatus hook.\n */\nexport interface UseStreamStatusOptions {\n  /**\n   * Update interval for elapsed time in milliseconds.\n   * @default 100\n   */\n  updateInterval?: number;\n\n  /**\n   * Whether to track elapsed time.\n   * @default true\n   */\n  trackElapsedTime?: boolean;\n\n  /**\n   * Custom status message generator.\n   */\n  formatStatusMessage?: (state: StreamState, details: StatusDetails) => string;\n}\n\n/**\n * Details provided to custom status message formatter.\n */\nexport interface StatusDetails {\n  elapsedTime: number | null;\n  bytesTransferred: number;\n  chunksReceived: number;\n  estimatedTimeRemaining: number | null;\n}\n\n// ============================================================================\n// Main Hook Implementation\n// ============================================================================\n\n/**\n * Hook for monitoring detailed stream status.\n *\n * @description\n * Provides comprehensive information about a stream's status,\n * including timing, transfer statistics, and human-readable messages.\n *\n * Features:\n * - Real-time state monitoring\n * - Elapsed time tracking\n * - Estimated time remaining calculation\n * - Transfer statistics (bytes, chunks)\n * - Customizable status messages\n *\n * @param boundaryId - Boundary ID to monitor\n * @param options - Optional configuration\n * @returns Detailed stream status\n *\n * @example\n * ```tsx\n * // Basic usage\n * const status = useStreamStatus('main-content');\n *\n * // With options\n * const status = useStreamStatus('main-content', {\n *   updateInterval: 50,\n *   formatStatusMessage: (state, details) => {\n *     if (state === StreamState.Streaming) {\n *       return `Loading: ${details.bytesTransferred} bytes`;\n *     }\n *     return STATUS_MESSAGES[state];\n *   },\n * });\n * ```\n */\nexport function useStreamStatus(\n  boundaryId: string,\n  options: UseStreamStatusOptions = {}\n): UseStreamStatusResult {\n  const { updateInterval = 100, trackElapsedTime = true, formatStatusMessage } = options;\n\n  const context = useOptionalStreamContext();\n\n  // State - Initialize based on current boundary state\n  const [state, setState] = useState<StreamState>(() => {\n    if (context !== null && context !== undefined) {\n      const currentState = context.getBoundaryState(boundaryId);\n      return currentState ?? StreamState.Idle;\n    }\n    return StreamState.Idle;\n  });\n  const [isRegistered, setIsRegistered] = useState(() => {\n    if (context !== null && context !== undefined) {\n      const currentState = context.getBoundaryState(boundaryId);\n      return currentState !== null;\n    }\n    return false;\n  });\n  const [bytesTransferred, setBytesTransferred] = useState(0);\n  const [chunksReceived, setChunksReceived] = useState(0);\n  const [elapsedTime, setElapsedTime] = useState<number | null>(null);\n  const [estimatedTimeRemaining, setEstimatedTimeRemaining] = useState<number | null>(null);\n\n  // Refs for timing\n  const startTimeRef = useRef<number | null>(null);\n  const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);\n  const previousBytesRef = useRef(0);\n  const previousTimeRef = useRef<number | null>(null);\n  const bytesPerSecondRef = useRef<number | null>(null);\n  const totalBytesRef = useRef<number | null>(null);\n\n  // ==========================================================================\n  // Subscription & State Updates\n  // ==========================================================================\n\n  useEffect(() => {\n    if (!context) return;\n\n    // Subscribe to events\n    const unsubscribe = context.subscribe((event) => {\n      if (event.boundaryId !== boundaryId) 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\n          // Track timing on state changes\n          if (payload.to === StreamState.Streaming && startTimeRef.current == null) {\n            startTimeRef.current = performance.now();\n          } else if (\n            payload.to === StreamState.Completed ||\n            payload.to === StreamState.Error ||\n            payload.to === StreamState.Aborted\n          ) {\n            // Stop timing\n            if (intervalRef.current) {\n              clearInterval(intervalRef.current);\n              intervalRef.current = null;\n            }\n          }\n          break;\n        }\n\n        case StreamEventType.Start: {\n          setIsRegistered(true);\n          startTimeRef.current = performance.now();\n          previousTimeRef.current = performance.now();\n          break;\n        }\n\n        case StreamEventType.Chunk: {\n          const chunk = event.payload as { size: number };\n          setChunksReceived((prev) => prev + 1);\n          setBytesTransferred((prev) => {\n            const newTotal = prev + chunk.size;\n\n            // Calculate bytes per second for ETA\n            const now = performance.now();\n            if (previousTimeRef.current != null) {\n              const timeDelta = now - previousTimeRef.current;\n              if (timeDelta > 100) {\n                // Only update rate every 100ms\n                const bytesDelta = newTotal - previousBytesRef.current;\n                bytesPerSecondRef.current = (bytesDelta / timeDelta) * 1000;\n                previousBytesRef.current = newTotal;\n                previousTimeRef.current = now;\n              }\n            }\n\n            return newTotal;\n          });\n          break;\n        }\n\n        case StreamEventType.Complete: {\n          // Final elapsed time\n          if (startTimeRef.current != null) {\n            setElapsedTime(performance.now() - startTimeRef.current);\n          }\n          setEstimatedTimeRemaining(0);\n          break;\n        }\n      }\n    });\n\n    return () => {\n      unsubscribe();\n      if (intervalRef.current) {\n        clearInterval(intervalRef.current);\n      }\n    };\n  }, [context, boundaryId]);\n\n  // ==========================================================================\n  // Elapsed Time Tracking\n  // ==========================================================================\n\n  useEffect(() => {\n    if (!trackElapsedTime) return;\n    if (state !== StreamState.Streaming) return;\n\n    intervalRef.current = setInterval(() => {\n      if (startTimeRef.current != null) {\n        const elapsed = performance.now() - startTimeRef.current;\n        setElapsedTime(elapsed);\n\n        // Calculate ETA if we have byte rate and total\n        if (\n          bytesPerSecondRef.current !== null &&\n          bytesPerSecondRef.current > 0 &&\n          totalBytesRef.current !== null\n        ) {\n          const remainingBytes = totalBytesRef.current - bytesTransferred;\n          const eta = (remainingBytes / bytesPerSecondRef.current) * 1000;\n          setEstimatedTimeRemaining(Math.max(0, eta));\n        }\n      }\n    }, updateInterval);\n\n    return () => {\n      if (intervalRef.current) {\n        clearInterval(intervalRef.current);\n        intervalRef.current = null;\n      }\n    };\n  }, [trackElapsedTime, state, updateInterval, bytesTransferred]);\n\n  // ==========================================================================\n  // Status Message\n  // ==========================================================================\n\n  const statusMessage = useMemo(() => {\n    const details: StatusDetails = {\n      elapsedTime,\n      bytesTransferred,\n      chunksReceived,\n      estimatedTimeRemaining,\n    };\n\n    if (formatStatusMessage) {\n      return formatStatusMessage(state, details);\n    }\n\n    return STATUS_MESSAGES[state];\n  }, [\n    state,\n    elapsedTime,\n    bytesTransferred,\n    chunksReceived,\n    estimatedTimeRemaining,\n    formatStatusMessage,\n  ]);\n\n  // ==========================================================================\n  // Return Result\n  // ==========================================================================\n\n  if (!context) {\n    return DEFAULT_RESULT;\n  }\n\n  return {\n    state,\n    statusMessage,\n    isRegistered,\n    elapsedTime,\n    estimatedTimeRemaining,\n    bytesTransferred,\n    chunksReceived,\n  };\n}\n\n// ============================================================================\n// Extended Status Hook\n// ============================================================================\n\n/**\n * Extended result with additional details.\n */\nexport interface UseExtendedStreamStatusResult extends UseStreamStatusResult {\n  /** Transfer rate in bytes per second */\n  bytesPerSecond: number | null;\n  /** Human-readable transfer rate */\n  transferRate: string;\n  /** Human-readable bytes transferred */\n  formattedBytes: string;\n  /** Human-readable elapsed time */\n  formattedElapsed: string;\n  /** Human-readable ETA */\n  formattedETA: string;\n  /** Whether stream is active (streaming or paused) */\n  isActive: boolean;\n  /** Whether stream has ended (completed, error, or aborted) */\n  hasEnded: boolean;\n}\n\n/**\n * Formats bytes to human-readable string.\n */\nfunction formatBytes(bytes: number): string {\n  if (bytes === 0) return '0 B';\n  const k = 1024;\n  const sizes = ['B', 'KB', 'MB', 'GB'];\n  const i = Math.floor(Math.log(bytes) / Math.log(k));\n  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;\n}\n\n/**\n * Formats milliseconds to human-readable duration.\n */\nfunction formatDuration(ms: number | null): string {\n  if (ms === null) return '--';\n  if (ms < 1000) return `${Math.round(ms)}ms`;\n  if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;\n  const minutes = Math.floor(ms / 60000);\n  const seconds = Math.round((ms % 60000) / 1000);\n  return `${minutes}m ${seconds}s`;\n}\n\n/**\n * Extended stream status hook with formatted values.\n *\n * @description\n * Provides all the information from useStreamStatus plus\n * human-readable formatted values for display.\n *\n * @example\n * ```tsx\n * function StreamDetails({ boundaryId }: { boundaryId: string }) {\n *   const status = useExtendedStreamStatus(boundaryId);\n *\n *   return (\n *     <div>\n *       <p>{status.statusMessage}</p>\n *       <p>Transferred: {status.formattedBytes}</p>\n *       <p>Rate: {status.transferRate}</p>\n *       <p>Elapsed: {status.formattedElapsed}</p>\n *       <p>ETA: {status.formattedETA}</p>\n *     </div>\n *   );\n * }\n * ```\n */\nexport function useExtendedStreamStatus(\n  boundaryId: string,\n  options: UseStreamStatusOptions = {}\n): UseExtendedStreamStatusResult {\n  const baseStatus = useStreamStatus(boundaryId, options);\n\n  // Track bytes per second locally\n  const [bytesPerSecond, setBytesPerSecond] = useState<number | null>(null);\n  const prevBytesRef = useRef(0);\n  const prevTimeRef = useRef<number | null>(null);\n\n  useEffect(() => {\n    if (baseStatus.state !== StreamState.Streaming) return;\n\n    const now = performance.now();\n    if (prevTimeRef.current !== null) {\n      const timeDelta = now - prevTimeRef.current;\n      if (timeDelta > 100) {\n        const bytesDelta = baseStatus.bytesTransferred - prevBytesRef.current;\n        setBytesPerSecond((bytesDelta / timeDelta) * 1000);\n        prevBytesRef.current = baseStatus.bytesTransferred;\n        prevTimeRef.current = now;\n      }\n    } else {\n      prevTimeRef.current = now;\n      prevBytesRef.current = baseStatus.bytesTransferred;\n    }\n  }, [baseStatus.bytesTransferred, baseStatus.state]);\n\n  const transferRate = useMemo(() => {\n    if (bytesPerSecond === null) return '--';\n    return `${formatBytes(bytesPerSecond)}/s`;\n  }, [bytesPerSecond]);\n\n  const formattedBytes = useMemo(\n    () => formatBytes(baseStatus.bytesTransferred),\n    [baseStatus.bytesTransferred]\n  );\n\n  const formattedElapsed = useMemo(\n    () => formatDuration(baseStatus.elapsedTime),\n    [baseStatus.elapsedTime]\n  );\n\n  const formattedETA = useMemo(\n    () => formatDuration(baseStatus.estimatedTimeRemaining),\n    [baseStatus.estimatedTimeRemaining]\n  );\n\n  const isActive =\n    baseStatus.state === StreamState.Streaming || baseStatus.state === StreamState.Paused;\n\n  const hasEnded =\n    baseStatus.state === StreamState.Completed ||\n    baseStatus.state === StreamState.Error ||\n    baseStatus.state === StreamState.Aborted;\n\n  return {\n    ...baseStatus,\n    bytesPerSecond,\n    transferRate,\n    formattedBytes,\n    formattedElapsed,\n    formattedETA,\n    isActive,\n    hasEnded,\n  };\n}\n"],"names":["STATUS_MESSAGES","StreamState","DEFAULT_RESULT","useStreamStatus","boundaryId","options","updateInterval","trackElapsedTime","formatStatusMessage","context","useOptionalStreamContext","state","setState","useState","isRegistered","setIsRegistered","bytesTransferred","setBytesTransferred","chunksReceived","setChunksReceived","elapsedTime","setElapsedTime","estimatedTimeRemaining","setEstimatedTimeRemaining","startTimeRef","useRef","intervalRef","previousBytesRef","previousTimeRef","bytesPerSecondRef","totalBytesRef","useEffect","unsubscribe","event","StreamEventType","payload","chunk","prev","newTotal","now","timeDelta","bytesDelta","elapsed","eta","statusMessage","useMemo","details","formatBytes","bytes","k","sizes","i","formatDuration","ms","minutes","seconds","useExtendedStreamStatus","baseStatus","bytesPerSecond","setBytesPerSecond","prevBytesRef","prevTimeRef","transferRate","formattedBytes","formattedElapsed","formattedETA","isActive","hasEnded"],"mappings":"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"}