// Import this first from sentry instrument! import '@utils/instrumentSentry'; // Now import other modules import { ProviderFiles } from '@api/provider/sessions'; import { PrismaRepository } from '@api/repository/repository.service'; import { HttpStatus, router } from '@api/routes/index.router'; import { eventManager, waMonitor } from '@api/server.module'; import { Auth, configService, Cors, HttpServer, ProviderSession, Webhook } from '@config/env.config'; import { onUnexpectedError } from '@config/error.config'; import { Logger } from '@config/logger.config'; import { ROOT_DIR } from '@config/path.config'; import * as Sentry from '@sentry/node'; import { ServerUP } from '@utils/server-up'; import axios from 'axios'; import compression from 'compression'; import cors from 'cors'; import express, { json, NextFunction, Request, Response, urlencoded } from 'express'; import { join } from 'path'; function initWA() { waMonitor.loadInstance(); } async function bootstrap() { const logger = new Logger('SERVER'); const app = express(); let providerFiles: ProviderFiles = null; if (configService.get('PROVIDER').ENABLED) { providerFiles = new ProviderFiles(configService); await providerFiles.onModuleInit(); logger.info('Provider:Files - ON'); } const prismaRepository = new PrismaRepository(configService); await prismaRepository.onModuleInit(); app.use( cors({ origin(requestOrigin, callback) { const { ORIGIN } = configService.get('CORS'); if (ORIGIN.includes('*')) { return callback(null, true); } if (ORIGIN.indexOf(requestOrigin) !== -1) { return callback(null, true); } return callback(new Error('Not allowed by CORS')); }, methods: [...configService.get('CORS').METHODS], credentials: configService.get('CORS').CREDENTIALS, }), urlencoded({ extended: true, limit: '136mb' }), json({ limit: '136mb' }), compression(), ); app.set('view engine', 'hbs'); app.set('views', join(ROOT_DIR, 'views')); app.use(express.static(join(ROOT_DIR, 'public'))); app.use('/store', express.static(join(ROOT_DIR, 'store'))); app.use('/', router); app.use( (err: Error, req: Request, res: Response, next: NextFunction) => { if (err) { const webhook = configService.get('WEBHOOK'); if (webhook.EVENTS.ERRORS_WEBHOOK && webhook.EVENTS.ERRORS_WEBHOOK != '' && webhook.EVENTS.ERRORS) { const tzoffset = new Date().getTimezoneOffset() * 60000; //offset in milliseconds const localISOTime = new Date(Date.now() - tzoffset).toISOString(); const now = localISOTime; const globalApiKey = configService.get('AUTHENTICATION').API_KEY.KEY; const serverUrl = configService.get('SERVER').URL; const errorData = { event: 'error', data: { error: err['error'] || 'Internal Server Error', message: err['message'] || 'Internal Server Error', status: err['status'] || 500, response: { message: err['message'] || 'Internal Server Error', }, }, date_time: now, api_key: globalApiKey, server_url: serverUrl, }; logger.error(errorData); const baseURL = webhook.EVENTS.ERRORS_WEBHOOK; const httpService = axios.create({ baseURL }); httpService.post('', errorData); } return res.status(err['status'] || 500).json({ status: err['status'] || 500, error: err['error'] || 'Internal Server Error', response: { message: err['message'] || 'Internal Server Error', }, }); } next(); }, (req: Request, res: Response, next: NextFunction) => { const { method, url } = req; res.status(HttpStatus.NOT_FOUND).json({ status: HttpStatus.NOT_FOUND, error: 'Not Found', response: { message: [`Cannot ${method.toUpperCase()} ${url}`], }, }); next(); }, ); const httpServer = configService.get('SERVER'); ServerUP.app = app; let server = ServerUP[httpServer.TYPE]; if (server === null) { logger.warn('SSL cert load failed — falling back to HTTP.'); logger.info("Ensure 'SSL_CONF_PRIVKEY' and 'SSL_CONF_FULLCHAIN' env vars point to valid certificate files."); httpServer.TYPE = 'http'; server = ServerUP[httpServer.TYPE]; } eventManager.init(server); if (process.env.SENTRY_DSN) { logger.info('Sentry - ON'); // Add this after all routes, // but before any and other error-handling middlewares are defined Sentry.setupExpressErrorHandler(app); } server.listen(httpServer.PORT, () => logger.log(httpServer.TYPE.toUpperCase() + ' - ON: ' + httpServer.PORT)); initWA(); onUnexpectedError(); } bootstrap();