Chat System
Real-time chat system using WebSockets for communication between customers and sellers about orders or general inquiries.
Overview
- WebSocket-based real-time messaging
- Order-specific chats and general chats
- File attachments support
- Chat archiving functionality
- Typing indicators and presence
- Message history with pagination
WebSocket Gateway
@WebSocketGateway({
cors: { origin: '*' },
namespace: '/chat',
maxHttpBufferSize: 10e6 // 10 MB
})
export class ChatGateway {
@WebSocketServer() server: Server;
async handleConnection(client: Socket) {
// Verify JWT token
const token = client.handshake.auth.token;
const payload = await this.authService.verifyAccessToken(token);
client.data.user = payload;
}
@SubscribeMessage('join')
async handleJoinChat(
@MessageBody() data: { chatId: string },
@ConnectedSocket() client: Socket
) {
// Verify membership
if (!(await this.chatRepository.isUserInChat(data.chatId, client.data.user.id))) {
client.disconnect();
return;
}
client.join(`chat:${data.chatId}`);
this.server.to(`chat:${data.chatId}`).emit('user joined', {
userId: client.data.user.id,
chatId: data.chatId
});
}
@SubscribeMessage('chat message')
async handleMessage(
@MessageBody() data: {
chatId: string;
content: string;
attachments?: File[];
},
@ConnectedSocket() client: Socket
) {
const user = client.data.user;
// Save attachments
let attachmentFiles = [];
if (data.attachments) {
attachmentFiles = await Promise.all(
data.attachments.map(file =>
this.storageService.upload(file, UploadObjectType.CHAT, data.chatId)
)
);
}
// Persist message
const message = await this.chatRepository.addMessage({
id: generateId(),
chatId: data.chatId,
senderId: user.id,
content: data.content,
timestamp: new Date(),
attachments: attachmentFiles
});
// Broadcast to chat room
this.server.to(`chat:${data.chatId}`).emit('message', {
...message,
sender: {
id: user.id,
fullName: user.fullName
}
});
}
}
Client Usage
Connect
import io from 'socket.io-client';
const socket = io('http://localhost:3000/chat', {
auth: {
token: accessToken
}
});
socket.on('connect', () => {
console.log('Connected to chat');
});
Join Chat
socket.emit('join', { chatId: 'chat-123' });
socket.on('user joined', (data) => {
console.log(`${data.userId} joined chat`);
});
Send Message
socket.emit('chat message', {
chatId: 'chat-123',
content: 'Hello!',
attachments: [] // Optional file attachments
});
Receive Messages
socket.on('message', (message) => {
console.log(`${message.sender.fullName}: ${message.content}`);
displayMessage(message);
});
REST API (for chat history)
List Chats
Get Chat Messages
Archive Chat
Best Practices
✅ Do
- Verify user membership before joining chat
- Authenticate WebSocket connections with JWT
- Store message history in database
- Support file attachments
- Implement message pagination
- Show typing indicators
❌ Don't
- Don't allow joining chats without verification
- Don't forget to disconnect unauthorized users
- Don't allow messages from non-members
- Don't store large files inline
- Don't skip message persistence