,
>(options: ServerOptions>): WebSocketHandler {
const server = makeServer(options);
interface Client {
handleMessage: (data: string) => Promise;
closed: (code: number, reason: string) => Promise;
}
const clients = new WeakMap();
return {
open(ws) {
const client: Client = {
handleMessage: () => {
throw new Error('Message received before handler was registered');
},
closed: () => {
throw new Error('Closed before handler was registered');
},
};
client.closed = server.opened(
{
// TODO: use protocol on socket once Bun exposes it
protocol: GRAPHQL_TRANSPORT_WS_PROTOCOL,
send: async (message) => {
// ws might have been destroyed in the meantime, send only if exists
if (clients.has(ws)) {
ws.sendText(message);
}
},
close: (code, reason) => {
if (clients.has(ws)) {
ws.close(code, reason);
}
},
onMessage: (cb) => (client.handleMessage = cb),
},
{ socket: ws } as Extra & Partial,
);
clients.set(ws, client);
},
message(ws, message) {
const client = clients.get(ws);
if (!client) throw new Error('Message received for a missing client');
return client.handleMessage(String(message));
},
close(ws, code, message) {
const client = clients.get(ws);
if (!client) throw new Error('Closing a missing client');
return client.closed(code, message);
},
};
}