release: bump version to 0.48.0
This commit is contained in:
@@ -54,6 +54,8 @@ interface UseWebSocketOptions {
|
||||
|
||||
interface UseWebSocketReturn {
|
||||
connected: boolean
|
||||
connecting: boolean
|
||||
status: 'connecting' | 'connected' | 'disconnected'
|
||||
lastMessage: WebSocketMessage | null
|
||||
sendMessage: (message: Record<string, unknown>) => void
|
||||
subscribe: (channels: string[]) => void
|
||||
@@ -65,6 +67,7 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
const {
|
||||
autoConnect = true,
|
||||
autoSubscribe = [],
|
||||
heartbeatInterval = 25000,
|
||||
onMessage,
|
||||
onConnect,
|
||||
onDisconnect,
|
||||
@@ -75,6 +78,7 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
|
||||
const wsRef = useRef<WebSocket | null>(null)
|
||||
const [connected, setConnected] = useState(false)
|
||||
const [connecting, setConnecting] = useState(false)
|
||||
const [lastMessage, setLastMessage] = useState<WebSocketMessage | null>(null)
|
||||
const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||
const heartbeatTimerRef = useRef<ReturnType<typeof setInterval> | null>(null)
|
||||
@@ -97,17 +101,21 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
|
||||
const connect = useCallback(() => {
|
||||
if (!token) {
|
||||
setConnected(false)
|
||||
setConnecting(false)
|
||||
return
|
||||
}
|
||||
|
||||
intentionalCloseRef.current = false
|
||||
setConnected(false)
|
||||
setConnecting(true)
|
||||
const candidates = buildWebSocketCandidates()
|
||||
let candidateIndex = 0
|
||||
let opened = false
|
||||
|
||||
const tryConnect = () => {
|
||||
const baseUrl = candidates[candidateIndex]
|
||||
const wsUrl = `${baseUrl}?token=${token}`
|
||||
const wsUrl = `${baseUrl}?token=${encodeURIComponent(token)}`
|
||||
activeWsUrlRef.current = baseUrl
|
||||
const ws = new WebSocket(wsUrl)
|
||||
|
||||
@@ -119,15 +127,27 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
}
|
||||
opened = true
|
||||
setConnected(true)
|
||||
setConnecting(false)
|
||||
if (autoSubscribeRef.current.length > 0) {
|
||||
ws.send(JSON.stringify({ type: 'subscribe', data: { channels: autoSubscribeRef.current } }))
|
||||
}
|
||||
if (heartbeatTimerRef.current) {
|
||||
clearInterval(heartbeatTimerRef.current)
|
||||
}
|
||||
heartbeatTimerRef.current = setInterval(() => {
|
||||
if (ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({ type: 'heartbeat' }))
|
||||
}
|
||||
}, heartbeatInterval)
|
||||
onConnectRef.current?.()
|
||||
}
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
try {
|
||||
const message: WebSocketMessage = JSON.parse(event.data)
|
||||
if (message.type === 'heartbeat' && message.data?.action === 'ping' && ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({ type: 'heartbeat' }))
|
||||
}
|
||||
setLastMessage(message)
|
||||
onMessageRef.current?.(message)
|
||||
} catch {
|
||||
@@ -150,10 +170,13 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
|
||||
if (!opened && candidateIndex < candidates.length - 1) {
|
||||
candidateIndex += 1
|
||||
setConnecting(true)
|
||||
tryConnect()
|
||||
return
|
||||
}
|
||||
|
||||
setConnecting(false)
|
||||
|
||||
if (intentionalCloseRef.current) {
|
||||
return
|
||||
}
|
||||
@@ -169,6 +192,9 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
|
||||
ws.onerror = (error) => {
|
||||
setConnected(false)
|
||||
if (opened || candidateIndex >= candidates.length - 1) {
|
||||
setConnecting(false)
|
||||
}
|
||||
if (intentionalCloseRef.current || ws.readyState === WebSocket.CLOSING || ws.readyState === WebSocket.CLOSED) {
|
||||
return
|
||||
}
|
||||
@@ -185,6 +211,7 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
tryConnect()
|
||||
} catch (error) {
|
||||
setConnected(false)
|
||||
setConnecting(false)
|
||||
console.warn('[WebSocket] Failed to initialize connection', { url: activeWsUrlRef.current, error })
|
||||
if (autoConnect && token) {
|
||||
reconnectTimeoutRef.current = setTimeout(() => {
|
||||
@@ -192,7 +219,7 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
}, 3000)
|
||||
}
|
||||
}
|
||||
}, [token, autoConnect])
|
||||
}, [token, autoConnect, heartbeatInterval])
|
||||
|
||||
const disconnect = useCallback(() => {
|
||||
intentionalCloseRef.current = true
|
||||
@@ -213,6 +240,7 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
}
|
||||
}
|
||||
setConnected(false)
|
||||
setConnecting(false)
|
||||
}, [])
|
||||
|
||||
const sendMessage = useCallback((message: Record<string, unknown>) => {
|
||||
@@ -237,6 +265,8 @@ export function useWebSocket(options: UseWebSocketOptions = {}): UseWebSocketRet
|
||||
|
||||
return {
|
||||
connected,
|
||||
connecting,
|
||||
status: connected ? 'connected' : connecting ? 'connecting' : 'disconnected',
|
||||
lastMessage,
|
||||
sendMessage,
|
||||
subscribe,
|
||||
|
||||
Reference in New Issue
Block a user