Spaces:
Sleeping
Sleeping
| require('dotenv').config(); | |
| const express = require('express'); | |
| const mongoose = require('mongoose'); | |
| const cors = require('cors'); | |
| const helmet = require('helmet'); | |
| const Analytics = require('./models/Analytics'); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; // 7860 is the default for HuggingFace Spaces | |
| // --- Middleware --- | |
| app.use(helmet()); // Adds security headers | |
| app.use(express.json()); // Parses JSON body | |
| // In production, replace '*' with your frontend domain (e.g., 'https://comprex.pages.dev') | |
| app.use(cors({ origin: '*' })); | |
| // --- Database Connection --- | |
| const connectDB = async () => { | |
| try { | |
| // We use the MONGO_URI from .env | |
| await mongoose.connect(process.env.MONGO_URI); | |
| console.log('β MongoDB Connected Successfully'); | |
| } catch (err) { | |
| console.error('β MongoDB Connection Error:', err); | |
| process.exit(1); // Exit if DB fails | |
| } | |
| }; | |
| connectDB(); | |
| // --- Routes --- | |
| // 1. Health Check | |
| app.get('/', (req, res) => { | |
| res.json({ status: 'active', message: 'CompreX Backend is running' }); | |
| }); | |
| // 2. Track Compression (Frontend calls this after compressing a file) | |
| app.post('/api/track', async (req, res) => { | |
| try { | |
| const { fileType, originalSize, compressedSize } = req.body; | |
| // Basic Validation | |
| if (!fileType || !originalSize || !compressedSize) { | |
| return res.status(400).json({ error: 'Missing required fields' }); | |
| } | |
| const newStat = await Analytics.create({ | |
| fileType, | |
| originalSize, | |
| compressedSize | |
| }); | |
| res.status(201).json({ success: true, id: newStat._id }); | |
| } catch (error) { | |
| console.error('Tracking Error:', error); | |
| res.status(500).json({ error: 'Server Error' }); | |
| } | |
| }); | |
| // 3. Get Dashboard Stats (For the Analytics Page) | |
| app.get('/api/stats', async (req, res) => { | |
| try { | |
| // Aggregation Pipeline for Performance | |
| const stats = await Analytics.aggregate([ | |
| { | |
| $group: { | |
| _id: null, | |
| totalFiles: { $sum: 1 }, | |
| totalOriginal: { $sum: "$originalSize" }, | |
| totalCompressed: { $sum: "$compressedSize" } | |
| } | |
| } | |
| ]); | |
| // Get Daily Activity for the last 7 days (For the Chart) | |
| const sevenDaysAgo = new Date(); | |
| sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); | |
| const history = await Analytics.aggregate([ | |
| { $match: { timestamp: { $gte: sevenDaysAgo } } }, | |
| { | |
| $group: { | |
| _id: { $dateToString: { format: "%Y-%m-%d", date: "$timestamp" } }, | |
| count: { $sum: 1 }, | |
| savedBytes: { $sum: { $subtract: ["$originalSize", "$compressedSize"] } } | |
| } | |
| }, | |
| { $sort: { _id: 1 } } // Sort by date ascending | |
| ]); | |
| const globalStats = stats[0] || { totalFiles: 0, totalOriginal: 0, totalCompressed: 0 }; | |
| const totalSaved = globalStats.totalOriginal - globalStats.totalCompressed; | |
| res.json({ | |
| totalFiles: globalStats.totalFiles, | |
| totalSavedBytes: totalSaved, | |
| history | |
| }); | |
| } catch (error) { | |
| console.error('Stats Error:', error); | |
| res.status(500).json({ error: 'Server Error' }); | |
| } | |
| }); | |
| // --- Start Server --- | |
| app.listen(PORT, () => { | |
| console.log(`π Server running on port ${PORT}`); | |
| }); |