import type { Server } from "socket.io"; import type { ServerToClientEvents, ClientToServerEvents, InterServerEvents, SocketData, } from "@storybid/shared"; import { registerLiveAuctionHandlers } from "./live-auction.js"; import { registerSilentAuctionHandlers } from "./silent-auction.js"; import { verifyToken } from "../lib/jwt.js"; type IO = Server; export function registerSocketHandlers(io: IO): void { // Auth middleware – validate JWT on handshake io.use((socket, next) => { const token = (socket.handshake.auth["token"] as string | undefined) ?? (socket.handshake.headers["authorization"] as string | undefined)?.replace("Bearer ", ""); if (!token) { // Allow unauthenticated connections for display board / public catalog return next(); } try { const payload = verifyToken(token); socket.data.bidderId = payload.role === "bidder" ? payload.sub : undefined; socket.data.staffId = payload.role !== "bidder" ? payload.sub : undefined; socket.data.role = payload.role; socket.data.deviceId = payload.deviceId; } catch { return next(new Error("Invalid token")); } next(); }); io.on("connection", (socket) => { console.log(`[socket] connected ${socket.id} role=${socket.data.role ?? "guest"}`); // Auto-join personal room for outbid / checkout notifications if (socket.data.bidderId) { void socket.join(`bidder:${socket.data.bidderId}`); } // Room join/leave for event-scoped broadcasts socket.on("join_event", (eventId) => { void socket.join(`event:${eventId}`); }); socket.on("leave_event", (eventId) => { void socket.leave(`event:${eventId}`); }); registerLiveAuctionHandlers(io, socket); registerSilentAuctionHandlers(io, socket); socket.on("disconnect", (reason) => { console.log(`[socket] disconnected ${socket.id} reason=${reason}`); }); }); }