Skip to content

Commit f6dece8

Browse files
committed
- Devtools <-> Client communication improvements + metaData passing
1 parent 01d5080 commit f6dece8

File tree

9 files changed

+152
-78
lines changed

9 files changed

+152
-78
lines changed

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

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { CacheValueType, ClientInstance } from "@hyper-fetch/core";
22
import { Emitter, Listener, Socket } from "@hyper-fetch/sockets";
33

4-
import { EmitableCoreEvents, EmitableCustomEvents, DevtoolsPluginOptions } from "devtools.types";
4+
import { EmitableCoreEvents, EmitableCustomEvents, DevtoolsPluginOptions, MessageTypes } from "devtools.types";
55

66
export class DevtoolsEventHandler {
77
client: ClientInstance;
@@ -10,6 +10,7 @@ export class DevtoolsEventHandler {
1010
socketListener: Listener<any, any, any>;
1111
unmountHooks: any; // TODO FIX ANY
1212
isConnected: boolean;
13+
isInitialized: boolean;
1314
eventQueue: any[] = [];
1415
connectionName: string;
1516

@@ -18,6 +19,7 @@ export class DevtoolsEventHandler {
1819
{ socketAddress = "ws://localhost", socketPort = 1234, appName, debug = false }: DevtoolsPluginOptions,
1920
) {
2021
this.isConnected = false;
22+
this.isInitialized = false;
2123
this.eventQueue = [];
2224
this.client = client;
2325
this.unmountHooks = this.initializeHooks();
@@ -51,23 +53,40 @@ export class DevtoolsEventHandler {
5153
console.log("[HyperFetch Devtools] connected");
5254
}
5355
this.isConnected = true;
54-
while (this.eventQueue.length > 0) {
55-
const nextEvent = this.eventQueue.shift();
56-
this.socketEmitter.emit({ payload: nextEvent });
57-
}
56+
this.socketEmitter.emit({
57+
payload: {
58+
messageType: MessageTypes.PLUGIN_INITIALIZED,
59+
eventData: {
60+
clientOptions: this.client.options,
61+
adapterOptions: this.client.adapter.options,
62+
},
63+
connectionName: this.connectionName,
64+
},
65+
});
5866
});
5967
this.socketListener.listen((message) => {
60-
const eventData = message.data.eventData as CacheValueType;
61-
client.cache.update(
62-
{ cacheKey: eventData.cacheKey, cache: true, cacheTime: eventData.cacheTime, staleTime: eventData.staleTime },
63-
eventData,
64-
true,
65-
);
68+
switch (message.data.messageType) {
69+
case MessageTypes.HF_DEVTOOLS_EVENT: {
70+
this.handleDevtoolsMessage(message);
71+
break;
72+
}
73+
case MessageTypes.CLIENT_INITIALIZED: {
74+
this.isInitialized = true;
75+
while (this.eventQueue.length > 0) {
76+
const nextEvent = this.eventQueue.shift();
77+
this.socketEmitter.emit({ payload: nextEvent });
78+
}
79+
break;
80+
}
81+
default: {
82+
console.error("NO EVENT TYPE", message);
83+
}
84+
}
6685
});
6786
}
6887

