import compression from "compression"; import cors from "cors"; import express, { Application } from "express"; import { Container } from "inversify"; import { InversifyExpressServer } from "inversify-express-utils"; import morgan from "morgan"; import { errorHandler, lastHandler, notFoundHandler } from "./core/app/app.errorHandler"; import { appConfig } from "./core/config/app.config"; import { Logger } from "./core/logging/logger"; import { customMorganFormat, stream } from "./core/logging/morgan"; import { containerModules } from "./IOC/ioc.config"; import { IOCTYPES } from "./IOC/ioc.types"; import { PassportAuth } from "./utils/passport.service"; import { setupSwagger } from "./utils/swagger"; //controller import "./modules/admin"; import "./modules/brand/brand.controller"; import "./modules/warranty/warranty.controller"; import "./modules/shipment/shipment.controller"; import "./modules/category/category.controller"; import "./modules/product/product.controller"; import "./modules/seller/seller.controller"; import "./modules/user/user.controller"; import "./modules/cart/cart.controller"; import "./modules/Coupon/coupon.controller"; import "./modules/order/order.controller"; import "./modules/return/return.controller"; import "./modules/blog/blog.controller"; import "./modules/landing/landing.controller"; import "./modules/ticket/ticket.controller"; import "./modules/chat/chat.controller"; import "./modules/job/job.controller"; import "./modules/faq/faq.controller"; import "./modules/notification/notification.controller"; import "./modules/wallet/wallet.controller"; import "./modules/payment/payment.controller"; import "./modules/address/address.controller"; import "./modules/newsletter/newsletter.controller"; import "./modules/contact-us/contactUs.controller"; import "./modules/cancel/cancel.controller"; import "./modules/about-us/aboutUs.controller"; import "./modules/learning/learning.controller"; import "./modules/fine/fine.controller"; import "./modules/media/media.controller"; import "./modules/site-setting/siteSetting.controller"; import "./modules/shop/shop.controller"; import "./modules/ping"; class App { private readonly _container: Container; // private readonly _port: number; private logger = new Logger(); constructor(container: Container) { this._container = container; // this._port = port; this.loadModules(); } private async loadModules() { await this._container.loadAsync(containerModules); } public Build(): Application { const server = new InversifyExpressServer(this._container, null /*,{ rootPath: "/api" }*/); return server .setConfig(async (app) => { await this.setMiddleware(app); }) .setErrorConfig((app) => { this.catchError(app); }) .build(); // .listen(this._port, () => { // this.logger.info(`listening on http://localhost:${this._port}`); // }); } private async setMiddleware(app: Application) { //remove x-powered-by header from response app.disable("x-powered-by"); this.logger.debug("disable the default x header of express"); /** * trust for reverse proxy to get correct ip address of user * Configure based on deployment environment */ const trustedProxies = process.env.TRUSTED_PROXIES; const trustProxyHops = process.env.TRUST_PROXY_HOPS; if (trustedProxies === "true") { // recommended for production with multiple proxies/CDNs app.set("trust proxy", 1); this.logger.debug("trust proxy enabled for first hop only (production with CDN/proxies)"); } else if (trustProxyHops && !isNaN(parseInt(trustProxyHops))) { // Trust specific number of proxy hops const hops = parseInt(trustProxyHops); app.set("trust proxy", hops); this.logger.debug(`trust proxy enabled for ${hops} hops`); } else if (trustedProxies && trustedProxies !== "false") { // Trust specific proxy IPs (comma-separated list) const proxyList = trustedProxies.split(",").map((ip) => ip.trim()); app.set("trust proxy", proxyList); this.logger.debug(`trust proxy enabled for specific IPs: ${trustedProxies}`); } else if (process.env.NODE_ENV === "development") { // For development, allow localhost proxies app.set("trust proxy", "loopback"); this.logger.debug("trust proxy enabled for development (loopback only)"); } else { // Production without reverse proxy - don't trust any proxies app.set("trust proxy", false); this.logger.debug("trust proxy disabled for security"); } // app.get("/ip", (request, response) => response.send(request.ip)); /** * compress the response */ app.use(compression()); /** * configure body parser */ app.use(express.json()); /** * configure morgan for http logging */ app.use(morgan(customMorganFormat, { stream })); /** * configure cors */ app.use(cors(appConfig.cors)); /** * config passport */ const passportAuth = this._container.get(IOCTYPES.PassportAuth); app.use(passportAuth.initialize()); passportAuth.plug(); /** * swagger document */ setupSwagger(app); this.logger.debug("setup swagger docs"); } private catchError(app: Application) { app.use(notFoundHandler()); app.use(errorHandler()); app.use(lastHandler()); } } export { App };