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.
- package/README.md +425 -699
- package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-C_F2vNNk.js +1081 -0
- package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-C_F2vNNk.js.map +1 -0
- package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-EzMJEQkx.cjs +2 -0
- package/dist/WebSocketStream.vue_vue_type_script_setup_true_lang-EzMJEQkx.cjs.map +1 -0
- package/dist/components/index.cjs +2 -0
- package/dist/components/index.cjs.map +1 -0
- package/dist/components/index.js +15 -0
- package/dist/components/index.js.map +1 -0
- package/dist/composables/index.cjs +2 -0
- package/dist/composables/index.cjs.map +1 -0
- package/dist/composables/index.js +15 -0
- package/dist/composables/index.js.map +1 -0
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +62 -2
- package/dist/index.js.map +1 -1
- package/dist/types.cjs +2 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/usePointCloud-D0qcpYFY.js +115 -0
- package/dist/usePointCloud-D0qcpYFY.js.map +1 -0
- package/dist/usePointCloud-D2csBAs8.cjs +2 -0
- package/dist/usePointCloud-D2csBAs8.cjs.map +1 -0
- package/dist/useWebSocket-7-qar6to.cjs +4 -0
- package/dist/useWebSocket-7-qar6to.cjs.map +1 -0
- package/dist/useWebSocket-CrE6QkTW.js +1278 -0
- package/dist/useWebSocket-CrE6QkTW.js.map +1 -0
- package/dist/utils/index.cjs +2 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.js +503 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/vue-streaming.css +1 -0
- package/package.json +126 -69
- package/dist/index.d.cts +0 -49
- package/dist/index.d.ts +0 -49
- package/dist/index.global.js +0 -8
- package/dist/index.global.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useWebSocket-7-qar6to.cjs","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","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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"}
|