ironie-nextjs/src/app/lib/useSSEStore.ts
2025-06-19 23:07:19 +02:00

72 lines
1.7 KiB
TypeScript

import { create } from 'zustand'
type SSEState = {
source: EventSource | null
isConnected: boolean
connect: (steamId: string) => EventSource | undefined
disconnect: () => void
}
export const useSSE = create<SSEState>((set, get) => {
let reconnectTimeout: NodeJS.Timeout | null = null
const connect = (steamId: string): EventSource | undefined => {
const current = get().source
if (current) return current
const source = new EventSource(`http://localhost:3001/events?steamId=${steamId}`)
source.onopen = () => {
set({ source, isConnected: true })
}
source.onmessage = (event) => {
console.log('[SSE] Nachricht:', event.data)
}
source.addEventListener('notification', (event) => {
try {
const data = JSON.parse((event as MessageEvent).data)
window.dispatchEvent(new CustomEvent(`sse-${data.type}`, { detail: data }))
} catch (err) {
console.error('[SSE] Ungültige Nachricht:', event)
}
})
source.onerror = (err) => {
console.warn('[SSE] Verbindung verloren, versuche Reconnect...')
source.close()
set({ source: null, isConnected: false })
if (!reconnectTimeout) {
reconnectTimeout = setTimeout(() => {
reconnectTimeout = null
connect(steamId)
}, 3000)
}
}
set({ source })
return source // ✅ wichtig
}
const disconnect = () => {
const source = get().source
if (source) {
source.close()
}
if (reconnectTimeout) {
clearTimeout(reconnectTimeout)
reconnectTimeout = null
}
set({ source: null, isConnected: false })
}
return {
source: null,
isConnected: false,
connect,
disconnect,
}
})