const express = require('express'); const mongoose = require('mongoose'); const cors = require('cors'); const helmet = require('helmet'); const rateLimit = require('express-rate-limit'); const { createServer } = require('http'); const { Server } = require('socket.io'); require('dotenv').config(); const authRoutes = require('./routes/auth'); const taskRoutes = require('./routes/tasks'); const userRoutes = require('./routes/users'); const documentRoutes = require('./routes/documents'); const analyticsRoutes = require('./routes/analytics'); const reportsRoutes = require('./routes/reports'); const { authenticateToken } = require('./middleware/auth'); const logger = require('./utils/logger'); const app = express(); const server = createServer(app); const io = new Server(server, { cors: { origin: process.env.FRONTEND_URL || "http://localhost:3000", methods: ["GET", "POST"] } }); // Rate limiting const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100 // limit each IP to 100 requests per windowMs }); // Middleware app.use(helmet()); app.use(limiter); app.use(cors({ origin: process.env.FRONTEND_URL || "http://localhost:3000", credentials: true })); app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true })); // Logging app.use(require('morgan')('combined', { stream: { write: message => logger.info(message.trim()) } })); // Socket.io connection handling io.use((socket, next) => { const token = socket.handshake.auth.token; if (!token) { return next(new Error('Authentication error')); } jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => { if (err) return next(new Error('Authentication error')); socket.userId = decoded.userId; next(); }); }); io.on('connection', (socket) => { logger.info(`User ${socket.userId} connected`); socket.join(`user_${socket.userId}`); socket.on('task:update', (data) => { socket.to(`user_${data.assignee}`).emit('task:update', data); }); socket.on('task:comment', (data) => { socket.to(`user_${data.taskAssignee}`).emit('task:comment', data); }); socket.on('disconnect', () => { logger.info(`User ${socket.userId} disconnected`); }); }); // Routes app.use('/api/auth', authRoutes); app.use('/api/tasks', authenticateToken, taskRoutes); app.use('/api/users', authenticateToken, userRoutes); app.use('/api/documents', authenticateToken, documentRoutes); app.use('/api/analytics', authenticateToken, analyticsRoutes); app.use('/api/reports', authenticateToken, reportsRoutes); // Health check app.get('/api/health', (req, res) => { res.json({ status: 'OK', timestamp: new Date().toISOString() }); }); // Error handling middleware app.use((err, req, res, next) => { logger.error(err.stack); res.status(500).json({ message: 'Something went wrong!' }); }); // 404 handler app.use('*', (req, res) => { res.status(404).json({ message: 'Route not found' }); }); // Database connection mongoose.connect(process.env.MONGO_URI || 'mongodb://localhost:27017/taskflow-pro', { useNewUrlParser: true, useUnifiedTopology: true, }) .then(() => { logger.info('Connected to MongoDB'); }) .catch((error) => { logger.error('MongoDB connection error:', error); process.exit(1); }); const PORT = process.env.PORT || 8080; server.listen(PORT, () => { logger.info(`Server running on port ${PORT}`); }); module.exports = { app, io };