Skip to content

Commit fb16f31

Browse files
authoredMar 28, 2025
Merge pull request #3 from appwrite/chore-update
chore: make synapse.send public and update tests
2 parents 9f8be2b + 9bdbdcc commit fb16f31

File tree

4 files changed

+100
-33
lines changed

4 files changed

+100
-33
lines changed
 

‎.github/workflows/publish.yml

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ on:
88
jobs:
99
publish:
1010
runs-on: ubuntu-latest
11-
1211
steps:
1312
- uses: actions/checkout@v4
1413

‎README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ synapse.disconnect();
7777

7878
```typescript
7979
// File operations through Synapse's filesystem service
80-
import { Synapse, Filesystem } from "synapse";
80+
import { Synapse, Filesystem } from "@appwrite.io/synapse";
8181

8282
const synapse = new Synapse();
8383
const filesystem = new Filesystem(synapse);
@@ -92,7 +92,7 @@ const { success, data } = await filesystem.getFolder("/path/to/dir");
9292

9393
```typescript
9494
// Get system usage statistics through Synapse's system service
95-
import { System } from "synapse";
95+
import { System } from "@appwrite.io/synapse";
9696

9797
const system = new System(synapse);
9898
const { success, data } = await system.getUsage();
@@ -105,7 +105,7 @@ console.log("Load Average (1m):", data.loadAverage1m);
105105

106106
```typescript
107107
// Perform Git operations through Synapse's git service
108-
import { Synapse, Git } from "synapse";
108+
import { Synapse, Git } from "@appwrite.io/synapse";
109109

110110
const synapse = new Synapse();
111111
const git = new Git(synapse);

‎src/synapse.ts

+37-29
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export type MessagePayload = {
99
export type MessageHandler = (message: MessagePayload) => void;
1010
export type ConnectionCallback = () => void;
1111
export type ErrorCallback = (error: Error) => void;
12+
export type Logger = (message: string) => void;
1213

1314
class Synapse {
1415
private ws: WebSocket | null = null;
@@ -18,27 +19,7 @@ class Synapse {
1819
onClose: (() => {}) as ConnectionCallback,
1920
onError: (() => {}) as ErrorCallback,
2021
};
21-
logger: (message: string) => void = console.log;
22-
23-
private send(
24-
type: string,
25-
payload: Record<string, unknown> = {},
26-
): Promise<MessagePayload> {
27-
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
28-
throw new Error("WebSocket is not connected");
29-
}
30-
31-
const message: MessagePayload = {
32-
type,
33-
requestId: Date.now().toString(),
34-
...payload,
35-
};
36-
37-
return new Promise((resolve) => {
38-
this.ws!.send(JSON.stringify(message));
39-
resolve(message);
40-
});
41-
}
22+
logger: Logger = console.log;
4223

4324
private handleMessage(event: WebSocket.MessageEvent): void {
4425
try {
@@ -52,14 +33,6 @@ class Synapse {
5233
}
5334
}
5435

55-
/**
56-
* Sets the logger function for the Synapse instance
57-
* @param logger - The logger function to use
58-
*/
59-
setLogger(logger: (message: string) => void): void {
60-
this.logger = logger;
61-
}
62-
6336
/**
6437
* Establishes a WebSocket connection to the specified URL and initializes the terminal
6538
* @param url - The WebSocket server URL to connect to
@@ -89,6 +62,41 @@ class Synapse {
8962
});
9063
}
9164

65+
/**
66+
* Sets the logger function for the Synapse instance
67+
* @param logger - The logger function to use
68+
*/
69+
setLogger(logger: Logger): void {
70+
this.logger = logger;
71+
}
72+
73+
/**
74+
* Sends a message to the WebSocket server
75+
* @param type - The type of message to send
76+
* @param payload - The payload of the message
77+
* @returns A promise that resolves with the message payload
78+
* @throws Error if WebSocket is not connected
79+
*/
80+
send(
81+
type: string,
82+
payload: Record<string, unknown> = {},
83+
): Promise<MessagePayload> {
84+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
85+
throw new Error("WebSocket is not connected");
86+
}
87+
88+
const message: MessagePayload = {
89+
type,
90+
requestId: Date.now().toString(),
91+
...payload,
92+
};
93+
94+
return new Promise((resolve) => {
95+
this.ws!.send(JSON.stringify(message));
96+
resolve(message);
97+
});
98+
}
99+
92100
/**
93101
* Sends a command to the terminal for execution
94102
* @param command - The command string to execute

‎tests/synapse.test.ts

+60
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,64 @@ describe("Synapse", () => {
141141
expect(handler).not.toHaveBeenCalled();
142142
});
143143
});
144+
145+
describe("send", () => {
146+
it("should send messages with correct format and return promise with message payload", async () => {
147+
const mockWs = {
148+
onopen: null as unknown as (event: WebSocket.Event) => void,
149+
onmessage: null as unknown as (event: WebSocket.MessageEvent) => void,
150+
onerror: null as unknown as (event: WebSocket.ErrorEvent) => void,
151+
onclose: null as unknown as (event: WebSocket.CloseEvent) => void,
152+
readyState: WebSocket.OPEN,
153+
send: jest.fn(),
154+
};
155+
156+
(WebSocket as unknown as jest.Mock).mockImplementation(() => mockWs);
157+
const connectPromise = synapse.connect("ws://localhost:8080");
158+
mockWs.onopen!({} as WebSocket.Event);
159+
await connectPromise;
160+
161+
const payload = { data: "test-data" };
162+
const result = await synapse.send("test-type", payload);
163+
164+
expect(mockWs.send).toHaveBeenCalledTimes(1);
165+
const sentMessage = JSON.parse(mockWs.send.mock.calls[0][0]);
166+
expect(sentMessage).toEqual({
167+
type: "test-type",
168+
requestId: expect.any(String),
169+
data: "test-data",
170+
});
171+
expect(result).toEqual({
172+
type: "test-type",
173+
requestId: expect.any(String),
174+
data: "test-data",
175+
});
176+
});
177+
178+
it("should throw error when WebSocket is not connected", () => {
179+
expect(() => synapse.send("test-type")).toThrow(
180+
"WebSocket is not connected",
181+
);
182+
});
183+
184+
it("should throw error when WebSocket is not in OPEN state", async () => {
185+
const mockWs = {
186+
onopen: null as unknown as (event: WebSocket.Event) => void,
187+
onmessage: null as unknown as (event: WebSocket.MessageEvent) => void,
188+
onerror: null as unknown as (event: WebSocket.ErrorEvent) => void,
189+
onclose: null as unknown as (event: WebSocket.CloseEvent) => void,
190+
readyState: WebSocket.CLOSED,
191+
send: jest.fn(),
192+
};
193+
194+
(WebSocket as unknown as jest.Mock).mockImplementation(() => mockWs);
195+
const connectPromise = synapse.connect("ws://localhost:8080");
196+
mockWs.onopen!({} as WebSocket.Event);
197+
await connectPromise;
198+
199+
expect(() => synapse.send("test-type")).toThrow(
200+
"WebSocket is not connected",
201+
);
202+
});
203+
});
144204
});

0 commit comments

Comments
 (0)
Please sign in to comment.