placemate-server / server.js
Mittalyash's picture
Upload server.js with huggingface_hub
ee58798 verified
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`);
});