Spaces:
Running
Running
| const express = require('express'); | |
| const dotenv = require('dotenv'); | |
| dotenv.config({ path: './config.env' }); | |
| const morgan = require('morgan'); | |
| const helmet = require('helmet'); | |
| const rateLimit = require('express-rate-limit'); | |
| const mongoSanitize = require('express-mongo-sanitize'); | |
| const xss = require('xss-clean'); | |
| const hpp = require('hpp'); | |
| const compression = require('compression'); | |
| const cors = require('cors'); | |
| const AppError = require('./utils/appError'); | |
| const globalErrorHandler = require('./middlewares/errorMiddleware'); | |
| const productRouter = require('./routes/productRoutes'); | |
| const authRouter = require('./routes/authRoutes'); | |
| const cartRouter = require('./routes/cartRoutes'); | |
| const orderRouter = require('./routes/orderRoutes'); | |
| const promoRouter = require('./routes/promoRoutes'); | |
| const categoryRouter = require('./routes/categoryRoutes'); | |
| const brandRouter = require('./routes/brandRoutes'); | |
| const providerRouter = require('./routes/providerRoutes'); | |
| const reviewRouter = require('./routes/reviewRouter'); | |
| const addressRoutes = require('./routes/addressRoutes'); | |
| const favoriteRouter = require('./routes/favoriteRoutes'); | |
| const imageRouter = require('./routes/imageRoutes'); | |
| const usersRouter = require('./routes/usersRoutes'); | |
| const adminRouter = require('./routes/adminRoutes'); | |
| const vendorRouter = require('./routes/vendorRoutes'); | |
| const newsletterRouter = require('./routes/newsletterRoutes'); | |
| const notificationRouter = require('./routes/notificationRoutes'); | |
| const contentRouter = require('./routes/contentRoutes'); | |
| const permissionRouter = require('./routes/permissionRoutes'); | |
| const shippingRouter = require('./routes/shippingRoutes'); | |
| const financeRouter = require('./routes/financeRoutes'); | |
| const paymentRouter = require('./routes/paymentRoutes'); | |
| const vendorRequestRouter = require('./routes/vendorRequestRoutes'); | |
| const returnRequestRouter = require('./routes/returnRequestRoutes'); | |
| const visitRouter = require('./routes/visitRoutes'); | |
| const app = express(); | |
| app.set('trust proxy', 1); | |
| // GLOBAL MIDDLEWARES | |
| // Implement CORS | |
| app.use( | |
| cors({ | |
| origin: [ | |
| 'http://localhost:5173', | |
| 'https://samoulla-web.vercel.app', | |
| 'https://samoulla.vercel.app', | |
| 'https://samoulla.com', | |
| 'https://www.samoulla.com', | |
| process.env.FRONTEND_URL, | |
| ].filter(Boolean), | |
| credentials: true, | |
| }), | |
| ); | |
| // Set security HTTP headers | |
| app.use(helmet()); | |
| // Development logging | |
| if (process.env.NODE_ENV === 'development') { | |
| app.use(morgan('dev')); | |
| } | |
| // Limit requests for auth routes (login/register/reset password) | |
| const authLimiter = rateLimit({ | |
| windowMs: 15 * 60 * 1000, // 15 minutes | |
| max: 200, | |
| message: | |
| 'Too many authentication attempts. Please try again after 15 minutes.', | |
| standardHeaders: true, | |
| legacyHeaders: false, | |
| validate: { trustProxy: false }, | |
| }); | |
| // Limit requests from same API (global browsing) | |
| const limiter = rateLimit({ | |
| windowMs: 15 * 60 * 1000, // 15 minutes | |
| max: process.env.NODE_ENV === 'development' ? 10000 : 20000, | |
| message: 'Too many requests from this IP, please try again in 15 minutes.', | |
| standardHeaders: true, | |
| legacyHeaders: false, | |
| validate: { trustProxy: false }, | |
| }); | |
| app.use('/samoulla/v1/auth', authLimiter); | |
| app.use('/samoulla', limiter); | |
| // Body parser, reading data from body into req.body | |
| app.use(express.json({ limit: '10kb' })); | |
| // Data sanitization against NoSQL query injection | |
| app.use(mongoSanitize()); | |
| // Data sanitization against XSS | |
| app.use(xss()); | |
| // Prevent parameter pollution | |
| app.use( | |
| hpp({ | |
| whitelist: [ | |
| 'price', | |
| 'ratingsAverage', | |
| 'ratingsQuantity', | |
| 'stock', | |
| 'brand', | |
| 'category', | |
| ], | |
| }), | |
| ); | |
| app.use(compression()); | |
| // HEALTH CHECK ROUTES (must stay lightweight and never be rate-limited) | |
| app.get('/', (req, res) => { | |
| res.status(200).json({ | |
| status: 'success', | |
| message: 'Samoulla Backend is Alive and Runningg! 🚀', | |
| }); | |
| }); | |
| app.get('/healthz', (req, res) => { | |
| res.status(200).json({ | |
| status: 'success', | |
| service: 'samoulla-backend', | |
| uptime: process.uptime(), | |
| timestamp: new Date().toISOString(), | |
| }); | |
| }); | |
| app.get('/samoulla/v1/health', (req, res) => { | |
| res.status(200).json({ | |
| status: 'success', | |
| service: 'samoulla-backend', | |
| uptime: process.uptime(), | |
| timestamp: new Date().toISOString(), | |
| }); | |
| }); | |
| // ROUTES | |
| app.use('/samoulla/v1/products', productRouter); | |
| app.use('/samoulla/v1/auth', authRouter); | |
| app.use('/samoulla/v1/cart', cartRouter); | |
| app.use('/samoulla/v1/orders', orderRouter); | |
| app.use('/samoulla/v1/promos', promoRouter); | |
| app.use('/samoulla/v1/categories', categoryRouter); | |
| app.use('/samoulla/v1/brands', brandRouter); | |
| app.use('/samoulla/v1/providers', providerRouter); | |
| app.use('/samoulla/v1/reviews', reviewRouter); | |
| app.use('/samoulla/v1/addresses', addressRoutes); | |
| app.use('/samoulla/v1/favorites', favoriteRouter); | |
| app.use('/samoulla/v1/images', imageRouter); | |
| app.use('/samoulla/v1/users', usersRouter); | |
| app.use('/samoulla/v1/admin', adminRouter); | |
| app.use('/samoulla/v1/vendor', vendorRouter); | |
| app.use('/samoulla/v1/newsletter', newsletterRouter); | |
| app.use('/samoulla/v1/notifications', notificationRouter); | |
| app.use('/samoulla/v1/content', contentRouter); | |
| app.use('/samoulla/v1/permissions', permissionRouter); | |
| app.use('/samoulla/v1/shipping', shippingRouter); | |
| app.use('/samoulla/v1/finance', financeRouter); | |
| app.use('/samoulla/v1/payment', paymentRouter); | |
| app.use('/samoulla/v1/vendor-requests', vendorRequestRouter); | |
| app.use('/samoulla/v1/return-requests', returnRequestRouter); | |
| app.use('/samoulla/v1/visits', visitRouter); | |
| app.all('*', (req, res, next) => { | |
| next(new AppError(`Can't find ${req.originalUrl} on this server!`, 404)); | |
| }); | |
| app.use(globalErrorHandler); | |
| module.exports = app; | |