vue-streaming 0.1.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +425 -699
  2. package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-C_F2vNNk.js +1081 -0
  3. package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-C_F2vNNk.js.map +1 -0
  4. package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-EzMJEQkx.cjs +2 -0
  5. package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-EzMJEQkx.cjs.map +1 -0
  6. package/dist/components/index.cjs +2 -0
  7. package/dist/components/index.cjs.map +1 -0
  8. package/dist/components/index.js +15 -0
  9. package/dist/components/index.js.map +1 -0
  10. package/dist/composables/index.cjs +2 -0
  11. package/dist/composables/index.cjs.map +1 -0
  12. package/dist/composables/index.js +15 -0
  13. package/dist/composables/index.js.map +1 -0
  14. package/dist/index.cjs +1 -3
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.js +62 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/types.cjs +2 -0
  19. package/dist/types.cjs.map +1 -0
  20. package/dist/types.js +2 -0
  21. package/dist/types.js.map +1 -0
  22. package/dist/usePointCloud-D0qcpYFY.js +115 -0
  23. package/dist/usePointCloud-D0qcpYFY.js.map +1 -0
  24. package/dist/usePointCloud-D2csBAs8.cjs +2 -0
  25. package/dist/usePointCloud-D2csBAs8.cjs.map +1 -0
  26. package/dist/useWebSocket-7-qar6to.cjs +4 -0
  27. package/dist/useWebSocket-7-qar6to.cjs.map +1 -0
  28. package/dist/useWebSocket-CrE6QkTW.js +1278 -0
  29. package/dist/useWebSocket-CrE6QkTW.js.map +1 -0
  30. package/dist/utils/index.cjs +2 -0
  31. package/dist/utils/index.cjs.map +1 -0
  32. package/dist/utils/index.js +503 -0
  33. package/dist/utils/index.js.map +1 -0
  34. package/dist/vue-streaming.css +1 -0
  35. package/package.json +126 -69
  36. package/dist/index.d.cts +0 -49
  37. package/dist/index.d.ts +0 -49
  38. package/dist/index.global.js +0 -8
  39. package/dist/index.global.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWebSocket-CrE6QkTW.js","sources":["../src/composables/useHLS.ts","../src/composables/useWebRTC.ts","../src/composables/useDataStream.ts","../src/composables/useHTTP.ts","../src/composables/useLaravelEcho.ts","../src/composables/useLongPolling.ts","../src/composables/useSocketIO.ts","../src/composables/useSSE.ts","../src/composables/useWebSocket.ts"],"sourcesContent":["/**\r\n * useHLS - Vue 3 HLS streaming composable with quality control\r\n * @module vue-streaming/composables/useHLS\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type { HLSCallbacks, HLSConfig, HLSLevel, HLSStats } from \"../types\";\r\n\r\n// HLS.js type\r\ninterface HLSInstance {\r\n loadSource: (url: string) => void;\r\n attachMedia: (element: HTMLVideoElement) => void;\r\n detachMedia: () => void;\r\n destroy: () => void;\r\n startLoad: (startPosition?: number) => void;\r\n stopLoad: () => void;\r\n recoverMediaError: () => void;\r\n levels: HLSLevel[];\r\n currentLevel: number;\r\n autoLevelEnabled: boolean;\r\n on: (event: string, callback: (...args: unknown[]) => void) => void;\r\n off: (event: string, callback: (...args: unknown[]) => void) => void;\r\n}\r\n\r\ninterface HLSStatic {\r\n isSupported: () => boolean;\r\n Events: Record<string, string>;\r\n ErrorTypes: Record<string, string>;\r\n new (config?: unknown): HLSInstance;\r\n}\r\n\r\nexport type HLSState =\r\n | \"idle\"\r\n | \"loading\"\r\n | \"loaded\"\r\n | \"playing\"\r\n | \"paused\"\r\n | \"buffering\"\r\n | \"seeking\"\r\n | \"ended\"\r\n | \"error\";\r\n\r\nexport interface UseHLSReturn {\r\n /** Stream state */\r\n state: Ref<HLSState>;\r\n /** Is playing */\r\n isPlaying: Ref<boolean>;\r\n /** Is buffering */\r\n isBuffering: Ref<boolean>;\r\n /** Available quality levels */\r\n levels: Ref<HLSLevel[]>;\r\n /** Current level index */\r\n currentLevel: Ref<number>;\r\n /** Auto level enabled */\r\n autoLevelEnabled: Ref<boolean>;\r\n /** Current time */\r\n currentTime: Ref<number>;\r\n /** Duration */\r\n duration: Ref<number>;\r\n /** Buffered percentage */\r\n buffered: Ref<number>;\r\n /** Volume */\r\n volume: Ref<number>;\r\n /** Muted */\r\n muted: Ref<boolean>;\r\n /** Stats */\r\n stats: Ref<HLSStats>;\r\n /** Error */\r\n error: Ref<Error | null>;\r\n /** HLS.js supported */\r\n isSupported: Ref<boolean>;\r\n /** Attach to video element */\r\n attach: (videoElement: HTMLVideoElement) => Promise<void>;\r\n /** Detach from video element */\r\n detach: () => void;\r\n /** Load source */\r\n load: (url?: string) => void;\r\n /** Play */\r\n play: () => Promise<void>;\r\n /** Pause */\r\n pause: () => void;\r\n /** Stop */\r\n stop: () => void;\r\n /** Seek to time */\r\n seek: (time: number) => void;\r\n /** Set quality level (-1 for auto) */\r\n setLevel: (level: number) => void;\r\n /** Set volume (0-1) */\r\n setVolume: (vol: number) => void;\r\n /** Toggle mute */\r\n toggleMute: () => void;\r\n /** Destroy HLS instance */\r\n destroy: () => void;\r\n}\r\n\r\nconst DEFAULT_CONFIG = {\r\n autoPlay: true,\r\n startLevel: -1,\r\n lowLatencyMode: false,\r\n maxBufferLength: 30,\r\n maxMaxBufferLength: 600,\r\n enableWorker: true,\r\n startPosition: -1,\r\n hlsConfig: {} as Record<string, unknown>,\r\n};\r\n\r\n/**\r\n * Vue 3 composable for HLS streaming with quality control\r\n *\r\n * @example\r\n * ```typescript\r\n * const videoRef = ref<HTMLVideoElement | null>(null)\r\n *\r\n * const {\r\n * state,\r\n * isPlaying,\r\n * levels,\r\n * currentLevel,\r\n * attach,\r\n * play,\r\n * pause,\r\n * setLevel\r\n * } = useHLS({\r\n * url: 'https://example.com/stream.m3u8',\r\n * autoPlay: true,\r\n * lowLatencyMode: true\r\n * }, {\r\n * onManifestLoaded: (levels) => console.log('Levels:', levels),\r\n * onLevelSwitched: (level) => console.log('Level:', level)\r\n * })\r\n *\r\n * onMounted(async () => {\r\n * if (videoRef.value) {\r\n * await attach(videoRef.value)\r\n * }\r\n * })\r\n * ```\r\n */\r\nexport function useHLS(\r\n config: HLSConfig,\r\n callbacks: HLSCallbacks = {},\r\n): UseHLSReturn {\r\n const cfg = { ...DEFAULT_CONFIG, ...config };\r\n\r\n // Reactive state\r\n const state = ref<HLSState>(\"idle\");\r\n const isPlaying = ref(false);\r\n const isBuffering = ref(false);\r\n const levels = ref<HLSLevel[]>([]);\r\n const currentLevel = ref(-1);\r\n const autoLevelEnabled = ref(true);\r\n const currentTime = ref(0);\r\n const duration = ref(0);\r\n const buffered = ref(0);\r\n const volume = ref(1);\r\n const muted = ref(false);\r\n const stats = ref<HLSStats>({\r\n bandwidth: 0,\r\n currentLevel: -1,\r\n bufferedDuration: 0,\r\n droppedFrames: 0,\r\n latency: 0,\r\n });\r\n const error = ref<Error | null>(null);\r\n const isSupported = ref(false);\r\n\r\n // Internal state\r\n let hls: HLSInstance | null = null;\r\n let Hls: HLSStatic | null = null;\r\n let videoElement: HTMLVideoElement | null = null;\r\n let timeUpdateInterval: ReturnType<typeof setInterval> | null = null;\r\n\r\n /**\r\n * Get HLS.js library\r\n */\r\n async function getHLS(): Promise<HLSStatic | null> {\r\n if (Hls) return Hls;\r\n\r\n try {\r\n const module = await import(\"hls.js\");\r\n Hls = module.default || module;\r\n isSupported.value = Hls.isSupported();\r\n return Hls;\r\n } catch {\r\n console.error(\"[useHLS] hls.js not installed. Run: npm install hls.js\");\r\n return null;\r\n }\r\n }\r\n\r\n /**\r\n * Update time info\r\n */\r\n function updateTimeInfo(): void {\r\n if (!videoElement) return;\r\n\r\n currentTime.value = videoElement.currentTime;\r\n duration.value = videoElement.duration || 0;\r\n\r\n // Calculate buffered percentage\r\n if (videoElement.buffered.length > 0) {\r\n const bufferedEnd = videoElement.buffered.end(\r\n videoElement.buffered.length - 1,\r\n );\r\n buffered.value =\r\n duration.value > 0 ? (bufferedEnd / duration.value) * 100 : 0;\r\n stats.value.bufferedDuration = bufferedEnd - videoElement.currentTime;\r\n }\r\n }\r\n\r\n /**\r\n * Setup video element events\r\n */\r\n function setupVideoEvents(video: HTMLVideoElement): void {\r\n video.onplay = () => {\r\n isPlaying.value = true;\r\n state.value = \"playing\";\r\n callbacks.onPlaybackStarted?.();\r\n };\r\n\r\n video.onpause = () => {\r\n isPlaying.value = false;\r\n state.value = \"paused\";\r\n };\r\n\r\n video.onended = () => {\r\n isPlaying.value = false;\r\n state.value = \"ended\";\r\n callbacks.onPlaybackEnded?.();\r\n };\r\n\r\n video.onwaiting = () => {\r\n isBuffering.value = true;\r\n state.value = \"buffering\";\r\n callbacks.onBuffering?.(true);\r\n };\r\n\r\n video.onplaying = () => {\r\n isBuffering.value = false;\r\n if (state.value === \"buffering\") {\r\n state.value = \"playing\";\r\n }\r\n callbacks.onBuffering?.(false);\r\n };\r\n\r\n video.onseeking = () => {\r\n state.value = \"seeking\";\r\n };\r\n\r\n video.onseeked = () => {\r\n state.value = isPlaying.value ? \"playing\" : \"paused\";\r\n };\r\n\r\n video.onvolumechange = () => {\r\n volume.value = video.volume;\r\n muted.value = video.muted;\r\n };\r\n\r\n video.onerror = () => {\r\n const err = new Error(video.error?.message || \"Video playback error\");\r\n error.value = err;\r\n state.value = \"error\";\r\n callbacks.onError?.(err, true);\r\n };\r\n\r\n // Start time update interval\r\n timeUpdateInterval = setInterval(updateTimeInfo, 250);\r\n }\r\n\r\n /**\r\n * Setup HLS events\r\n */\r\n function setupHLSEvents(): void {\r\n if (!hls || !Hls) return;\r\n\r\n hls.on(\r\n Hls.Events.MANIFEST_PARSED,\r\n (_event: string, data: { levels: HLSLevel[] }) => {\r\n levels.value = data.levels.map((level, index) => ({\r\n index,\r\n bitrate: level.bitrate,\r\n width: level.width,\r\n height: level.height,\r\n codec: level.codec,\r\n name: `${level.height}p`,\r\n }));\r\n state.value = \"loaded\";\r\n callbacks.onManifestLoaded?.(levels.value);\r\n },\r\n );\r\n\r\n hls.on(\r\n Hls.Events.LEVEL_SWITCHED,\r\n (_event: string, data: { level: number }) => {\r\n currentLevel.value = data.level;\r\n stats.value.currentLevel = data.level;\r\n callbacks.onLevelSwitched?.(data.level);\r\n },\r\n );\r\n\r\n hls.on(\r\n Hls.Events.FRAG_LOADED,\r\n (\r\n _event: string,\r\n data: {\r\n frag: { duration: number };\r\n stats: { loading: { end: number; start: number } };\r\n },\r\n ) => {\r\n stats.value.bandwidth =\r\n (data.frag.duration * 8 * 1000000) /\r\n (data.stats.loading.end - data.stats.loading.start);\r\n },\r\n );\r\n\r\n hls.on(\r\n Hls.Events.ERROR,\r\n (\r\n _event: string,\r\n data: { fatal: boolean; type: string; details: string },\r\n ) => {\r\n const err = new Error(`HLS Error: ${data.type} - ${data.details}`);\r\n error.value = err;\r\n\r\n if (data.fatal) {\r\n state.value = \"error\";\r\n\r\n // Try to recover from media errors\r\n if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {\r\n hls?.recoverMediaError();\r\n }\r\n }\r\n\r\n callbacks.onError?.(err, data.fatal);\r\n },\r\n );\r\n }\r\n\r\n /**\r\n * Attach HLS to video element\r\n */\r\n async function attach(video: HTMLVideoElement): Promise<void> {\r\n const HlsLib = await getHLS();\r\n\r\n if (!HlsLib) {\r\n throw new Error(\"HLS.js is not available\");\r\n }\r\n\r\n if (!HlsLib.isSupported()) {\r\n // Try native HLS support (Safari)\r\n if (video.canPlayType(\"application/vnd.apple.mpegurl\")) {\r\n video.src = cfg.url;\r\n videoElement = video;\r\n setupVideoEvents(video);\r\n state.value = \"loaded\";\r\n\r\n if (cfg.autoPlay) {\r\n await play();\r\n }\r\n return;\r\n }\r\n\r\n throw new Error(\"HLS is not supported in this browser\");\r\n }\r\n\r\n videoElement = video;\r\n state.value = \"loading\";\r\n\r\n hls = new HlsLib({\r\n startLevel: cfg.startLevel,\r\n lowLatencyMode: cfg.lowLatencyMode,\r\n maxBufferLength: cfg.maxBufferLength,\r\n enableWorker: cfg.enableWorker,\r\n startPosition: cfg.startPosition,\r\n });\r\n\r\n setupHLSEvents();\r\n setupVideoEvents(video);\r\n\r\n hls.loadSource(cfg.url);\r\n hls.attachMedia(video);\r\n\r\n if (cfg.autoPlay) {\r\n hls.on(HlsLib.Events.MANIFEST_PARSED, () => {\r\n play();\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Detach from video element\r\n */\r\n function detach(): void {\r\n if (hls) {\r\n hls.detachMedia();\r\n }\r\n\r\n if (timeUpdateInterval) {\r\n clearInterval(timeUpdateInterval);\r\n timeUpdateInterval = null;\r\n }\r\n\r\n videoElement = null;\r\n }\r\n\r\n /**\r\n * Load new source\r\n */\r\n function load(url?: string): void {\r\n const sourceUrl = url || cfg.url;\r\n\r\n if (hls) {\r\n hls.loadSource(sourceUrl);\r\n } else if (videoElement) {\r\n videoElement.src = sourceUrl;\r\n }\r\n\r\n state.value = \"loading\";\r\n }\r\n\r\n /**\r\n * Play video\r\n */\r\n async function play(): Promise<void> {\r\n if (!videoElement) {\r\n throw new Error(\"No video element attached\");\r\n }\r\n\r\n try {\r\n await videoElement.play();\r\n } catch (err) {\r\n // Handle autoplay restrictions\r\n if ((err as Error).name === \"NotAllowedError\") {\r\n muted.value = true;\r\n videoElement.muted = true;\r\n await videoElement.play();\r\n } else {\r\n throw err;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Pause video\r\n */\r\n function pause(): void {\r\n videoElement?.pause();\r\n }\r\n\r\n /**\r\n * Stop playback\r\n */\r\n function stop(): void {\r\n if (hls) {\r\n hls.stopLoad();\r\n }\r\n\r\n if (videoElement) {\r\n videoElement.pause();\r\n videoElement.currentTime = 0;\r\n }\r\n\r\n isPlaying.value = false;\r\n state.value = \"idle\";\r\n }\r\n\r\n /**\r\n * Seek to time\r\n */\r\n function seek(time: number): void {\r\n if (videoElement) {\r\n videoElement.currentTime = time;\r\n }\r\n }\r\n\r\n /**\r\n * Set quality level (-1 for auto)\r\n */\r\n function setLevel(level: number): void {\r\n if (hls) {\r\n hls.currentLevel = level;\r\n autoLevelEnabled.value = level === -1;\r\n }\r\n }\r\n\r\n /**\r\n * Set volume (0-1)\r\n */\r\n function setVolume(vol: number): void {\r\n if (videoElement) {\r\n videoElement.volume = Math.max(0, Math.min(1, vol));\r\n }\r\n }\r\n\r\n /**\r\n * Toggle mute\r\n */\r\n function toggleMute(): void {\r\n if (videoElement) {\r\n videoElement.muted = !videoElement.muted;\r\n }\r\n }\r\n\r\n /**\r\n * Destroy HLS instance\r\n */\r\n function destroy(): void {\r\n if (timeUpdateInterval) {\r\n clearInterval(timeUpdateInterval);\r\n timeUpdateInterval = null;\r\n }\r\n\r\n if (hls) {\r\n hls.destroy();\r\n hls = null;\r\n }\r\n\r\n videoElement = null;\r\n state.value = \"idle\";\r\n levels.value = [];\r\n currentLevel.value = -1;\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n destroy();\r\n });\r\n\r\n return {\r\n state,\r\n isPlaying,\r\n isBuffering,\r\n levels,\r\n currentLevel,\r\n autoLevelEnabled,\r\n currentTime,\r\n duration,\r\n buffered,\r\n volume,\r\n muted,\r\n stats,\r\n error,\r\n isSupported,\r\n attach,\r\n detach,\r\n load,\r\n play,\r\n pause,\r\n stop,\r\n seek,\r\n setLevel,\r\n setVolume,\r\n toggleMute,\r\n destroy,\r\n };\r\n}\r\n","/**\r\n * useWebRTC - Vue 3 WebRTC composable with data channels\r\n * @module vue-streaming/composables/useWebRTC\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type {\r\n BoundingBox3D,\r\n DetectionFrame,\r\n Point3D,\r\n PointCloudFrame,\r\n WebRTCCallbacks,\r\n WebRTCConfig,\r\n} from \"../types\";\r\nimport {\r\n bboxesToDetectionFrame,\r\n normalizeBboxes,\r\n parseArrayBboxFormat,\r\n} from \"../utils/bbox\";\r\nimport {\r\n parsePointCloudBinary,\r\n parsePointCloudJSON,\r\n} from \"../utils/pointcloud\";\r\n\r\nexport interface UseWebRTCReturn {\r\n /** Is running */\r\n isRunning: Ref<boolean>;\r\n /** Connection state */\r\n connectionState: Ref<string>;\r\n /** Data channels */\r\n dataChannels: Ref<Map<string, RTCDataChannel>>;\r\n /** Last point cloud frame */\r\n lastPointCloudFrame: Ref<PointCloudFrame | null>;\r\n /** Last detection frame */\r\n lastDetectionFrame: Ref<DetectionFrame | null>;\r\n /** Last bounding boxes */\r\n lastBoundingBoxes: Ref<BoundingBox3D[]>;\r\n /** Error */\r\n error: Ref<Error | null>;\r\n /** Start connection */\r\n start: () => Promise<void>;\r\n /** Stop connection */\r\n stop: () => void;\r\n /** Send control message */\r\n sendControl: (stream: string, enabled: boolean) => void;\r\n /** Send data on channel */\r\n sendOnChannel: (channelLabel: string, data: string | ArrayBuffer) => boolean;\r\n /** Get peer connection */\r\n getPeerConnection: () => RTCPeerConnection | null;\r\n}\r\n\r\nconst DEFAULT_CONFIG: Required<\r\n Omit<\r\n WebRTCConfig,\r\n \"signalingUrl\" | \"iceServers\" | \"pointCloudFormat\" | \"maxReconnectDelay\"\r\n >\r\n> & { iceServers: RTCIceServer[] } = {\r\n iceServers: [{ urls: \"stun:stun.l.google.com:19302\" }],\r\n iceGatheringTimeout: 2000,\r\n enablePointCloud: true,\r\n enableDetections: true,\r\n autoReconnect: true,\r\n maxReconnectAttempts: 5,\r\n reconnectDelay: 3000,\r\n};\r\n\r\n/**\r\n * Wait for ICE gathering to complete\r\n */\r\nfunction waitForIceGatheringComplete(\r\n pc: RTCPeerConnection,\r\n timeout: number,\r\n): Promise<void> {\r\n return new Promise((resolve) => {\r\n if (pc.iceGatheringState === \"complete\") {\r\n resolve();\r\n return;\r\n }\r\n\r\n const timeoutId = setTimeout(() => {\r\n resolve();\r\n }, timeout);\r\n\r\n pc.onicegatheringstatechange = () => {\r\n if (pc.iceGatheringState === \"complete\") {\r\n clearTimeout(timeoutId);\r\n resolve();\r\n }\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * Vue 3 composable for WebRTC streaming with data channels\r\n *\r\n * @example\r\n * ```typescript\r\n * const {\r\n * isRunning,\r\n * connectionState,\r\n * lastPointCloudFrame,\r\n * lastBoundingBoxes,\r\n * start,\r\n * stop,\r\n * sendControl\r\n * } = useWebRTC({\r\n * signalingUrl: 'http://server:8009/webrtc/signaling',\r\n * enablePointCloud: true,\r\n * enableDetections: true\r\n * }, {\r\n * onPointCloudFrame: (frame) => console.log('Points:', frame.points.length),\r\n * onBoundingBoxData: (bboxes) => console.log('Boxes:', bboxes.length),\r\n * onConnectionState: (state) => console.log('State:', state)\r\n * })\r\n *\r\n * await start()\r\n * sendControl('pointcloud', true)\r\n * ```\r\n */\r\nexport function useWebRTC(\r\n config: WebRTCConfig,\r\n callbacks: WebRTCCallbacks = {},\r\n): UseWebRTCReturn {\r\n const cfg = { ...DEFAULT_CONFIG, ...config };\r\n\r\n // Reactive state\r\n const isRunning = ref(false);\r\n const connectionState = ref<string>(\"idle\");\r\n const dataChannels = ref<Map<string, RTCDataChannel>>(new Map());\r\n const lastPointCloudFrame = ref<PointCloudFrame | null>(null);\r\n const lastDetectionFrame = ref<DetectionFrame | null>(null);\r\n const lastBoundingBoxes = ref<BoundingBox3D[]>([]);\r\n const error = ref<Error | null>(null);\r\n\r\n // Internal state\r\n let pc: RTCPeerConnection | null = null;\r\n let controlChannel: RTCDataChannel | null = null;\r\n let pointcloudChannel: RTCDataChannel | null = null;\r\n let bboxChannel: RTCDataChannel | null = null;\r\n let reconnectAttempts = 0;\r\n let reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\r\n\r\n /**\r\n * Send control message\r\n */\r\n function sendControl(stream: string, enabled: boolean): void {\r\n if (!controlChannel || controlChannel.readyState !== \"open\") return;\r\n\r\n const payload = { type: \"control\", stream, enabled };\r\n controlChannel.send(JSON.stringify(payload));\r\n }\r\n\r\n /**\r\n * Send data on specific channel\r\n */\r\n function sendOnChannel(\r\n channelLabel: string,\r\n data: string | ArrayBuffer,\r\n ): boolean {\r\n const channel = dataChannels.value.get(channelLabel);\r\n if (!channel || channel.readyState !== \"open\") {\r\n console.warn(`[useWebRTC] Channel ${channelLabel} not available`);\r\n return false;\r\n }\r\n\r\n try {\r\n channel.send(data);\r\n return true;\r\n } catch (err) {\r\n console.error(`[useWebRTC] Send error on ${channelLabel}:`, err);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Handle incoming data channel\r\n */\r\n function handleDataChannel(channel: RTCDataChannel): void {\r\n dataChannels.value.set(channel.label, channel);\r\n callbacks.onDataChannel?.(channel);\r\n\r\n switch (channel.label) {\r\n case \"pointcloud\":\r\n setupPointCloudChannel(channel);\r\n break;\r\n\r\n case \"pointcloud_b\":\r\n case \"bbox\":\r\n case \"bounding_boxes\":\r\n case \"detections\":\r\n setupBboxChannel(channel);\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Setup point cloud data channel\r\n */\r\n function setupPointCloudChannel(channel: RTCDataChannel): void {\r\n pointcloudChannel = channel;\r\n pointcloudChannel.binaryType = \"arraybuffer\";\r\n\r\n pointcloudChannel.onopen = () => {\r\n callbacks.onStatus?.(\"Pointcloud channel open\");\r\n if (cfg.enablePointCloud) {\r\n sendControl(\"pointcloud\", true);\r\n }\r\n };\r\n\r\n pointcloudChannel.onmessage = (evt: MessageEvent) => {\r\n try {\r\n let points: Point3D[] = [];\r\n\r\n if (evt.data instanceof ArrayBuffer && evt.data.byteLength > 0) {\r\n const buffer = evt.data as ArrayBuffer;\r\n\r\n // Emit raw data first\r\n callbacks.onPointCloudData?.(buffer);\r\n\r\n // Try to parse as JSON first\r\n try {\r\n const text = new TextDecoder().decode(buffer);\r\n if (text.startsWith(\"[\") || text.startsWith(\"{\")) {\r\n const jsonPoints = parsePointCloudJSON(text);\r\n if (jsonPoints && jsonPoints.length > 0) {\r\n points = jsonPoints;\r\n }\r\n }\r\n } catch {\r\n // Not valid text, continue with binary parsing\r\n }\r\n\r\n // If JSON didn't work, parse as binary\r\n if (points.length === 0) {\r\n points = parsePointCloudBinary(buffer);\r\n }\r\n } else if (typeof evt.data === \"string\") {\r\n const jsonPoints = parsePointCloudJSON(evt.data);\r\n if (jsonPoints) {\r\n points = jsonPoints;\r\n }\r\n }\r\n\r\n // Emit parsed frame\r\n if (points.length > 0) {\r\n const frame: PointCloudFrame = {\r\n points,\r\n timestamp: Date.now(),\r\n format: \"parsed\",\r\n };\r\n lastPointCloudFrame.value = frame;\r\n callbacks.onPointCloudFrame?.(frame);\r\n }\r\n } catch (e) {\r\n console.error(\"[useWebRTC] Error parsing pointcloud data:\", e);\r\n }\r\n };\r\n\r\n pointcloudChannel.onerror = (err: Event) => {\r\n console.error(\"[useWebRTC] Pointcloud channel error:\", err);\r\n callbacks.onStatus?.(\"Pointcloud channel error\");\r\n };\r\n\r\n pointcloudChannel.onclose = () => {\r\n callbacks.onStatus?.(\"Pointcloud channel closed\");\r\n };\r\n }\r\n\r\n /**\r\n * Setup bounding box data channel\r\n */\r\n function setupBboxChannel(channel: RTCDataChannel): void {\r\n bboxChannel = channel;\r\n bboxChannel.binaryType = \"arraybuffer\";\r\n\r\n bboxChannel.onopen = () => {\r\n callbacks.onStatus?.(\"BBox channel open\");\r\n if (cfg.enableDetections) {\r\n sendControl(\"bbox\", true);\r\n }\r\n };\r\n\r\n bboxChannel.onmessage = (evt: MessageEvent) => {\r\n try {\r\n let rawData: unknown;\r\n\r\n if (typeof evt.data === \"string\") {\r\n rawData = JSON.parse(evt.data);\r\n } else if (evt.data instanceof ArrayBuffer) {\r\n const text = new TextDecoder().decode(evt.data);\r\n try {\r\n rawData = JSON.parse(text);\r\n } catch {\r\n return;\r\n }\r\n } else {\r\n return;\r\n }\r\n\r\n if (Array.isArray(rawData)) {\r\n let bboxes: BoundingBox3D[];\r\n\r\n // Check if it's array of arrays format\r\n if (\r\n rawData.length > 0 &&\r\n Array.isArray(rawData[0]) &&\r\n typeof rawData[0][0] === \"number\"\r\n ) {\r\n bboxes = parseArrayBboxFormat(rawData as number[][]);\r\n } else {\r\n bboxes = normalizeBboxes(rawData);\r\n }\r\n\r\n if (bboxes.length > 0) {\r\n lastBoundingBoxes.value = bboxes;\r\n callbacks.onBoundingBoxData?.(bboxes);\r\n\r\n // Also emit as DetectionFrame\r\n const detectionFrame = bboxesToDetectionFrame(bboxes);\r\n lastDetectionFrame.value = detectionFrame;\r\n callbacks.onDetectionFrame?.(detectionFrame);\r\n }\r\n }\r\n } catch (e) {\r\n console.error(\"[useWebRTC] Error parsing bbox data:\", e);\r\n }\r\n };\r\n\r\n bboxChannel.onerror = (err: Event) => {\r\n console.error(\"[useWebRTC] BBox channel error:\", err);\r\n };\r\n\r\n bboxChannel.onclose = () => {\r\n callbacks.onStatus?.(\"BBox channel closed\");\r\n };\r\n }\r\n\r\n /**\r\n * Start WebRTC connection\r\n */\r\n async function start(): Promise<void> {\r\n if (isRunning.value) return;\r\n\r\n callbacks.onStatus?.(\"Creating WebRTC connection...\");\r\n connectionState.value = \"connecting\";\r\n error.value = null;\r\n\r\n try {\r\n // Cleanup previous connection\r\n if (pc) {\r\n pc.close();\r\n pc = null;\r\n }\r\n\r\n // Create new peer connection\r\n pc = new RTCPeerConnection({\r\n iceServers: cfg.iceServers,\r\n });\r\n\r\n // Connection state handling\r\n pc.onconnectionstatechange = () => {\r\n const state = pc?.connectionState ?? \"closed\";\r\n connectionState.value = state;\r\n callbacks.onConnectionState?.(state);\r\n\r\n if (state === \"failed\" || state === \"disconnected\") {\r\n const err = new Error(`Connection ${state}`);\r\n error.value = err;\r\n callbacks.onError?.(err);\r\n\r\n if (\r\n cfg.autoReconnect &&\r\n reconnectAttempts < cfg.maxReconnectAttempts\r\n ) {\r\n scheduleReconnect();\r\n }\r\n }\r\n\r\n if (state === \"connected\") {\r\n reconnectAttempts = 0;\r\n }\r\n };\r\n\r\n // Data channel handling\r\n pc.ondatachannel = (event: RTCDataChannelEvent) => {\r\n handleDataChannel(event.channel);\r\n };\r\n\r\n // Create control channel\r\n controlChannel = pc.createDataChannel(\"control\");\r\n controlChannel.onopen = () => {\r\n callbacks.onStatus?.(\"Control channel open\");\r\n dataChannels.value.set(\"control\", controlChannel!);\r\n };\r\n\r\n // Create SDP offer\r\n const offer = await pc.createOffer();\r\n await pc.setLocalDescription(offer);\r\n\r\n // Wait for ICE gathering\r\n await waitForIceGatheringComplete(pc, cfg.iceGatheringTimeout);\r\n\r\n const offerSDP = pc.localDescription?.sdp ?? \"\";\r\n if (!offerSDP) throw new Error(\"Empty SDP offer\");\r\n\r\n // Send offer to signaling server\r\n const response = await fetch(cfg.signalingUrl, {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({ offer: offerSDP }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`Signaling failed: HTTP ${response.status}`);\r\n }\r\n\r\n const data = await response.json();\r\n\r\n if (!data.answer) {\r\n throw new Error(\"No answer SDP in response\");\r\n }\r\n\r\n // Set remote description\r\n await pc.setRemoteDescription({ type: \"answer\", sdp: data.answer });\r\n\r\n isRunning.value = true;\r\n callbacks.onStatus?.(\"Connected, waiting for data...\");\r\n callbacks.onConnectionState?.(pc.connectionState);\r\n } catch (e) {\r\n const err = e instanceof Error ? e : new Error(String(e));\r\n error.value = err;\r\n connectionState.value = \"error\";\r\n callbacks.onStatus?.(`Error: ${err.message}`);\r\n callbacks.onError?.(err);\r\n stop();\r\n\r\n if (cfg.autoReconnect && reconnectAttempts < cfg.maxReconnectAttempts) {\r\n scheduleReconnect();\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Stop WebRTC connection\r\n */\r\n function stop(): void {\r\n isRunning.value = false;\r\n connectionState.value = \"closed\";\r\n callbacks.onStatus?.(\"Stopped\");\r\n callbacks.onConnectionState?.(\"closed\");\r\n\r\n // Cancel pending reconnect\r\n if (reconnectTimeout) {\r\n clearTimeout(reconnectTimeout);\r\n reconnectTimeout = null;\r\n }\r\n\r\n // Close channels\r\n dataChannels.value.forEach((channel) => channel.close());\r\n dataChannels.value.clear();\r\n\r\n controlChannel = null;\r\n pointcloudChannel = null;\r\n bboxChannel = null;\r\n\r\n // Close peer connection\r\n if (pc) {\r\n pc.close();\r\n pc = null;\r\n }\r\n }\r\n\r\n /**\r\n * Schedule reconnection attempt\r\n */\r\n function scheduleReconnect(): void {\r\n if (reconnectTimeout) return;\r\n\r\n reconnectAttempts++;\r\n callbacks.onStatus?.(\r\n `Reconnecting in ${cfg.reconnectDelay / 1000}s (attempt ${reconnectAttempts}/${cfg.maxReconnectAttempts})...`,\r\n );\r\n\r\n reconnectTimeout = setTimeout(() => {\r\n reconnectTimeout = null;\r\n start();\r\n }, cfg.reconnectDelay);\r\n }\r\n\r\n /**\r\n * Get peer connection instance\r\n */\r\n function getPeerConnection(): RTCPeerConnection | null {\r\n return pc;\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n stop();\r\n });\r\n\r\n return {\r\n isRunning,\r\n connectionState,\r\n dataChannels,\r\n lastPointCloudFrame,\r\n lastDetectionFrame,\r\n lastBoundingBoxes,\r\n error,\r\n start,\r\n stop,\r\n sendControl,\r\n sendOnChannel,\r\n getPeerConnection,\r\n };\r\n}\r\n","/**\r\n * useDataStream - Vue 3 Generic Data Stream composable\r\n * @module vue-streaming/composables/useDataStream\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type { DataStreamCallbacks, DataStreamConfig } from \"../types\";\r\n\r\nexport interface UseDataStreamReturn<T = unknown> {\r\n /** Latest data */\r\n data: Ref<T | null>;\r\n /** Data buffer/history */\r\n buffer: Ref<T[]>;\r\n /** Buffer size */\r\n bufferSize: Ref<number>;\r\n /** Is streaming */\r\n isStreaming: Ref<boolean>;\r\n /** Items per second */\r\n itemsPerSecond: Ref<number>;\r\n /** Total items received */\r\n totalItems: Ref<number>;\r\n /** Last error */\r\n error: Ref<Error | null>;\r\n /** Start streaming */\r\n start: () => void;\r\n /** Stop streaming */\r\n stop: () => void;\r\n /** Push data to stream */\r\n push: (data: unknown) => void;\r\n /** Clear buffer */\r\n clear: () => void;\r\n /** Get buffer as array */\r\n getBuffer: () => T[];\r\n /** Subscribe to data */\r\n subscribe: (callback: (data: T) => void) => () => void;\r\n}\r\n\r\nconst DEFAULT_CONFIG = {\r\n transform: (data: unknown) => data,\r\n filter: () => true,\r\n bufferSize: 100,\r\n throttleMs: 0,\r\n flushInterval: 0,\r\n deduplicate: false,\r\n dedupeKey: null as ((item: unknown) => string) | string | null,\r\n deduplicateKey: null as ((item: unknown) => string) | string | null,\r\n batchSize: 0,\r\n batchTimeoutMs: 0,\r\n};\r\n\r\n/**\r\n * Vue 3 composable for generic data streaming\r\n *\r\n * @example\r\n * ```typescript\r\n * interface SensorData {\r\n * id: string\r\n * value: number\r\n * timestamp: number\r\n * }\r\n *\r\n * const {\r\n * data,\r\n * buffer,\r\n * isStreaming,\r\n * itemsPerSecond,\r\n * start,\r\n * stop,\r\n * push,\r\n * subscribe\r\n * } = useDataStream<SensorData>({\r\n * bufferSize: 50,\r\n * deduplicate: true,\r\n * dedupeKey: (item) => item.id,\r\n * transform: (raw) => ({\r\n * id: raw.sensor_id,\r\n * value: parseFloat(raw.reading),\r\n * timestamp: Date.now()\r\n * })\r\n * }, {\r\n * onData: (data) => console.log('New data:', data),\r\n * onBatch: (batch) => console.log('Batch:', batch.length)\r\n * })\r\n *\r\n * start()\r\n *\r\n * // Push data from various sources\r\n * websocket.onmessage = (evt) => push(JSON.parse(evt.data))\r\n *\r\n * // Or subscribe for custom handling\r\n * const unsubscribe = subscribe((data) => {\r\n * updateChart(data)\r\n * })\r\n * ```\r\n */\r\nexport function useDataStream<T = unknown>(\r\n config: DataStreamConfig<T> = {},\r\n callbacks: DataStreamCallbacks<T> = {},\r\n): UseDataStreamReturn<T> {\r\n const cfg = { ...DEFAULT_CONFIG, ...config } as Required<DataStreamConfig<T>>;\r\n\r\n // Reactive state\r\n const data = ref<T | null>(null) as Ref<T | null>;\r\n const buffer = ref<T[]>([]) as Ref<T[]>;\r\n const bufferSize = ref(cfg.bufferSize);\r\n const isStreaming = ref(false);\r\n const itemsPerSecond = ref(0);\r\n const totalItems = ref(0);\r\n const error = ref<Error | null>(null);\r\n\r\n // Internal state\r\n const subscribers = new Set<(data: T) => void>();\r\n const seenKeys = new Set<string | number>();\r\n let itemsThisSecond = 0;\r\n let rateInterval: ReturnType<typeof setInterval> | null = null;\r\n let flushInterval: ReturnType<typeof setInterval> | null = null;\r\n let pendingBatch: T[] = [];\r\n\r\n /**\r\n * Calculate items per second\r\n */\r\n function startRateCalculation(): void {\r\n if (rateInterval) return;\r\n\r\n rateInterval = setInterval(() => {\r\n itemsPerSecond.value = itemsThisSecond;\r\n itemsThisSecond = 0;\r\n }, 1000);\r\n }\r\n\r\n /**\r\n * Stop rate calculation\r\n */\r\n function stopRateCalculation(): void {\r\n if (rateInterval) {\r\n clearInterval(rateInterval);\r\n rateInterval = null;\r\n }\r\n itemsPerSecond.value = 0;\r\n }\r\n\r\n /**\r\n * Start flush interval for batching\r\n */\r\n function startFlushInterval(): void {\r\n if (!cfg.flushInterval || cfg.flushInterval <= 0 || flushInterval) return;\r\n\r\n flushInterval = setInterval(() => {\r\n if (pendingBatch.length > 0) {\r\n callbacks.onBatch?.(pendingBatch);\r\n pendingBatch = [];\r\n }\r\n }, cfg.flushInterval);\r\n }\r\n\r\n /**\r\n * Stop flush interval\r\n */\r\n function stopFlushInterval(): void {\r\n if (flushInterval) {\r\n clearInterval(flushInterval);\r\n flushInterval = null;\r\n }\r\n\r\n // Flush remaining batch\r\n if (pendingBatch.length > 0) {\r\n callbacks.onBatch?.(pendingBatch);\r\n pendingBatch = [];\r\n }\r\n }\r\n\r\n /**\r\n * Start streaming\r\n */\r\n function start(): void {\r\n if (isStreaming.value) return;\r\n\r\n isStreaming.value = true;\r\n startRateCalculation();\r\n startFlushInterval();\r\n }\r\n\r\n /**\r\n * Stop streaming\r\n */\r\n function stop(): void {\r\n isStreaming.value = false;\r\n stopRateCalculation();\r\n stopFlushInterval();\r\n }\r\n\r\n /**\r\n * Push data to stream\r\n */\r\n function push(rawData: unknown): void {\r\n if (!isStreaming.value) return;\r\n\r\n try {\r\n // Transform data\r\n const transformed = cfg.transform(rawData) as T;\r\n\r\n // Deduplication check\r\n if (cfg.deduplicate) {\r\n const key = cfg.dedupeKey(transformed);\r\n if (key && seenKeys.has(key)) {\r\n return;\r\n }\r\n if (key) {\r\n seenKeys.add(key);\r\n\r\n // Limit seen keys size\r\n if (seenKeys.size > cfg.bufferSize * 2) {\r\n const keysArray = Array.from(seenKeys);\r\n keysArray\r\n .slice(0, cfg.bufferSize)\r\n .forEach((k) => seenKeys.delete(k));\r\n }\r\n }\r\n }\r\n\r\n // Update state\r\n data.value = transformed;\r\n totalItems.value++;\r\n itemsThisSecond++;\r\n\r\n // Add to buffer\r\n buffer.value = [...buffer.value, transformed].slice(-cfg.bufferSize);\r\n\r\n // Check buffer full\r\n if (buffer.value.length >= cfg.bufferSize) {\r\n callbacks.onBufferFull?.();\r\n }\r\n\r\n // Add to pending batch for flush interval\r\n if (cfg.flushInterval && cfg.flushInterval > 0) {\r\n pendingBatch.push(transformed);\r\n }\r\n\r\n // Notify callbacks and subscribers\r\n callbacks.onData?.(transformed);\r\n subscribers.forEach((cb) => cb(transformed));\r\n } catch (err) {\r\n const e = err instanceof Error ? err : new Error(String(err));\r\n error.value = e;\r\n callbacks.onError?.(e);\r\n }\r\n }\r\n\r\n /**\r\n * Clear buffer and state\r\n */\r\n function clear(): void {\r\n data.value = null;\r\n buffer.value = [];\r\n seenKeys.clear();\r\n totalItems.value = 0;\r\n pendingBatch = [];\r\n }\r\n\r\n /**\r\n * Get buffer as array\r\n */\r\n function getBuffer(): T[] {\r\n return [...buffer.value];\r\n }\r\n\r\n /**\r\n * Subscribe to data\r\n */\r\n function subscribe(callback: (data: T) => void): () => void {\r\n subscribers.add(callback);\r\n\r\n return () => {\r\n subscribers.delete(callback);\r\n };\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n stop();\r\n subscribers.clear();\r\n clear();\r\n });\r\n\r\n return {\r\n data,\r\n buffer,\r\n bufferSize,\r\n isStreaming,\r\n itemsPerSecond,\r\n totalItems,\r\n error,\r\n start,\r\n stop,\r\n push,\r\n clear,\r\n getBuffer,\r\n subscribe,\r\n };\r\n}\r\n","/**\r\n * useHTTP - Vue 3 HTTP Streaming composable using Fetch API\r\n * @module vue-streaming/composables/useHTTP\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type { ConnectionState } from \"../types\";\r\nimport { createReconnectManager } from \"../utils/reconnect\";\r\n\r\nexport interface HTTPStreamConfig {\r\n /** HTTP endpoint URL */\r\n url: string;\r\n /** HTTP method (default: GET) */\r\n method?: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\";\r\n /** Request headers */\r\n headers?: Record<string, string>;\r\n /** Request body (for POST/PUT/PATCH) */\r\n body?: unknown;\r\n /** Enable credentials (cookies) */\r\n credentials?: RequestCredentials;\r\n /** Auto-connect on creation */\r\n autoConnect?: boolean;\r\n /** Auto-reconnect on error */\r\n autoReconnect?: boolean;\r\n /** Max reconnection attempts */\r\n maxReconnectAttempts?: number;\r\n /** Reconnection delay (ms) */\r\n reconnectDelay?: number;\r\n /** Max reconnection delay (ms) */\r\n maxReconnectDelay?: number;\r\n /** Process each chunk as line-delimited JSON (NDJSON) */\r\n ndjson?: boolean;\r\n /** Custom chunk parser */\r\n parseChunk?: (chunk: string) => unknown;\r\n}\r\n\r\nexport interface HTTPStreamCallbacks {\r\n onOpen?: () => void;\r\n onChunk?: (data: unknown, rawChunk: string) => void;\r\n onComplete?: () => void;\r\n onError?: (error: Error) => void;\r\n onProgress?: (bytesReceived: number) => void;\r\n onReconnecting?: (attempt: number, maxAttempts: number) => void;\r\n onReconnected?: () => void;\r\n onReconnectFailed?: () => void;\r\n}\r\n\r\nexport interface UseHTTPStreamReturn {\r\n /** Connection state */\r\n isConnected: Ref<boolean>;\r\n /** Is currently streaming */\r\n isStreaming: Ref<boolean>;\r\n /** Connection state string */\r\n connectionState: Ref<ConnectionState>;\r\n /** Last received chunk */\r\n lastChunk: Ref<unknown>;\r\n /** All received chunks */\r\n chunks: Ref<unknown[]>;\r\n /** Total bytes received */\r\n bytesReceived: Ref<number>;\r\n /** Error state */\r\n error: Ref<Error | null>;\r\n /** Reconnect attempts */\r\n reconnectAttempts: Ref<number>;\r\n /** Start streaming */\r\n connect: () => Promise<void>;\r\n /** Stop streaming */\r\n disconnect: () => void;\r\n /** Clear received chunks */\r\n clearChunks: () => void;\r\n}\r\n\r\nconst DEFAULT_CONFIG: Required<\r\n Omit<HTTPStreamConfig, \"url\" | \"body\" | \"parseChunk\">\r\n> = {\r\n method: \"GET\",\r\n headers: {},\r\n credentials: \"same-origin\",\r\n autoConnect: true,\r\n autoReconnect: true,\r\n maxReconnectAttempts: 5,\r\n reconnectDelay: 1000,\r\n maxReconnectDelay: 30000,\r\n ndjson: true,\r\n};\r\n\r\n/**\r\n * Vue 3 composable for HTTP Streaming using Fetch API with ReadableStream\r\n *\r\n * @example\r\n * ```typescript\r\n * const {\r\n * isStreaming,\r\n * lastChunk,\r\n * chunks,\r\n * connect,\r\n * disconnect\r\n * } = useHTTPStream({\r\n * url: 'https://api.example.com/stream',\r\n * method: 'GET',\r\n * ndjson: true\r\n * }, {\r\n * onChunk: (data) => console.log('Received chunk:', data),\r\n * onComplete: () => console.log('Stream completed')\r\n * })\r\n *\r\n * // For POST requests with body\r\n * const { connect: postStream } = useHTTPStream({\r\n * url: 'https://api.example.com/ai/generate',\r\n * method: 'POST',\r\n * body: { prompt: 'Hello AI' },\r\n * headers: { 'Content-Type': 'application/json' }\r\n * })\r\n * ```\r\n */\r\nexport function useHTTPStream(\r\n config: HTTPStreamConfig,\r\n callbacks: HTTPStreamCallbacks = {},\r\n): UseHTTPStreamReturn {\r\n const cfg = { ...DEFAULT_CONFIG, ...config };\r\n\r\n // Reactive state\r\n const isConnected = ref(false);\r\n const isStreaming = ref(false);\r\n const connectionState = ref<ConnectionState>(\"disconnected\");\r\n const lastChunk = ref<unknown>(null);\r\n const chunks = ref<unknown[]>([]);\r\n const bytesReceived = ref(0);\r\n const error = ref<Error | null>(null);\r\n const reconnectAttempts = ref(0);\r\n\r\n // Internal state\r\n let abortController: AbortController | null = null;\r\n let isManualClose = false;\r\n\r\n // Reconnection manager\r\n const reconnectManager = createReconnectManager({\r\n maxAttempts: cfg.maxReconnectAttempts,\r\n delay: cfg.reconnectDelay,\r\n delayMax: cfg.maxReconnectDelay,\r\n onAttempt: (attempt: number, maxAttempts: number) => {\r\n reconnectAttempts.value = attempt;\r\n connectionState.value = \"reconnecting\";\r\n callbacks.onReconnecting?.(attempt, maxAttempts);\r\n },\r\n onSuccess: () => {\r\n reconnectAttempts.value = 0;\r\n callbacks.onReconnected?.();\r\n },\r\n onFailure: () => {\r\n connectionState.value = \"failed\";\r\n callbacks.onReconnectFailed?.();\r\n },\r\n });\r\n\r\n /**\r\n * Parse NDJSON line\r\n */\r\n function parseNDJSON(line: string): unknown | null {\r\n const trimmed = line.trim();\r\n if (!trimmed) return null;\r\n\r\n try {\r\n return JSON.parse(trimmed);\r\n } catch {\r\n return trimmed;\r\n }\r\n }\r\n\r\n /**\r\n * Process a chunk of data\r\n */\r\n function processChunk(chunk: string): void {\r\n if (!chunk) return;\r\n\r\n let parsed: unknown;\r\n\r\n if (cfg.parseChunk) {\r\n parsed = cfg.parseChunk(chunk);\r\n } else if (cfg.ndjson) {\r\n // Handle NDJSON - split by newlines and parse each\r\n const lines = chunk.split(\"\\n\");\r\n for (const line of lines) {\r\n const data = parseNDJSON(line);\r\n if (data !== null) {\r\n lastChunk.value = data;\r\n chunks.value.push(data);\r\n callbacks.onChunk?.(data, line);\r\n }\r\n }\r\n return;\r\n } else {\r\n parsed = chunk;\r\n }\r\n\r\n if (parsed !== null && parsed !== undefined) {\r\n lastChunk.value = parsed;\r\n chunks.value.push(parsed);\r\n callbacks.onChunk?.(parsed, chunk);\r\n }\r\n }\r\n\r\n /**\r\n * Start HTTP streaming\r\n */\r\n async function connect(): Promise<void> {\r\n if (isStreaming.value) {\r\n return;\r\n }\r\n\r\n isManualClose = false;\r\n connectionState.value = \"connecting\";\r\n error.value = null;\r\n abortController = new AbortController();\r\n\r\n try {\r\n const requestInit: RequestInit = {\r\n method: cfg.method,\r\n headers: {\r\n Accept:\r\n \"text/event-stream, application/x-ndjson, application/json, text/plain\",\r\n ...cfg.headers,\r\n },\r\n credentials: cfg.credentials,\r\n signal: abortController.signal,\r\n };\r\n\r\n if (cfg.body && [\"POST\", \"PUT\", \"PATCH\"].includes(cfg.method)) {\r\n requestInit.body =\r\n typeof cfg.body === \"string\" ? cfg.body : JSON.stringify(cfg.body);\r\n }\r\n\r\n const response = await fetch(cfg.url, requestInit);\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n if (!response.body) {\r\n throw new Error(\"Response body is not readable\");\r\n }\r\n\r\n isConnected.value = true;\r\n isStreaming.value = true;\r\n connectionState.value = \"connected\";\r\n callbacks.onOpen?.();\r\n\r\n const reader = response.body.getReader();\r\n const decoder = new TextDecoder();\r\n let buffer = \"\";\r\n\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n\r\n if (done) {\r\n // Process any remaining buffer\r\n if (buffer) {\r\n processChunk(buffer);\r\n }\r\n break;\r\n }\r\n\r\n const chunk = decoder.decode(value, { stream: true });\r\n bytesReceived.value += value.length;\r\n callbacks.onProgress?.(bytesReceived.value);\r\n\r\n // Buffer handling for partial lines\r\n buffer += chunk;\r\n\r\n // Process complete lines\r\n const lastNewlineIndex = buffer.lastIndexOf(\"\\n\");\r\n if (lastNewlineIndex !== -1) {\r\n const completeData = buffer.slice(0, lastNewlineIndex);\r\n buffer = buffer.slice(lastNewlineIndex + 1);\r\n processChunk(completeData);\r\n }\r\n }\r\n\r\n // Stream completed normally\r\n isStreaming.value = false;\r\n connectionState.value = \"disconnected\";\r\n callbacks.onComplete?.();\r\n } catch (err) {\r\n if ((err as Error).name === \"AbortError\") {\r\n // Manual abort, don't treat as error\r\n return;\r\n }\r\n\r\n error.value = err as Error;\r\n isConnected.value = false;\r\n isStreaming.value = false;\r\n connectionState.value = \"error\";\r\n callbacks.onError?.(err as Error);\r\n\r\n if (!isManualClose && cfg.autoReconnect) {\r\n reconnectManager.scheduleReconnect(async () => {\r\n try {\r\n await connect();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Stop HTTP streaming\r\n */\r\n function disconnect(): void {\r\n isManualClose = true;\r\n reconnectManager.cancel();\r\n\r\n if (abortController) {\r\n abortController.abort();\r\n abortController = null;\r\n }\r\n\r\n isConnected.value = false;\r\n isStreaming.value = false;\r\n connectionState.value = \"disconnected\";\r\n }\r\n\r\n /**\r\n * Clear received chunks\r\n */\r\n function clearChunks(): void {\r\n chunks.value = [];\r\n lastChunk.value = null;\r\n bytesReceived.value = 0;\r\n }\r\n\r\n // Auto-connect if configured\r\n if (cfg.autoConnect) {\r\n connect();\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n disconnect();\r\n });\r\n\r\n return {\r\n isConnected,\r\n isStreaming,\r\n connectionState,\r\n lastChunk,\r\n chunks,\r\n bytesReceived,\r\n error,\r\n reconnectAttempts,\r\n connect,\r\n disconnect,\r\n clearChunks,\r\n };\r\n}\r\n","/**\r\n * useLaravelEcho - Vue 3 Laravel Echo/Pusher composable\r\n * @module vue-streaming/composables/useLaravelEcho\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type {\r\n ConnectionState,\r\n EchoChannelInfo,\r\n EchoChannelType,\r\n EchoMember,\r\n LaravelEchoCallbacks,\r\n LaravelEchoConfig,\r\n} from \"../types\";\r\n\r\n// Echo/Pusher types\r\ninterface PusherChannel {\r\n bind: (event: string, callback: (data: unknown) => void) => PusherChannel;\r\n unbind: (event?: string, callback?: (data: unknown) => void) => PusherChannel;\r\n trigger: (event: string, data: unknown) => PusherChannel;\r\n}\r\n\r\ninterface PresenceChannel extends PusherChannel {\r\n here: (callback: (members: EchoMember[]) => void) => PresenceChannel;\r\n joining: (callback: (member: EchoMember) => void) => PresenceChannel;\r\n leaving: (callback: (member: EchoMember) => void) => PresenceChannel;\r\n}\r\n\r\ninterface EchoInstance {\r\n channel: (name: string) => PusherChannel;\r\n private: (name: string) => PusherChannel;\r\n join: (name: string) => PresenceChannel;\r\n leave: (name: string) => void;\r\n leaveChannel: (name: string) => void;\r\n disconnect: () => void;\r\n connector: {\r\n pusher: {\r\n connection: {\r\n socket_id?: string;\r\n state: string;\r\n bind: (event: string, callback: (...args: unknown[]) => void) => void;\r\n unbind: (\r\n event: string,\r\n callback?: (...args: unknown[]) => void,\r\n ) => void;\r\n };\r\n };\r\n };\r\n}\r\n\r\nexport interface UseEchoReturn {\r\n /** Connection state */\r\n isConnected: Ref<boolean>;\r\n /** Connection state string */\r\n connectionState: Ref<ConnectionState>;\r\n /** Socket ID */\r\n socketId: Ref<string | null>;\r\n /** Subscribed channels */\r\n channels: Ref<EchoChannelInfo[]>;\r\n /** Last error */\r\n error: Ref<Error | null>;\r\n /** Connect to server */\r\n connect: () => Promise<void>;\r\n /** Disconnect from server */\r\n disconnect: () => void;\r\n /** Subscribe to public channel */\r\n channel: (name: string) => ChannelWrapper;\r\n /** Subscribe to private channel */\r\n privateChannel: (name: string) => ChannelWrapper;\r\n /** Join presence channel */\r\n presenceChannel: (name: string) => PresenceChannelWrapper;\r\n /** Leave channel */\r\n leave: (name: string) => void;\r\n /** Leave all channels */\r\n leaveAll: () => void;\r\n}\r\n\r\nexport interface ChannelWrapper {\r\n /** Listen for event */\r\n listen: (event: string, callback: (data: unknown) => void) => ChannelWrapper;\r\n /** Stop listening for event */\r\n stopListening: (\r\n event: string,\r\n callback?: (data: unknown) => void,\r\n ) => ChannelWrapper;\r\n /** Listen for whisper event (client event) */\r\n listenForWhisper: (\r\n event: string,\r\n callback: (data: unknown) => void,\r\n ) => ChannelWrapper;\r\n /** Send whisper event (client event) */\r\n whisper: (event: string, data: unknown) => ChannelWrapper;\r\n}\r\n\r\nexport interface PresenceChannelWrapper extends ChannelWrapper {\r\n /** Get current members */\r\n here: (callback: (members: EchoMember[]) => void) => PresenceChannelWrapper;\r\n /** Listen for member joining */\r\n joining: (callback: (member: EchoMember) => void) => PresenceChannelWrapper;\r\n /** Listen for member leaving */\r\n leaving: (callback: (member: EchoMember) => void) => PresenceChannelWrapper;\r\n}\r\n\r\nconst DEFAULT_CONFIG = {\r\n broadcaster: \"pusher\" as const,\r\n wsPort: 6001,\r\n wssPort: 6001,\r\n forceTLS: false,\r\n disableStats: false,\r\n cluster: \"mt1\",\r\n authEndpoint: \"/broadcasting/auth\",\r\n authHeaders: {} as Record<string, string>,\r\n auth: { headers: {} as Record<string, string> },\r\n enabledTransports: [\"ws\", \"wss\"],\r\n options: {} as Record<string, unknown>,\r\n};\r\n\r\n/**\r\n * Vue 3 composable for Laravel Echo/Pusher\r\n *\r\n * @example\r\n * ```typescript\r\n * const {\r\n * isConnected,\r\n * socketId,\r\n * channels,\r\n * connect,\r\n * disconnect,\r\n * channel,\r\n * privateChannel,\r\n * presenceChannel\r\n * } = useLaravelEcho({\r\n * key: 'your-pusher-key',\r\n * wsHost: 'ws.example.com',\r\n * wsPort: 6001,\r\n * authEndpoint: 'https://api.example.com/broadcasting/auth'\r\n * }, {\r\n * onConnected: (socketId) => console.log('Connected:', socketId)\r\n * })\r\n *\r\n * await connect()\r\n *\r\n * // Public channel\r\n * channel('events').listen('NewEvent', (data) => {\r\n * console.log('Event:', data)\r\n * })\r\n *\r\n * // Private channel\r\n * privateChannel('user.123').listen('MessageReceived', (data) => {\r\n * console.log('Private message:', data)\r\n * })\r\n *\r\n * // Presence channel\r\n * presenceChannel('room.456')\r\n * .here((members) => console.log('Members:', members))\r\n * .joining((member) => console.log('Joined:', member))\r\n * .leaving((member) => console.log('Left:', member))\r\n * .listen('ChatMessage', (data) => console.log('Chat:', data))\r\n * ```\r\n */\r\nexport function useLaravelEcho(\r\n config: LaravelEchoConfig,\r\n callbacks: LaravelEchoCallbacks = {},\r\n): UseEchoReturn {\r\n const cfg = { ...DEFAULT_CONFIG, ...config };\r\n\r\n // Reactive state\r\n const isConnected = ref(false);\r\n const connectionState = ref<ConnectionState>(\"idle\");\r\n const socketId = ref<string | null>(null);\r\n const channels = ref<EchoChannelInfo[]>([]);\r\n const error = ref<Error | null>(null);\r\n\r\n // Internal state\r\n let echo: EchoInstance | null = null;\r\n\r\n /**\r\n * Get Echo instance\r\n */\r\n async function getEchoInstance(): Promise<EchoInstance> {\r\n if (echo) return echo;\r\n\r\n try {\r\n // Import Laravel Echo and Pusher\r\n const [{ default: Echo }, { default: Pusher }] = await Promise.all([\r\n import(\"laravel-echo\"),\r\n import(\"pusher-js\"),\r\n ]);\r\n\r\n // Make Pusher available globally (required by Echo)\r\n (window as unknown as Record<string, unknown>).Pusher = Pusher;\r\n\r\n echo = new Echo({\r\n broadcaster: \"pusher\",\r\n key: cfg.key,\r\n wsHost: cfg.wsHost,\r\n wsPort: cfg.wsPort,\r\n wssPort: cfg.wssPort,\r\n forceTLS: cfg.forceTLS,\r\n cluster: cfg.cluster,\r\n authEndpoint: cfg.authEndpoint,\r\n auth: {\r\n headers: cfg.authHeaders,\r\n },\r\n enabledTransports: cfg.enabledTransports,\r\n disableStats: true,\r\n }) as EchoInstance;\r\n\r\n return echo;\r\n } catch {\r\n throw new Error(\r\n \"laravel-echo and/or pusher-js not installed. Run: npm install laravel-echo pusher-js\",\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Add channel to tracking\r\n */\r\n function trackChannel(name: string, type: EchoChannelType): void {\r\n const exists = channels.value.find((c) => c.name === name);\r\n if (!exists) {\r\n channels.value = [\r\n ...channels.value,\r\n { name, type, subscribedAt: new Date() },\r\n ];\r\n callbacks.onSubscribed?.(name);\r\n }\r\n }\r\n\r\n /**\r\n * Remove channel from tracking\r\n */\r\n function untrackChannel(name: string): void {\r\n channels.value = channels.value.filter((c) => c.name !== name);\r\n }\r\n\r\n /**\r\n * Connect to Echo server\r\n */\r\n async function connect(): Promise<void> {\r\n connectionState.value = \"connecting\";\r\n error.value = null;\r\n\r\n try {\r\n const echoInstance = await getEchoInstance();\r\n\r\n // Listen for connection state changes\r\n const pusher = echoInstance.connector.pusher;\r\n\r\n pusher.connection.bind(\"connected\", () => {\r\n isConnected.value = true;\r\n connectionState.value = \"connected\";\r\n socketId.value = pusher.connection.socket_id || null;\r\n callbacks.onConnected?.(socketId.value || \"\");\r\n });\r\n\r\n pusher.connection.bind(\"disconnected\", () => {\r\n isConnected.value = false;\r\n connectionState.value = \"disconnected\";\r\n socketId.value = null;\r\n callbacks.onDisconnected?.();\r\n });\r\n\r\n pusher.connection.bind(\"error\", (err: Error) => {\r\n error.value = err;\r\n connectionState.value = \"error\";\r\n callbacks.onError?.(err);\r\n });\r\n\r\n // Check if already connected\r\n if (pusher.connection.state === \"connected\") {\r\n isConnected.value = true;\r\n connectionState.value = \"connected\";\r\n socketId.value = pusher.connection.socket_id || null;\r\n callbacks.onConnected?.(socketId.value || \"\");\r\n }\r\n } catch (err) {\r\n const e = err instanceof Error ? err : new Error(String(err));\r\n error.value = e;\r\n connectionState.value = \"error\";\r\n throw e;\r\n }\r\n }\r\n\r\n /**\r\n * Disconnect from server\r\n */\r\n function disconnect(): void {\r\n if (echo) {\r\n echo.disconnect();\r\n echo = null;\r\n }\r\n\r\n isConnected.value = false;\r\n connectionState.value = \"closed\";\r\n socketId.value = null;\r\n channels.value = [];\r\n }\r\n\r\n /**\r\n * Create channel wrapper\r\n */\r\n function createChannelWrapper(\r\n channel: PusherChannel,\r\n name: string,\r\n ): ChannelWrapper {\r\n return {\r\n listen(event: string, callback: (data: unknown) => void): ChannelWrapper {\r\n channel.bind(event.startsWith(\".\") ? event : `.${event}`, callback);\r\n return this;\r\n },\r\n stopListening(\r\n event: string,\r\n callback?: (data: unknown) => void,\r\n ): ChannelWrapper {\r\n channel.unbind(event.startsWith(\".\") ? event : `.${event}`, callback);\r\n return this;\r\n },\r\n listenForWhisper(\r\n event: string,\r\n callback: (data: unknown) => void,\r\n ): ChannelWrapper {\r\n channel.bind(`client-${event}`, callback);\r\n return this;\r\n },\r\n whisper(event: string, data: unknown): ChannelWrapper {\r\n channel.trigger(`client-${event}`, data);\r\n return this;\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Create presence channel wrapper\r\n */\r\n function createPresenceChannelWrapper(\r\n channel: PresenceChannel,\r\n name: string,\r\n ): PresenceChannelWrapper {\r\n const base = createChannelWrapper(channel, name);\r\n\r\n return {\r\n ...base,\r\n here(callback: (members: EchoMember[]) => void): PresenceChannelWrapper {\r\n channel.here(callback);\r\n return this;\r\n },\r\n joining(callback: (member: EchoMember) => void): PresenceChannelWrapper {\r\n channel.joining((member) => {\r\n callbacks.onMemberJoined?.(name, member);\r\n callback(member);\r\n });\r\n return this;\r\n },\r\n leaving(callback: (member: EchoMember) => void): PresenceChannelWrapper {\r\n channel.leaving((member) => {\r\n callbacks.onMemberLeft?.(name, member);\r\n callback(member);\r\n });\r\n return this;\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * Subscribe to public channel\r\n */\r\n function channel(name: string): ChannelWrapper {\r\n if (!echo) {\r\n throw new Error(\"Echo not connected. Call connect() first.\");\r\n }\r\n\r\n const ch = echo.channel(name);\r\n trackChannel(name, \"public\");\r\n return createChannelWrapper(ch, name);\r\n }\r\n\r\n /**\r\n * Subscribe to private channel\r\n */\r\n function privateChannel(name: string): ChannelWrapper {\r\n if (!echo) {\r\n throw new Error(\"Echo not connected. Call connect() first.\");\r\n }\r\n\r\n const ch = echo.private(name);\r\n trackChannel(`private-${name}`, \"private\");\r\n return createChannelWrapper(ch, name);\r\n }\r\n\r\n /**\r\n * Join presence channel\r\n */\r\n function presenceChannel(name: string): PresenceChannelWrapper {\r\n if (!echo) {\r\n throw new Error(\"Echo not connected. Call connect() first.\");\r\n }\r\n\r\n const ch = echo.join(name);\r\n trackChannel(`presence-${name}`, \"presence\");\r\n return createPresenceChannelWrapper(ch, name);\r\n }\r\n\r\n /**\r\n * Leave channel\r\n */\r\n function leave(name: string): void {\r\n if (echo) {\r\n echo.leaveChannel(name);\r\n untrackChannel(name);\r\n untrackChannel(`private-${name}`);\r\n untrackChannel(`presence-${name}`);\r\n }\r\n }\r\n\r\n /**\r\n * Leave all channels\r\n */\r\n function leaveAll(): void {\r\n const channelNames = [...channels.value.map((c) => c.name)];\r\n channelNames.forEach((name) => leave(name));\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n disconnect();\r\n });\r\n\r\n return {\r\n isConnected,\r\n connectionState,\r\n socketId,\r\n channels,\r\n error,\r\n connect,\r\n disconnect,\r\n channel,\r\n privateChannel,\r\n presenceChannel,\r\n leave,\r\n leaveAll,\r\n };\r\n}\r\n","/**\r\n * useLongPolling - Vue 3 Long Polling composable\r\n * @module vue-streaming/composables/useLongPolling\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type { ConnectionState } from \"../types\";\r\nimport { createReconnectManager } from \"../utils/reconnect\";\r\n\r\nexport interface LongPollingConfig {\r\n /** Polling endpoint URL */\r\n url: string;\r\n /** HTTP method (default: GET) */\r\n method?: \"GET\" | \"POST\";\r\n /** Request headers */\r\n headers?: Record<string, string>;\r\n /** Request body (for POST) */\r\n body?: unknown;\r\n /** Enable credentials (cookies) */\r\n credentials?: RequestCredentials;\r\n /** Polling interval in ms (default: 0 = immediate) */\r\n interval?: number;\r\n /** Request timeout in ms (default: 30000) */\r\n timeout?: number;\r\n /** Auto-start polling on creation */\r\n autoStart?: boolean;\r\n /** Auto-restart on error */\r\n autoRestart?: boolean;\r\n /** Max restart attempts */\r\n maxRestartAttempts?: number;\r\n /** Restart delay (ms) */\r\n restartDelay?: number;\r\n /** Max restart delay (ms) */\r\n maxRestartDelay?: number;\r\n /** Include last message timestamp in requests */\r\n includeTimestamp?: boolean;\r\n /** Timestamp parameter name */\r\n timestampParam?: string;\r\n}\r\n\r\nexport interface LongPollingCallbacks {\r\n onStart?: () => void;\r\n onData?: (data: unknown) => void;\r\n onError?: (error: Error) => void;\r\n onStop?: () => void;\r\n onRestarting?: (attempt: number, maxAttempts: number) => void;\r\n onRestarted?: () => void;\r\n onRestartFailed?: () => void;\r\n}\r\n\r\nexport interface UseLongPollingReturn {\r\n /** Is currently polling */\r\n isPolling: Ref<boolean>;\r\n /** Connection state string */\r\n connectionState: Ref<ConnectionState>;\r\n /** Last received data */\r\n lastData: Ref<unknown>;\r\n /** All received data */\r\n dataHistory: Ref<unknown[]>;\r\n /** Total requests made */\r\n requestCount: Ref<number>;\r\n /** Error state */\r\n error: Ref<Error | null>;\r\n /** Restart attempts */\r\n restartAttempts: Ref<number>;\r\n /** Start polling */\r\n start: () => void;\r\n /** Stop polling */\r\n stop: () => void;\r\n /** Force immediate poll */\r\n poll: () => Promise<void>;\r\n /** Clear data history */\r\n clearHistory: () => void;\r\n}\r\n\r\nconst DEFAULT_CONFIG: Required<Omit<LongPollingConfig, \"url\" | \"body\">> = {\r\n method: \"GET\",\r\n headers: {},\r\n credentials: \"same-origin\",\r\n interval: 0,\r\n timeout: 30000,\r\n autoStart: true,\r\n autoRestart: true,\r\n maxRestartAttempts: 5,\r\n restartDelay: 1000,\r\n maxRestartDelay: 30000,\r\n includeTimestamp: false,\r\n timestampParam: \"since\",\r\n};\r\n\r\n/**\r\n * Vue 3 composable for Long Polling\r\n *\r\n * @example\r\n * ```typescript\r\n * const {\r\n * isPolling,\r\n * lastData,\r\n * dataHistory,\r\n * start,\r\n * stop\r\n * } = useLongPolling({\r\n * url: 'https://api.example.com/poll',\r\n * timeout: 30000,\r\n * interval: 0 // Immediate re-poll\r\n * }, {\r\n * onData: (data) => console.log('New data:', data),\r\n * onError: (err) => console.error('Poll error:', err)\r\n * })\r\n *\r\n * // Manual control\r\n * start() // Start polling\r\n * stop() // Stop polling\r\n * poll() // Force immediate poll\r\n * ```\r\n */\r\nexport function useLongPolling(\r\n config: LongPollingConfig,\r\n callbacks: LongPollingCallbacks = {},\r\n): UseLongPollingReturn {\r\n const cfg = { ...DEFAULT_CONFIG, ...config };\r\n\r\n // Reactive state\r\n const isPolling = ref(false);\r\n const connectionState = ref<ConnectionState>(\"disconnected\");\r\n const lastData = ref<unknown>(null);\r\n const dataHistory = ref<unknown[]>([]);\r\n const requestCount = ref(0);\r\n const error = ref<Error | null>(null);\r\n const restartAttempts = ref(0);\r\n\r\n // Internal state\r\n let abortController: AbortController | null = null;\r\n let pollTimeout: ReturnType<typeof setTimeout> | null = null;\r\n let isManualStop = false;\r\n let lastTimestamp: number | null = null;\r\n\r\n // Restart manager\r\n const restartManager = createReconnectManager({\r\n maxAttempts: cfg.maxRestartAttempts,\r\n delay: cfg.restartDelay,\r\n delayMax: cfg.maxRestartDelay,\r\n onAttempt: (attempt: number, maxAttempts: number) => {\r\n restartAttempts.value = attempt;\r\n connectionState.value = \"reconnecting\";\r\n callbacks.onRestarting?.(attempt, maxAttempts);\r\n },\r\n onSuccess: () => {\r\n restartAttempts.value = 0;\r\n callbacks.onRestarted?.();\r\n },\r\n onFailure: () => {\r\n connectionState.value = \"failed\";\r\n callbacks.onRestartFailed?.();\r\n },\r\n });\r\n\r\n /**\r\n * Build URL with optional timestamp\r\n */\r\n function buildUrl(): string {\r\n if (!cfg.includeTimestamp || !lastTimestamp) {\r\n return cfg.url;\r\n }\r\n\r\n const url = new URL(cfg.url);\r\n url.searchParams.set(cfg.timestampParam, lastTimestamp.toString());\r\n return url.toString();\r\n }\r\n\r\n /**\r\n * Execute a single poll request\r\n */\r\n async function executePoll(): Promise<unknown> {\r\n abortController = new AbortController();\r\n\r\n // Setup timeout\r\n const timeoutId = setTimeout(() => {\r\n abortController?.abort();\r\n }, cfg.timeout);\r\n\r\n try {\r\n const requestInit: RequestInit = {\r\n method: cfg.method,\r\n headers: {\r\n Accept: \"application/json\",\r\n ...cfg.headers,\r\n },\r\n credentials: cfg.credentials,\r\n signal: abortController.signal,\r\n };\r\n\r\n if (cfg.body && cfg.method === \"POST\") {\r\n requestInit.body =\r\n typeof cfg.body === \"string\" ? cfg.body : JSON.stringify(cfg.body);\r\n requestInit.headers = {\r\n ...requestInit.headers,\r\n \"Content-Type\": \"application/json\",\r\n };\r\n }\r\n\r\n const response = await fetch(buildUrl(), requestInit);\r\n\r\n clearTimeout(timeoutId);\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\r\n }\r\n\r\n const data = await response.json();\r\n return data;\r\n } catch (err) {\r\n clearTimeout(timeoutId);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Main polling loop\r\n */\r\n async function pollLoop(): Promise<void> {\r\n while (isPolling.value && !isManualStop) {\r\n try {\r\n requestCount.value++;\r\n const data = await executePoll();\r\n\r\n // Update timestamp for next request\r\n lastTimestamp = Date.now();\r\n\r\n // Store data\r\n lastData.value = data;\r\n dataHistory.value.push(data);\r\n error.value = null;\r\n\r\n callbacks.onData?.(data);\r\n\r\n // Wait for interval before next poll\r\n if (cfg.interval > 0 && isPolling.value && !isManualStop) {\r\n await new Promise<void>((resolve) => {\r\n pollTimeout = setTimeout(resolve, cfg.interval);\r\n });\r\n }\r\n } catch (err) {\r\n if ((err as Error).name === \"AbortError\") {\r\n // Check if it was a timeout or manual abort\r\n if (isManualStop) {\r\n break;\r\n }\r\n // Timeout - continue polling\r\n continue;\r\n }\r\n\r\n error.value = err as Error;\r\n callbacks.onError?.(err as Error);\r\n\r\n if (!isManualStop && cfg.autoRestart) {\r\n isPolling.value = false;\r\n connectionState.value = \"error\";\r\n\r\n restartManager.scheduleReconnect(async () => {\r\n try {\r\n await startPolling();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n });\r\n return;\r\n }\r\n\r\n break;\r\n }\r\n }\r\n\r\n // Polling stopped\r\n if (!isManualStop) {\r\n isPolling.value = false;\r\n connectionState.value = \"disconnected\";\r\n }\r\n }\r\n\r\n /**\r\n * Start polling\r\n */\r\n async function startPolling(): Promise<void> {\r\n if (isPolling.value) {\r\n return;\r\n }\r\n\r\n isManualStop = false;\r\n isPolling.value = true;\r\n connectionState.value = \"connected\";\r\n error.value = null;\r\n callbacks.onStart?.();\r\n\r\n // Start polling loop (don't await - runs in background)\r\n pollLoop();\r\n }\r\n\r\n /**\r\n * Start polling (public API)\r\n */\r\n function start(): void {\r\n startPolling();\r\n }\r\n\r\n /**\r\n * Stop polling\r\n */\r\n function stop(): void {\r\n isManualStop = true;\r\n restartManager.cancel();\r\n\r\n if (pollTimeout) {\r\n clearTimeout(pollTimeout);\r\n pollTimeout = null;\r\n }\r\n\r\n if (abortController) {\r\n abortController.abort();\r\n abortController = null;\r\n }\r\n\r\n isPolling.value = false;\r\n connectionState.value = \"disconnected\";\r\n callbacks.onStop?.();\r\n }\r\n\r\n /**\r\n * Force immediate poll\r\n */\r\n async function poll(): Promise<void> {\r\n const wasPolling = isPolling.value;\r\n\r\n // Cancel current pending poll\r\n if (pollTimeout) {\r\n clearTimeout(pollTimeout);\r\n pollTimeout = null;\r\n }\r\n\r\n try {\r\n const data = await executePoll();\r\n lastTimestamp = Date.now();\r\n lastData.value = data;\r\n dataHistory.value.push(data);\r\n callbacks.onData?.(data);\r\n } catch (err) {\r\n if ((err as Error).name !== \"AbortError\") {\r\n error.value = err as Error;\r\n callbacks.onError?.(err as Error);\r\n }\r\n }\r\n\r\n // Restart polling loop if it was running\r\n if (wasPolling && !isManualStop) {\r\n pollLoop();\r\n }\r\n }\r\n\r\n /**\r\n * Clear data history\r\n */\r\n function clearHistory(): void {\r\n dataHistory.value = [];\r\n lastData.value = null;\r\n requestCount.value = 0;\r\n }\r\n\r\n // Auto-start if configured\r\n if (cfg.autoStart) {\r\n start();\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n stop();\r\n });\r\n\r\n return {\r\n isPolling,\r\n connectionState,\r\n lastData,\r\n dataHistory,\r\n requestCount,\r\n error,\r\n restartAttempts,\r\n start,\r\n stop,\r\n poll,\r\n clearHistory,\r\n };\r\n}\r\n","/**\r\n * useSocketIO - Vue 3 Socket.IO composable with rooms and events\r\n * @module vue-streaming/composables/useSocketIO\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type {\r\n ConnectionState,\r\n SocketIOCallbacks,\r\n SocketIOConfig,\r\n SocketIORoom,\r\n} from \"../types\";\r\n\r\n// Socket.IO client type\r\ntype SocketIOClient = {\r\n id?: string;\r\n connected: boolean;\r\n connect: () => void;\r\n disconnect: () => void;\r\n emit: (event: string, ...args: unknown[]) => void;\r\n on: (event: string, callback: (...args: unknown[]) => void) => void;\r\n off: (event: string, callback?: (...args: unknown[]) => void) => void;\r\n io: {\r\n on: (event: string, callback: (...args: unknown[]) => void) => void;\r\n off: (event: string, callback?: (...args: unknown[]) => void) => void;\r\n };\r\n};\r\n\r\nexport interface UseSocketIOReturn {\r\n /** Connection state */\r\n isConnected: Ref<boolean>;\r\n /** Connection state string */\r\n connectionState: Ref<ConnectionState>;\r\n /** Socket ID */\r\n socketId: Ref<string | null>;\r\n /** Joined rooms */\r\n rooms: Ref<SocketIORoom[]>;\r\n /** Reconnect attempts */\r\n reconnectAttempts: Ref<number>;\r\n /** Last error */\r\n error: Ref<Error | null>;\r\n /** Connect to server */\r\n connect: () => Promise<void>;\r\n /** Disconnect from server */\r\n disconnect: () => void;\r\n /** Emit event */\r\n emit: <T = unknown>(event: string, data?: T) => void;\r\n /** Emit event with acknowledgement */\r\n emitWithAck: <T = unknown, R = unknown>(\r\n event: string,\r\n data?: T,\r\n timeout?: number,\r\n ) => Promise<R>;\r\n /** Listen for event */\r\n on: <T = unknown>(event: string, callback: (data: T) => void) => void;\r\n /** Remove event listener */\r\n off: (event: string, callback?: (...args: unknown[]) => void) => void;\r\n /** Join a room */\r\n join: (room: string) => Promise<void>;\r\n /** Leave a room */\r\n leave: (room: string) => Promise<void>;\r\n /** Get raw socket instance */\r\n getSocket: () => SocketIOClient | null;\r\n}\r\n\r\nconst DEFAULT_CONFIG = {\r\n path: \"/socket.io\",\r\n namespace: \"/\",\r\n reconnection: true,\r\n reconnectionAttempts: 5,\r\n reconnectionDelay: 1000,\r\n transports: [\"websocket\", \"polling\"],\r\n extraHeaders: {} as Record<string, string>,\r\n options: {} as Record<string, unknown>,\r\n autoConnect: true,\r\n autoReconnect: true,\r\n maxReconnectAttempts: 5,\r\n reconnectDelay: 1000,\r\n};\r\n\r\n/**\r\n * Vue 3 composable for Socket.IO connections\r\n *\r\n * @example\r\n * ```typescript\r\n * const {\r\n * isConnected,\r\n * socketId,\r\n * rooms,\r\n * connect,\r\n * disconnect,\r\n * emit,\r\n * on,\r\n * join,\r\n * leave\r\n * } = useSocketIO({\r\n * url: 'http://localhost:3000',\r\n * namespace: '/live',\r\n * auth: { token: 'your-token' }\r\n * }, {\r\n * onConnect: (id) => console.log('Connected:', id),\r\n * onDisconnect: (reason) => console.log('Disconnected:', reason)\r\n * })\r\n *\r\n * await connect()\r\n * await join('room-1')\r\n *\r\n * on('message', (data) => console.log('Message:', data))\r\n * emit('chat', { text: 'Hello!' })\r\n * ```\r\n */\r\nexport function useSocketIO(\r\n config: SocketIOConfig,\r\n callbacks: SocketIOCallbacks = {},\r\n): UseSocketIOReturn {\r\n const cfg = { ...DEFAULT_CONFIG, ...config };\r\n\r\n // Reactive state\r\n const isConnected = ref(false);\r\n const connectionState = ref<ConnectionState>(\"idle\");\r\n const socketId = ref<string | null>(null);\r\n const rooms = ref<SocketIORoom[]>([]);\r\n const reconnectAttempts = ref(0);\r\n const error = ref<Error | null>(null);\r\n\r\n // Internal state\r\n let socket: SocketIOClient | null = null;\r\n let io: ((url: string, options: unknown) => SocketIOClient) | null = null;\r\n\r\n /**\r\n * Get Socket.IO client\r\n */\r\n async function getIOClient(): Promise<typeof io> {\r\n if (io) return io;\r\n\r\n try {\r\n // Dynamic import for Socket.IO client\r\n const module = await import(\"socket.io-client\");\r\n io = module.io || module.default;\r\n return io;\r\n } catch {\r\n throw new Error(\r\n \"socket.io-client is not installed. Run: npm install socket.io-client\",\r\n );\r\n }\r\n }\r\n\r\n /**\r\n * Connect to Socket.IO server\r\n */\r\n async function connect(): Promise<void> {\r\n if (socket?.connected) {\r\n return;\r\n }\r\n\r\n connectionState.value = \"connecting\";\r\n error.value = null;\r\n\r\n return new Promise(async (resolve, reject) => {\r\n try {\r\n const ioClient = await getIOClient();\r\n if (!ioClient) {\r\n throw new Error(\"Socket.IO client not available\");\r\n }\r\n\r\n const url =\r\n cfg.namespace === \"/\" ? cfg.url : `${cfg.url}${cfg.namespace}`;\r\n\r\n socket = ioClient(url, {\r\n path: cfg.path,\r\n auth: cfg.auth,\r\n reconnection: cfg.reconnection,\r\n reconnectionAttempts: cfg.reconnectionAttempts,\r\n reconnectionDelay: cfg.reconnectionDelay,\r\n transports: cfg.transports,\r\n extraHeaders: cfg.extraHeaders,\r\n });\r\n\r\n socket.on(\"connect\", () => {\r\n isConnected.value = true;\r\n connectionState.value = \"connected\";\r\n socketId.value = socket?.id || null;\r\n reconnectAttempts.value = 0;\r\n callbacks.onConnect?.(socketId.value || \"\");\r\n resolve();\r\n });\r\n\r\n socket.on(\"disconnect\", (reason: string) => {\r\n isConnected.value = false;\r\n connectionState.value = \"disconnected\";\r\n socketId.value = null;\r\n callbacks.onDisconnect?.(reason);\r\n });\r\n\r\n socket.on(\"connect_error\", (err: Error) => {\r\n error.value = err;\r\n connectionState.value = \"error\";\r\n callbacks.onError?.(err);\r\n reject(err);\r\n });\r\n\r\n socket.io.on(\"reconnect_attempt\", (attempt: number) => {\r\n reconnectAttempts.value = attempt;\r\n connectionState.value = \"reconnecting\";\r\n callbacks.onReconnecting?.(attempt);\r\n });\r\n\r\n socket.io.on(\"reconnect_failed\", () => {\r\n connectionState.value = \"error\";\r\n callbacks.onReconnectFailed?.();\r\n });\r\n\r\n socket.connect();\r\n } catch (err) {\r\n const e = err instanceof Error ? err : new Error(String(err));\r\n error.value = e;\r\n connectionState.value = \"error\";\r\n reject(e);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Disconnect from server\r\n */\r\n function disconnect(): void {\r\n if (socket) {\r\n socket.disconnect();\r\n socket = null;\r\n }\r\n\r\n isConnected.value = false;\r\n connectionState.value = \"closed\";\r\n socketId.value = null;\r\n rooms.value = [];\r\n }\r\n\r\n /**\r\n * Emit event to server\r\n */\r\n function emit<T = unknown>(event: string, data?: T): void {\r\n if (!socket?.connected) {\r\n console.warn(\"[useSocketIO] Cannot emit: Socket is not connected\");\r\n return;\r\n }\r\n\r\n socket.emit(event, data);\r\n }\r\n\r\n /**\r\n * Emit event with acknowledgement\r\n */\r\n function emitWithAck<T = unknown, R = unknown>(\r\n event: string,\r\n data?: T,\r\n timeout: number = 5000,\r\n ): Promise<R> {\r\n return new Promise((resolve, reject) => {\r\n if (!socket?.connected) {\r\n reject(new Error(\"Socket is not connected\"));\r\n return;\r\n }\r\n\r\n const timeoutId = setTimeout(() => {\r\n reject(new Error(`Emit timeout for event: ${event}`));\r\n }, timeout);\r\n\r\n socket.emit(event, data, (response: R) => {\r\n clearTimeout(timeoutId);\r\n resolve(response);\r\n });\r\n });\r\n }\r\n\r\n /**\r\n * Listen for event\r\n */\r\n function on<T = unknown>(event: string, callback: (data: T) => void): void {\r\n if (!socket) {\r\n console.warn(\"[useSocketIO] Cannot listen: Socket not initialized\");\r\n return;\r\n }\r\n\r\n socket.on(event, callback as (...args: unknown[]) => void);\r\n }\r\n\r\n /**\r\n * Remove event listener\r\n */\r\n function off(event: string, callback?: (...args: unknown[]) => void): void {\r\n if (!socket) return;\r\n socket.off(event, callback);\r\n }\r\n\r\n /**\r\n * Join a room\r\n */\r\n async function join(room: string): Promise<void> {\r\n if (!socket?.connected) {\r\n throw new Error(\"Socket is not connected\");\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n socket!.emit(\"join\", room, (response: { error?: string }) => {\r\n if (response?.error) {\r\n reject(new Error(response.error));\r\n } else {\r\n const roomInfo: SocketIORoom = {\r\n name: room,\r\n joinedAt: new Date(),\r\n };\r\n rooms.value = [...rooms.value, roomInfo];\r\n resolve();\r\n }\r\n });\r\n\r\n // Fallback: resolve after timeout if no ack\r\n setTimeout(resolve, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Leave a room\r\n */\r\n async function leave(room: string): Promise<void> {\r\n if (!socket?.connected) {\r\n return;\r\n }\r\n\r\n return new Promise((resolve) => {\r\n socket!.emit(\"leave\", room, () => {\r\n rooms.value = rooms.value.filter((r) => r.name !== room);\r\n resolve();\r\n });\r\n\r\n // Fallback: resolve after timeout\r\n setTimeout(() => {\r\n rooms.value = rooms.value.filter((r) => r.name !== room);\r\n resolve();\r\n }, 1000);\r\n });\r\n }\r\n\r\n /**\r\n * Get raw socket instance\r\n */\r\n function getSocket(): SocketIOClient | null {\r\n return socket;\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n disconnect();\r\n });\r\n\r\n return {\r\n isConnected,\r\n connectionState,\r\n socketId,\r\n rooms,\r\n reconnectAttempts,\r\n error,\r\n connect,\r\n disconnect,\r\n emit,\r\n emitWithAck,\r\n on,\r\n off,\r\n join,\r\n leave,\r\n getSocket,\r\n };\r\n}\r\n","/**\r\n * useSSE - Vue 3 Server-Sent Events composable\r\n * @module vue-streaming/composables/useSSE\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type { ConnectionState } from \"../types\";\r\nimport { createReconnectManager } from \"../utils/reconnect\";\r\n\r\nexport interface SSEConfig {\r\n /** SSE endpoint URL */\r\n url: string;\r\n /** Enable credentials (cookies) */\r\n withCredentials?: boolean;\r\n /** Auto-connect on creation */\r\n autoConnect?: boolean;\r\n /** Auto-reconnect on error */\r\n autoReconnect?: boolean;\r\n /** Max reconnection attempts */\r\n maxReconnectAttempts?: number;\r\n /** Reconnection delay (ms) */\r\n reconnectDelay?: number;\r\n /** Max reconnection delay (ms) */\r\n maxReconnectDelay?: number;\r\n /** Event types to listen for (default: ['message']) */\r\n eventTypes?: string[];\r\n}\r\n\r\nexport interface SSECallbacks {\r\n onOpen?: () => void;\r\n onMessage?: (data: unknown, event: MessageEvent) => void;\r\n onError?: (error: Event) => void;\r\n onEvent?: (eventType: string, data: unknown, event: MessageEvent) => void;\r\n onReconnecting?: (attempt: number, maxAttempts: number) => void;\r\n onReconnected?: () => void;\r\n onReconnectFailed?: () => void;\r\n}\r\n\r\nexport interface UseSSEReturn {\r\n /** Connection state */\r\n isConnected: Ref<boolean>;\r\n /** Connection state string */\r\n connectionState: Ref<ConnectionState>;\r\n /** Last received data */\r\n lastMessage: Ref<unknown>;\r\n /** Last event type */\r\n lastEventType: Ref<string>;\r\n /** Last event ID */\r\n lastEventId: Ref<string | null>;\r\n /** Error state */\r\n error: Ref<Event | null>;\r\n /** Reconnect attempts */\r\n reconnectAttempts: Ref<number>;\r\n /** Connect to SSE endpoint */\r\n connect: () => void;\r\n /** Disconnect from SSE endpoint */\r\n disconnect: () => void;\r\n /** Add event listener for specific event type */\r\n addEventListener: (type: string, callback: (data: unknown) => void) => void;\r\n /** Remove event listener */\r\n removeEventListener: (\r\n type: string,\r\n callback: (data: unknown) => void,\r\n ) => void;\r\n}\r\n\r\nconst DEFAULT_CONFIG: Required<Omit<SSEConfig, \"url\">> = {\r\n withCredentials: false,\r\n autoConnect: true,\r\n autoReconnect: true,\r\n maxReconnectAttempts: 5,\r\n reconnectDelay: 1000,\r\n maxReconnectDelay: 30000,\r\n eventTypes: [\"message\"],\r\n};\r\n\r\n/**\r\n * Vue 3 composable for Server-Sent Events (SSE)\r\n *\r\n * @example\r\n * ```typescript\r\n * const {\r\n * isConnected,\r\n * lastMessage,\r\n * connect,\r\n * disconnect,\r\n * addEventListener\r\n * } = useSSE({\r\n * url: 'https://api.example.com/events',\r\n * eventTypes: ['message', 'update', 'notification']\r\n * }, {\r\n * onMessage: (data) => console.log('Message:', data),\r\n * onEvent: (type, data) => console.log(`Event [${type}]:`, data)\r\n * })\r\n *\r\n * // Listen for specific events\r\n * addEventListener('notification', (data) => {\r\n * showNotification(data)\r\n * })\r\n * ```\r\n */\r\nexport function useSSE(\r\n config: SSEConfig,\r\n callbacks: SSECallbacks = {},\r\n): UseSSEReturn {\r\n const cfg = { ...DEFAULT_CONFIG, ...config };\r\n\r\n // Reactive state\r\n const isConnected = ref(false);\r\n const connectionState = ref<ConnectionState>(\"disconnected\");\r\n const lastMessage = ref<unknown>(null);\r\n const lastEventType = ref<string>(\"\");\r\n const lastEventId = ref<string | null>(null);\r\n const error = ref<Event | null>(null);\r\n const reconnectAttempts = ref(0);\r\n\r\n // Internal state\r\n let eventSource: EventSource | null = null;\r\n let isManualClose = false;\r\n const eventListeners = new Map<string, Set<(data: unknown) => void>>();\r\n\r\n // Reconnection manager\r\n const reconnectManager = createReconnectManager({\r\n maxAttempts: cfg.maxReconnectAttempts,\r\n delay: cfg.reconnectDelay,\r\n delayMax: cfg.maxReconnectDelay,\r\n onAttempt: (attempt: number, maxAttempts: number) => {\r\n reconnectAttempts.value = attempt;\r\n connectionState.value = \"reconnecting\";\r\n callbacks.onReconnecting?.(attempt, maxAttempts);\r\n },\r\n onSuccess: () => {\r\n reconnectAttempts.value = 0;\r\n callbacks.onReconnected?.();\r\n },\r\n onFailure: () => {\r\n connectionState.value = \"failed\";\r\n callbacks.onReconnectFailed?.();\r\n },\r\n });\r\n\r\n /**\r\n * Handle incoming message\r\n */\r\n function handleMessage(event: MessageEvent): void {\r\n try {\r\n let data: unknown;\r\n try {\r\n data = JSON.parse(event.data);\r\n } catch {\r\n data = event.data;\r\n }\r\n\r\n lastMessage.value = data;\r\n lastEventType.value = event.type || \"message\";\r\n lastEventId.value = event.lastEventId || null;\r\n\r\n callbacks.onMessage?.(data, event);\r\n callbacks.onEvent?.(event.type || \"message\", data, event);\r\n\r\n // Notify specific listeners\r\n const listeners = eventListeners.get(event.type || \"message\");\r\n if (listeners) {\r\n listeners.forEach((cb) => cb(data));\r\n }\r\n } catch (err) {\r\n console.error(\"[useSSE] Error processing message:\", err);\r\n }\r\n }\r\n\r\n /**\r\n * Handle open event\r\n */\r\n function handleOpen(): void {\r\n isConnected.value = true;\r\n connectionState.value = \"connected\";\r\n error.value = null;\r\n reconnectManager.reset();\r\n callbacks.onOpen?.();\r\n }\r\n\r\n /**\r\n * Handle error event\r\n */\r\n function handleError(event: Event): void {\r\n error.value = event;\r\n callbacks.onError?.(event);\r\n\r\n if (eventSource?.readyState === EventSource.CLOSED) {\r\n isConnected.value = false;\r\n connectionState.value = \"error\";\r\n\r\n if (!isManualClose && cfg.autoReconnect) {\r\n reconnectManager.scheduleReconnect(async () => {\r\n try {\r\n connect();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Connect to SSE endpoint\r\n */\r\n function connect(): void {\r\n if (eventSource && eventSource.readyState !== EventSource.CLOSED) {\r\n return;\r\n }\r\n\r\n isManualClose = false;\r\n connectionState.value = \"connecting\";\r\n\r\n try {\r\n eventSource = new EventSource(cfg.url, {\r\n withCredentials: cfg.withCredentials,\r\n });\r\n\r\n // Setup default message handler\r\n eventSource.onmessage = handleMessage;\r\n eventSource.onopen = handleOpen;\r\n eventSource.onerror = handleError;\r\n\r\n // Setup custom event type handlers\r\n cfg.eventTypes.forEach((eventType) => {\r\n if (eventType !== \"message\" && eventSource) {\r\n eventSource.addEventListener(\r\n eventType,\r\n handleMessage as EventListener,\r\n );\r\n }\r\n });\r\n } catch (err) {\r\n connectionState.value = \"error\";\r\n error.value = err as Event;\r\n callbacks.onError?.(err as Event);\r\n }\r\n }\r\n\r\n /**\r\n * Disconnect from SSE endpoint\r\n */\r\n function disconnect(): void {\r\n isManualClose = true;\r\n reconnectManager.cancel();\r\n\r\n if (eventSource) {\r\n eventSource.close();\r\n eventSource = null;\r\n }\r\n\r\n isConnected.value = false;\r\n connectionState.value = \"disconnected\";\r\n }\r\n\r\n /**\r\n * Add event listener for specific event type\r\n */\r\n function addEventListener(\r\n type: string,\r\n callback: (data: unknown) => void,\r\n ): void {\r\n if (!eventListeners.has(type)) {\r\n eventListeners.set(type, new Set());\r\n\r\n // Add listener to EventSource if connected\r\n if (eventSource && type !== \"message\") {\r\n eventSource.addEventListener(type, handleMessage as EventListener);\r\n }\r\n }\r\n eventListeners.get(type)!.add(callback);\r\n }\r\n\r\n /**\r\n * Remove event listener\r\n */\r\n function removeEventListener(\r\n type: string,\r\n callback: (data: unknown) => void,\r\n ): void {\r\n const listeners = eventListeners.get(type);\r\n if (listeners) {\r\n listeners.delete(callback);\r\n if (listeners.size === 0) {\r\n eventListeners.delete(type);\r\n }\r\n }\r\n }\r\n\r\n // Auto-connect if configured\r\n if (cfg.autoConnect) {\r\n connect();\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n disconnect();\r\n eventListeners.clear();\r\n });\r\n\r\n return {\r\n isConnected,\r\n connectionState,\r\n lastMessage,\r\n lastEventType,\r\n lastEventId,\r\n error,\r\n reconnectAttempts,\r\n connect,\r\n disconnect,\r\n addEventListener,\r\n removeEventListener,\r\n };\r\n}\r\n","/**\r\n * useWebSocket - Vue 3 WebSocket composable with auto-reconnect\r\n * @module vue-streaming/composables/useWebSocket\r\n */\r\n\r\nimport { onUnmounted, ref, type Ref } from \"vue\";\r\nimport type {\r\n ConnectionState,\r\n WebSocketCallbacks,\r\n WebSocketConfig,\r\n} from \"../types\";\r\nimport { createReconnectManager } from \"../utils/reconnect\";\r\n\r\nexport interface UseWebSocketReturn {\r\n /** Connection state */\r\n isConnected: Ref<boolean>;\r\n /** Connection state string */\r\n connectionState: Ref<ConnectionState>;\r\n /** WebSocket ready state */\r\n readyState: Ref<number>;\r\n /** Buffered amount */\r\n bufferedAmount: Ref<number>;\r\n /** Last message received */\r\n lastMessage: Ref<unknown>;\r\n /** Last error */\r\n error: Ref<Event | null>;\r\n /** Reconnect attempts */\r\n reconnectAttempts: Ref<number>;\r\n /** Connect to WebSocket */\r\n connect: () => Promise<void>;\r\n /** Disconnect from WebSocket */\r\n disconnect: () => void;\r\n /** Send data */\r\n send: (data: string | ArrayBuffer | Blob) => boolean;\r\n /** Send JSON data */\r\n sendJSON: <T>(data: T) => boolean;\r\n}\r\n\r\nconst DEFAULT_CONFIG: Required<Omit<WebSocketConfig, \"url\" | \"protocols\">> = {\r\n autoReconnect: true,\r\n maxReconnectAttempts: 5,\r\n reconnectDelay: 1000,\r\n reconnectDelayMax: 30000,\r\n pingInterval: 0,\r\n binaryType: \"arraybuffer\",\r\n};\r\n\r\n/**\r\n * Vue 3 composable for WebSocket connections with auto-reconnect\r\n *\r\n * @example\r\n * ```typescript\r\n * const {\r\n * isConnected,\r\n * connectionState,\r\n * lastMessage,\r\n * connect,\r\n * disconnect,\r\n * send,\r\n * sendJSON\r\n * } = useWebSocket({\r\n * url: 'wss://api.example.com/ws',\r\n * autoReconnect: true,\r\n * maxReconnectAttempts: 5\r\n * }, {\r\n * onMessage: (data) => console.log('Received:', data),\r\n * onOpen: () => console.log('Connected'),\r\n * onClose: () => console.log('Disconnected')\r\n * })\r\n *\r\n * await connect()\r\n * sendJSON({ type: 'subscribe', channel: 'updates' })\r\n * ```\r\n */\r\nexport function useWebSocket(\r\n config: WebSocketConfig,\r\n callbacks: WebSocketCallbacks = {},\r\n): UseWebSocketReturn {\r\n const cfg = { ...DEFAULT_CONFIG, ...config };\r\n\r\n // Reactive state\r\n const isConnected = ref(false);\r\n const connectionState = ref<ConnectionState>(\"idle\");\r\n const readyState = ref<number>(WebSocket.CLOSED);\r\n const bufferedAmount = ref(0);\r\n const lastMessage = ref<unknown>(null);\r\n const error = ref<Event | null>(null);\r\n const reconnectAttempts = ref(0);\r\n\r\n // Internal state\r\n let ws: WebSocket | null = null;\r\n let pingTimer: ReturnType<typeof setInterval> | null = null;\r\n let isManualClose = false;\r\n\r\n // Reconnection manager\r\n const reconnectManager = createReconnectManager({\r\n maxAttempts: cfg.maxReconnectAttempts,\r\n delay: cfg.reconnectDelay,\r\n delayMax: cfg.reconnectDelayMax,\r\n onAttempt: (attempt, maxAttempts) => {\r\n reconnectAttempts.value = attempt;\r\n connectionState.value = \"reconnecting\";\r\n callbacks.onReconnecting?.(attempt, maxAttempts);\r\n },\r\n onSuccess: () => {\r\n reconnectAttempts.value = 0;\r\n },\r\n onFailure: () => {\r\n connectionState.value = \"error\";\r\n callbacks.onReconnectFailed?.();\r\n },\r\n });\r\n\r\n /**\r\n * Start ping/pong heartbeat\r\n */\r\n function startPing(): void {\r\n if (!cfg.pingInterval || cfg.pingInterval <= 0) return;\r\n\r\n pingTimer = setInterval(() => {\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n // Send ping as text (WebSocket API doesn't expose protocol-level ping)\r\n ws.send(JSON.stringify({ type: \"ping\", timestamp: Date.now() }));\r\n }\r\n }, cfg.pingInterval);\r\n }\r\n\r\n /**\r\n * Stop ping timer\r\n */\r\n function stopPing(): void {\r\n if (pingTimer) {\r\n clearInterval(pingTimer);\r\n pingTimer = null;\r\n }\r\n }\r\n\r\n /**\r\n * Update buffered amount\r\n */\r\n function updateBufferedAmount(): void {\r\n if (ws) {\r\n bufferedAmount.value = ws.bufferedAmount;\r\n }\r\n }\r\n\r\n /**\r\n * Connect to WebSocket server\r\n */\r\n async function connect(): Promise<void> {\r\n if (ws && ws.readyState === WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n isManualClose = false;\r\n connectionState.value = \"connecting\";\r\n error.value = null;\r\n\r\n return new Promise((resolve, reject) => {\r\n try {\r\n ws = new WebSocket(cfg.url, cfg.protocols);\r\n ws.binaryType = cfg.binaryType;\r\n\r\n ws.onopen = () => {\r\n isConnected.value = true;\r\n connectionState.value = \"connected\";\r\n readyState.value = WebSocket.OPEN;\r\n reconnectManager.reset();\r\n reconnectAttempts.value = 0;\r\n startPing();\r\n callbacks.onOpen?.();\r\n resolve();\r\n };\r\n\r\n ws.onclose = (event) => {\r\n isConnected.value = false;\r\n connectionState.value = \"disconnected\";\r\n readyState.value = WebSocket.CLOSED;\r\n stopPing();\r\n callbacks.onClose?.(event.code, event.reason);\r\n\r\n // Auto-reconnect if not manually closed\r\n if (!isManualClose && cfg.autoReconnect) {\r\n reconnectManager.scheduleReconnect(async () => {\r\n try {\r\n await connect();\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n });\r\n }\r\n };\r\n\r\n ws.onerror = (event) => {\r\n error.value = event;\r\n connectionState.value = \"error\";\r\n callbacks.onError?.(event);\r\n reject(event);\r\n };\r\n\r\n ws.onmessage = (event) => {\r\n lastMessage.value = event.data;\r\n updateBufferedAmount();\r\n\r\n // Parse data if it's JSON\r\n let parsedData = event.data;\r\n if (typeof event.data === \"string\") {\r\n try {\r\n parsedData = JSON.parse(event.data);\r\n } catch {\r\n // Keep as string if not valid JSON\r\n }\r\n }\r\n\r\n callbacks.onMessage?.(parsedData, event);\r\n };\r\n\r\n readyState.value = ws.readyState;\r\n } catch (err) {\r\n connectionState.value = \"error\";\r\n reject(err);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Disconnect from WebSocket server\r\n */\r\n function disconnect(): void {\r\n isManualClose = true;\r\n reconnectManager.cancel();\r\n stopPing();\r\n\r\n if (ws) {\r\n ws.close(1000, \"Client disconnect\");\r\n ws = null;\r\n }\r\n\r\n isConnected.value = false;\r\n connectionState.value = \"closed\";\r\n readyState.value = WebSocket.CLOSED;\r\n }\r\n\r\n /**\r\n * Send data through WebSocket\r\n */\r\n function send(data: string | ArrayBuffer | Blob): boolean {\r\n if (!ws || ws.readyState !== WebSocket.OPEN) {\r\n console.warn(\"[useWebSocket] Cannot send: WebSocket is not connected\");\r\n return false;\r\n }\r\n\r\n try {\r\n ws.send(data);\r\n updateBufferedAmount();\r\n return true;\r\n } catch (err) {\r\n console.error(\"[useWebSocket] Send error:\", err);\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Send JSON data through WebSocket\r\n */\r\n function sendJSON<T>(data: T): boolean {\r\n return send(JSON.stringify(data));\r\n }\r\n\r\n // Cleanup on unmount\r\n onUnmounted(() => {\r\n disconnect();\r\n });\r\n\r\n return {\r\n isConnected,\r\n connectionState,\r\n readyState,\r\n bufferedAmount,\r\n lastMessage,\r\n error,\r\n reconnectAttempts,\r\n connect,\r\n disconnect,\r\n send,\r\n sendJSON,\r\n };\r\n}\r\n"],"names":["DEFAULT_CONFIG","useHLS","config","callbacks","cfg","state","ref","isPlaying","isBuffering","levels","currentLevel","autoLevelEnabled","currentTime","duration","buffered","volume","muted","stats","error","isSupported","hls","Hls","videoElement","timeUpdateInterval","getHLS","module","updateTimeInfo","bufferedEnd","setupVideoEvents","video","_a","err","_b","setupHLSEvents","_event","data","level","index","attach","HlsLib","play","detach","load","url","sourceUrl","pause","stop","seek","time","setLevel","setVolume","vol","toggleMute","destroy","onUnmounted","waitForIceGatheringComplete","pc","timeout","resolve","timeoutId","useWebRTC","isRunning","connectionState","dataChannels","lastPointCloudFrame","lastDetectionFrame","lastBoundingBoxes","controlChannel","pointcloudChannel","bboxChannel","reconnectAttempts","reconnectTimeout","sendControl","stream","enabled","payload","sendOnChannel","channelLabel","channel","handleDataChannel","setupPointCloudChannel","setupBboxChannel","evt","points","buffer","text","jsonPoints","parsePointCloudJSON","parsePointCloudBinary","frame","e","rawData","bboxes","parseArrayBboxFormat","normalizeBboxes","detectionFrame","bboxesToDetectionFrame","start","scheduleReconnect","event","offer","offerSDP","response","_c","_d","_e","_f","getPeerConnection","useDataStream","bufferSize","isStreaming","itemsPerSecond","totalItems","subscribers","seenKeys","itemsThisSecond","rateInterval","flushInterval","pendingBatch","startRateCalculation","stopRateCalculation","startFlushInterval","stopFlushInterval","push","transformed","key","k","cb","clear","getBuffer","subscribe","callback","useHTTPStream","isConnected","lastChunk","chunks","bytesReceived","abortController","isManualClose","reconnectManager","createReconnectManager","attempt","maxAttempts","parseNDJSON","line","trimmed","processChunk","chunk","parsed","lines","connect","requestInit","reader","decoder","done","value","lastNewlineIndex","completeData","disconnect","clearChunks","useLaravelEcho","socketId","channels","echo","getEchoInstance","Echo","Pusher","trackChannel","name","type","c","untrackChannel","pusher","createChannelWrapper","createPresenceChannelWrapper","member","ch","privateChannel","presenceChannel","leave","leaveAll","useLongPolling","isPolling","lastData","dataHistory","requestCount","restartAttempts","pollTimeout","isManualStop","lastTimestamp","restartManager","buildUrl","executePoll","pollLoop","startPolling","poll","wasPolling","clearHistory","useSocketIO","rooms","socket","io","getIOClient","reject","ioClient","reason","emit","emitWithAck","on","off","join","room","roomInfo","r","getSocket","useSSE","lastMessage","lastEventType","lastEventId","eventSource","eventListeners","handleMessage","listeners","handleOpen","handleError","eventType","addEventListener","removeEventListener","useWebSocket","readyState","bufferedAmount","ws","pingTimer","startPing","stopPing","updateBufferedAmount","parsedData","send","sendJSON"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const x={person:16711680,car:65280,truck:255,bicycle:16776960,motorcycle:16711935,bus:65535,pedestrian:16737792,vehicle:65280,default:65280},L={0:16711680,1:65280,2:255,3:16776960,4:16711935,5:65535,6:16746496,7:8978176,8:35071,9:16711816,10:8913151,11:65416,12:16777096,13:8978431,14:16746751,15:8947848,33:16737792},O={0:"Person",1:"Car",2:"Truck",3:"Bicycle",4:"Motorcycle",5:"Bus",6:"Train",7:"Traffic Light",8:"Fire Hydrant",9:"Stop Sign",10:"Parking Meter",11:"Bench",12:"Bird",13:"Cat",14:"Dog",15:"Horse",33:"Object"};exports.BBOX_COLORS={...x};exports.BBOX_COLORS_BY_ID={...L};exports.CLASS_LABELS={...O};function I(e){e.colors&&(exports.BBOX_COLORS={...exports.BBOX_COLORS,...e.colors}),e.colorsByClassId&&(exports.BBOX_COLORS_BY_ID={...exports.BBOX_COLORS_BY_ID,...e.colorsByClassId}),e.classLabels&&(exports.CLASS_LABELS={...exports.CLASS_LABELS,...e.classLabels})}function M(){exports.BBOX_COLORS={...x},exports.BBOX_COLORS_BY_ID={...L},exports.CLASS_LABELS={...O}}function F(){return{...exports.BBOX_COLORS}}function P(){return{...exports.BBOX_COLORS_BY_ID}}function E(){return{...exports.CLASS_LABELS}}function X(e,n){exports.BBOX_COLORS[e.toLowerCase()]=n}function U(e,n){exports.BBOX_COLORS_BY_ID[e]=n}function T(e,n){exports.CLASS_LABELS[e]=n}function Y(e){const n=e.toLowerCase();return exports.BBOX_COLORS[n]??exports.BBOX_COLORS.default}function A(e){return exports.BBOX_COLORS_BY_ID[e]??65280}function S(e){return exports.CLASS_LABELS[e]??`Class ${e}`}function _(e,n=0){const o=e[0]??0;return{id:n,label:S(o),center:{x:e[1]??0,y:e[2]??0,z:e[3]??0},dimensions:{width:e[4]??1,height:e[5]??1,depth:e[6]??1},rotation:{x:0,y:e[7]??0,z:0},confidence:e[8]??1,color:A(o)}}function N(e){return e.map((n,o)=>_(n,o))}function k(e){return e.map((n,o)=>{const t=Math.floor(n[0]??o);return{id:t,label:`Person ${t}`,center:{x:n[1]??0,y:n[2]??0,z:n[3]??0},dimensions:{width:Math.abs(n[4]??1),height:Math.abs(n[5]??1),depth:Math.abs(n[6]??1)},rotation:{x:0,y:n[7]??0,z:0},confidence:n[8]??1,color:65280}})}function v(e){return e.map((n,o)=>{const t=n,r=t.center||{x:t.x||t.centerX||0,y:t.y||t.centerY||0,z:t.z||t.centerZ||0},i=t.dimensions||t.size||{width:t.width||t.w||1,height:t.height||t.h||1,depth:t.depth||t.d||t.length||1},c=t.rotation||{x:t.rotX||t.rx||0,y:t.rotY||t.ry||t.yaw||0,z:t.rotZ||t.rz||0};return{id:t.id??o,label:t.label||t.class||t.className,center:r,dimensions:i,rotation:c,color:t.color,confidence:t.confidence||t.score||t.prob}})}function w(e){return{id:e.id,label:e.label||"unknown",confidence:e.confidence||1,boundingBox:{x:e.center.x-(e.dimensions.width||1)/2,y:e.center.y-(e.dimensions.height||1)/2,width:e.dimensions.width||1,height:e.dimensions.height||1},trackId:String(e.id)}}function j(e){return{detections:e.map(w),timestamp:Date.now()}}function D(e,n){const{center:o,dimensions:t}=e,{center:r,dimensions:i}=n,c=Math.max(o.x-t.width/2,r.x-i.width/2),s=Math.max(o.y-t.height/2,r.y-i.height/2),a=Math.max(o.z-t.depth/2,r.z-i.depth/2),u=Math.min(o.x+t.width/2,r.x+i.width/2),h=Math.min(o.y+t.height/2,r.y+i.height/2),f=Math.min(o.z+t.depth/2,r.z+i.depth/2),l=Math.max(0,u-c),y=Math.max(0,h-s),B=Math.max(0,f-a),d=l*y*B,g=t.width*t.height*t.depth,p=i.width*i.height*i.depth,b=g+p-d;return b>0?d/b:0}function V(e,n){return e.filter(o=>(o.confidence??1)>=n)}function H(e,n=.5){if(e.length===0)return[];const o=[...e].sort((i,c)=>(c.confidence??1)-(i.confidence??1)),t=[],r=new Set;for(let i=0;i<o.length;i++)if(!r.has(i)){t.push(o[i]);for(let c=i+1;c<o.length;c++){if(r.has(c))continue;D(o[i],o[c])>=n&&r.add(c)}}return t}const m={DRACO:[68,82,65,67,79],BINARY_HEADER:[80,67,76,68],PLY:[112,108,121],PCD:[35,32,46,80,67,68]};function J(e){if(typeof e=="string")try{return JSON.parse(e),"json"}catch{if(e.startsWith("ply"))return"ply";if(e.startsWith("# .PCD"))return"pcd"}const n=new Uint8Array(e instanceof ArrayBuffer?e:e instanceof Uint8Array?e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength):new TextEncoder().encode(e).buffer);return C(n,m.DRACO)?"draco":C(n,m.BINARY_HEADER)?"binary-header":C(n,m.PLY)?"ply":C(n,m.PCD)?"pcd":n.length%12===0?"raw-float32":n.length%24===0?"raw-float32-rgb":"raw-float32"}function C(e,n){if(e.length<n.length)return!1;for(let o=0;o<n.length;o++)if(e[o]!==n[o])return!1;return!0}function W(e){const n=[],o=new Uint8Array(e),t=new DataView(e),r=e.byteLength;if(r>=5&&String.fromCharCode(o[0],o[1],o[2],o[3],o[4])==="DRACO")return console.warn("[PointCloud] DRACO format detected - requires external decoder"),[];if(r>=4&&String.fromCharCode(o[0],o[1],o[2],o[3])==="PCLD")return Z(e);let i=0,c=0,s=12;if(r>=4){const a=t.getUint32(0,!0);if(a>0&&a<r/12&&a<1e7&&(c=a,i=4,r>=8)){const u=t.getUint32(4,!0);u===3?(s=12,i=8):u===4?(s=16,i=8):u===6&&(s=24,i=8)}}c===0&&(r%16===0?(s=16,c=r/16):r%12===0?(s=12,c=r/12):r%15===0?(s=15,c=r/15):(s=12,c=Math.floor(r/12)));for(let a=0;a<c&&i+s<=r;a++){try{const u=t.getFloat32(i,!0),h=t.getFloat32(i+4,!0),f=t.getFloat32(i+8,!0);if(!Number.isFinite(u)||!Number.isFinite(h)||!Number.isFinite(f)||Math.abs(u)>1e5||Math.abs(h)>1e5||Math.abs(f)>1e5){i+=s;continue}const l={x:u,y:h,z:f};if(s===16){const y=t.getFloat32(i+12,!0);Number.isFinite(y)&&y>=0&&y<=1?l.intensity=y:(l.r=t.getUint8(i+12)/255,l.g=t.getUint8(i+13)/255,l.b=t.getUint8(i+14)/255)}else s===15?(l.r=t.getUint8(i+12)/255,l.g=t.getUint8(i+13)/255,l.b=t.getUint8(i+14)/255):s===24&&(l.r=t.getFloat32(i+12,!0),l.g=t.getFloat32(i+16,!0),l.b=t.getFloat32(i+20,!0));n.push(l)}catch{}i+=s}return n}function Z(e){const n=new Uint8Array(e),o=new DataView(e),t=[],r=o.getUint32(8,!0),i=o.getUint32(12,!0),c=(i&1)!==0,s=(i&2)!==0;let a=12;c&&(a+=3),s&&(a+=4);const u=16;for(let h=0;h<r;h++){let f=u+h*a;const l=o.getFloat32(f,!0),y=o.getFloat32(f+4,!0),B=o.getFloat32(f+8,!0);if(f+=12,!Number.isFinite(l)||!Number.isFinite(y)||!Number.isFinite(B))continue;const d={x:l,y,z:B};c&&(d.r=n[f]/255,d.g=n[f+1]/255,d.b=n[f+2]/255,f+=3),s&&(d.intensity=o.getFloat32(f,!0)),t.push(d)}return t}function z(e){try{const n=JSON.parse(e);if(Array.isArray(n)){if(n.length===0)return[];const o=n[0];if(Array.isArray(o))return n.map(t=>({x:t[0]??0,y:t[1]??0,z:t[2]??0,r:t[3],g:t[4],b:t[5],intensity:t[6]}));if(typeof o=="object"&&o!==null)return n.map(t=>({x:t.x??t.X??0,y:t.y??t.Y??0,z:t.z??t.Z??0,r:t.r??t.R??t.red,g:t.g??t.G??t.green,b:t.b??t.B??t.blue,intensity:t.intensity??t.i??t.I}))}if(n&&typeof n=="object"){const o=n.points||n.data||n.cloud;if(Array.isArray(o))return z(JSON.stringify(o))}return null}catch{return null}}function $(e){if(e.length===0)return{min:{x:0,y:0,z:0},max:{x:0,y:0,z:0}};let n=1/0,o=-1/0,t=1/0,r=-1/0,i=1/0,c=-1/0;for(const s of e)s.x<n&&(n=s.x),s.x>o&&(o=s.x),s.y<t&&(t=s.y),s.y>r&&(r=s.y),s.z<i&&(i=s.z),s.z>c&&(c=s.z);return{min:{x:n,y:t,z:i},max:{x:o,y:r,z:c}}}function G(e,n=1,o={x:0,y:0,z:0}){return n===1&&o.x===0&&o.y===0&&o.z===0?e:e.map(t=>({...t,x:t.x*n+o.x,y:t.y*n+o.y,z:t.z*n+o.z}))}function q(e,n){if(n<=0)return e;const o=new Map;for(const r of e){const i=Math.floor(r.x/n),c=Math.floor(r.y/n),s=Math.floor(r.z/n),a=`${i},${c},${s}`;o.has(a)||o.set(a,[]),o.get(a).push(r)}const t=[];for(const r of o.values()){const i={x:0,y:0,z:0};let c=!1,s=0,a=0,u=0,h=0,f=!1;for(const y of r)i.x+=y.x,i.y+=y.y,i.z+=y.z,y.r!==void 0&&(c=!0,s+=y.r,a+=y.g??0,u+=y.b??0),y.intensity!==void 0&&(f=!0,h+=y.intensity);const l=r.length;i.x/=l,i.y/=l,i.z/=l,c&&(i.r=s/l,i.g=a/l,i.b=u/l),f&&(i.intensity=h/l),t.push(i)}return t}function K(e){const n={attempts:0,isReconnecting:!1,lastAttempt:null,nextAttempt:null};let o=null;const{maxAttempts:t,delay:r,delayMax:i=r*10,backoffMultiplier:c=1.5,onAttempt:s,onSuccess:a,onFailure:u}=e;function h(){const d=r*Math.pow(c,n.attempts);return Math.min(d,i)}function f(d){if(n.isReconnecting||n.attempts>=t){n.attempts>=t&&(u==null||u());return}n.isReconnecting=!0,n.attempts++,n.lastAttempt=Date.now();const g=h();n.nextAttempt=Date.now()+g,s==null||s(n.attempts,t),o=setTimeout(async()=>{try{await d()?(l(),a==null||a()):(n.isReconnecting=!1,f(d))}catch{n.isReconnecting=!1,f(d)}},g)}function l(){n.attempts=0,n.isReconnecting=!1,n.lastAttempt=null,n.nextAttempt=null,o&&(clearTimeout(o),o=null)}function y(){n.isReconnecting=!1,n.nextAttempt=null,o&&(clearTimeout(o),o=null)}function B(){return n.attempts<t}return{state:n,scheduleReconnect:f,reset:l,cancel:y,shouldReconnect:B,calculateDelay:h}}function R(e){return new Promise(n=>setTimeout(n,e))}async function Q(e,n={}){const{maxAttempts:o=3,delay:t=1e3,delayMax:r=3e4,backoffMultiplier:i=2,onAttempt:c}=n;let s=null;for(let a=1;a<=o;a++)try{return c==null||c(a),await e()}catch(u){if(s=u instanceof Error?u:new Error(String(u)),a<o){const h=Math.min(t*Math.pow(i,a-1),r);await R(h)}}throw s}exports.DEFAULT_BBOX_COLORS=x;exports.DEFAULT_BBOX_COLORS_BY_ID=L;exports.DEFAULT_CLASS_LABELS=O;exports.bbox3DToDetection=w;exports.bboxesToDetectionFrame=j;exports.calculateBounds=$;exports.calculateIoU3D=D;exports.configureBBox=I;exports.createReconnectManager=K;exports.delay=R;exports.detectPointCloudFormat=J;exports.downsamplePointCloud=q;exports.filterByConfidence=V;exports.getBBoxColors=F;exports.getBBoxColorsByClassId=P;exports.getClassLabels=E;exports.getColorForClassId=A;exports.getColorForLabel=Y;exports.getLabelForClassId=S;exports.nms3D=H;exports.normalizeBboxes=v;exports.parseArrayBboxFormat=k;exports.parseArrayBoundingBox=_;exports.parseArrayBoundingBoxes=N;exports.parsePointCloudBinary=W;exports.parsePointCloudJSON=z;exports.resetBBoxConfig=M;exports.retryWithBackoff=Q;exports.setBBoxColor=X;exports.setBBoxColorByClassId=U;exports.setClassLabel=T;exports.transformPoints=G;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../src/utils/bbox.ts","../../src/utils/pointcloud.ts","../../src/utils/reconnect.ts"],"sourcesContent":["/**\r\n * Bounding Box utilities\r\n * @module vue-streaming/utils/bbox\r\n */\r\n\r\nimport type { BoundingBox3D, Detection } from \"../types\";\r\n\r\n// =============================================================================\r\n// Configuration Types\r\n// =============================================================================\r\n\r\n/**\r\n * Configuration options for bounding box colors and labels\r\n */\r\nexport interface BBoxConfig {\r\n /** Color palette for different object classes (by name) */\r\n colors?: Record<string, number>;\r\n /** Color palette for different object classes (by class ID) */\r\n colorsByClassId?: Record<number, number>;\r\n /** Class ID to label mapping */\r\n classLabels?: Record<number, string>;\r\n}\r\n\r\n// =============================================================================\r\n// Default Color Palettes\r\n// =============================================================================\r\n\r\n/**\r\n * Default color palette for different object classes (by name)\r\n */\r\nexport const DEFAULT_BBOX_COLORS: Record<string, number> = {\r\n person: 0xff0000,\r\n car: 0x00ff00,\r\n truck: 0x0000ff,\r\n bicycle: 0xffff00,\r\n motorcycle: 0xff00ff,\r\n bus: 0x00ffff,\r\n pedestrian: 0xff6600,\r\n vehicle: 0x00ff00,\r\n default: 0x00ff00,\r\n};\r\n\r\n/**\r\n * Default color palette for different object classes (by class ID)\r\n */\r\nexport const DEFAULT_BBOX_COLORS_BY_ID: Record<number, number> = {\r\n 0: 0xff0000, // Person - Red\r\n 1: 0x00ff00, // Car - Green\r\n 2: 0x0000ff, // Truck - Blue\r\n 3: 0xffff00, // Bicycle - Yellow\r\n 4: 0xff00ff, // Motorcycle - Magenta\r\n 5: 0x00ffff, // Bus - Cyan\r\n 6: 0xff8800, // Train - Orange\r\n 7: 0x88ff00, // Traffic Light - Lime\r\n 8: 0x0088ff, // Fire Hydrant - Light Blue\r\n 9: 0xff0088, // Stop Sign - Pink\r\n 10: 0x8800ff, // Parking Meter - Purple\r\n 11: 0x00ff88, // Bench - Teal\r\n 12: 0xffff88, // Bird - Light Yellow\r\n 13: 0x88ffff, // Cat - Light Cyan\r\n 14: 0xff88ff, // Dog - Light Magenta\r\n 15: 0x888888, // Horse - Gray\r\n 33: 0xff6600, // Class 33 - Orange\r\n};\r\n\r\n/**\r\n * Default class ID to label mapping\r\n */\r\nexport const DEFAULT_CLASS_LABELS: Record<number, string> = {\r\n 0: \"Person\",\r\n 1: \"Car\",\r\n 2: \"Truck\",\r\n 3: \"Bicycle\",\r\n 4: \"Motorcycle\",\r\n 5: \"Bus\",\r\n 6: \"Train\",\r\n 7: \"Traffic Light\",\r\n 8: \"Fire Hydrant\",\r\n 9: \"Stop Sign\",\r\n 10: \"Parking Meter\",\r\n 11: \"Bench\",\r\n 12: \"Bird\",\r\n 13: \"Cat\",\r\n 14: \"Dog\",\r\n 15: \"Horse\",\r\n 33: \"Object\",\r\n};\r\n\r\n// =============================================================================\r\n// Runtime Configuration (Mutable)\r\n// =============================================================================\r\n\r\n/**\r\n * Current runtime color palette for different object classes (by name)\r\n * @deprecated Use `getBBoxColors()` instead for reading, and `configureBBox()` for setting\r\n */\r\nexport let BBOX_COLORS: Record<string, number> = { ...DEFAULT_BBOX_COLORS };\r\n\r\n/**\r\n * Current runtime color palette for different object classes (by class ID)\r\n * @deprecated Use `getBBoxColorsByClassId()` instead for reading, and `configureBBox()` for setting\r\n */\r\nexport let BBOX_COLORS_BY_ID: Record<number, number> = {\r\n ...DEFAULT_BBOX_COLORS_BY_ID,\r\n};\r\n\r\n/**\r\n * Current runtime class ID to label mapping\r\n * @deprecated Use `getClassLabels()` instead for reading, and `configureBBox()` for setting\r\n */\r\nexport let CLASS_LABELS: Record<number, string> = { ...DEFAULT_CLASS_LABELS };\r\n\r\n// =============================================================================\r\n// Configuration Functions\r\n// =============================================================================\r\n\r\n/**\r\n * Configure bounding box colors and labels globally\r\n *\r\n * @param config - Configuration options\r\n * @example\r\n * ```typescript\r\n * import { configureBBox } from 'vue-streaming';\r\n *\r\n * // Override specific colors by label\r\n * configureBBox({\r\n * colors: {\r\n * person: 0x00ffff, // Cyan instead of red\r\n * car: 0xff00ff, // Magenta instead of green\r\n * }\r\n * });\r\n *\r\n * // Override colors by class ID\r\n * configureBBox({\r\n * colorsByClassId: {\r\n * 0: 0x00ffff, // Person - Cyan\r\n * 1: 0xff00ff, // Car - Magenta\r\n * }\r\n * });\r\n *\r\n * // Override class labels\r\n * configureBBox({\r\n * classLabels: {\r\n * 0: \"Human\", // Instead of \"Person\"\r\n * 1: \"Vehicle\", // Instead of \"Car\"\r\n * }\r\n * });\r\n *\r\n * // Configure all at once\r\n * configureBBox({\r\n * colors: { person: 0x00ffff },\r\n * colorsByClassId: { 0: 0x00ffff },\r\n * classLabels: { 0: \"Human\" }\r\n * });\r\n * ```\r\n */\r\nexport function configureBBox(config: BBoxConfig): void {\r\n if (config.colors) {\r\n BBOX_COLORS = { ...BBOX_COLORS, ...config.colors };\r\n }\r\n if (config.colorsByClassId) {\r\n BBOX_COLORS_BY_ID = { ...BBOX_COLORS_BY_ID, ...config.colorsByClassId };\r\n }\r\n if (config.classLabels) {\r\n CLASS_LABELS = { ...CLASS_LABELS, ...config.classLabels };\r\n }\r\n}\r\n\r\n/**\r\n * Reset bounding box configuration to defaults\r\n *\r\n * @example\r\n * ```typescript\r\n * import { resetBBoxConfig } from 'vue-streaming';\r\n *\r\n * // Reset all to defaults\r\n * resetBBoxConfig();\r\n * ```\r\n */\r\nexport function resetBBoxConfig(): void {\r\n BBOX_COLORS = { ...DEFAULT_BBOX_COLORS };\r\n BBOX_COLORS_BY_ID = { ...DEFAULT_BBOX_COLORS_BY_ID };\r\n CLASS_LABELS = { ...DEFAULT_CLASS_LABELS };\r\n}\r\n\r\n/**\r\n * Get current bounding box colors by label\r\n *\r\n * @returns Current color mapping by label name\r\n */\r\nexport function getBBoxColors(): Record<string, number> {\r\n return { ...BBOX_COLORS };\r\n}\r\n\r\n/**\r\n * Get current bounding box colors by class ID\r\n *\r\n * @returns Current color mapping by class ID\r\n */\r\nexport function getBBoxColorsByClassId(): Record<number, number> {\r\n return { ...BBOX_COLORS_BY_ID };\r\n}\r\n\r\n/**\r\n * Get current class labels\r\n *\r\n * @returns Current class label mapping\r\n */\r\nexport function getClassLabels(): Record<number, string> {\r\n return { ...CLASS_LABELS };\r\n}\r\n\r\n/**\r\n * Set a single color for a label\r\n *\r\n * @param label - The label name (e.g., \"person\", \"car\")\r\n * @param color - The color value (hex number, e.g., 0xff0000)\r\n */\r\nexport function setBBoxColor(label: string, color: number): void {\r\n BBOX_COLORS[label.toLowerCase()] = color;\r\n}\r\n\r\n/**\r\n * Set a single color for a class ID\r\n *\r\n * @param classId - The class ID number\r\n * @param color - The color value (hex number, e.g., 0xff0000)\r\n */\r\nexport function setBBoxColorByClassId(classId: number, color: number): void {\r\n BBOX_COLORS_BY_ID[classId] = color;\r\n}\r\n\r\n/**\r\n * Set a single class label\r\n *\r\n * @param classId - The class ID number\r\n * @param label - The label string\r\n */\r\nexport function setClassLabel(classId: number, label: string): void {\r\n CLASS_LABELS[classId] = label;\r\n}\r\n\r\n// =============================================================================\r\n// Color Utilities\r\n// =============================================================================\r\n\r\n/**\r\n * Get color for a specific label\r\n */\r\nexport function getColorForLabel(label: string): number {\r\n const normalizedLabel = label.toLowerCase();\r\n return BBOX_COLORS[normalizedLabel] ?? BBOX_COLORS.default;\r\n}\r\n\r\n/**\r\n * Get color for a specific class ID\r\n */\r\nexport function getColorForClassId(classId: number): number {\r\n return BBOX_COLORS_BY_ID[classId] ?? 0x00ff00;\r\n}\r\n\r\n/**\r\n * Get label for a specific class ID\r\n */\r\nexport function getLabelForClassId(classId: number): string {\r\n return CLASS_LABELS[classId] ?? `Class ${classId}`;\r\n}\r\n\r\n// =============================================================================\r\n// Parsing Utilities\r\n// =============================================================================\r\n\r\n/**\r\n * Parse array-format bounding box data\r\n * Format: [class_id, center_x, center_y, center_z, width, height, depth, rotation_yaw, confidence, ...]\r\n */\r\nexport function parseArrayBoundingBox(\r\n arr: number[],\r\n index: number = 0,\r\n): BoundingBox3D {\r\n const classId = arr[0] ?? 0;\r\n\r\n return {\r\n id: index,\r\n label: getLabelForClassId(classId),\r\n center: {\r\n x: arr[1] ?? 0,\r\n y: arr[2] ?? 0,\r\n z: arr[3] ?? 0,\r\n },\r\n dimensions: {\r\n width: arr[4] ?? 1,\r\n height: arr[5] ?? 1,\r\n depth: arr[6] ?? 1,\r\n },\r\n rotation: {\r\n x: 0,\r\n y: arr[7] ?? 0,\r\n z: 0,\r\n },\r\n confidence: arr[8] ?? 1,\r\n color: getColorForClassId(classId),\r\n };\r\n}\r\n\r\n/**\r\n * Parse array of array-format bounding boxes\r\n */\r\nexport function parseArrayBoundingBoxes(data: number[][]): BoundingBox3D[] {\r\n return data.map((arr, index) => parseArrayBoundingBox(arr, index));\r\n}\r\n\r\n/**\r\n * Parse array-format bounding boxes (person tracking format)\r\n * Format: [[object_id, cx, cy, cz, width, height, depth, rotation_yaw, confidence], ...]\r\n */\r\nexport function parseArrayBboxFormat(data: number[][]): BoundingBox3D[] {\r\n return data.map((arr, index) => {\r\n const personId = Math.floor(arr[0] ?? index);\r\n\r\n return {\r\n id: personId,\r\n label: `Person ${personId}`,\r\n center: {\r\n x: arr[1] ?? 0,\r\n y: arr[2] ?? 0,\r\n z: arr[3] ?? 0,\r\n },\r\n dimensions: {\r\n width: Math.abs(arr[4] ?? 1),\r\n height: Math.abs(arr[5] ?? 1),\r\n depth: Math.abs(arr[6] ?? 1),\r\n },\r\n rotation: {\r\n x: 0,\r\n y: arr[7] ?? 0,\r\n z: 0,\r\n },\r\n confidence: arr[8] ?? 1,\r\n color: 0x00ff00,\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * Normalize various bbox formats to BoundingBox3D\r\n */\r\nexport function normalizeBboxes(bboxes: unknown[]): BoundingBox3D[] {\r\n return bboxes.map((bbox: unknown, index: number) => {\r\n const b = bbox as Record<string, unknown>;\r\n\r\n const center = (b.center as { x: number; y: number; z: number }) || {\r\n x: (b.x as number) || (b.centerX as number) || 0,\r\n y: (b.y as number) || (b.centerY as number) || 0,\r\n z: (b.z as number) || (b.centerZ as number) || 0,\r\n };\r\n\r\n const dimensions = (b.dimensions as {\r\n width: number;\r\n height: number;\r\n depth: number;\r\n }) ||\r\n (b.size as { width: number; height: number; depth: number }) || {\r\n width: (b.width as number) || (b.w as number) || 1,\r\n height: (b.height as number) || (b.h as number) || 1,\r\n depth:\r\n (b.depth as number) || (b.d as number) || (b.length as number) || 1,\r\n };\r\n\r\n const rotation = (b.rotation as { x: number; y: number; z: number }) || {\r\n x: (b.rotX as number) || (b.rx as number) || 0,\r\n y: (b.rotY as number) || (b.ry as number) || (b.yaw as number) || 0,\r\n z: (b.rotZ as number) || (b.rz as number) || 0,\r\n };\r\n\r\n return {\r\n id: (b.id as string | number) ?? index,\r\n label:\r\n (b.label as string) || (b.class as string) || (b.className as string),\r\n center,\r\n dimensions,\r\n rotation,\r\n color: b.color as string | number | undefined,\r\n confidence:\r\n (b.confidence as number) || (b.score as number) || (b.prob as number),\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * Convert BoundingBox3D to Detection (2D projection)\r\n */\r\nexport function bbox3DToDetection(bbox: BoundingBox3D): Detection {\r\n return {\r\n id: bbox.id,\r\n label: bbox.label || \"unknown\",\r\n confidence: bbox.confidence || 1,\r\n boundingBox: {\r\n x: bbox.center.x - (bbox.dimensions.width || 1) / 2,\r\n y: bbox.center.y - (bbox.dimensions.height || 1) / 2,\r\n width: bbox.dimensions.width || 1,\r\n height: bbox.dimensions.height || 1,\r\n },\r\n trackId: String(bbox.id),\r\n };\r\n}\r\n\r\n/**\r\n * Convert array of BoundingBox3D to DetectionFrame\r\n */\r\nexport function bboxesToDetectionFrame(bboxes: BoundingBox3D[]): {\r\n detections: Detection[];\r\n timestamp: number;\r\n} {\r\n return {\r\n detections: bboxes.map(bbox3DToDetection),\r\n timestamp: Date.now(),\r\n };\r\n}\r\n\r\n/**\r\n * Calculate IoU (Intersection over Union) between two 3D bounding boxes\r\n */\r\nexport function calculateIoU3D(\r\n box1: BoundingBox3D,\r\n box2: BoundingBox3D,\r\n): number {\r\n const { center: c1, dimensions: d1 } = box1;\r\n const { center: c2, dimensions: d2 } = box2;\r\n\r\n // Calculate intersection\r\n const x1 = Math.max(c1.x - d1.width / 2, c2.x - d2.width / 2);\r\n const y1 = Math.max(c1.y - d1.height / 2, c2.y - d2.height / 2);\r\n const z1 = Math.max(c1.z - d1.depth / 2, c2.z - d2.depth / 2);\r\n\r\n const x2 = Math.min(c1.x + d1.width / 2, c2.x + d2.width / 2);\r\n const y2 = Math.min(c1.y + d1.height / 2, c2.y + d2.height / 2);\r\n const z2 = Math.min(c1.z + d1.depth / 2, c2.z + d2.depth / 2);\r\n\r\n const intersectionWidth = Math.max(0, x2 - x1);\r\n const intersectionHeight = Math.max(0, y2 - y1);\r\n const intersectionDepth = Math.max(0, z2 - z1);\r\n\r\n const intersectionVolume =\r\n intersectionWidth * intersectionHeight * intersectionDepth;\r\n\r\n // Calculate union\r\n const volume1 = d1.width * d1.height * d1.depth;\r\n const volume2 = d2.width * d2.height * d2.depth;\r\n const unionVolume = volume1 + volume2 - intersectionVolume;\r\n\r\n return unionVolume > 0 ? intersectionVolume / unionVolume : 0;\r\n}\r\n\r\n/**\r\n * Filter bounding boxes by confidence threshold\r\n */\r\nexport function filterByConfidence(\r\n bboxes: BoundingBox3D[],\r\n threshold: number,\r\n): BoundingBox3D[] {\r\n return bboxes.filter((bbox) => (bbox.confidence ?? 1) >= threshold);\r\n}\r\n\r\n/**\r\n * Non-maximum suppression for 3D bounding boxes\r\n */\r\nexport function nms3D(\r\n bboxes: BoundingBox3D[],\r\n iouThreshold: number = 0.5,\r\n): BoundingBox3D[] {\r\n if (bboxes.length === 0) return [];\r\n\r\n // Sort by confidence (descending)\r\n const sorted = [...bboxes].sort(\r\n (a, b) => (b.confidence ?? 1) - (a.confidence ?? 1),\r\n );\r\n const kept: BoundingBox3D[] = [];\r\n const suppressed = new Set<number>();\r\n\r\n for (let i = 0; i < sorted.length; i++) {\r\n if (suppressed.has(i)) continue;\r\n\r\n kept.push(sorted[i]);\r\n\r\n for (let j = i + 1; j < sorted.length; j++) {\r\n if (suppressed.has(j)) continue;\r\n\r\n const iou = calculateIoU3D(sorted[i], sorted[j]);\r\n if (iou >= iouThreshold) {\r\n suppressed.add(j);\r\n }\r\n }\r\n }\r\n\r\n return kept;\r\n}\r\n","/**\r\n * Point Cloud parsing utilities\r\n * @module vue-streaming/utils/pointcloud\r\n */\r\n\r\nimport type { DecodedPointCloud, Point3D, PointCloudFormat } from \"../types\";\r\n\r\n// =============================================================================\r\n// Magic Bytes for Format Detection\r\n// =============================================================================\r\n\r\nconst MAGIC_BYTES = {\r\n DRACO: [0x44, 0x52, 0x41, 0x43, 0x4f], // \"DRACO\"\r\n BINARY_HEADER: [0x50, 0x43, 0x4c, 0x44], // \"PCLD\"\r\n PLY: [0x70, 0x6c, 0x79], // \"ply\"\r\n PCD: [0x23, 0x20, 0x2e, 0x50, 0x43, 0x44], // \"# .PCD\"\r\n};\r\n\r\n/**\r\n * Detect point cloud format from data\r\n */\r\nexport function detectPointCloudFormat(\r\n data: ArrayBuffer | Uint8Array | string,\r\n): PointCloudFormat {\r\n if (typeof data === \"string\") {\r\n try {\r\n JSON.parse(data);\r\n return \"json\";\r\n } catch {\r\n if (data.startsWith(\"ply\")) return \"ply\";\r\n if (data.startsWith(\"# .PCD\")) return \"pcd\";\r\n }\r\n }\r\n\r\n const bytes = new Uint8Array(\r\n data instanceof ArrayBuffer\r\n ? data\r\n : data instanceof Uint8Array\r\n ? data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength)\r\n : new TextEncoder().encode(data).buffer,\r\n );\r\n\r\n if (matchMagicBytes(bytes, MAGIC_BYTES.DRACO)) return \"draco\";\r\n if (matchMagicBytes(bytes, MAGIC_BYTES.BINARY_HEADER)) return \"binary-header\";\r\n if (matchMagicBytes(bytes, MAGIC_BYTES.PLY)) return \"ply\";\r\n if (matchMagicBytes(bytes, MAGIC_BYTES.PCD)) return \"pcd\";\r\n\r\n // Check by size\r\n if (bytes.length % 12 === 0) return \"raw-float32\";\r\n if (bytes.length % 24 === 0) return \"raw-float32-rgb\";\r\n\r\n return \"raw-float32\";\r\n}\r\n\r\nfunction matchMagicBytes(data: Uint8Array, magic: number[]): boolean {\r\n if (data.length < magic.length) return false;\r\n for (let i = 0; i < magic.length; i++) {\r\n if (data[i] !== magic[i]) return false;\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n * Parse binary point cloud data\r\n */\r\nexport function parsePointCloudBinary(buffer: ArrayBuffer): Point3D[] {\r\n const points: Point3D[] = [];\r\n const bytes = new Uint8Array(buffer);\r\n const dataView = new DataView(buffer);\r\n const byteLength = buffer.byteLength;\r\n\r\n // Check for DRACO format\r\n if (byteLength >= 5) {\r\n const magic = String.fromCharCode(\r\n bytes[0],\r\n bytes[1],\r\n bytes[2],\r\n bytes[3],\r\n bytes[4],\r\n );\r\n if (magic === \"DRACO\") {\r\n console.warn(\r\n \"[PointCloud] DRACO format detected - requires external decoder\",\r\n );\r\n return [];\r\n }\r\n }\r\n\r\n // Check for PCLD header format\r\n if (byteLength >= 4) {\r\n const magic = String.fromCharCode(bytes[0], bytes[1], bytes[2], bytes[3]);\r\n if (magic === \"PCLD\") {\r\n return decodePCLDFormat(buffer);\r\n }\r\n }\r\n\r\n // Detect format based on buffer size\r\n let offset = 0;\r\n let pointCount = 0;\r\n let bytesPerPoint = 12; // Default: XYZ float32\r\n\r\n // Try to read header if present\r\n if (byteLength >= 4) {\r\n const possibleCount = dataView.getUint32(0, true);\r\n if (\r\n possibleCount > 0 &&\r\n possibleCount < byteLength / 12 &&\r\n possibleCount < 10000000\r\n ) {\r\n pointCount = possibleCount;\r\n offset = 4;\r\n\r\n if (byteLength >= 8) {\r\n const formatIndicator = dataView.getUint32(4, true);\r\n if (formatIndicator === 3) {\r\n bytesPerPoint = 12;\r\n offset = 8;\r\n } else if (formatIndicator === 4) {\r\n bytesPerPoint = 16;\r\n offset = 8;\r\n } else if (formatIndicator === 6) {\r\n bytesPerPoint = 24;\r\n offset = 8;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Calculate based on buffer size if no header\r\n if (pointCount === 0) {\r\n if (byteLength % 16 === 0) {\r\n bytesPerPoint = 16;\r\n pointCount = byteLength / 16;\r\n } else if (byteLength % 12 === 0) {\r\n bytesPerPoint = 12;\r\n pointCount = byteLength / 12;\r\n } else if (byteLength % 15 === 0) {\r\n bytesPerPoint = 15;\r\n pointCount = byteLength / 15;\r\n } else {\r\n bytesPerPoint = 12;\r\n pointCount = Math.floor(byteLength / 12);\r\n }\r\n }\r\n\r\n // Parse points\r\n for (let i = 0; i < pointCount && offset + bytesPerPoint <= byteLength; i++) {\r\n try {\r\n const x = dataView.getFloat32(offset, true);\r\n const y = dataView.getFloat32(offset + 4, true);\r\n const z = dataView.getFloat32(offset + 8, true);\r\n\r\n if (\r\n !Number.isFinite(x) ||\r\n !Number.isFinite(y) ||\r\n !Number.isFinite(z) ||\r\n Math.abs(x) > 100000 ||\r\n Math.abs(y) > 100000 ||\r\n Math.abs(z) > 100000\r\n ) {\r\n offset += bytesPerPoint;\r\n continue;\r\n }\r\n\r\n const point: Point3D = { x, y, z };\r\n\r\n if (bytesPerPoint === 16) {\r\n const extraValue = dataView.getFloat32(offset + 12, true);\r\n if (Number.isFinite(extraValue) && extraValue >= 0 && extraValue <= 1) {\r\n point.intensity = extraValue;\r\n } else {\r\n point.r = dataView.getUint8(offset + 12) / 255;\r\n point.g = dataView.getUint8(offset + 13) / 255;\r\n point.b = dataView.getUint8(offset + 14) / 255;\r\n }\r\n } else if (bytesPerPoint === 15) {\r\n point.r = dataView.getUint8(offset + 12) / 255;\r\n point.g = dataView.getUint8(offset + 13) / 255;\r\n point.b = dataView.getUint8(offset + 14) / 255;\r\n } else if (bytesPerPoint === 24) {\r\n point.r = dataView.getFloat32(offset + 12, true);\r\n point.g = dataView.getFloat32(offset + 16, true);\r\n point.b = dataView.getFloat32(offset + 20, true);\r\n }\r\n\r\n points.push(point);\r\n } catch {\r\n // Skip malformed points\r\n }\r\n\r\n offset += bytesPerPoint;\r\n }\r\n\r\n return points;\r\n}\r\n\r\n/**\r\n * Decode PCLD header format\r\n */\r\nfunction decodePCLDFormat(buffer: ArrayBuffer): Point3D[] {\r\n const bytes = new Uint8Array(buffer);\r\n const view = new DataView(buffer);\r\n const points: Point3D[] = [];\r\n\r\n const numPoints = view.getUint32(8, true);\r\n const flags = view.getUint32(12, true);\r\n\r\n const hasColor = (flags & 0x01) !== 0;\r\n const hasIntensity = (flags & 0x02) !== 0;\r\n\r\n let bytesPerPoint = 12;\r\n if (hasColor) bytesPerPoint += 3;\r\n if (hasIntensity) bytesPerPoint += 4;\r\n\r\n const headerSize = 16;\r\n\r\n for (let i = 0; i < numPoints; i++) {\r\n let offset = headerSize + i * bytesPerPoint;\r\n\r\n const x = view.getFloat32(offset, true);\r\n const y = view.getFloat32(offset + 4, true);\r\n const z = view.getFloat32(offset + 8, true);\r\n offset += 12;\r\n\r\n if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z))\r\n continue;\r\n\r\n const point: Point3D = { x, y, z };\r\n\r\n if (hasColor) {\r\n point.r = bytes[offset] / 255;\r\n point.g = bytes[offset + 1] / 255;\r\n point.b = bytes[offset + 2] / 255;\r\n offset += 3;\r\n }\r\n\r\n if (hasIntensity) {\r\n point.intensity = view.getFloat32(offset, true);\r\n }\r\n\r\n points.push(point);\r\n }\r\n\r\n return points;\r\n}\r\n\r\n/**\r\n * Parse JSON point cloud data\r\n */\r\nexport function parsePointCloudJSON(text: string): Point3D[] | null {\r\n try {\r\n const data = JSON.parse(text);\r\n\r\n if (Array.isArray(data)) {\r\n if (data.length === 0) return [];\r\n\r\n const first = data[0];\r\n\r\n // Array of arrays [[x,y,z], ...]\r\n if (Array.isArray(first)) {\r\n return data.map((arr: number[]) => ({\r\n x: arr[0] ?? 0,\r\n y: arr[1] ?? 0,\r\n z: arr[2] ?? 0,\r\n r: arr[3],\r\n g: arr[4],\r\n b: arr[5],\r\n intensity: arr[6],\r\n }));\r\n }\r\n\r\n // Array of objects [{x,y,z}, ...]\r\n if (typeof first === \"object\" && first !== null) {\r\n return data.map((p: Record<string, number>) => ({\r\n x: p.x ?? p.X ?? 0,\r\n y: p.y ?? p.Y ?? 0,\r\n z: p.z ?? p.Z ?? 0,\r\n r: p.r ?? p.R ?? p.red,\r\n g: p.g ?? p.G ?? p.green,\r\n b: p.b ?? p.B ?? p.blue,\r\n intensity: p.intensity ?? p.i ?? p.I,\r\n }));\r\n }\r\n }\r\n\r\n // Object with points array\r\n if (data && typeof data === \"object\") {\r\n const pointsArray = data.points || data.data || data.cloud;\r\n if (Array.isArray(pointsArray)) {\r\n return parsePointCloudJSON(JSON.stringify(pointsArray));\r\n }\r\n }\r\n\r\n return null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Calculate bounds for point cloud\r\n */\r\nexport function calculateBounds(\r\n points: Point3D[],\r\n): DecodedPointCloud[\"bounds\"] {\r\n if (points.length === 0) {\r\n return {\r\n min: { x: 0, y: 0, z: 0 },\r\n max: { x: 0, y: 0, z: 0 },\r\n };\r\n }\r\n\r\n let minX = Infinity,\r\n maxX = -Infinity;\r\n let minY = Infinity,\r\n maxY = -Infinity;\r\n let minZ = Infinity,\r\n maxZ = -Infinity;\r\n\r\n for (const p of points) {\r\n if (p.x < minX) minX = p.x;\r\n if (p.x > maxX) maxX = p.x;\r\n if (p.y < minY) minY = p.y;\r\n if (p.y > maxY) maxY = p.y;\r\n if (p.z < minZ) minZ = p.z;\r\n if (p.z > maxZ) maxZ = p.z;\r\n }\r\n\r\n return {\r\n min: { x: minX, y: minY, z: minZ },\r\n max: { x: maxX, y: maxY, z: maxZ },\r\n };\r\n}\r\n\r\n/**\r\n * Transform points with scale and offset\r\n */\r\nexport function transformPoints(\r\n points: Point3D[],\r\n scale: number = 1,\r\n offset: { x: number; y: number; z: number } = { x: 0, y: 0, z: 0 },\r\n): Point3D[] {\r\n if (scale === 1 && offset.x === 0 && offset.y === 0 && offset.z === 0) {\r\n return points;\r\n }\r\n\r\n return points.map((p) => ({\r\n ...p,\r\n x: p.x * scale + offset.x,\r\n y: p.y * scale + offset.y,\r\n z: p.z * scale + offset.z,\r\n }));\r\n}\r\n\r\n/**\r\n * Downsample point cloud using voxel grid\r\n */\r\nexport function downsamplePointCloud(\r\n points: Point3D[],\r\n voxelSize: number,\r\n): Point3D[] {\r\n if (voxelSize <= 0) return points;\r\n\r\n const voxelMap = new Map<string, Point3D[]>();\r\n\r\n for (const point of points) {\r\n const vx = Math.floor(point.x / voxelSize);\r\n const vy = Math.floor(point.y / voxelSize);\r\n const vz = Math.floor(point.z / voxelSize);\r\n const key = `${vx},${vy},${vz}`;\r\n\r\n if (!voxelMap.has(key)) {\r\n voxelMap.set(key, []);\r\n }\r\n voxelMap.get(key)!.push(point);\r\n }\r\n\r\n const result: Point3D[] = [];\r\n\r\n for (const voxelPoints of voxelMap.values()) {\r\n // Average all points in voxel\r\n const avg: Point3D = { x: 0, y: 0, z: 0 };\r\n let hasColor = false;\r\n let r = 0,\r\n g = 0,\r\n b = 0;\r\n let intensity = 0;\r\n let hasIntensity = false;\r\n\r\n for (const p of voxelPoints) {\r\n avg.x += p.x;\r\n avg.y += p.y;\r\n avg.z += p.z;\r\n\r\n if (p.r !== undefined) {\r\n hasColor = true;\r\n r += p.r;\r\n g += p.g ?? 0;\r\n b += p.b ?? 0;\r\n }\r\n\r\n if (p.intensity !== undefined) {\r\n hasIntensity = true;\r\n intensity += p.intensity;\r\n }\r\n }\r\n\r\n const count = voxelPoints.length;\r\n avg.x /= count;\r\n avg.y /= count;\r\n avg.z /= count;\r\n\r\n if (hasColor) {\r\n avg.r = r / count;\r\n avg.g = g / count;\r\n avg.b = b / count;\r\n }\r\n\r\n if (hasIntensity) {\r\n avg.intensity = intensity / count;\r\n }\r\n\r\n result.push(avg);\r\n }\r\n\r\n return result;\r\n}\r\n","/**\r\n * Reconnection utilities\r\n * @module vue-streaming/utils/reconnect\r\n */\r\n\r\nimport type { ReconnectOptions } from \"../types\";\r\n\r\nexport interface ReconnectState {\r\n attempts: number;\r\n isReconnecting: boolean;\r\n lastAttempt: number | null;\r\n nextAttempt: number | null;\r\n}\r\n\r\n/**\r\n * Create a reconnection manager with exponential backoff\r\n */\r\nexport function createReconnectManager(options: ReconnectOptions) {\r\n const state: ReconnectState = {\r\n attempts: 0,\r\n isReconnecting: false,\r\n lastAttempt: null,\r\n nextAttempt: null,\r\n };\r\n\r\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\r\n\r\n const {\r\n maxAttempts,\r\n delay,\r\n delayMax = delay * 10,\r\n backoffMultiplier = 1.5,\r\n onAttempt,\r\n onSuccess,\r\n onFailure,\r\n } = options;\r\n\r\n /**\r\n * Calculate delay with exponential backoff\r\n */\r\n function calculateDelay(): number {\r\n const baseDelay = delay * Math.pow(backoffMultiplier, state.attempts);\r\n return Math.min(baseDelay, delayMax);\r\n }\r\n\r\n /**\r\n * Schedule a reconnection attempt\r\n */\r\n function scheduleReconnect(connectFn: () => Promise<boolean>): void {\r\n if (state.isReconnecting || state.attempts >= maxAttempts) {\r\n if (state.attempts >= maxAttempts) {\r\n onFailure?.();\r\n }\r\n return;\r\n }\r\n\r\n state.isReconnecting = true;\r\n state.attempts++;\r\n state.lastAttempt = Date.now();\r\n\r\n const currentDelay = calculateDelay();\r\n state.nextAttempt = Date.now() + currentDelay;\r\n\r\n onAttempt?.(state.attempts, maxAttempts);\r\n\r\n timeoutId = setTimeout(async () => {\r\n try {\r\n const success = await connectFn();\r\n if (success) {\r\n reset();\r\n onSuccess?.();\r\n } else {\r\n state.isReconnecting = false;\r\n scheduleReconnect(connectFn);\r\n }\r\n } catch {\r\n state.isReconnecting = false;\r\n scheduleReconnect(connectFn);\r\n }\r\n }, currentDelay);\r\n }\r\n\r\n /**\r\n * Reset reconnection state\r\n */\r\n function reset(): void {\r\n state.attempts = 0;\r\n state.isReconnecting = false;\r\n state.lastAttempt = null;\r\n state.nextAttempt = null;\r\n\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n timeoutId = null;\r\n }\r\n }\r\n\r\n /**\r\n * Cancel pending reconnection\r\n */\r\n function cancel(): void {\r\n state.isReconnecting = false;\r\n state.nextAttempt = null;\r\n\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n timeoutId = null;\r\n }\r\n }\r\n\r\n /**\r\n * Check if should attempt reconnection\r\n */\r\n function shouldReconnect(): boolean {\r\n return state.attempts < maxAttempts;\r\n }\r\n\r\n return {\r\n state,\r\n scheduleReconnect,\r\n reset,\r\n cancel,\r\n shouldReconnect,\r\n calculateDelay,\r\n };\r\n}\r\n\r\n/**\r\n * Simple delay utility\r\n */\r\nexport function delay(ms: number): Promise<void> {\r\n return new Promise((resolve) => setTimeout(resolve, ms));\r\n}\r\n\r\n/**\r\n * Retry a function with exponential backoff\r\n */\r\nexport async function retryWithBackoff<T>(\r\n fn: () => Promise<T>,\r\n options: {\r\n maxAttempts?: number;\r\n delay?: number;\r\n delayMax?: number;\r\n backoffMultiplier?: number;\r\n onAttempt?: (attempt: number) => void;\r\n } = {},\r\n): Promise<T> {\r\n const {\r\n maxAttempts = 3,\r\n delay: baseDelay = 1000,\r\n delayMax = 30000,\r\n backoffMultiplier = 2,\r\n onAttempt,\r\n } = options;\r\n\r\n let lastError: Error | null = null;\r\n\r\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\r\n try {\r\n onAttempt?.(attempt);\r\n return await fn();\r\n } catch (error) {\r\n lastError = error instanceof Error ? error : new Error(String(error));\r\n\r\n if (attempt < maxAttempts) {\r\n const waitTime = Math.min(\r\n baseDelay * Math.pow(backoffMultiplier, attempt - 1),\r\n delayMax,\r\n );\r\n await delay(waitTime);\r\n }\r\n }\r\n }\r\n\r\n throw lastError;\r\n}\r\n"],"names":["DEFAULT_BBOX_COLORS","DEFAULT_BBOX_COLORS_BY_ID","DEFAULT_CLASS_LABELS","BBOX_COLORS","BBOX_COLORS_BY_ID","CLASS_LABELS","configureBBox","config","resetBBoxConfig","getBBoxColors","getBBoxColorsByClassId","getClassLabels","setBBoxColor","label","color","setBBoxColorByClassId","classId","setClassLabel","getColorForLabel","normalizedLabel","getColorForClassId","getLabelForClassId","parseArrayBoundingBox","arr","index","parseArrayBoundingBoxes","data","parseArrayBboxFormat","personId","normalizeBboxes","bboxes","bbox","b","center","dimensions","rotation","bbox3DToDetection","bboxesToDetectionFrame","calculateIoU3D","box1","box2","c1","d1","c2","d2","x1","y1","z1","x2","y2","z2","intersectionWidth","intersectionHeight","intersectionDepth","intersectionVolume","volume1","volume2","unionVolume","filterByConfidence","threshold","nms3D","iouThreshold","sorted","a","kept","suppressed","j","MAGIC_BYTES","detectPointCloudFormat","bytes","matchMagicBytes","magic","i","parsePointCloudBinary","buffer","points","dataView","byteLength","decodePCLDFormat","offset","pointCount","bytesPerPoint","possibleCount","formatIndicator","x","y","z","point","extraValue","view","numPoints","flags","hasColor","hasIntensity","headerSize","parsePointCloudJSON","text","first","p","pointsArray","calculateBounds","minX","maxX","minY","maxY","minZ","maxZ","transformPoints","scale","downsamplePointCloud","voxelSize","voxelMap","vx","vy","vz","key","result","voxelPoints","avg","r","g","intensity","count","createReconnectManager","options","state","timeoutId","maxAttempts","delay","delayMax","backoffMultiplier","onAttempt","onSuccess","onFailure","calculateDelay","baseDelay","scheduleReconnect","connectFn","currentDelay","reset","cancel","shouldReconnect","ms","resolve","retryWithBackoff","fn","lastError","attempt","error","waitTime"],"mappings":"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"}