import dotenv = require('dotenv'); dotenv.config({ quiet: true }); import express = require('express'); import cors = require('cors'); import morgan = require('morgan'); import { logger, LogHeader, LogPayload } from './services/logging/logger'; const app = express() app.use(morgan((tokens: morgan.TokenIndexer, req: express.Request, res: express.Response) => { const head: LogHeader = { type: 'http', level: 'info', depth: 'normal', timestamp: new Date().toISOString(), } const payload: LogPayload = { message: 'HTTP request completed', data: { method: tokens.method(req, res), path: tokens.url(req, res), status: Number(tokens.status(req, res)), response_time_ms: Number(tokens['response-time'](req, res)), user_id: req.user?.id, user_name: req.user?.name, user_agent: req.headers['user-agent'], }, } logger.log(head.level, head.type, payload.message, payload.data, head.depth) return ''; }, { skip: (req: express.Request) => { return req.originalUrl === '/members/me' || req.originalUrl === '/ping'; } })) app.use(cors({ origin: [process.env.CLIENT_URL], // your SPA origins credentials: true })); app.use(express.json()) app.set('trust proxy', 1); const port = process.env.SERVER_PORT; //glitchtip setup import sentry = require('@sentry/node'); if (process.env.DISABLE_GLITCHTIP === "true") { logger.info('app', 'Glitchtip disabled', null, 'normal') } else { let dsn = process.env.GLITCHTIP_DSN; let release = process.env.APPLICATION_VERSION; let environment = process.env.APPLICATION_ENVIRONMENT; sentry.init({ dsn: dsn, release: release, environment: environment, integrations: [sentry.captureConsoleIntegration({ levels: ['error'] })] }); logger.info('app', 'Glitchtip initialized', null, 'normal') } //session setup import path = require('path'); // import session = require('express-session'); import session = require('express-session'); import passport = require('passport'); const SQLiteStore = require('connect-sqlite3')(session); const cookieOptions: session.CookieOptions = { httpOnly: true, sameSite: 'lax', domain: process.env.CLIENT_DOMAIN, maxAge: 1000 * 60 * 60 * 24 * 30, //30 days } const sessionOptions: session.SessionOptions = { secret: 'whatever', resave: false, saveUninitialized: false, store: new SQLiteStore({ db: 'sessions.db', dir: './' }), rolling: true, cookie: cookieOptions } import { initializeDiscordIntegrations } from './services/integrations/discord'; //event bus setup initializeDiscordIntegrations(); app.use(session(sessionOptions)); app.use(passport.authenticate('session')); // Mount route modules import { applicationRouter } from './routes/applications'; import { memberRanks, ranks } from './routes/ranks'; import { memberRouter } from './routes/members'; import { loaRouter } from './routes/loa'; import { status, memberStatus } from './routes/statuses'; import { authRouter } from './routes/auth'; import { roles, memberRoles } from './routes/roles'; import { courseRouter, eventRouter } from './routes/course'; import { calendarRouter } from './routes/calendar'; import { docsRouter } from './routes/docs'; import { units } from './routes/units'; app.use('/application', applicationRouter); app.use('/ranks', ranks); app.use('/memberRanks', memberRanks); app.use('/members', memberRouter); app.use('/loa', loaRouter); app.use('/status', status) app.use('/memberStatus', memberStatus) app.use('/roles', roles) app.use('/memberRoles', memberRoles) app.use('/course', courseRouter) app.use('/courseEvent', eventRouter) app.use('/calendar', calendarRouter) app.use('/units', units) app.use('/docs', docsRouter) app.use('/', authRouter) app.get('/ping', (req, res) => { res.status(200).json({ message: 'pong' }); }); app.listen(port, () => { logger.info('app', `Example app listening on port ${port} `) })