chatstorm
Version:
ChatStorm - Real-Time Chat Server for Your App. ChatStorm is a powerful, lightning-fast Socket.io-based chat server that enables seamless real-time messaging in your application. Whether you're building a messaging app, live chat feature, or a collaborati
571 lines (445 loc) ⢠15.5 kB
Markdown
# ā” ChatStorm

**A powerful, lightning-fast Socket.io-based chat server for your applications**
[](https://www.npmjs.com/package/chatstorm)
[](https://opensource.org/licenses/ISC)
[](https://nodejs.org/)
---
## š Features
- ā” **Real-Time Messaging** - Instant message delivery using Socket.io
- šļø **MongoDB Integration** - Persistent message storage and history
- š **Private Messaging** - Secure one-on-one conversations
- š± **Cross-Platform** - Works with web and mobile applications
- šÆ **Easy Integration** - Simple setup with minimal configuration
- š **Scalable** - Handles multiple concurrent users effortlessly
- šØ **Customizable** - Flexible architecture for your needs
---
## š¦ Installation
### Prerequisites
- Node.js 18+
- MongoDB database
- npm or yarn package manager
### Step 1: Install ChatStorm
```bash
npm install chatstorm
```
### Step 2: Environment Setup
Create a `.env` file in your project root:
```bash
# MongoDB Connection
MONGODB_URL=mongodb://localhost:27017/chatstorm
# Server Port
PORT=3000
```
---
## š ļø Quick Start
### Basic Implementation
```javascript
const http = require("http");
const cors = require("cors");
const express = require("express");
const ChatStorm = require("chatstorm");
require("dotenv").config();
// Initialize Express app
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Basic route
app.get("/", (req, res) => {
res.send("Welcome to ChatStorm ā”");
});
// Server setup
let server;
try {
// Create HTTP server
const nodeServer = http.createServer(app);
// Initialize ChatStorm with MongoDB URL
// ChatStorm will handle MongoDB connection internally
ChatStorm(nodeServer, process.env.MONGODB_URL);
// Start server
server = nodeServer.listen(process.env.PORT, "0.0.0.0", () => {
console.log(`š Server running on port ${process.env.PORT}`);
});
} catch (error) {
console.error("ā Error:", error);
}
```
### Complete Example
```javascript
const http = require("http");
const cors = require("cors");
const express = require("express");
const ChatStorm = require("chatstorm");
require("dotenv").config();
const app = express();
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Routes
app.get("/", (req, res) => {
res.json({
message: "Welcome to ChatStorm ā”",
version: "1.0.4",
status: "running"
});
});
app.get("/health", (req, res) => {
res.json({ status: "healthy", timestamp: new Date().toISOString() });
});
// Server initialization
let server;
try {
// Create HTTP server
const nodeServer = http.createServer(app);
// Initialize ChatStorm with MongoDB URL
// ChatStorm will handle MongoDB connection internally
ChatStorm(nodeServer, process.env.MONGODB_URL);
// Start server
server = nodeServer.listen(process.env.PORT, "0.0.0.0", () => {
console.log(`š ChatStorm server running on port ${process.env.PORT}`);
console.log(`š± Access your chat server at: http://localhost:${process.env.PORT}`);
});
} catch (error) {
console.error("ā Server initialization failed:", error);
}
// Graceful shutdown
const exitHandler = () => {
if (server) {
server.close(() => {
console.log("š Server closed gracefully");
process.exit(1);
});
} else {
process.exit(1);
}
};
process.on("uncaughtException", exitHandler);
process.on("unhandledRejection", exitHandler);
process.on("SIGTERM", () => {
console.log("š“ SIGTERM received");
if (server) {
server.close();
}
});
```
---
## š§ Configuration
### ChatStorm Initialization
```javascript
ChatStorm(nodeServer, mongoDBUrl)
```
**Parameters:**
- `nodeServer` (required): HTTP server instance created with `http.createServer()`
- `mongoDBUrl` (required): MongoDB connection string
**Note:** ChatStorm handles the MongoDB connection internally. You don't need to call `mongoose.connect()` separately.
### Environment Variables
| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `MONGODB_URL` | MongoDB connection string | - | ā
|
| `PORT` | Server port | `3000` | ā |
### MongoDB Setup
1. **Local MongoDB:**
```bash
MONGODB_URL=mongodb://localhost:27017/chatstorm
```
2. **MongoDB Atlas (Cloud):**
```bash
MONGODB_URL=mongodb+srv://username:password@cluster.mongodb.net/chatstorm
```
---
## šļø Project Structure
```
chatstorm/
āāā Config/
ā āāā rainbow.js # Animated logging utility
āāā model/
ā āāā chat.model.js # Chat room model
ā āāā messages.model.js # Message model
ā āāā socket.model.js # Socket connection model
ā āāā user.model.js # User model
āāā Sockets/
ā āāā config.js # Socket.io configuration
ā āāā controller.js # Socket event handlers
āāā server.js # Main server file
āāā package.json # Dependencies and scripts
```
---
## š Development
### Running in Development Mode
```bash
npm run dev
```
### Available Scripts
- `npm run dev` - Start development server with nodemon
- `npm test` - Run tests (placeholder)
---
## š API Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/` | Welcome message |
| `GET` | `/health` | Health check |
---
## š Socket Events
### Client ā Server
| Event | Data | Description |
|-------|------|-------------|
| `joinchat` | `{receiverId: string}` | Join a chat with another user |
| `send_message` | `{receiverId: string, message: object}` | Send a message to a user |
| `chat_message` | `{receiverId: string, keyword?: string}` | Get chat history with a user (automatically marks messages as seen) |
| `get_chatlist` | `{keyword?: string}` | Get list of all chats with unread counts |
| `delete_message` | `{messageId: string}` | Delete a specific message |
| `user_typing` | `{receiverId: string, type: string}` | Send typing indicator (`user_typing` or `stop_typing`) |
| `leave_chat` | `{receiverId: string}` | Leave a chat conversation |
| `check_online_status` | `{receiverId: string}` | Check if a user is online |
| `call-user` | `{userId: string, offer: object, type: string}` | Initiate a video call |
| `answer-call` | `{userId: string, answer: object}` | Answer an incoming call |
| `reject-call` | `{userId: string}` | Reject an incoming call |
| `leave-call` | `{userId: string}` | Leave an active call |
| `ice-candidate` | `{userId: string, candidate: object}` | Send ICE candidate for WebRTC |
| `disconnect_user` | `{}` | Disconnect user session |
### Server ā Client
| Event | Data | Description |
|-------|------|-------------|
| `handshake_success` | `{message: string, success: boolean, data: UserObject}` | Chat joined successfully. Returns structured user data |
| `chat_status` | `{message: string, isJoined?: boolean, isLeft?: boolean, data?: UserObject}` | Chat status update (user joined/left) |
| `message_sent` | `{message: string, data: MessageObject, success: boolean}` | Message sent confirmation with structured user data |
| `receive_message` | `{message: string, data: MessageObject, success: boolean}` | Receive a new message with structured user data |
| `retrieve_message` | `{data: MessageArray, success: boolean, message: string}` | Chat history retrieved (messages marked as seen) |
| `chatlist` | `{data: ChatArray, message: string, success: boolean}` | Chat list received with unread counts and structured user data |
| `message_update` | `{data: MessageObject, receiverId: string, success: boolean, message: string}` | Message updated (deleted) - sender notification |
| `message_update_receiver` | `{data: MessageObject, senderId: string, success: boolean, message: string}` | Message update notification for receiver |
| `typing_alert` | `{data: {senderId: string, isTyping: boolean}, message: string, success: boolean}` | Typing indicator received |
| `online_status` | `{isOnline: boolean, receiverId: string, message: string}` | Online status response |
| `incoming-call` | `{from: string, offer: object, type: string, user: UserObject}` | Incoming call notification |
| `call-answered` | `{answer: object}` | Call answered notification |
| `call-ended` | `{userId: string}` | Call ended notification |
| `ice-candidate` | `{candidate: object}` | ICE candidate received |
| `leave` | `{message: string, success: boolean}` | Disconnect confirmation |
| `error_notify` | `{message: string, success: boolean}` | Error notification |
### Data Structures
#### UserObject
```typescript
{
_id: string;
image?: string;
name?: string;
username?: string;
email?: string;
phone?: string;
fullName?: string;
firstName?: string;
lastName?: string;
gender?: string;
age?: number;
status?: string;
role?: string;
isDeleted?: boolean;
isOnline?: boolean; // Only in chatlist
phoneNumber?: string; // Only in message responses
}
```
#### MessageObject
```typescript
{
_id: string;
message: {
text?: string;
media?: string;
url?: string;
};
senderId: UserObject;
receiverId: UserObject;
chatId: string;
isSeen: boolean;
isDeleted: boolean;
createdAt: Date;
updatedAt: Date;
user: UserObject; // Current user context
senderDetails: UserObject;
receiverDetails: UserObject;
}
```
#### ChatObject (in chatlist)
```typescript
{
_id: string;
senderId: UserObject;
receiverId: UserObject;
lastMessage: string;
unreadCount: number; // Count of unread messages for current user
messageCount: number; // Count of all unread messages (isSeen: false)
createdAt: Date;
updatedAt: Date;
}
```
### Important Notes
- **Authentication**: All socket connections require a `token` header in the handshake with a valid MongoDB ObjectId
- **Message Seen Status**: When `chat_message` is called, all messages between the users are automatically marked as `isSeen: true`
- **Unread Count**: The `unreadCount` in chatlist represents messages where `receiverId` matches the current user and `isSeen: false`
- **Message Count**: The `messageCount` in chatlist represents all messages in the chat where `isSeen: false`
- **Online Status**: Users' online status is automatically tracked and included in chatlist responses
---
## š” Usage Examples
### Client-Side Implementation
```javascript
import io from 'socket.io-client';
// Connect to socket with authentication token
const socket = io('http://localhost:3000', {
extraHeaders: {
token: 'YOUR_USER_ID' // MongoDB ObjectId
}
});
// Listen for connection
socket.on('connect', () => {
console.log('Connected to ChatStorm');
});
// Join a chat
socket.emit('joinchat', { receiverId: 'RECEIVER_USER_ID' });
// Listen for join confirmation
socket.on('handshake_success', (data) => {
console.log('Chat joined:', data);
});
// Listen for chat status updates (user joined/left)
socket.on('chat_status', (data) => {
if (data.isJoined) {
console.log('User joined:', data.data);
} else if (data.isLeft) {
console.log('User left the chat');
}
});
// Send a message
socket.emit('send_message', {
receiverId: 'RECEIVER_USER_ID',
message: {
text: 'Hello, how are you?'
}
});
// Listen for sent message confirmation
socket.on('message_sent', (data) => {
console.log('Message sent:', data);
});
// Listen for received messages
socket.on('receive_message', (data) => {
console.log('New message:', data);
});
// Get chat history (automatically marks messages as seen)
socket.emit('chat_message', {
receiverId: 'RECEIVER_USER_ID',
keyword: 'search term' // optional
});
// Listen for chat history
socket.on('retrieve_message', (data) => {
console.log('Chat history:', data.data);
});
// Get chat list with unread counts
socket.emit('get_chatlist', { keyword: 'search' }); // keyword is optional
socket.on('chatlist', (data) => {
data.data.forEach(chat => {
console.log(`Chat with ${chat.senderId.name}: ${chat.unreadCount} unread messages`);
});
});
// Leave a chat
socket.emit('leave_chat', { receiverId: 'RECEIVER_USER_ID' });
socket.on('chat_status', (data) => {
if (data.isLeft) {
console.log('Left chat successfully');
}
});
// Check online status
socket.emit('check_online_status', { receiverId: 'RECEIVER_USER_ID' });
socket.on('online_status', (data) => {
console.log(`User is ${data.isOnline ? 'online' : 'offline'}`);
});
// Typing indicator
socket.emit('user_typing', {
receiverId: 'RECEIVER_USER_ID',
type: 'user_typing' // or 'stop_typing'
});
socket.on('typing_alert', (data) => {
if (data.data.isTyping) {
console.log('User is typing...');
}
});
// Delete a message
socket.emit('delete_message', { messageId: 'MESSAGE_ID' });
socket.on('message_update', (data) => {
console.log('Message deleted:', data);
});
// Error handling
socket.on('error_notify', (error) => {
console.error('Socket error:', error);
});
// Disconnect
socket.emit('disconnect_user', {});
socket.on('leave', (data) => {
console.log('Disconnected:', data);
});
```
### React Example
```javascript
import { useEffect, useState } from 'react';
import io from 'socket.io-client';
function ChatComponent({ userId, receiverId }) {
const [socket, setSocket] = useState(null);
const [messages, setMessages] = useState([]);
const [isOnline, setIsOnline] = useState(false);
useEffect(() => {
// Initialize socket connection
const newSocket = io('http://localhost:3000', {
extraHeaders: {
token: userId
}
});
setSocket(newSocket);
// Join chat
newSocket.emit('joinchat', { receiverId });
// Listen for messages
newSocket.on('receive_message', (data) => {
setMessages(prev => [...prev, data.data]);
});
// Listen for online status
newSocket.on('online_status', (data) => {
setIsOnline(data.isOnline);
});
// Cleanup
return () => {
newSocket.emit('leave_chat', { receiverId });
newSocket.close();
};
}, [userId, receiverId]);
const sendMessage = (text) => {
socket?.emit('send_message', {
receiverId,
message: { text }
});
};
return (
<div>
<div>Status: {isOnline ? 'š¢ Online' : 'š“ Offline'}</div>
{/* Chat UI */}
</div>
);
}
```
---
## š¤ Contributing
We welcome contributions! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
4. Push to the branch (`git push origin feature/AmazingFeature`)
5. Open a Pull Request
---
## š License
This project is licensed under the ISC License - see the [LICENSE](LICENSE) file for details.
---
## šØāš» Author
**Vikas Rajput**
- GitHub: [@vikasrajput](https://github.com/Vikas-Rajput-JS)
- NPM: [chatstorm](https://www.npmjs.com/package/chatstorm)
---
## ā Support
If you find ChatStorm helpful, please give it a star on GitHub!
**Made with ā¤ļø for the developer community**