Skip to content

Commit c0b1078

Browse files
authored
Unify and simplify actor and RPC message types (#1462)
1 parent 36cd3bb commit c0b1078

16 files changed

+353
-521
lines changed

src/application/hooks/useActorEvent.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/* eslint-disable @typescript-eslint/no-explicit-any */
22
import { useEffect, useLayoutEffect, useRef } from "react";
3-
import type { PanelMessage } from "../../extension/messages";
43
import { getPanelActor } from "../../extension/devtools/panelActor";
4+
import type { ActorMessage } from "../../extension/actor";
55

6-
export function useActorEvent<TName extends PanelMessage["type"]>(
6+
export function useActorEvent<TName extends ActorMessage["type"]>(
77
name: TName,
8-
callback: Extract<PanelMessage, { type: TName }> extends infer Message
8+
callback: Extract<ActorMessage, { type: TName }> extends infer Message
99
? (message: Message) => void
1010
: never
1111
) {

src/application/schema.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
1-
import type { DevtoolsRPCMessage } from "../extension/messages";
21
import type { RpcClient } from "../extension/rpc";
32
import typeDefs from "./localSchema.graphql";
43
import { makeExecutableSchema } from "@graphql-tools/schema";
54
import type { Resolvers } from "./types/resolvers";
65
import { getOperationName } from "@apollo/client/utilities";
76
import { print } from "graphql";
87

9-
export function createSchemaWithRpcClient(
10-
rpcClient: RpcClient<DevtoolsRPCMessage>
11-
) {
8+
export function createSchemaWithRpcClient(rpcClient: RpcClient) {
129
return makeExecutableSchema({
1310
typeDefs,
1411
resolvers: createResolvers(rpcClient),
1512
});
1613
}
1714

18-
function createResolvers(client: RpcClient<DevtoolsRPCMessage>): Resolvers {
15+
function createResolvers(client: RpcClient): Resolvers {
1916
const rpcClient = client.withTimeout(3000);
2017

2118
return {

src/extension/__tests__/actor.test.ts

Lines changed: 57 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createActor } from "../actor";
22
import { MessageType } from "../messages";
33

4-
function createTestAdapter<Messages = unknown>() {
4+
function createTestAdapter() {
55
let listener: ((message: unknown) => void) | null;
66
const removeListener = jest.fn(() => {
77
listener = null;
@@ -12,10 +12,10 @@ function createTestAdapter<Messages = unknown>() {
1212
simulatePlainMessage: (message: unknown) => {
1313
listener?.(message);
1414
},
15-
simulateDevtoolsMessage: (message: Messages) => {
15+
simulateDevtoolsMessage: (message: Record<string, unknown>) => {
1616
listener?.({
1717
source: "apollo-client-devtools",
18-
type: MessageType.Event,
18+
type: MessageType.Actor,
1919
message,
2020
});
2121
},
@@ -29,171 +29,154 @@ function createTestAdapter<Messages = unknown>() {
2929
}
3030

3131
test("sends messages to specified adapter in devtools message format", () => {
32-
type Message = { type: "test"; payload: string };
33-
3432
const adapter = createTestAdapter();
35-
const actor = createActor<Message>(adapter);
33+
const actor = createActor(adapter);
3634

37-
actor.send({ type: "test", payload: "Hello" });
35+
actor.send({ type: "clientTerminated", clientId: "1" });
3836

3937
expect(adapter.postMessage).toHaveBeenCalledWith({
4038
id: expect.any(String),
4139
source: "apollo-client-devtools",
42-
type: MessageType.Event,
40+
type: MessageType.Actor,
4341
message: {
44-
type: "test",
45-
payload: "Hello",
42+
type: "clientTerminated",
43+
clientId: "1",
4644
},
4745
});
4846
});
4947

5048
test("calls message callback when subscribing to a message", () => {
51-
type Message = { type: "connect"; payload: string } | { type: "disconnect" };
52-
53-
const adapter = createTestAdapter<Message>();
54-
const actor = createActor<Message>(adapter);
49+
const adapter = createTestAdapter();
50+
const actor = createActor(adapter);
5551

5652
const handleConnect = jest.fn();
5753
const handleDisconnect = jest.fn();
5854

59-
actor.on("connect", handleConnect);
60-
actor.on("disconnect", handleDisconnect);
55+
actor.on("initializePanel", handleConnect);
56+
actor.on("clientTerminated", handleDisconnect);
6157

62-
adapter.simulateDevtoolsMessage({
63-
type: "connect",
64-
payload: "Connected!",
65-
});
58+
adapter.simulateDevtoolsMessage({ type: "initializePanel" });
6659

6760
expect(handleConnect).toHaveBeenCalledTimes(1);
68-
expect(handleConnect).toHaveBeenCalledWith({
69-
type: "connect",
70-
payload: "Connected!",
71-
});
61+
expect(handleConnect).toHaveBeenCalledWith({ type: "initializePanel" });
7262
expect(handleDisconnect).not.toHaveBeenCalled();
7363

74-
adapter.simulateDevtoolsMessage({ type: "disconnect" });
75-
adapter.simulateDevtoolsMessage({ type: "disconnect" });
64+
adapter.simulateDevtoolsMessage({ type: "clientTerminated", clientId: "1" });
65+
adapter.simulateDevtoolsMessage({ type: "clientTerminated", clientId: "2" });
7666

7767
expect(handleDisconnect).toHaveBeenCalledTimes(2);
78-
expect(handleDisconnect).toHaveBeenCalledWith({ type: "disconnect" });
68+
expect(handleDisconnect).toHaveBeenCalledWith({
69+
type: "clientTerminated",
70+
clientId: "1",
71+
});
72+
expect(handleDisconnect).toHaveBeenCalledWith({
73+
type: "clientTerminated",
74+
clientId: "2",
75+
});
7976
});
8077

8178
test("calls all listeners for the same message", () => {
82-
type Message = { type: "test" };
83-
84-
const adapter = createTestAdapter<Message>();
85-
const actor = createActor<Message>(adapter);
79+
const adapter = createTestAdapter();
80+
const actor = createActor(adapter);
8681

8782
const handleMessage = jest.fn();
8883
const handleMessage2 = jest.fn();
8984
const handleMessage3 = jest.fn();
9085

91-
actor.on("test", handleMessage);
92-
actor.on("test", handleMessage2);
93-
actor.on("test", handleMessage3);
86+
actor.on("initializePanel", handleMessage);
87+
actor.on("initializePanel", handleMessage2);
88+
actor.on("initializePanel", handleMessage3);
9489

95-
adapter.simulateDevtoolsMessage({ type: "test" });
90+
adapter.simulateDevtoolsMessage({ type: "initializePanel" });
9691

9792
expect(handleMessage).toHaveBeenCalledTimes(1);
9893
expect(handleMessage2).toHaveBeenCalledTimes(1);
9994
expect(handleMessage3).toHaveBeenCalledTimes(1);
10095
});
10196

10297
test("ignores messages that don't originate from devtools", () => {
103-
type Message = { type: "test" };
10498
const adapter = createTestAdapter();
105-
const actor = createActor<Message>(adapter);
99+
const actor = createActor(adapter);
106100

107101
const handleMessage = jest.fn();
108-
actor.on("test", handleMessage);
102+
actor.on("initializePanel", handleMessage);
109103

110-
adapter.simulatePlainMessage({ type: "test" });
104+
adapter.simulatePlainMessage({ type: "initializePanel" });
111105

112106
expect(handleMessage).not.toHaveBeenCalled();
113107
});
114108

115109
test.each([MessageType.RPCRequest, MessageType.RPCResponse])(
116110
"ignores messages that are %s messages",
117111
(messageType) => {
118-
type Message = { type: "test" };
119112
const adapter = createTestAdapter();
120-
const actor = createActor<Message>(adapter);
113+
const actor = createActor(adapter);
121114

122115
const handleMessage = jest.fn();
123-
actor.on("test", handleMessage);
116+
actor.on("initializePanel", handleMessage);
124117

125118
adapter.simulatePlainMessage({
126119
source: "apollo-client-devtools",
127120
type: messageType,
128-
message: { type: "test" },
121+
message: { type: "initializePanel" },
129122
});
130123

131124
expect(handleMessage).not.toHaveBeenCalled();
132125
}
133126
);
134127

135128
test("does not add listener to adapter until first subscribed actor listener", () => {
136-
type Message = { type: "test" };
137-
138129
const adapter = createTestAdapter();
139-
const actor = createActor<Message>(adapter);
130+
const actor = createActor(adapter);
140131

141132
expect(adapter.addListener).not.toHaveBeenCalled();
142133

143-
actor.send({ type: "test" });
134+
actor.send({ type: "initializePanel" });
144135
expect(adapter.addListener).not.toHaveBeenCalled();
145136

146-
actor.on("test", () => {});
137+
actor.on("initializePanel", () => {});
147138
expect(adapter.addListener).toHaveBeenCalledTimes(1);
148139
});
149140

150141
test("adds a single listener to adapter regardless of subscribed actor listeners", () => {
151-
type Message =
152-
| { type: "test" }
153-
| { type: "greet" }
154-
| { type: "connect" }
155-
| { type: "disconnect" };
156-
157142
const adapter = createTestAdapter();
158-
const actor = createActor<Message>(adapter);
143+
const actor = createActor(adapter);
159144

160-
actor.on("test", () => {});
161-
actor.on("greet", () => {});
162-
actor.on("disconnect", () => {});
163-
actor.on("connect", () => {});
145+
actor.on("initializePanel", () => {});
146+
actor.on("registerClient", () => {});
147+
actor.on("clientTerminated", () => {});
148+
actor.on("panelShown", () => {});
164149

165150
expect(adapter.addListener).toHaveBeenCalledTimes(1);
166151
});
167152

168153
test("can unsubscribe from a message by calling the returned function", () => {
169-
type Message = { type: "test" };
170-
const adapter = createTestAdapter<Message>();
171-
const actor = createActor<Message>(adapter);
154+
const adapter = createTestAdapter();
155+
const actor = createActor(adapter);
172156

173157
const handleMessage = jest.fn();
174-
const unsubscribe = actor.on("test", handleMessage);
158+
const unsubscribe = actor.on("initializePanel", handleMessage);
175159

176-
adapter.simulateDevtoolsMessage({ type: "test" });
160+
adapter.simulateDevtoolsMessage({ type: "initializePanel" });
177161

178162
expect(handleMessage).toHaveBeenCalledTimes(1);
179163

180164
handleMessage.mockClear();
181165
unsubscribe();
182166

183-
adapter.simulateDevtoolsMessage({ type: "test" });
167+
adapter.simulateDevtoolsMessage({ type: "initializePanel" });
184168

185169
expect(handleMessage).not.toHaveBeenCalled();
186170
});
187171

188172
test("removes listener on adapter when unsubscribing from last actor listener", () => {
189-
type Message = { type: "connect" } | { type: "disconnect" };
190-
const adapter = createTestAdapter<Message>();
191-
const actor = createActor<Message>(adapter);
173+
const adapter = createTestAdapter();
174+
const actor = createActor(adapter);
192175

193176
const handleConnect = jest.fn();
194177
const handleDisconnect = jest.fn();
195-
const unsubscribeConnect = actor.on("connect", handleConnect);
196-
const unsubscribeDisconnect = actor.on("connect", handleDisconnect);
178+
const unsubscribeConnect = actor.on("initializePanel", handleConnect);
179+
const unsubscribeDisconnect = actor.on("clientTerminated", handleDisconnect);
197180

198181
unsubscribeConnect();
199182

@@ -205,12 +188,11 @@ test("removes listener on adapter when unsubscribing from last actor listener",
205188
});
206189

207190
test("re-adds listener on adapter when subscribing actor listener after disconnecting", () => {
208-
type Message = { type: "connect" };
209-
const adapter = createTestAdapter<Message>();
210-
const actor = createActor<Message>(adapter);
191+
const adapter = createTestAdapter();
192+
const actor = createActor(adapter);
211193

212194
const handleConnect = jest.fn();
213-
const unsubscribeConnect = actor.on("connect", handleConnect);
195+
const unsubscribeConnect = actor.on("initializePanel", handleConnect);
214196

215197
expect(adapter.addListener).toHaveBeenCalledTimes(1);
216198

@@ -219,6 +201,6 @@ test("re-adds listener on adapter when subscribing actor listener after disconne
219201

220202
adapter.addListener.mockClear();
221203

222-
actor.on("connect", handleConnect);
204+
actor.on("initializePanel", handleConnect);
223205
expect(adapter.addListener).toHaveBeenCalledTimes(1);
224206
});

0 commit comments

Comments
 (0)