import { useEffect } from 'react'; import { useDeviceServiceContext, usePatientServiceContext, useWebSocketServiceContext } from '../services'; import { useSaveScope, type SaveOperation } from '../utils/saveOperation'; export const useFhirDeviceBroadcast = () => { const { subscribe, unsubscribe } = useWebSocketServiceContext(); const { fetchDevicesWithPolling } = useDeviceServiceContext(); const { patientState } = usePatientServiceContext(); const patientId = patientState?.id; const scope = useSaveScope(patientId ? `Device-list/${patientId}` : undefined); useEffect(() => { if (!patientId || !patientState) return; const patient = { ...patientState, id: patientId }; let live = true; let active: SaveOperation | undefined; const events = [ 'com.akashichealthrecords.fhir.device.created', 'com.akashichealthrecords.fhir.device.updated', 'com.akashichealthrecords.fhir.device.deleted', ]; const handleDeviceEvent = async (event: { type?: string; data?: { id?: string; resourceType?: string } }) => { if (!live || !event?.type || !events.includes(event.type) || typeof event.data?.id !== 'string' || !/^[A-Za-z0-9.-]+$/.test(event.data.id) || (event.data.resourceType && event.data.resourceType !== 'Device')) return; active?.retire(); const operation = scope.start(); active = operation; try { // The service publishes only its authorized list; a pushed record never enters the cache. await operation.step(() => fetchDevicesWithPolling(patient, true, operation.transport)); } catch { return; } finally { operation.retire(); if (active === operation) active = undefined; } }; for (const event of events) subscribe(event, handleDeviceEvent); return () => { live = false; active?.retire(); for (const event of events) unsubscribe(event, handleDeviceEvent); }; }, [patientId, patientState, fetchDevicesWithPolling, subscribe, unsubscribe, scope]); };