135 lines
3.2 KiB
TypeScript
135 lines
3.2 KiB
TypeScript
import type { Server as HttpServer } from "node:http";
|
|
//import { dirname, join } from "node:path";
|
|
//import { fileURLToPath } from "node:url";
|
|
import { instrument } from "@socket.io/admin-ui";
|
|
import { Server } from "socket.io";
|
|
import { auth } from "utils/auth.utils.js";
|
|
import { createLogger } from "../logger/logger.controller.js";
|
|
import { allowedOrigins } from "../utils/cors.utils.js";
|
|
import { registerEmitter } from "./roomEmitter.socket.js";
|
|
import { createRoomEmitter, preseedRoom } from "./roomService.socket.js";
|
|
|
|
//const __filename = fileURLToPath(import.meta.url);
|
|
//const __dirname = dirname(__filename);
|
|
const log = createLogger({ module: "socket.io", subModule: "setup" });
|
|
|
|
//import type { Session, User } from "better-auth"; // adjust if needed
|
|
import { protectedRooms } from "./roomDefinitions.socket.js";
|
|
|
|
// declare module "socket.io" {
|
|
// interface Socket {
|
|
// user?: User | any;
|
|
// session?: Session;
|
|
// }
|
|
// }
|
|
|
|
export const setupSocketIORoutes = (baseUrl: string, server: HttpServer) => {
|
|
const io = new Server(server, {
|
|
path: `${baseUrl}/api/socket.io`,
|
|
cors: {
|
|
origin: allowedOrigins,
|
|
credentials: true,
|
|
},
|
|
});
|
|
|
|
// ✅ Create emitter instance
|
|
const { addDataToRoom } = createRoomEmitter(io);
|
|
registerEmitter(addDataToRoom);
|
|
|
|
io.use(async (socket, next) => {
|
|
try {
|
|
//const cookieHeader = socket.handshake.headers.cookie;
|
|
const headers = new Headers();
|
|
|
|
for (const [key, value] of Object.entries(socket.request.headers)) {
|
|
if (typeof value === "string") {
|
|
headers.set(key, value);
|
|
} else if (Array.isArray(value)) {
|
|
headers.set(key, value.join(", "));
|
|
}
|
|
}
|
|
|
|
const session = await auth.api.getSession({
|
|
headers,
|
|
});
|
|
|
|
if (!session) {
|
|
return next(); // allow connection, but no auth
|
|
}
|
|
|
|
if (session) {
|
|
socket.user = session.user;
|
|
socket.session = session as any;
|
|
}
|
|
|
|
next();
|
|
} catch (err) {
|
|
next();
|
|
}
|
|
});
|
|
|
|
io.on("connection", (s) => {
|
|
log.info({}, `User connected: ${s.id}`);
|
|
|
|
s.emit("welcome", {
|
|
serverTime: Date.now(),
|
|
availableRooms: ["logs", "labels"],
|
|
version: "1.0.0",
|
|
});
|
|
|
|
s.on("join-room", async (rn) => {
|
|
const config = protectedRooms[rn];
|
|
|
|
if (config?.requiresAuth && !s.user) {
|
|
return s.emit("room-error", {
|
|
room: rn,
|
|
message: "Authentication required",
|
|
});
|
|
}
|
|
|
|
if (config?.role && s.user?.role !== config.role) {
|
|
return s.emit("room-error", {
|
|
room: rn,
|
|
message: `Not authorized to be in room: ${rn}`,
|
|
});
|
|
}
|
|
s.join(rn);
|
|
|
|
// get room seeded
|
|
const history = await preseedRoom(rn);
|
|
log.info({}, `User joined ${rn}: ${s.id}`);
|
|
// send the intial data
|
|
s.emit("room-update", {
|
|
roomId: rn,
|
|
payloads: history,
|
|
initial: true,
|
|
});
|
|
});
|
|
|
|
s.on("leave-room", (room) => {
|
|
s.leave(room);
|
|
log.info({}, `${s.id} left room: ${room}`);
|
|
});
|
|
});
|
|
|
|
io.on("disconnect", (s) => {
|
|
log.info({}, "User disconnected:", s.id);
|
|
});
|
|
|
|
// admin stuff
|
|
|
|
const admin = io.of("/admin");
|
|
admin.on("connection", (s) => {
|
|
log.info({}, `User connected: ${s.id}`);
|
|
});
|
|
|
|
admin.on("disconnect", (s) => {
|
|
log.info({}, "User disconnected:", s.id);
|
|
});
|
|
|
|
instrument(io, {
|
|
auth: false,
|
|
//namespaceName: "/admin",
|
|
});
|
|
};
|