Skip to content

Commit 329982c

Browse files
committed
Merge branch '6.0.0' of github.com:BetterTyped/hyper-fetch into 6.0.0
2 parents 42f5bda + 5563347 commit 329982c

File tree

6 files changed

+103
-33
lines changed

6 files changed

+103
-33
lines changed

packages/devtools-plugin/src/devtools.event.handler.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export class DevtoolsEventHandler {
3131

3232
this.socketEmitter = this.socket.createEmitter<any>()({ topic: "DEVTOOLS_PLUGIN_EMITTER" });
3333
this.socketListener = this.socket.createListener<any>()({ topic: "DEVTOOLS_PLUGIN_LISTENER" });
34-
this.socket.connect().then(() => console.log("CONNECTED"));
34+
this.socket.connect();
3535
this.socket.onDisconnected(() => {
3636
// TODO handle reconnection?
3737
});
@@ -41,8 +41,6 @@ export class DevtoolsEventHandler {
4141
this.socket.onConnected(() => {
4242
this.isConnected = true;
4343
while (this.eventQueue.length > 0) {
44-
// TODO - optimize with Dequeue to have O(1)
45-
// TODO - add timestamps for particular events.
4644
const nextEvent = this.eventQueue.shift();
4745
this.socketEmitter.emit({ payload: nextEvent });
4846
}

packages/devtools/__tests__/helpers/helpers.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ export const connectDevtoolsClient = ({
1616
} = {}) => {
1717
const client = new Client({ url: baseUrl });
1818

19-
const devtools = devtoolsPlugin({
19+
const plugin = devtoolsPlugin({
2020
appName: clientName,
2121
socketAddress,
2222
socketPort,
2323
});
2424

25-
client.addPlugin(devtools);
25+
client.addPlugin(plugin);
2626

27-
return client;
27+
return { client, plugin };
2828
};
2929

3030
export const connectDevtoolsFrontend = async ({
@@ -34,22 +34,20 @@ export const connectDevtoolsFrontend = async ({
3434
socketAddress?: string;
3535
socketPort?: number;
3636
}) => {
37-
const initSocket = new Socket({
37+
let initSocket = new Socket({
3838
url: `ws://${socketAddress}:${socketPort}`,
3939
adapterOptions: { autoConnect: false },
4040
}).setDebug(true);
41-
const socketConnected = initSocket.setQueryParams({ connectionName: ConnectionName.HF_DEVTOOLS_APP });
41+
initSocket = initSocket.setQueryParams({ connectionName: ConnectionName.HF_DEVTOOLS_APP });
4242

43-
await socketConnected.connect();
43+
await initSocket.connect();
44+
return initSocket;
4445
};
4546

4647
export const listenForServerMessage = async (wss: any) => {
4748
return new Promise((resolve) => {
4849
wss.on("connection", (wsConn, request) => {
49-
console.log("CONNECTION LISTEN FOR SERVER", request.url);
5050
wsConn.on("message", (message) => {
51-
console.log("CONNECTION LISTEN FOR SERVER MESSAGE", request.url);
52-
console.log("MESSAGE", message);
5351
return resolve(message);
5452
});
5553
});

packages/devtools/__tests__/server/server.spec.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { MessageType } from "types/messages.types";
12
import { startServer } from "../../src/server";
2-
import { connectDevtoolsFrontend, connectDevtoolsClient } from "../helpers/helpers";
3+
import { connectDevtoolsFrontend, connectDevtoolsClient, listenForServerMessage } from "../helpers/helpers";
34
import { waitFor } from "@testing-library/react";
45
// TODO handle lost connection from client
56
describe("Devtools Socket Server", () => {
@@ -15,4 +16,39 @@ describe("Devtools Socket Server", () => {
1516
await waitFor(() => expect(Object.keys(connections || {}).length).toBeGreaterThan(0));
1617
});
1718
});
19+
describe("If connection to the frontend app is established and then disconnected and reconnected again", () => {
20+
it("Should allow for reconnection", async () => {
21+
let receivedMessage = null;
22+
const { DEVTOOLS_FRONTEND_WS_CONNECTION, connections } = (await startServer()) || {};
23+
24+
const socket = await connectDevtoolsFrontend({
25+
socketAddress: "localhost",
26+
socketPort: 1234,
27+
});
28+
socket.onMessage((message) => {
29+
receivedMessage = message;
30+
return message;
31+
});
32+
const { plugin } = await connectDevtoolsClient();
33+
await waitFor(() => expect(Object.keys(connections || {}).length).toBeGreaterThan(0));
34+
35+
expect(DEVTOOLS_FRONTEND_WS_CONNECTION).toBeDefined();
36+
expect(connections?.["HF_DEVTOOLS_CLIENT_test-client"].ws).toBeDefined();
37+
38+
await plugin.data.emitter?.socket.disconnect();
39+
await waitFor(() => expect(connections?.["HF_DEVTOOLS_CLIENT_test-client"].ws).toBeNull);
40+
await waitFor(() => expect(receivedMessage).toBeDefined);
41+
expect(receivedMessage).toEqual({
42+
event: { messageType: MessageType.DEVTOOLS_CLIENT_HANGUP, connectionName: "HF_DEVTOOLS_CLIENT_test-client" },
43+
});
44+
45+
await socket.disconnect();
46+
expect(DEVTOOLS_FRONTEND_WS_CONNECTION).toBeNull();
47+
48+
await socket.connect();
49+
await plugin.data.emitter?.socket.connect();
50+
expect(DEVTOOLS_FRONTEND_WS_CONNECTION).toBeDefined();
51+
await waitFor(() => expect(connections?.["HF_DEVTOOLS_CLIENT_test-client"].ws).toBeDefined);
52+
});
53+
});
1854
});

packages/devtools/src/server/index.ts

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import { SocketTopics } from "../sockets/topics";
66
import { MessageType, MessageTypes } from "../types/messages.types";
77
import { ConnectionName } from "../sockets/connection.name";
88

9-
const sendHandshake = (devtoolsAppConnection: WebSocket, connectionName: string) => {
10-
devtoolsAppConnection.send(
9+
// TODO - handle message with info about lostConnection for a given app when connection is lost on frontend side.
10+
11+
const initializeFrontendForConnection = (devtoolsAppConnection: WebSocket, connectionName: string) => {
12+
devtoolsAppConnection?.send(
1113
JSON.stringify({
1214
...{
1315
topic: SocketTopics.DEVTOOLS_APP_MAIN_LISTENER,
@@ -17,26 +19,38 @@ const sendHandshake = (devtoolsAppConnection: WebSocket, connectionName: string)
1719
);
1820
};
1921

20-
// TODO - add heartbeat + cleanup of hangup connections.
22+
const getConnectionName = (requestUrl: string) => {
23+
const queryParams = url.parse(requestUrl, true).query;
24+
const { connectionName } = (queryParams || {}) as { connectionName: string };
25+
return connectionName;
26+
};
2127

22-
const connections: Record<string, { ws: WebSocket; handshake: "pending" | "sent" | "confirmed"; events: any[] }> = {};
28+
const connections: Record<
29+
string,
30+
{
31+
ws: WebSocket | null;
32+
frontendStatus: "pending" | "sent" | "initialized";
33+
events: any[];
34+
status: "connected" | "hangup";
35+
}
36+
> = {};
2337
const addConnection = (devtoolsAppConnection: WebSocket | null, connectionName: string, connection: WebSocket) => {
2438
if (!connections[connectionName]) {
25-
connections[connectionName] = { ws: connection, handshake: "pending", events: [] };
39+
connections[connectionName] = { ws: connection, frontendStatus: "pending", events: [], status: "connected" };
2640
} else {
2741
connections[connectionName].ws = connection;
2842
}
2943
if (devtoolsAppConnection) {
30-
sendHandshake(devtoolsAppConnection, connectionName);
31-
connections[connectionName].handshake = "sent";
44+
initializeFrontendForConnection(devtoolsAppConnection, connectionName);
45+
connections[connectionName].frontendStatus = "sent";
3246
}
3347
};
3448

35-
const sendPendingHandshakes = (devtoolsAppConnection: WebSocket) => {
49+
const initializePendingFrontends = (devtoolsAppConnection: WebSocket) => {
3650
Object.keys(connections).forEach((connectionName) => {
37-
if (connections[connectionName].handshake === "pending") {
38-
sendHandshake(devtoolsAppConnection, connectionName);
39-
connections[connectionName].handshake = "sent";
51+
if (connections[connectionName].frontendStatus === "pending") {
52+
initializeFrontendForConnection(devtoolsAppConnection, connectionName);
53+
connections[connectionName].frontendStatus = "sent";
4054
}
4155
});
4256
};
@@ -53,22 +67,45 @@ export const startServer = async (port = 1234) => {
5367
let DEVTOOLS_FRONTEND_WS_CONNECTION: WebSocket | null = null;
5468

5569
wss.on("connection", (wsConn, request) => {
56-
const queryParams = url.parse(request.url!, true).query;
57-
const { connectionName } = queryParams as { connectionName: string };
70+
const connectionName = getConnectionName(request.url || "");
5871
if (!connectionName) {
5972
console.error("MISSING CONNECTION NAME", request.url);
6073
return;
6174
}
62-
// TODO HANDLE REFRESHING CONNECTION AND HANGUP
6375
if (connectionName && connectionName === ConnectionName.HF_DEVTOOLS_APP) {
6476
DEVTOOLS_FRONTEND_WS_CONNECTION = wsConn;
65-
sendPendingHandshakes(DEVTOOLS_FRONTEND_WS_CONNECTION);
77+
initializePendingFrontends(DEVTOOLS_FRONTEND_WS_CONNECTION);
6678
}
6779
if (connectionName && !Array.isArray(connectionName) && connectionName.startsWith("HF_DEVTOOLS_CLIENT")) {
6880
addConnection(DEVTOOLS_FRONTEND_WS_CONNECTION, connectionName, wsConn);
6981
}
7082
wsConn.on("error", console.error);
71-
83+
wsConn.on("close", () => {
84+
const closedConnectionName = getConnectionName(request.url || "");
85+
if (!closedConnectionName) {
86+
return;
87+
}
88+
if (closedConnectionName === ConnectionName.HF_DEVTOOLS_APP) {
89+
DEVTOOLS_FRONTEND_WS_CONNECTION = null;
90+
}
91+
if (connections[connectionName]) {
92+
const hangupConnection = connections[connectionName];
93+
hangupConnection.ws = null;
94+
hangupConnection.status = "hangup";
95+
if (!DEVTOOLS_FRONTEND_WS_CONNECTION) {
96+
console.error(`Something went wrong. Connection to devtools frontend and devtools plugin lost.`);
97+
return;
98+
}
99+
DEVTOOLS_FRONTEND_WS_CONNECTION.send(
100+
JSON.stringify({
101+
...{
102+
topic: SocketTopics.DEVTOOLS_APP_MAIN_LISTENER,
103+
data: { messageType: MessageType.DEVTOOLS_CLIENT_HANGUP, connectionName },
104+
},
105+
}),
106+
);
107+
}
108+
});
72109
wsConn.on("message", (msg: MessageTypes) => {
73110
const message = JSON.parse(msg.toString()) as MessageTypes;
74111
if (!DEVTOOLS_FRONTEND_WS_CONNECTION) {
@@ -80,7 +117,7 @@ export const startServer = async (port = 1234) => {
80117
case MessageType.HF_DEVTOOLS_EVENT: {
81118
const { connectionName } = message.data;
82119
console.log("RECEIVED EVENT FROM DEVTOOLS", message);
83-
if (connections[connectionName]) {
120+
if (connections[connectionName]?.ws) {
84121
connections[connectionName].ws.send(
85122
JSON.stringify({ ...message, topic: SocketTopics.DEVTOOLS_PLUGIN_LISTENER }),
86123
);
@@ -93,15 +130,15 @@ export const startServer = async (port = 1234) => {
93130
return;
94131
}
95132

96-
connections[message.data.connectionName].handshake = "confirmed";
133+
connections[message.data.connectionName].frontendStatus = "initialized";
97134
const connectionEvents = connections[message.data.connectionName]?.events;
98135
sendStoredEvents(DEVTOOLS_FRONTEND_WS_CONNECTION, connectionEvents);
99136

100137
return;
101138
}
102139
case MessageType.HF_APP_EVENT: {
103140
const conn = message.data.connectionName;
104-
if (connections[conn]?.handshake && DEVTOOLS_FRONTEND_WS_CONNECTION) {
141+
if (connections[conn]?.frontendStatus && DEVTOOLS_FRONTEND_WS_CONNECTION) {
105142
DEVTOOLS_FRONTEND_WS_CONNECTION.send(
106143
JSON.stringify({ ...message, topic: SocketTopics.DEVTOOLS_APP_CLIENT_LISTENER }),
107144
);

packages/devtools/src/types/messages.types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ export enum EmitableCustomEvents {
1919
export enum MessageType {
2020
DEVTOOLS_CLIENT_INIT = "DEVTOOLS_CLIENT_INIT",
2121
DEVTOOLS_CLIENT_CONFIRM = "DEVTOOLS_CLIENT_CONFIRM",
22+
DEVTOOLS_CLIENT_HANGUP = "DEVTOOLS_CLIENT_HANGUP",
23+
DEVTOOLS_CLIENT_RECONNECTED = "DEVTOOLS_CLIENT_RECONNECTED",
2224
HF_APP_EVENT = "HF_APP_EVENT",
2325
HF_DEVTOOLS_EVENT = "HF_DEVTOOLS_EVENT",
2426
}

packages/sockets/src/socket/socket.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ export class Socket<Adapter extends SocketAdapterInstance = WebsocketAdapterType
8787
};
8888

8989
setQueryParams = (queryParams: ExtractAdapterQueryParamsType<Adapter>) => {
90-
console.log("SETTING QUERY PARAMS", queryParams);
9190
this.adapter.setQueryParams(queryParams);
9291
return this;
9392
};

0 commit comments

Comments
 (0)