summaryrefslogtreecommitdiffstats
path: root/src/hooks/useRequests.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/hooks/useRequests.tsx')
-rw-r--r--src/hooks/useRequests.tsx253
1 files changed, 170 insertions, 83 deletions
diff --git a/src/hooks/useRequests.tsx b/src/hooks/useRequests.tsx
index 1361949..3135aa2 100644
--- a/src/hooks/useRequests.tsx
+++ b/src/hooks/useRequests.tsx
@@ -1,68 +1,32 @@
1import { useCallback, useEffect, useMemo, useState } from "react"; 1import { useCallback, useEffect, useMemo, useState } from "react";
2import { getHost } from "~/utils"; 2import { getHost } from "~/utils";
3 3import {
4export type Headers = [string, string][]; 4 Call,
5export type Method = 5 Frame,
6 | "GET" 6 Frames,
7 | "HEAD" 7 Historic,
8 | "POST" 8 ReadyState,
9 | "PUT" 9 Request,
10 | "DELETE" 10 RequestResponseType,
11 | "CONNECT" 11 Requests,
12 | "OPTIONS" 12 Response,
13 | "TRACE" 13 ResponsePayload,
14 | "PATCH"; 14 Responses,
15 15 WebsocketConnect,
16export interface RequestPayload { 16 WebsocketConnected,
17 id: string; 17 WebsocketConnectedPayload,
18 timestamp: string; 18 WebsocketDisconnectPayload,
19 body: string; 19 WebsocketInboundPayload,
20 headers: Headers; 20 WebsocketOutboundPayload,
21 method: Method; 21 WebsocketType,
22 path: string; 22} from "~/types";
23}
24
25interface Request {
26 type: "request";
27 payload: RequestPayload;
28}
29
30export interface ResponsePayload {
31 id: string;
32 timing: number;
33 body: string;
34 headers: Headers;
35 status: number;
36}
37
38interface Response {
39 type: "response";
40 payload: ResponsePayload;
41}
42
43interface Historic {
44 type: "historic";
45 payload: (Request | Response)[];
46}
47
48export interface RequestResponse {
49 request: RequestPayload;
50 response?: ResponsePayload;
51}
52
53export enum ReadyState {
54 CONNECTING = 0,
55 OPEN = 1,
56 CLOSING = 2,
57 CLOSED = 3,
58}
59 23
60export interface useRequestsProps { 24export interface useRequestsProps {
61 onConnect: () => Promise<void>; 25 onConnect: () => Promise<void>;
62} 26}
63 27
64export interface UseRequests { 28export interface UseRequests {
65 calls: RequestResponse[]; 29 calls: Call[];
66 readyState: ReadyState; 30 readyState: ReadyState;
67 clear: () => void; 31 clear: () => void;
68} 32}
@@ -73,8 +37,9 @@ export default function useRequests({
73 const wsHost = useMemo(getHost, []); 37 const wsHost = useMemo(getHost, []);
74 38
75 const [initialConnection, setInitialConnection] = useState(true); 39 const [initialConnection, setInitialConnection] = useState(true);
76 const [requests, setRequests] = useState<RequestPayload[]>([]); 40 const [requests, setRequests] = useState<Requests>([]);
77 const [responses, setResponses] = useState<ResponsePayload[]>([]); 41 const [responses, setResponses] = useState<Responses>({});
42 const [websocketFrames, setWebsocketFrames] = useState<Frames>({});
78 43
79 const connect = useCallback( 44 const connect = useCallback(
80 () => new WebSocket(`ws://${wsHost}/inspect/`), 45 () => new WebSocket(`ws://${wsHost}/inspect/`),
@@ -96,36 +61,140 @@ export default function useRequests({
96 setInitialConnection(false); 61 setInitialConnection(false);
97 setReadyState(ws.readyState); 62 setReadyState(ws.readyState);
98 }; 63 };
99 const onMessage = ({ data }) => { 64 const onMessage = ({ data }: { data: string }) => {
100 const { type, payload } = JSON.parse(data) as 65 const { type, payload } = JSON.parse(data) as
101 | Historic 66 | Historic
102 | Request 67 | RequestResponseType
103 | Response; 68 | WebsocketType;
104 69
105 switch (type) { 70 switch (type) {
106 case "historic": 71 case "historic":
107 if (initialConnection) { 72 if (initialConnection) {
108 const requests = (payload as (Request | Response)[]).filter( 73 const requests = (
109 ({ type }) => type === "request" 74 payload as (RequestResponseType | WebsocketType)[]
110 ); 75 )
111 const responses = (payload as (Request | Response)[]).filter( 76 .filter(
112 ({ type }) => type === "response" 77 ({ type }) => type === "request" || type == "websocket_connect"
113 ); 78 )
79 .map((payload) => {
80 if (
81 (payload as WebsocketConnect).payload.method === undefined
82 ) {
83 (payload as Request | WebsocketConnect).payload.method =
84 "GET";
85 }
86
87 return payload;
88 });
89 const responses = (
90 payload as (RequestResponseType | WebsocketType)[]
91 )
92 .filter(
93 ({ type }) =>
94 type === "response" || type == "websocket_connected"
95 )
96 .map(({ type, ...item }) => {
97 if (type == "websocket_connected") {
98 (item.payload as WebsocketConnectedPayload).status = 101;
99 }
100
101 return { type, ...item };
102 })
103 .reduce<{ [id: string]: Response | WebsocketConnected }>(
104 (out, item) => ({
105 ...out,
106 [item.payload.id]: item as Response | WebsocketConnected,
107 }),
108 {}
109 );
110 const frames = (payload as (RequestResponseType | WebsocketType)[])
111 .filter(
112 ({ type }) =>
113 type == "websocket_inbound" ||
114 type == "websocket_outbound" ||
115 type == "websocket_disconnect"
116 )
117 .reduce<Frames>((out, item) => {
118 if (!out.hasOwnProperty(item.payload.id)) {
119 out[item.payload.id] = [];
120 }
121
122 out[item.payload.id].push(item as Frame);
123 return out;
124 }, {});
114 setRequests((rqs) => [ 125 setRequests((rqs) => [
115 ...rqs, 126 ...rqs,
116 ...requests.map(({ payload }) => payload as RequestPayload), 127 ...requests.map(
128 (payload) => payload as Request | WebsocketConnect
129 ),
117 ]); 130 ]);
118 setResponses((rps) => [ 131 setResponses((rps) => ({
119 ...rps, 132 ...rps,
120 ...responses.map(({ payload }) => payload as ResponsePayload), 133 ...responses,
121 ]); 134 }));
135 setWebsocketFrames((frms) => ({
136 ...frms,
137 ...frames,
138 }));
122 } 139 }
123 break; 140 break;
124 case "request": 141 case "request":
125 setRequests((rqs) => [...rqs, payload as RequestPayload]); 142 case "websocket_connect":
143 setRequests((rqs) => [
144 ...rqs,
145 {
146 type,
147 payload:
148 type === "request"
149 ? payload
150 : {
151 ...payload,
152 method: "GET",
153 },
154 } as Request | WebsocketConnect,
155 ]);
126 break; 156 break;
127 case "response": 157 case "response":
128 setResponses((rps) => [...rps, payload as ResponsePayload]); 158 case "websocket_connected":
159 if (type == "websocket_connected") {
160 (payload as WebsocketConnectedPayload).status = 101;
161 }
162 setResponses((rps) => ({
163 ...rps,
164 [(payload as ResponsePayload | WebsocketConnectedPayload).id]: {
165 type,
166 payload,
167 } as Response | WebsocketConnected,
168 }));
169 break;
170 case "websocket_inbound":
171 case "websocket_outbound":
172 case "websocket_disconnect":
173 setWebsocketFrames((frms) => {
174 const id = (
175 payload as
176 | WebsocketInboundPayload
177 | WebsocketOutboundPayload
178 | WebsocketDisconnectPayload
179 ).id;
180
181 const newFrms = { ...frms };
182