import express from 'express'; import path from 'path'; import cors from 'cors'; import { fileURLToPath } from 'url'; import dotenv from 'dotenv'; // Load environment variables dotenv.config(); // Import database and routes import pool, { testConnection } from './server/db.js'; import authRoutes from './server/routes/auth.js'; import masterDataRoutes from './server/routes/master-data.js'; import settingsRoutes from './server/routes/settings.js'; import damageReportsRoutes from './server/routes/damage-reports.js'; import inspectionsRoutes from './server/routes/inspections.js'; import inventoryRoutes from './server/routes/inventory.js'; import persediaanRoutes from './server/routes/persediaan.js'; // Konfigurasi __dirname untuk ES Modules const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const app = express(); const PORT = process.env.PORT || 3005; // Middleware app.use(cors()); app.use(express.json({ limit: '50mb' })); app.use(express.urlencoded({ extended: true, limit: '50mb' })); // Request Logger for Debugging app.use((req, res, next) => { console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`); next(); }); // API Routes - Moved before static to prioritize matching app.use('/api', authRoutes); app.use('/api', masterDataRoutes); app.use('/api', settingsRoutes); app.use('/api', damageReportsRoutes); app.use('/api', inspectionsRoutes); app.use('/api', inventoryRoutes); app.use('/api', persediaanRoutes); // Menyajikan file statis dari folder 'public' (gambar lokal, dll) app.use(express.static(path.join(__dirname, 'public'))); // Menyajikan file statis dari folder 'dist' (hasil build Vite) app.use(express.static(path.join(__dirname, 'dist'))); // Image Proxy Endpoint - Bypass CORS for Google Drive images app.get('/api/image-proxy', async (req, res) => { const imageUrl = req.query.url; if (!imageUrl) { return res.status(400).send('Missing url parameter'); } console.log('[Image Proxy] Fetching:', imageUrl); try { // Dynamic import for node-fetch (ESM compatible) const fetch = (await import('node-fetch')).default; const response = await fetch(imageUrl, { headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', 'Accept': 'image/webp,image/apng,image/*,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.9' }, redirect: 'follow' }); if (!response.ok) { console.log('[Image Proxy] Failed with status:', response.status); return res.status(response.status).send('Failed to fetch image'); } const contentType = response.headers.get('content-type') || 'image/png'; const arrayBuffer = await response.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); console.log('[Image Proxy] Success, size:', buffer.length, 'bytes'); // Set CORS headers res.set({ 'Content-Type': contentType, 'Access-Control-Allow-Origin': '*', 'Cache-Control': 'public, max-age=86400' // Cache for 1 day }); res.send(buffer); } catch (error) { console.error('[Image Proxy] Error:', error.message); res.status(500).send('Failed to proxy image: ' + error.message); } }); // Wildcard route untuk Single Page Application (SPA) // Mengembalikan index.html untuk semua route yang tidak dikenali server // Ini penting agar React Router menangani routing di sisi klien app.get('*', (req, res) => { res.sendFile(path.join(__dirname, 'dist', 'index.html')); }); // Start server with database connection test const startServer = async () => { // Test database connection const dbConnected = await testConnection(); if (!dbConnected) { console.warn('āš ļø Database connection failed. Server will start but API calls may fail.'); } app.listen(PORT, () => { console.log(`\nšŸš€ Server is running on port ${PORT}`); console.log(`šŸ“ Access locally at http://localhost:${PORT}`); console.log(`šŸ—„ļø Database: ${process.env.DB_NAME || 'Not configured'}`); }); }; startServer();