summaryrefslogtreecommitdiffstats
path: root/src/hooks/useRequests.tsx
blob: dfc3b80757dc34b6468d0ae2151dbbd933d4be96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { useCallback, useEffect, useMemo, useState } from "react";
import { getHost } from "~/utils";
import {
  Historic,
  ReadyState,
  Request,
  RequestPayload,
  RequestResponse,
  Response,
  ResponsePayload,
  WebsocketType,
} from "~/types";

export interface useRequestsProps {
  onConnect: () => Promise<void>;
}

export interface UseRequests {
  calls: RequestResponse[];
  readyState: ReadyState;
  clear: () => void;
}

export default function useRequests({
  onConnect,
}: useRequestsProps): UseRequests {
  const wsHost = useMemo(getHost, []);

  const [initialConnection, setInitialConnection] = useState(true);
  const [requests, setRequests] = useState<RequestPayload[]>([]);
  const [responses, setResponses] = useState<ResponsePayload[]>([]);
  const [websocketFrames, setWebsocketFrames] =
    useState<WebsocketType["payload"]>();

  const connect = useCallback(
    () => new WebSocket(`ws://${wsHost}/inspect/`),
    [wsHost]
  );

  const [ws, setWs] = useState<WebSocket>(() => connect());
  const [readyState, setReadyState] = useState<ReadyState>(ws.readyState);

  useEffect(() => {
    setReadyState(ws.readyState);

    const onClose = () => {
      setReadyState(ws.readyState);
      setWs(connect());
    };
    const onOpen = () => {
      onConnect();
      setInitialConnection(false);
      setReadyState(ws.readyState);
    };
    const onMessage = ({ data }) => {
      const { type, payload } = JSON.parse(data) as
        | Historic
        | Request
        | Response;

      console.debug(type, payload);

      switch (type) {
        case "historic":
          if (initialConnection) {
            const requests = (payload as (Request | Response)[]).filter(
              ({ type }) => type === "request"
            );
            const responses = (payload as (Request | Response)[]).filter(
              ({ type }) => type === "response"
            );
            setRequests((rqs) => [
              ...rqs,
              ...requests.map(({ payload }) => payload as RequestPayload),
            ]);
            setResponses((rps) => [
              ...rps,
              ...responses.map(({ payload }) => payload as ResponsePayload),
            ]);
          }
          break;
        case "request":
          setRequests((rqs) => [...rqs, payload as RequestPayload]);
          break;
        case "response":
          setResponses((rps) => [...rps, payload as ResponsePayload]);
          break;
      }
    };

    ws.addEventListener("message", onMessage);
    ws.addEventListener("close", onClose);
    ws.addEventListener("open", onOpen);

    return () => {
      ws.removeEventListener("message", onMessage);
      ws.removeEventListener("close", onClose);
      ws.removeEventListener("open", onOpen);
    };
  }, [ws]);

  return {
    calls: useMemo<RequestResponse[]>(
      () =>
        requests.map((request) => ({
          request: request,
          response: responses.find(({ id }) => id === request.id),
        })),
      [requests, responses]
    ),
    readyState,
    clear: () => {
      setRequests([]);
      setResponses([]);
    },
  };
}