Spaces:
Sleeping
Sleeping
File size: 5,249 Bytes
1906404 ee58798 1906404 | 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 | import express from 'express';
import cors from 'cors';
import 'dotenv/config';
// Import route modules
import authRoutes from './routes/auth.js';
import interviewRoutes from './routes/interview.js';
import atsRoutes from './routes/ats.js';
import resumeRoutes from './routes/resume.js';
import companyRoutes from './routes/company.js';
import dashboardRoutes from './routes/dashboard.js';
// Initialize Express App
const app = express();
const port = process.env.PORT || 3001;
// ββ Middleware ββ
app.use(cors({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
app.get('/', (req, res) => {
res.send('<h1>PlaceMate AI API Server is Running</h1><p>Health check at /api/health</p>');
});
// ββ Health Check ββ
app.get('/api/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// ββ API Routes ββ
app.use('/api/auth', authRoutes);
app.use('/api/interview', interviewRoutes);
app.use('/api/ats', atsRoutes);
app.use('/api/resume', resumeRoutes);
app.use('/api/company', companyRoutes);
app.use('/api/dashboard', dashboardRoutes);
// ββ Legacy Backward-Compatible Routes ββ
// These keep the existing frontend interview components working
// (they call /api/chat, /api/dsa/*, /api/resume/generate directly)
import { chatInterview } from './services/aiService.js';
import Groq from 'groq-sdk';
const groq = new Groq({ apiKey: process.env.GROQ_API_KEY });
app.post('/api/chat', async (req, res) => {
try {
const { history } = req.body;
if (!history) return res.status(400).json({ error: 'Chat history is required.' });
const message = await chatInterview(history);
res.json({ message });
} catch (error) {
console.error('Error in /api/chat:', error);
res.status(500).json({ error: 'Failed to get response from AI model.' });
}
});
app.post('/api/dsa/question', async (req, res) => {
try {
const { difficulty } = req.body;
const difficultyLevel = difficulty === 'intern' ? 'medium' : 'medium-hard';
const response = await groq.chat.completions.create({
model: 'llama-3.3-70b-versatile',
messages: [
{ role: 'system', content: 'You are a technical interviewer. Respond with valid JSON only.' },
{ role: 'user', content: `Generate a single data structures and algorithms coding problem suitable for a ${difficultyLevel} level interview.\n\nReturn ONLY a JSON object:\n{\n "title": "Problem Title",\n "description": "Detailed problem description with examples, constraints, and input/output format",\n "difficulty": "${difficultyLevel}"\n}` }
],
max_tokens: 2048,
temperature: 0.7,
});
const text = response.choices[0]?.message?.content || '';
const jsonMatch = text.match(/\{[\s\S]*\}/);
if (jsonMatch) {
res.json({ question: JSON.parse(jsonMatch[0]) });
} else {
res.json({ question: { title: 'Two Sum', description: 'Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.', difficulty: difficultyLevel } });
}
} catch (error) {
console.error('Error in /api/dsa/question:', error);
res.status(500).json({ error: 'Failed to generate DSA question.' });
}
});
app.post('/api/dsa/evaluate', async (req, res) => {
try {
const { question, code, language, explanation } = req.body;
if (!question || !code || !language || !explanation) return res.status(400).json({ error: 'All fields are required.' });
const response = await groq.chat.completions.create({
model: 'llama-3.3-70b-versatile',
messages: [
{ role: 'system', content: 'You are a technical interviewer. Respond with valid JSON only.' },
{ role: 'user', content: `Evaluate this DSA solution:\n\nProblem: ${question.title}\nDescription: ${question.description}\nCode (${language}): ${code}\nExplanation: ${explanation}\n\nReturn ONLY JSON: { "score": <0-100>, "strengths": [...], "weaknesses": [...], "advice": [...] }` }
],
max_tokens: 2048,
temperature: 0.7,
});
const text = response.choices[0]?.message?.content || '';
const jsonMatch = text.match(/\{[\s\S]*\}/);
if (jsonMatch) {
res.json({ feedback: JSON.parse(jsonMatch[0]) });
} else {
res.status(500).json({ error: 'Failed to parse feedback.' });
}
} catch (error) {
console.error('Error in /api/dsa/evaluate:', error);
res.status(500).json({ error: 'Failed to evaluate DSA solution.' });
}
});
// ββ 404 Handler ββ
app.use('/api/*', (req, res) => {
res.status(404).json({ error: `Route ${req.method} ${req.originalUrl} not found.` });
});
// ββ Global Error Handler ββ
app.use((err, req, res, next) => {
console.error('Unhandled error:', err);
res.status(500).json({ error: 'Internal server error.' });
});
// ββ Start Server ββ
app.listen(port, () => {
console.log(`\nπ PlaceMate API Server running on http://localhost:${port}`);
console.log(` Health check: http://localhost:${port}/api/health`);
console.log(` Routes: auth, interview, ats, resume, company, dashboard\n`);
}); |