- Type response bodies in gameController.test.ts to fix no-unsafe-member-access - Replace async methods with Promise.resolve() in InMemoryGameSessionStore and InMemoryLobbyGameStore to satisfy require-await rule - Add argsIgnorePattern and varsIgnorePattern to eslint config so underscore-prefixed params are globally ignored - Fix no-misused-promises in ws/index.ts, lobbyHandlers, gameHandlers, __root.tsx, login.tsx and play.tsx by using void + .catch() - Fix no-floating-promises on navigate calls in login.tsx - Move API_URL outside Play component to fix useCallback dependency warning - Type fetch response bodies in play.tsx to fix no-unsafe-assignment - Add only-throw-error: off for route files (TanStack Router throw redirect) - Remove unused WebSocket import from express.d.ts - Fix unsafe return in connections.ts by typing empty Map constructor - Exclude scripts/ folder from eslint - Add targeted override for better-auth auth-client.ts (upstream typing issue)
65 lines
1.8 KiB
TypeScript
65 lines
1.8 KiB
TypeScript
import { WebSocketServer } from "ws";
|
|
import type { WebSocket } from "ws";
|
|
import type { Server } from "http";
|
|
import type { IncomingMessage } from "http";
|
|
import { handleUpgrade } from "./auth.js";
|
|
import { handleMessage, type AuthenticatedUser } from "./router.js";
|
|
import { removeConnection } from "./connections.js";
|
|
import { handleLobbyLeave } from "./handlers/lobbyHandlers.js";
|
|
|
|
export const setupWebSocket = (server: Server): WebSocketServer => {
|
|
const wss = new WebSocketServer({ noServer: true });
|
|
|
|
server.on("upgrade", (request, socket, head) => {
|
|
if (request.url !== "/ws") {
|
|
socket.destroy();
|
|
return;
|
|
}
|
|
void handleUpgrade(request, socket, head, wss).catch((err) => {
|
|
console.error("WebSocket upgrade error:", err);
|
|
socket.destroy();
|
|
});
|
|
});
|
|
|
|
wss.on(
|
|
"connection",
|
|
(ws: WebSocket, _request: IncomingMessage, auth: AuthenticatedUser) => {
|
|
ws.on("message", (rawData) => {
|
|
void handleMessage(ws, rawData, auth).catch((err) => {
|
|
console.error(
|
|
`WebSocket message error for user ${auth.user.id}:`,
|
|
err,
|
|
);
|
|
});
|
|
});
|
|
|
|
ws.on("close", () => {
|
|
void handleDisconnect(ws, auth).catch((err) => {
|
|
console.error(
|
|
`WebSocket disconnect error for user ${auth.user.id}:`,
|
|
err,
|
|
);
|
|
});
|
|
});
|
|
|
|
ws.on("error", (err) => {
|
|
console.error(`WebSocket error for user ${auth.user.id}:`, err);
|
|
});
|
|
},
|
|
);
|
|
|
|
return wss;
|
|
};
|
|
|
|
const handleDisconnect = async (
|
|
ws: WebSocket,
|
|
auth: AuthenticatedUser,
|
|
): Promise<void> => {
|
|
if (!ws.lobbyId) return; // user connected but never joined a lobby
|
|
removeConnection(ws.lobbyId, auth.user.id);
|
|
await handleLobbyLeave(
|
|
ws,
|
|
{ type: "lobby:leave", lobbyId: ws.lobbyId },
|
|
auth.user,
|
|
);
|
|
};
|