File size: 2,529 Bytes
ece569a
7853dfb
ece569a
 
 
 
 
 
 
e23c8e9
 
 
 
ece569a
 
e23c8e9
 
 
 
 
 
 
ece569a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7853dfb
ece569a
 
 
7853dfb
 
 
 
 
 
 
 
 
 
 
ece569a
3d52d95
a793f2f
3d52d95
 
 
a793f2f
 
 
 
 
 
 
 
 
 
 
 
 
3d52d95
ece569a
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
const { Server } = require('socket.io');
const prisma = require('./prisma');

class SocketManager {
  constructor() {
    this.io = null;
  }

  init(server) {
    const allowedOrigins = process.env.FRONTEND_URL
      ? process.env.FRONTEND_URL.split(',').map(url => url.trim())
      : ['http://localhost:3000'];

    this.io = new Server(server, {
      cors: {
        origin: (origin, callback) => {
          if (!origin || allowedOrigins.includes(origin)) {
            callback(null, true);
          } else {
            callback(new Error('Not allowed by CORS'));
          }
        },
        methods: ['GET', 'POST'],
        credentials: true
      }
    });

    this.io.on('connection', (socket) => {
      socket.on('join', (threadId) => {
        if (threadId) {
          socket.join(`thread:${threadId}`);
        }
      });

      socket.on('leave', (threadId) => {
        if (threadId) {
          socket.leave(`thread:${threadId}`);
        }
      });

      socket.on('joinWorkspace', (workspaceId) => {
        if (workspaceId) {
          socket.join(`workspace:${workspaceId}`);
        }
      });

      socket.on('leaveWorkspace', (workspaceId) => {
        if (workspaceId) {
          socket.leave(`workspace:${workspaceId}`);
        }
      });
    });
  }

  broadcastToThread(threadId, message) {
    if (this.io) {
      this.io.to(`thread:${threadId}`).emit('message', message);
    }
  }

  async sendNotification(workspaceId, payload) {
    if (this.io) {
      this.io.to(`workspace:${workspaceId}`).emit('notification', payload);
    }
    try {
      await prisma.notification.create({
        data: {
          workspaceId,
          type: payload.type,
          payload: JSON.stringify(payload),
        }
      });
    } catch (err) {
      console.error('Failed to persist notification:', err);
    }
  }

  async broadcastGlobalNotification(payload) {
    if (this.io) {
      this.io.emit('notification', payload);
    }
    try {
      const workspaces = await prisma.workspace.findMany({ select: { id: true } });
      if (workspaces.length > 0) {
        const notifications = workspaces.map(ws => ({
          workspaceId: ws.id,
          type: payload.type,
          payload: JSON.stringify(payload),
        }));
        await prisma.notification.createMany({ data: notifications });
      }
    } catch (err) {
      console.error('Failed to persist global notifications:', err);
    }
  }
}

const socketManager = new SocketManager();
module.exports = socketManager;