const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); const morgan = require('morgan'); const { Pool } = require('pg'); require('dotenv').config(); const app = express(); const PORT = process.env.PORT || 5000; // Database configuration const pool = new Pool({ connectionString: process.env.DATABASE_URL || 'postgresql://postgres:password@localhost:5432/byop_sample', ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false }); // Middleware app.use(helmet()); app.use(cors()); app.use(morgan('combined')); app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Health check endpoint app.get('/health', (req, res) => { res.status(200).json({ status: 'healthy', timestamp: new Date().toISOString(), uptime: process.uptime(), environment: process.env.NODE_ENV || 'development' }); }); // Root endpoint app.get('/', (req, res) => { res.json({ message: '🚀 BYOP Sample Backend API', version: '1.0.0', endpoints: { health: '/health', users: '/api/users', stats: '/api/stats' }, database: { status: 'connected', host: process.env.DATABASE_URL ? 'configured' : 'localhost' } }); }); // Initialize database tables async function initializeDatabase() { try { await pool.query(` CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, role VARCHAR(100) DEFAULT 'user', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) `); console.log('✅ Database tables initialized'); } catch (error) { console.error('❌ Database initialization error:', error); } } // Get all users app.get('/api/users', async (req, res) => { try { const result = await pool.query('SELECT * FROM users ORDER BY created_at DESC'); res.json(result.rows); } catch (error) { console.error('Error fetching users:', error); res.status(500).json({ error: 'Failed to fetch users', details: error.message }); } }); // Get user by ID app.get('/api/users/:id', async (req, res) => { try { const { id } = req.params; const result = await pool.query('SELECT * FROM users WHERE id = $1', [id]); if (result.rows.length === 0) { return res.status(404).json({ error: 'User not found' }); } res.json(result.rows[0]); } catch (error) { console.error('Error fetching user:', error); res.status(500).json({ error: 'Failed to fetch user', details: error.message }); } }); // Create new user app.post('/api/users', async (req, res) => { try { const { name, email, role = 'user' } = req.body; if (!name || !email) { return res.status(400).json({ error: 'Name and email are required' }); } const result = await pool.query( 'INSERT INTO users (name, email, role) VALUES ($1, $2, $3) RETURNING *', [name, email, role] ); res.status(201).json(result.rows[0]); } catch (error) { console.error('Error creating user:', error); if (error.code === '23505') { // Unique violation return res.status(409).json({ error: 'User with this email already exists' }); } res.status(500).json({ error: 'Failed to create user', details: error.message }); } }); // Update user app.put('/api/users/:id', async (req, res) => { try { const { id } = req.params; const { name, email, role } = req.body; const result = await pool.query( 'UPDATE users SET name = COALESCE($1, name), email = COALESCE($2, email), role = COALESCE($3, role), updated_at = CURRENT_TIMESTAMP WHERE id = $4 RETURNING *', [name, email, role, id] ); if (result.rows.length === 0) { return res.status(404).json({ error: 'User not found' }); } res.json(result.rows[0]); } catch (error) { console.error('Error updating user:', error); res.status(500).json({ error: 'Failed to update user', details: error.message }); } }); // Delete user app.delete('/api/users/:id', async (req, res) => { try { const { id } = req.params; const result = await pool.query('DELETE FROM users WHERE id = $1 RETURNING *', [id]); if (result.rows.length === 0) { return res.status(404).json({ error: 'User not found' }); } res.json({ message: 'User deleted successfully', user: result.rows[0] }); } catch (error) { console.error('Error deleting user:', error); res.status(500).json({ error: 'Failed to delete user', details: error.message }); } }); // Get application statistics app.get('/api/stats', async (req, res) => { try { const totalUsersResult = await pool.query('SELECT COUNT(*) as count FROM users'); const recentUsersResult = await pool.query('SELECT COUNT(*) as count FROM users WHERE created_at > NOW() - INTERVAL \'7 days\''); const stats = { totalUsers: parseInt(totalUsersResult.rows[0].count), activeUsers: parseInt(recentUsersResult.rows[0].count), serverStatus: 'Running', databaseStatus: 'Connected', uptime: Math.floor(process.uptime()), timestamp: new Date().toISOString(), environment: process.env.NODE_ENV || 'development' }; res.json(stats); } catch (error) { console.error('Error fetching stats:', error); res.status(500).json({ error: 'Failed to fetch stats', details: error.message, serverStatus: 'Running', databaseStatus: 'Error', totalUsers: 0, activeUsers: 0 }); } }); // Error handling middleware app.use((err, req, res, next) => { console.error('Unhandled error:', err); res.status(500).json({ error: 'Internal server error', details: process.env.NODE_ENV === 'development' ? err.message : 'Something went wrong' }); }); // 404 handler app.use('*', (req, res) => { res.status(404).json({ error: 'Endpoint not found' }); }); // Start server app.listen(PORT, '0.0.0.0', async () => { console.log(`🚀 BYOP Sample Backend running on port ${PORT}`); console.log(`📊 Environment: ${process.env.NODE_ENV || 'development'}`); console.log(`🔗 Database: ${process.env.DATABASE_URL ? 'Configured' : 'Default local'}`); // Initialize database await initializeDatabase(); console.log('✅ Server ready to accept connections'); }); // Graceful shutdown handling process.on('SIGTERM', () => { console.log('🛑 SIGTERM received, shutting down gracefully'); server.close(() => { console.log('💤 Process terminated'); pool.end(); }); }); process.on('SIGINT', () => { console.log('🛑 SIGINT received, shutting down gracefully'); process.exit(0); });