github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/ui/dashboard/src/hooks/useDashboardWebSocket.ts (about) 1 import isEmpty from "lodash/isEmpty"; 2 import useWebSocket, { ReadyState } from "react-use-websocket"; 3 import { 4 DashboardDataMode, 5 DashboardDataModeCLISnapshot, 6 DashboardDataModeLive, 7 IActions, 8 ReceivedSocketMessagePayload, 9 } from "../types"; 10 import { useCallback, useEffect, useRef } from "react"; 11 12 export const SocketActions: IActions = { 13 CLEAR_DASHBOARD: "clear_dashboard", 14 GET_AVAILABLE_DASHBOARDS: "get_available_dashboards", 15 GET_DASHBOARD_METADATA: "get_dashboard_metadata", 16 SELECT_DASHBOARD: "select_dashboard", 17 SELECT_SNAPSHOT: "select_snapshot", 18 INPUT_CHANGED: "input_changed", 19 }; 20 21 const useDashboardWebSocket = ( 22 dataMode: DashboardDataMode, 23 dispatch: (action: any) => void, 24 eventHandler: (event: ReceivedSocketMessagePayload) => void, 25 socketUrlFactory?: () => Promise<string> 26 ) => { 27 const didUnmount = useRef(false); 28 // const [socketUrl, setSocketUrl] = useState<string | null>( 29 // !socketUrlFactory ? getSocketServerUrl() : null 30 // ); 31 32 const getSocketServerUrl = useCallback(async () => { 33 if (socketUrlFactory) { 34 return socketUrlFactory(); 35 } 36 37 // In this scenario the browser will be at http://localhost:3000, 38 // therefore we have no idea what host + port the dashboard server 39 // is on, so assume it's the default 40 if (process.env.NODE_ENV === "development") { 41 return "ws://localhost:9194/ws"; 42 } 43 // Otherwise, it's a production build, so use the URL details 44 const url = new URL(window.location.toString()); 45 return `${url.protocol === "https:" ? "wss" : "ws"}://${url.host}/ws`; 46 }, [socketUrlFactory]); 47 48 const { lastJsonMessage, readyState, sendJsonMessage } = useWebSocket( 49 getSocketServerUrl, 50 { 51 shouldReconnect: () => { 52 /* 53 useWebSocket will handle unmounting for you, but this is an example of a 54 case in which you would not want it to automatically reconnect 55 */ 56 return !didUnmount.current; 57 }, 58 reconnectAttempts: 10, 59 reconnectInterval: 3000, 60 }, 61 dataMode === DashboardDataModeLive || 62 dataMode === DashboardDataModeCLISnapshot 63 ); 64 65 useEffect(() => { 66 if (!lastJsonMessage || isEmpty(lastJsonMessage)) { 67 return; 68 } 69 const typedEvent = lastJsonMessage as ReceivedSocketMessagePayload; 70 if (!typedEvent || !typedEvent.action) { 71 return; 72 } 73 eventHandler(typedEvent); 74 }, [eventHandler, lastJsonMessage]); 75 76 useEffect(() => { 77 if (readyState !== ReadyState.OPEN || !sendJsonMessage) { 78 return; 79 } 80 sendJsonMessage({ action: SocketActions.GET_DASHBOARD_METADATA }); 81 sendJsonMessage({ action: SocketActions.GET_AVAILABLE_DASHBOARDS }); 82 }, [readyState, sendJsonMessage]); 83 84 useEffect(() => { 85 return () => { 86 didUnmount.current = true; 87 }; 88 }, []); 89 90 return { 91 ready: readyState === ReadyState.OPEN, 92 send: sendJsonMessage, 93 }; 94 }; 95 96 export default useDashboardWebSocket;