File size: 4,505 Bytes
d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b c869f17 d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b 3e12ae4 d4abe4b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | import Fastify from 'fastify';
import cors from '@fastify/cors';
import websocket from '@fastify/websocket';
import swagger from '@fastify/swagger';
import swaggerUi from '@fastify/swagger-ui';
import { config, validateConfig } from './utils/config.js';
import { logger } from './utils/logger.js';
import { swaggerOptions, swaggerUiOptions } from './utils/swagger.js';
import { MedagenAgent } from './agent/agent-executor.js';
import { SupabaseService } from './services/supabase.service.js';
import { MapsService } from './services/maps.service.js';
import { registerRoutes } from './routes/index.js';
import { wsConnectionManager } from './services/websocket.service.js';
async function startServer() {
try {
// Validate configuration
logger.info('Validating configuration...');
validateConfig();
// Create Fastify instance
const fastify = Fastify({
logger: false, // Use custom logger
requestIdLogLabel: 'reqId',
disableRequestLogging: false,
requestIdHeader: 'x-request-id'
});
// Register CORS
await fastify.register(cors, {
origin: true, // Allow all origins (adjust for production)
credentials: true
});
// Register WebSocket
await fastify.register(websocket, {
options: {
maxPayload: 10 * 1024, // 10KB max message size
verifyClient: (_info, callback) => {
// Optional: Add custom verification logic here
callback(true);
}
}
});
// Register Swagger
await fastify.register(swagger as any, swaggerOptions);
await fastify.register(swaggerUi, swaggerUiOptions);
// Initialize services
logger.info('Initializing services...');
const supabaseService = new SupabaseService();
const mapsService = new MapsService();
// Initialize agent
logger.info('Initializing Medagen Agent...');
const agent = new MedagenAgent(supabaseService, mapsService);
await agent.initialize();
// Register routes
logger.info('Registering routes...');
await registerRoutes(fastify, agent, supabaseService, mapsService);
// Add request logging
fastify.addHook('onRequest', async (request) => {
logger.info({
method: request.method,
url: request.url,
ip: request.ip
}, 'Incoming request');
});
// Add response logging
fastify.addHook('onResponse', async (request, reply) => {
logger.info({
method: request.method,
url: request.url,
statusCode: reply.statusCode
}, 'Request completed');
});
// Error handler
fastify.setErrorHandler((error, _request, reply) => {
// Handle validation errors (Fastify schema validation)
if (error && typeof error === 'object' && 'validation' in error && error.validation) {
const validationError = error as { validation?: unknown; message?: string };
logger.warn({ validation: error.validation }, 'Validation error');
return reply.status(400).send({
error: 'Validation Error',
message: validationError.message || 'Validation failed',
details: error.validation
});
}
// Handle other errors
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error({ error }, 'Unhandled error');
return reply.status(500).send({
error: 'Internal Server Error',
message: process.env.NODE_ENV === 'development' ? errorMessage : 'An error occurred'
});
});
// Start server
const port = config.port;
const host = process.env.HOST || '0.0.0.0';
await fastify.listen({ port, host });
logger.info(`π Medagen Backend is running on http://${host}:${port}`);
logger.info(`π Health check: http://${host}:${port}/health`);
logger.info(`π₯ Triage endpoint: http://${host}:${port}/api/health-check`);
logger.info(`π WebSocket endpoint: ws://${host}:${port}/ws/chat`);
logger.info(`π Swagger docs: http://${host}:${port}/docs`);
} catch (error) {
logger.error({ error }, 'Failed to start server');
process.exit(1);
}
}
// Handle graceful shutdown
process.on('SIGINT', () => {
logger.info('Received SIGINT, shutting down gracefully...');
wsConnectionManager.destroy();
process.exit(0);
});
process.on('SIGTERM', () => {
logger.info('Received SIGTERM, shutting down gracefully...');
wsConnectionManager.destroy();
process.exit(0);
});
// Start the server
startServer();
|