6988
sendEvent = (eventType: EmitableCoreEvents | EmitableCustomEvents, data: any) => {
70-
if (this.isConnected) {
89+
if (this.isConnected && this.isInitialized) {
7190
try {
7291
this.socketEmitter.emit({
7392
payload: {
@@ -90,6 +109,28 @@ export class DevtoolsEventHandler {
90109
}
91110
};
92111

112+
handleDevtoolsMessage = (message: any) => {
113+
switch (message.data.eventType) {
114+
case EmitableCoreEvents.ON_CACHE_CHANGE: {
115+
const eventData = message.data.eventData as CacheValueType;
116+
this.client.cache.update(
117+
{
118+
cacheKey: eventData.cacheKey,
119+
cache: true,
120+
cacheTime: eventData.cacheTime,
121+
staleTime: eventData.staleTime,
122+
},
123+
eventData,
124+
true,
125+
);
126+
break;
127+
}
128+
default: {
129+
console.error("NO EVENT TYPE", message);
130+
}
131+
}
132+
};
133+
93134
initializeHooks = () => {
94135
return {
95136
unmountOnRequestStart: this.unmountOnRequestStart(),
@@ -159,7 +200,6 @@ export class DevtoolsEventHandler {
159200
this.sendEvent(EmitableCoreEvents.ON_CACHE_INVALIDATE, {});
160201
});
161202
};
162-
163203
unmountCacheDelete = () => {
164204
return this.client.cache.events.onDelete(() => {
165205
this.sendEvent(EmitableCoreEvents.ON_CACHE_DELETE, {});

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@ export const devtoolsPlugin = (options: DevtoolsPluginOptions) => {
77
const plugin = new Plugin({
88
name: "devtools-plugin",
99
data: {
10-
emitter: undefined as DevtoolsEventHandler | undefined,
10+
eventHandler: undefined as DevtoolsEventHandler | undefined,
1111
requests: [] as RequestInstance[],
1212
},
1313
});
1414

1515
plugin.onMount(({ client }) => {
16-
plugin.data.emitter = new DevtoolsEventHandler(client, options);
16+
plugin.data.eventHandler = new DevtoolsEventHandler(client, options);
1717
});
1818

1919
plugin.onRequestCreate(({ request }) => {
2020
plugin.data.requests.push(request);
21-
plugin.data.emitter?.sendEvent(EmitableCustomEvents.REQUEST_CREATED, plugin.data.requests);
21+
plugin.data.eventHandler?.sendEvent(EmitableCustomEvents.REQUEST_CREATED, plugin.data.requests);
2222
});
2323

2424
return plugin;

packages/devtools-plugin/src/devtools.types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,10 @@ export enum EmitableCustomEvents {
1616
REQUEST_CREATED = "REQUEST_CREATED",
1717
}
1818

19+
export enum MessageTypes {
20+
HF_DEVTOOLS_EVENT = "HF_DEVTOOLS_EVENT",
21+
PLUGIN_INITIALIZED = "PLUGIN_INITIALIZED",
22+
CLIENT_INITIALIZED = "CLIENT_INITIALIZED",
23+
}
24+
1925
export type DevtoolsPluginOptions = { appName: string; socketAddress?: string; socketPort?: number; debug?: boolean };

packages/devtools/__tests__/helpers/helpers.ts

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Client } from "@hyper-fetch/core";
22
import { devtoolsPlugin } from "@hyper-fetch/devtools-plugin";
33
import { Socket } from "@hyper-fetch/sockets";
4+
45
import { ConnectionName } from "frontend/constants/connection.name";
56

67
export const connectDevtoolsClient = ({
@@ -43,22 +44,3 @@ export const connectDevtoolsFrontend = async ({
4344
await initSocket.connect();
4445
return initSocket;
4546
};
46-
47-
export const listenForServerMessage = async (wss: any) => {
48-
return new Promise((resolve) => {
49-
wss.on("connection", (wsConn, request) => {
50-
wsConn.on("message", (message) => {
51-
return resolve(message);
52-
});
53-
});
54-
});
55-
};
56-
57-
export const listenForSocketMessage = async (socket: Socket) => {
58-
return new Promise((resolve) => {
59-
socket.onMessage((message) => {
60-
console.log("SOCKET MESSAGE", message);
61-
return resolve(message);
62-
});
63-
});
64-
};

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

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1-
import { MessageType } from "types/messages.types";
2-
import { startServer } from "../../src/server";
3-
import { connectDevtoolsFrontend, connectDevtoolsClient, listenForServerMessage } from "../helpers/helpers";
41
import { waitFor } from "@testing-library/react";
5-
// TODO handle lost connection from client
2+
3+
import { MessageType } from "types/messages.types";
4+
import { StartServer, startServer } from "../../src/server";
5+
import { connectDevtoolsFrontend, connectDevtoolsClient } from "../helpers/helpers";
6+
67
describe("Devtools Socket Server", () => {
8+
let serverObject: StartServer | null = null;
9+
beforeEach(async () => {
10+
serverObject = await startServer();
11+
});
12+
afterEach(async () => {
13+
await serverObject?.server?.close();
14+
jest.clearAllMocks();
15+
});
716
describe("If connection to the frontend is established and client is connected", () => {
817
it("Should created the appropriate connections", async () => {
9-
const { connections, DEVTOOLS_FRONTEND_WS_CONNECTION } = (await startServer()) || {};
18+
const { connections, DEVTOOLS_FRONTEND_WS_CONNECTION } = serverObject || {};
1019
await connectDevtoolsFrontend({
1120
socketAddress: "localhost",
1221
socketPort: 1234,
@@ -18,8 +27,8 @@ describe("Devtools Socket Server", () => {
1827
});
1928
describe("If connection to the frontend app is established and then disconnected and reconnected again", () => {
2029
it("Should allow for reconnection", async () => {
21-
let receivedMessage = null;
22-
const { DEVTOOLS_FRONTEND_WS_CONNECTION, connections } = (await startServer()) || {};
30+
let receivedMessage: any = null;
31+
const { DEVTOOLS_FRONTEND_WS_CONNECTION, connections } = serverObject || {};
2332

2433
const socket = await connectDevtoolsFrontend({
2534
socketAddress: "localhost",
@@ -35,7 +44,7 @@ describe("Devtools Socket Server", () => {
3544
expect(DEVTOOLS_FRONTEND_WS_CONNECTION).toBeDefined();
3645
expect(connections?.["HF_DEVTOOLS_CLIENT_test-client"].ws).toBeDefined();
3746

38-
await plugin.data.emitter?.socket.disconnect();
47+
await plugin.data.eventHandler?.socket.disconnect();
3948
await waitFor(() => expect(connections?.["HF_DEVTOOLS_CLIENT_test-client"].ws).toBeNull);
4049
await waitFor(() => expect(receivedMessage).toBeDefined);
4150
expect(receivedMessage).toEqual({
@@ -46,9 +55,29 @@ describe("Devtools Socket Server", () => {
4655
expect(DEVTOOLS_FRONTEND_WS_CONNECTION).toBeNull();
4756

4857
await socket.connect();
49-
await plugin.data.emitter?.socket.connect();
58+
await plugin.data.eventHandler?.socket.connect();
5059
expect(DEVTOOLS_FRONTEND_WS_CONNECTION).toBeDefined();
5160
await waitFor(() => expect(connections?.["HF_DEVTOOLS_CLIENT_test-client"].ws).toBeDefined);
5261
});
5362
});
63+
describe("If the frontend connection is established and initialized", () => {
64+
it("Should send the appropriate metadata to the client", async () => {
65+
const clientReceivedMessages: any = [];
66+
const { connections } = serverObject || {};
67+
const socket = await connectDevtoolsFrontend({
68+
socketAddress: "localhost",
69+
socketPort: 1234,
70+
});
71+
socket.onMessage((message) => {
72+
clientReceivedMessages.push(message);
73+
return message;
74+
});
75+
const { client } = connectDevtoolsClient();
76+
await waitFor(() => expect(Object.keys(connections || {}).length).toBeGreaterThan(0));
77+
await waitFor(() => expect(clientReceivedMessages.length).toBeGreaterThan(0));
78+
const receivedMetaData = clientReceivedMessages[0].event.eventData;
79+
expect(receivedMetaData.clientOptions).toEqual(client.options);
80+
expect(receivedMetaData.adapterOptions).toEqual(client.adapter.options);
81+
});
82+
});
5483
});

packages/devtools/src/frontend/context/projects/bridge/bridge.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export const Bridge = memo(({ port, address = "localhost" }: { port: number; add
6464

6565
// TODO - Kacper fix this type?
6666
devtoolsListener.listen((event: any) => {
67-
const { connectionName, messageType } = event.data;
67+
const { connectionName, messageType, eventData } = event.data;
6868

6969
nameRef.current = connectionName;
7070

@@ -78,7 +78,7 @@ export const Bridge = memo(({ port, address = "localhost" }: { port: number; add
7878
...prev,
7979
[connectionName]: {
8080
name: connectionName,
81-
// TODO - Kacper add the adapter name to event and pick adapter here
81+
metaData: eventData,
8282
client: new Client({ url: "http://localhost.dummyhost:5000" }),
8383
connected: true,
8484
eventListener,

packages/devtools/src/frontend/context/projects/connection/connection.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,18 @@ import { createContext } from "frontend/utils/context";
88
export type Connection = {
99
name: string;
1010
client: ClientInstance;
11+
metaData: {
12+
clientOptions: { url?: string };
13+
// TODO - not sure if any is the best approach
14+
adapterOptions: {
15+
name?: string;
16+
defaultMethod?: any;
17+
defaultExtra?: any;
18+
systemErrorStatus?: any;
19+
systemErrorExtra?: any;
20+
defaultRequestOptions?: any;
21+
};
22+
};
1123
connected: boolean;
1224
eventListener: ExtendListener<ListenerInstance, { response: BaseMessage["data"] }>;
1325
eventEmitter: ExtendEmitter<EmitterInstance, { payload: BaseMessage["data"] }>;

0 commit comments

Comments
 (0)