// Load environment variables first import dotenv from 'dotenv'; // Load backend-specific environment variables dotenv.config({ path: '.env.backend' }); // Then load frontend environment variables (will override if there are duplicates) dotenv.config(); import express from 'express'; import { createServer } from 'http'; import { parse } from 'url'; import next from 'next'; import cors from 'cors'; import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; // Import your backend routes import connectDB from './backend/config/db.js'; import authRoutes from './backend/routes/auth.routes.js'; import inviteRoutes from './backend/routes/invites.routes.js'; import staffAuthRoutes from './backend/routes/staffAuth.routes.js'; import orderRoutes from './backend/routes/orders.routes.js'; import productRoutes from './backend/routes/products.routes.js'; import categoryRoutes from './backend/routes/categories.routes.js'; import shippingRoutes from './backend/routes/shipping.routes.js'; import storeRoutes from './backend/routes/storefront.routes.js'; import cryptoRoutes from './backend/routes/crypto.routes.js'; import blockedUsersRoutes from './backend/routes/blockedUsers.routes.js'; import chatRoutes from './backend/routes/chat.routes.js'; import stockRoutes from './backend/routes/stock.routes.js'; import promotionRoutes from './backend/routes/promotion.routes.js'; import { startCryptoPriceUpdater } from './backend/controllers/cryptoController.js'; import { protectTelegramApi } from './backend/middleware/telegramAuthMiddleware.js'; import { processTelegramMessage, createTelegramChat } from './backend/controllers/chat.controller.js'; import logger from './backend/utils/logger.js'; const dev = process.env.NODE_ENV !== 'production'; const hostname = 'localhost'; // Use port 3000 for the integrated application // Original backend was on 3001, which is causing the conflict const port = process.env.PORT || 3000; // Initialize Next.js const app = next({ dev, hostname, port }); const handle = app.getRequestHandler(); app.prepare().then(() => { const server = express(); // Connect to MongoDB connectDB(); // Add security headers and handle CORS server.use((req, res, next) => { // Basic security headers res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('X-Frame-Options', 'DENY'); res.setHeader('X-XSS-Protection', '1; mode=block'); // Handle CORS const origin = req.headers.origin; const host = req.headers.host; // CORS handling (simplified for local development) res.setHeader('Access-Control-Allow-Origin', origin || '*'); res.setHeader('Access-Control-Allow-Credentials', 'true'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, Origin'); res.setHeader('Access-Control-Expose-Headers', 'Content-Type, Authorization'); res.setHeader('Access-Control-Max-Age', '86400'); // Log the request for debugging logger.info(`Request from ${req.ip} - Origin: ${origin || 'null'} - Host: ${host}`); // Handle preflight requests if (req.method === 'OPTIONS') { res.status(204).end(); return; } next(); }); // Parse JSON for all routes server.use(express.json({ limit: "15mb" })); // Direct routes for Telegram API to bypass JWT middleware server.post("/api/telegram/message", protectTelegramApi, processTelegramMessage); server.post("/api/telegram/create", protectTelegramApi, createTelegramChat); server.get("/api/telegram/test-auth", protectTelegramApi, (req, res) => { res.status(200).json({ success: true, message: "Authentication successful", headers: { authHeader: req.headers.authorization ? req.headers.authorization.substring(0, 10) + "..." : "undefined", xApiKey: req.headers['x-api-key'] ? req.headers['x-api-key'].substring(0, 10) + "..." : "undefined" } }); }); // Register API routes server.use("/api/products", productRoutes); server.use("/api/chats", chatRoutes); server.use("/api/auth", authRoutes); server.use("/api/staff/auth", staffAuthRoutes); server.use("/api/invite", inviteRoutes); server.use("/api/orders", orderRoutes); server.use("/api/categories", categoryRoutes); server.use("/api/shipping-options", shippingRoutes); server.use("/api/storefront", storeRoutes); server.use("/api/crypto", cryptoRoutes); server.use("/api/blocked-users", blockedUsersRoutes); server.use("/api/stock", stockRoutes); server.use("/api/promotions", promotionRoutes); // Start crypto price updater startCryptoPriceUpdater(60); // For all other routes, use Next.js server.all('*', (req, res) => { return handle(req, res); }); server.listen(port, () => { console.log(`> Ready on http://${hostname}:${port}`); }); });