// src/gateway/server.ts
import { WebSocketServer, WebSocket } from "ws";
import { randomUUID } from "node:crypto";
import type { RpcFrame, RpcRequest, RpcResponse } from "./protocol.js";
type ClientConnection = {
id: string;
ws: WebSocket;
subscribedEvents: Set<string>;
};
export class Gateway {
private wss: WebSocketServer;
private clients = new Map<string, ClientConnection>();
private handlers = new Map<string, (params: unknown) => Promise<unknown>>();
constructor(port: number) {
this.wss = new WebSocketServer({ port });
this.wss.on("connection", (ws) => this.handleConnection(ws));
}
// 注册 RPC 方法处理器
registerMethod(method: string, handler: (params: unknown) => Promise<unknown>) {
this.handlers.set(method, handler);
}
// 向所有订阅者广播事件
broadcast(event: string, payload?: unknown) {
const frame: RpcFrame = { type: "event", event, payload };
const data = JSON.stringify(frame);
for (const client of this.clients.values()) {
if (client.subscribedEvents.has(event) || client.subscribedEvents.has("*")) {
client.ws.send(data);
}
}
}
private handleConnection(ws: WebSocket) {
const clientId = randomUUID();
const client: ClientConnection = {
id: clientId,
ws,
subscribedEvents: new Set(["*"]), // 默认订阅所有事件
};
this.clients.set(clientId, client);
ws.on("message", async (raw) => {
try {
const frame = JSON.parse(raw.toString()) as RpcFrame;
if (frame.type === "req") {
await this.handleRequest(client, frame);
}
} catch (err) {
console.error("Frame parse error:", err);
}
});
ws.on("close", () => {
this.clients.delete(clientId);
});
}
private async handleRequest(client: ClientConnection, req: RpcRequest) {
const handler = this.handlers.get(req.method);
const res: RpcResponse = { type: "res", id: req.id };
if (!handler) {
res.error = `Unknown method: ${req.method}`;
} else {
try {
res.result = await handler(req.params);
} catch (err) {
res.error = err instanceof Error ? err.message : String(err);
}
}
client.ws.send(JSON.stringify(res));
}
}