fazeel007's picture
Update system flow and add default research papers for demo
e57738d
console.log("πŸš€ Starting KnowledgeBridge server...");
// Add global error handlers to catch crashes
process.on('uncaughtException', (error) => {
console.error('πŸ’₯ Uncaught Exception:', error);
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('πŸ’₯ Unhandled Rejection at:', promise, 'reason:', reason);
process.exit(1);
});
import { config } from "dotenv";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
import express, { type Request, Response, NextFunction } from "express";
import rateLimit from "express-rate-limit";
import helmet from "helmet";
import { body, validationResult } from "express-validator";
console.log("βœ… Basic imports loaded successfully");
import { registerRoutes } from "./routes";
import { setupVite, serveStatic, log } from "./vite";
console.log("βœ… All imports loaded successfully");
// Get the directory name for ES modules
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Load environment variables from .env file
config({ path: join(__dirname, '../.env') });
const app = express();
// Trust proxy for Hugging Face Spaces infrastructure
if (process.env.NODE_ENV === 'production') {
app.set('trust proxy', true);
}
console.log("βœ… Express app created");
console.log("βœ… Server setup starting");
// Security middleware
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: process.env.NODE_ENV === 'production'
? ["'self'", "'unsafe-inline'", "'unsafe-eval'"]
: ["'self'", "'unsafe-inline'", "'unsafe-eval'", "https://replit.com"], // Allow Replit in dev
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"],
connectSrc: ["'self'", "https://api.studio.nebius.ai", "https://api.github.com"],
frameAncestors: process.env.NODE_ENV === 'production'
? ["'self'", "https://*.hf.space", "https://huggingface.co"]
: ["'self'"], // Allow HF domains in production
},
},
}));
// Rate limiting configuration for production (HF Spaces) vs development
const rateLimitConfig = process.env.NODE_ENV === 'production' ? {
// For HF Spaces - configure for proxy environment
windowMs: 15 * 60 * 1000, // 15 minutes
max: 1000, // Higher limit since we can't reliably identify individual users
message: {
error: "Too many requests, please try again later."
},
standardHeaders: true,
legacyHeaders: false,
// Use a combination of headers for better user identification in proxy environment
keyGenerator: (req) => {
return req.ip + '|' + (req.headers['x-forwarded-for'] || req.headers['cf-connecting-ip'] || req.connection.remoteAddress);
},
// Skip validation that was causing the errors
validate: false,
} : {
// For development - normal rate limiting
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: {
error: "Too many requests from this IP, please try again later."
},
standardHeaders: true,
legacyHeaders: false,
};
const limiter = rateLimit(rateLimitConfig);
export const strictLimiter = process.env.NODE_ENV === 'production' ?
rateLimit({
windowMs: 5 * 60 * 1000, // 5 minutes
max: 50, // More generous limit for production
message: {
error: "Too many requests, please try again later."
},
keyGenerator: (req) => {
return req.ip + '|' + (req.headers['x-forwarded-for'] || req.headers['cf-connecting-ip'] || req.connection.remoteAddress);
},
validate: false,
}) :
rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 10, // limit each IP to 10 requests per minute for sensitive endpoints
message: {
error: "Too many requests, please try again later."
}
});
app.use(limiter);
// Body parsing with size limits
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: false, limit: '10mb' }));
app.use((req, res, next) => {
const start = Date.now();
const path = req.path;
let capturedJsonResponse: Record<string, any> | undefined = undefined;
const originalResJson = res.json;
res.json = function (bodyJson, ...args) {
capturedJsonResponse = bodyJson;
return originalResJson.apply(res, [bodyJson, ...args]);
};
res.on("finish", () => {
const duration = Date.now() - start;
if (path.startsWith("/api")) {
let logLine = `${req.method} ${path} ${res.statusCode} in ${duration}ms`;
if (capturedJsonResponse) {
logLine += ` :: ${JSON.stringify(capturedJsonResponse)}`;
}
if (logLine.length > 80) {
logLine = logLine.slice(0, 79) + "…";
}
log(logLine);
}
});
next();
});
(async () => {
const server = await registerRoutes(app);
app.use((err: any, req: Request, res: Response, _next: NextFunction) => {
const status = err.status || err.statusCode || 500;
const message = status === 500 ? "Internal Server Error" : err.message || "Internal Server Error";
console.error(`Error ${status} on ${req.method} ${req.url}:`, err);
// Only send response if not already sent
if (!res.headersSent) {
res.status(status).json({
message,
...(process.env.NODE_ENV === 'development' && { stack: err.stack })
});
}
// Log error but don't throw - throwing here crashes the server
if (status === 500) {
console.error('Internal server error:', err.stack);
}
});
// importantly only setup vite in development and after
// setting up all the other routes so the catch-all route
// doesn't interfere with the other routes
console.log(`Environment: NODE_ENV=${process.env.NODE_ENV}, app.get('env')=${app.get('env')}`);
// Add basic health endpoint before static serving to ensure server is responsive
app.get("/ping", (_req, res) => {
res.json({ status: "ok", timestamp: new Date().toISOString() });
});
if (process.env.NODE_ENV === "development") {
console.log("Setting up Vite development server");
await setupVite(app, server);
} else {
console.log("Setting up static file serving for production");
serveStatic(app);
}
// Seed database with default documents for demo purposes
console.log("🌱 Initializing database with default documents...");
try {
const { seedDefaultDocuments } = await import('./seed-documents');
await seedDefaultDocuments();
} catch (error) {
console.warn("⚠️ Failed to seed default documents:", error);
}
// Serve the app on the configured port (5000 for local, 7860 for HF Spaces)
// this serves both the API and the client.
const port = process.env.PORT ? parseInt(process.env.PORT) : (process.env.NODE_ENV === 'production' ? 7860 : 5000);
server.listen({
port,
host: "0.0.0.0",
reusePort: true,
}, () => {
log(`serving on port ${port}`);
});
})();