225 lines
8.6 KiB
JavaScript
225 lines
8.6 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.webSocketService = void 0;
|
|
const express_1 = __importDefault(require("express"));
|
|
const http_1 = require("http");
|
|
const cookie_parser_1 = __importDefault(require("cookie-parser"));
|
|
const helmet_1 = __importDefault(require("helmet"));
|
|
const ormconfig_1 = require("../Infrastructure/ormconfig");
|
|
const userRouter_1 = __importDefault(require("./routers/userRouter"));
|
|
const organizationRouter_1 = __importDefault(require("./routers/organizationRouter"));
|
|
const deckRouter_1 = __importDefault(require("./routers/deckRouter"));
|
|
const chatRouter_1 = __importDefault(require("./routers/chatRouter"));
|
|
const contactRouter_1 = __importDefault(require("./routers/contactRouter"));
|
|
const adminRouter_1 = __importDefault(require("./routers/adminRouter"));
|
|
const deckImportExportRouter_1 = __importDefault(require("./routers/deckImportExportRouter"));
|
|
const Logger_1 = require("../Application/Services/Logger");
|
|
const WebSocketService_1 = require("../Application/Services/WebSocketService");
|
|
const swaggerUiSetup_1 = require("./swagger/swaggerUiSetup");
|
|
const app = (0, express_1.default)();
|
|
const httpServer = (0, http_1.createServer)(app);
|
|
const PORT = process.env.PORT || 3000;
|
|
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
const loggingService = Logger_1.LoggingService.getInstance();
|
|
(0, Logger_1.logStartup)('SerpentRace Backend starting up', {
|
|
environment: process.env.NODE_ENV || 'development',
|
|
port: PORT,
|
|
nodeVersion: process.version,
|
|
chatInactivityTimeout: process.env.CHAT_INACTIVITY_TIMEOUT_MINUTES || '30'
|
|
});
|
|
app.use((0, helmet_1.default)({
|
|
contentSecurityPolicy: isDevelopment ? false : undefined
|
|
}));
|
|
app.use(express_1.default.json({ limit: '10mb' }));
|
|
app.use(express_1.default.urlencoded({ extended: true, limit: '10mb' }));
|
|
app.use((0, cookie_parser_1.default)());
|
|
app.use(loggingService.requestLoggingMiddleware());
|
|
app.use((req, res, next) => {
|
|
const origin = req.headers.origin;
|
|
const allowedOrigins = ['http://localhost:3000', 'http://localhost:3001', 'http://localhost:8080'];
|
|
if (!origin || allowedOrigins.includes(origin)) {
|
|
res.setHeader('Access-Control-Allow-Origin', origin || '*');
|
|
}
|
|
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
|
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Cookie');
|
|
if (req.method === 'OPTIONS') {
|
|
res.status(200).end();
|
|
return;
|
|
}
|
|
next();
|
|
});
|
|
if (isDevelopment) {
|
|
app.use((req, res, next) => {
|
|
(0, Logger_1.logRequest)(`${req.method} ${req.path}`, req, res);
|
|
next();
|
|
});
|
|
}
|
|
// Setup Swagger documentation
|
|
(0, swaggerUiSetup_1.setupSwagger)(app);
|
|
app.get('/', (req, res) => {
|
|
res.json({
|
|
service: 'SerpentRace Backend API',
|
|
status: 'running',
|
|
version: '1.0.0',
|
|
endpoints: {
|
|
swagger: '/api-docs',
|
|
users: '/api/users',
|
|
organizations: '/api/organizations',
|
|
decks: '/api/decks',
|
|
chats: '/api/chats',
|
|
contacts: '/api/contacts',
|
|
admin: '/api/admin',
|
|
deckImportExport: '/api/deck-import-export',
|
|
health: '/health'
|
|
},
|
|
websocket: {
|
|
enabled: true,
|
|
events: [
|
|
'chat:join', 'chat:leave', 'message:send',
|
|
'group:create', 'chat:direct', 'game:chat:create',
|
|
'chat:history'
|
|
]
|
|
}
|
|
});
|
|
});
|
|
app.get('/health', async (req, res) => {
|
|
try {
|
|
const isDbConnected = ormconfig_1.AppDataSource.isInitialized;
|
|
res.json({
|
|
status: 'healthy',
|
|
timestamp: new Date().toISOString(),
|
|
service: 'SerpentRace Backend API',
|
|
version: '1.0.0',
|
|
environment: process.env.NODE_ENV || 'development',
|
|
database: {
|
|
connected: isDbConnected,
|
|
type: ormconfig_1.AppDataSource.options.type
|
|
},
|
|
websocket: {
|
|
enabled: true
|
|
},
|
|
uptime: process.uptime()
|
|
});
|
|
}
|
|
catch (error) {
|
|
res.status(503).json({
|
|
status: 'unhealthy',
|
|
timestamp: new Date().toISOString(),
|
|
error: 'Service health check failed'
|
|
});
|
|
}
|
|
});
|
|
// API Routes
|
|
app.use('/api/users', userRouter_1.default);
|
|
app.use('/api/organizations', organizationRouter_1.default);
|
|
app.use('/api/decks', deckRouter_1.default);
|
|
app.use('/api/chats', chatRouter_1.default);
|
|
app.use('/api/contacts', contactRouter_1.default);
|
|
app.use('/api/admin', adminRouter_1.default);
|
|
app.use('/api/deck-import-export', deckImportExportRouter_1.default);
|
|
// Global error handler (must be after routes)
|
|
app.use(loggingService.errorLoggingMiddleware());
|
|
app.use((error, req, res, next) => {
|
|
(0, Logger_1.logError)('Global error handler caught unhandled error', error, req, res);
|
|
// Don't expose internal error details in production
|
|
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
res.status(500).json({
|
|
error: 'Internal server error',
|
|
timestamp: new Date().toISOString(),
|
|
...(isDevelopment && { details: error.message, stack: error.stack })
|
|
});
|
|
});
|
|
// Handle 404 routes
|
|
app.use((req, res) => {
|
|
res.status(404).json({
|
|
error: 'Route not found',
|
|
path: req.originalUrl,
|
|
method: req.method,
|
|
timestamp: new Date().toISOString()
|
|
});
|
|
});
|
|
// Initialize WebSocket service after database connection
|
|
let webSocketService;
|
|
// Initialize database connection
|
|
ormconfig_1.AppDataSource.initialize()
|
|
.then(() => {
|
|
const dbOptions = ormconfig_1.AppDataSource.options;
|
|
(0, Logger_1.logConnection)('Database connection established', 'postgresql', 'success', {
|
|
type: dbOptions.type,
|
|
host: dbOptions.host,
|
|
database: dbOptions.database
|
|
});
|
|
// Initialize WebSocket service after database is connected
|
|
exports.webSocketService = webSocketService = new WebSocketService_1.WebSocketService(httpServer);
|
|
(0, Logger_1.logStartup)('WebSocket service initialized', {
|
|
chatInactivityTimeout: process.env.CHAT_INACTIVITY_TIMEOUT_MINUTES || '30'
|
|
});
|
|
})
|
|
.catch((error) => {
|
|
const dbOptions = ormconfig_1.AppDataSource.options;
|
|
(0, Logger_1.logConnection)('Database connection failed', 'postgresql', 'failure', {
|
|
error: error.message,
|
|
type: dbOptions.type,
|
|
host: dbOptions.host,
|
|
database: dbOptions.database
|
|
});
|
|
process.exit(1);
|
|
});
|
|
// Start server with WebSocket support
|
|
const server = httpServer.listen(PORT, () => {
|
|
(0, Logger_1.logStartup)('Server started successfully', {
|
|
port: PORT,
|
|
environment: process.env.NODE_ENV || 'development',
|
|
timestamp: new Date().toISOString(),
|
|
endpoints: {
|
|
health: `/health`,
|
|
swagger: `/api-docs`,
|
|
users: `/api/users`,
|
|
organizations: `/api/organizations`,
|
|
decks: `/api/decks`,
|
|
chats: `/api/chats`
|
|
},
|
|
websocket: {
|
|
enabled: true,
|
|
chatInactivityTimeout: `${process.env.CHAT_INACTIVITY_TIMEOUT_MINUTES || '30'} minutes`
|
|
}
|
|
});
|
|
});
|
|
// Graceful shutdown
|
|
const gracefulShutdown = async (signal) => {
|
|
(0, Logger_1.logStartup)(`Received ${signal}. Shutting down gracefully...`);
|
|
server.close(() => {
|
|
(0, Logger_1.logStartup)('HTTP server closed');
|
|
if (ormconfig_1.AppDataSource.isInitialized) {
|
|
ormconfig_1.AppDataSource.destroy()
|
|
.then(() => {
|
|
(0, Logger_1.logConnection)('Database connection closed', 'postgresql', 'success');
|
|
process.exit(0);
|
|
})
|
|
.catch((error) => {
|
|
(0, Logger_1.logError)('Error during database shutdown', error);
|
|
process.exit(1);
|
|
});
|
|
}
|
|
else {
|
|
process.exit(0);
|
|
}
|
|
});
|
|
};
|
|
process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
|
|
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
// Handle uncaught exceptions
|
|
process.on('uncaughtException', (error) => {
|
|
(0, Logger_1.logError)('Uncaught Exception - Server will shut down', error);
|
|
process.exit(1);
|
|
});
|
|
// Handle unhandled promise rejections
|
|
process.on('unhandledRejection', (reason, promise) => {
|
|
(0, Logger_1.logError)('Unhandled Rejection - Server will shut down', new Error(String(reason)), undefined, undefined);
|
|
process.exit(1);
|
|
});
|
|
//# sourceMappingURL=index.js.map
|