feat: add SseProvider — SSE to ReactQuery bridge with tests
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { useUnit } from 'effector-react'
|
||||
import { createEventStream } from '@/shared/lib/sse'
|
||||
import { $token } from '@/shared/model/auth'
|
||||
|
||||
export function SseProvider() {
|
||||
const token = useUnit($token)
|
||||
const queryClient = useQueryClient()
|
||||
const sourceRef = useRef<EventSource | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (!token) {
|
||||
if (sourceRef.current) {
|
||||
sourceRef.current.close()
|
||||
sourceRef.current = null
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const es = createEventStream(token)
|
||||
sourceRef.current = es
|
||||
|
||||
function handleEvent(eventName: string) {
|
||||
return function (event: MessageEvent) {
|
||||
try {
|
||||
const data = JSON.parse(event.data)
|
||||
const orderId = data.orderId
|
||||
|
||||
switch (eventName) {
|
||||
case 'message:new':
|
||||
queryClient.invalidateQueries({ queryKey: ['me', 'messages', 'unread-count'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['me', 'conversations'] })
|
||||
if (orderId) {
|
||||
queryClient.invalidateQueries({ queryKey: ['me', 'orders', orderId] })
|
||||
queryClient.invalidateQueries({ queryKey: ['admin', 'orders', orderId] })
|
||||
}
|
||||
break
|
||||
case 'order:statusChanged':
|
||||
if (orderId) {
|
||||
queryClient.invalidateQueries({ queryKey: ['me', 'orders', orderId] })
|
||||
queryClient.invalidateQueries({ queryKey: ['admin', 'orders', orderId] })
|
||||
}
|
||||
break
|
||||
case 'order:updated':
|
||||
if (orderId) {
|
||||
queryClient.invalidateQueries({ queryKey: ['me', 'orders', orderId] })
|
||||
queryClient.invalidateQueries({ queryKey: ['admin', 'orders', orderId] })
|
||||
}
|
||||
break
|
||||
case 'order:new':
|
||||
queryClient.invalidateQueries({ queryKey: ['admin', 'orders', 'summary'] })
|
||||
queryClient.invalidateQueries({ queryKey: ['admin', 'orders'] })
|
||||
break
|
||||
}
|
||||
} catch {
|
||||
// ignore parse errors (e.g. heartbit comments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const messageNewHandler = handleEvent('message:new')
|
||||
const orderStatusHandler = handleEvent('order:statusChanged')
|
||||
const orderUpdatedHandler = handleEvent('order:updated')
|
||||
const orderNewHandler = handleEvent('order:new')
|
||||
|
||||
es.addEventListener('message:new', messageNewHandler)
|
||||
es.addEventListener('order:statusChanged', orderStatusHandler)
|
||||
es.addEventListener('order:updated', orderUpdatedHandler)
|
||||
es.addEventListener('order:new', orderNewHandler)
|
||||
|
||||
return () => {
|
||||
es.removeEventListener('message:new', messageNewHandler)
|
||||
es.removeEventListener('order:statusChanged', orderStatusHandler)
|
||||
es.removeEventListener('order:updated', orderUpdatedHandler)
|
||||
es.removeEventListener('order:new', orderNewHandler)
|
||||
es.close()
|
||||
sourceRef.current = null
|
||||
}
|
||||
}, [token, queryClient])
|
||||
|
||||
return null
|
||||
}
|
||||
Reference in New Issue
Block a user