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;