|
|
import express from 'express' |
|
|
import { createServer } from 'http' |
|
|
import { Server } from 'socket.io' |
|
|
import cors from 'cors' |
|
|
import helmet from 'helmet' |
|
|
import compression from 'compression' |
|
|
import morgan from 'morgan' |
|
|
import dotenv from 'dotenv' |
|
|
import path from 'path' |
|
|
|
|
|
|
|
|
dotenv.config() |
|
|
|
|
|
|
|
|
import authRoutes from './routes/auth' |
|
|
import userRoutes from './routes/users' |
|
|
import chatRoutes from './routes/chats' |
|
|
import messageRoutes from './routes/messages' |
|
|
import uploadRoutes from './routes/upload' |
|
|
import adminRoutes from './routes/admin' |
|
|
|
|
|
|
|
|
import { errorHandler } from './middleware/errorHandler' |
|
|
import { rateLimiter } from './middleware/rateLimiter' |
|
|
import { authMiddleware } from './middleware/auth' |
|
|
|
|
|
|
|
|
import { setupSocketHandlers } from './socket' |
|
|
|
|
|
|
|
|
import { initializeDatabase } from './config/database' |
|
|
|
|
|
const app = express() |
|
|
const server = createServer(app) |
|
|
|
|
|
|
|
|
const io = new Server(server, { |
|
|
cors: { |
|
|
origin: process.env.CORS_ORIGIN || "http://localhost:5173", |
|
|
methods: ["GET", "POST"], |
|
|
credentials: true |
|
|
}, |
|
|
transports: ['websocket', 'polling'] |
|
|
}) |
|
|
|
|
|
|
|
|
app.use(helmet({ |
|
|
crossOriginEmbedderPolicy: false, |
|
|
contentSecurityPolicy: { |
|
|
directives: { |
|
|
defaultSrc: ["'self'"], |
|
|
styleSrc: ["'self'", "'unsafe-inline'"], |
|
|
scriptSrc: ["'self'"], |
|
|
imgSrc: ["'self'", "data:", "https:"], |
|
|
}, |
|
|
}, |
|
|
})) |
|
|
|
|
|
app.use(cors({ |
|
|
origin: process.env.CORS_ORIGIN || "http://localhost:5173", |
|
|
credentials: true |
|
|
})) |
|
|
|
|
|
app.use(compression()) |
|
|
app.use(morgan('combined')) |
|
|
app.use(express.json({ limit: '10mb' })) |
|
|
app.use(express.urlencoded({ extended: true, limit: '10mb' })) |
|
|
|
|
|
|
|
|
app.use(rateLimiter) |
|
|
|
|
|
|
|
|
app.use('/uploads', express.static(path.join(__dirname, '../uploads'))) |
|
|
|
|
|
|
|
|
app.get('/health', (req, res) => { |
|
|
res.json({ |
|
|
status: 'OK', |
|
|
timestamp: new Date().toISOString(), |
|
|
uptime: process.uptime() |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
app.use('/api/auth', authRoutes) |
|
|
app.use('/api/users', authMiddleware, userRoutes) |
|
|
app.use('/api/chats', authMiddleware, chatRoutes) |
|
|
app.use('/api/messages', authMiddleware, messageRoutes) |
|
|
app.use('/api/upload', authMiddleware, uploadRoutes) |
|
|
app.use('/api/admin', authMiddleware, adminRoutes) |
|
|
|
|
|
|
|
|
app.use('*', (req, res) => { |
|
|
res.status(404).json({ |
|
|
success: false, |
|
|
error: 'Route not found' |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
app.use(errorHandler) |
|
|
|
|
|
|
|
|
setupSocketHandlers(io) |
|
|
|
|
|
|
|
|
async function startServer() { |
|
|
try { |
|
|
|
|
|
await initializeDatabase() |
|
|
console.log('Database connected successfully') |
|
|
|
|
|
const PORT = process.env.PORT || 3001 |
|
|
const HOST = process.env.HOST || 'localhost' |
|
|
|
|
|
server.listen(PORT, () => { |
|
|
console.log(`π Server running on http://${HOST}:${PORT}`) |
|
|
console.log(`π‘ Socket.IO server ready`) |
|
|
console.log(`π Environment: ${process.env.NODE_ENV || 'development'}`) |
|
|
}) |
|
|
} catch (error) { |
|
|
console.error('Failed to start server:', error) |
|
|
process.exit(1) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
process.on('SIGTERM', () => { |
|
|
console.log('SIGTERM received, shutting down gracefully') |
|
|
server.close(() => { |
|
|
console.log('Server closed') |
|
|
process.exit(0) |
|
|
}) |
|
|
}) |
|
|
|
|
|
process.on('SIGINT', () => { |
|
|
console.log('SIGINT received, shutting down gracefully') |
|
|
server.close(() => { |
|
|
console.log('Server closed') |
|
|
process.exit(0) |
|
|
}) |
|
|
}) |
|
|
|
|
|
|
|
|
process.on('uncaughtException', (error) => { |
|
|
console.error('Uncaught Exception:', error) |
|
|
process.exit(1) |
|
|
}) |
|
|
|
|
|
process.on('unhandledRejection', (reason, promise) => { |
|
|
console.error('Unhandled Rejection at:', promise, 'reason:', reason) |
|
|
process.exit(1) |
|
|
}) |
|
|
|
|
|
startServer() |
|
|
|
|
|
export { app, server, io } |
|
|
|