/** * Simple data API for Weight Tracker * This script handles data storage operations when deployed in Docker * Includes authentication for password protection */ const fs = require('fs'); const path = require('path'); const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors'); const { initAuth, generateHash } = require('./auth-middleware'); // Create Express app const app = express(); const port = process.env.PORT || 3000; // Data file path in the Docker volume const DATA_DIR = process.env.DATA_DIR || '/data'; const DATA_FILE = path.join(DATA_DIR, 'weight-tracker-data.json'); // Print data file path for debugging console.log(`[STARTUP] Data directory: ${DATA_DIR}`); console.log(`[STARTUP] Data file path: ${DATA_FILE}`); // List files in data directory if it exists if (fs.existsSync(DATA_DIR)) { try { const files = fs.readdirSync(DATA_DIR); console.log(`[STARTUP] Files in ${DATA_DIR}:`, files); // If data file exists, log its size and content preview if (fs.existsSync(DATA_FILE)) { const stats = fs.statSync(DATA_FILE); console.log(`[STARTUP] Data file exists: ${DATA_FILE}, size: ${stats.size} bytes`); if (stats.size > 0) { const preview = fs.readFileSync(DATA_FILE, 'utf8').substring(0, 200); console.log(`[STARTUP] Data file content preview: ${preview}...`); } else { console.log(`[STARTUP] Data file is empty`); } } else { console.log(`[STARTUP] Data file does not exist: ${DATA_FILE}`); } } catch (error) { console.error(`[STARTUP] Error reading data directory: ${error.message}`); } } else { console.log(`[STARTUP] Data directory does not exist: ${DATA_DIR}`); } // Middleware app.use(cors()); app.use(bodyParser.json({ limit: '5mb' })); app.use(bodyParser.urlencoded({ extended: true })); // For parsing form data app.use(express.static('public')); // Serve static files // Copy login.html to the correct location for serving const loginHtmlPath = path.join(__dirname, 'login.html'); if (fs.existsSync(loginHtmlPath)) { // Ensure public directory exists const publicDir = path.join(__dirname, 'public'); if (!fs.existsSync(publicDir)) { fs.mkdirSync(publicDir, { recursive: true }); } // Copy login.html to public directory fs.copyFileSync(loginHtmlPath, path.join(publicDir, 'login.html')); console.log('Login page copied to public directory'); } // Initialize authentication middleware initAuth(app); // Ensure data directory exists if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR, { recursive: true }); console.log(`Created data directory: ${DATA_DIR}`); } // Initialize data file if it doesn't exist if (!fs.existsSync(DATA_FILE)) { const defaultData = { weights: [], meals: [], version: '1.0.0' }; fs.writeFileSync(DATA_FILE, JSON.stringify(defaultData, null, 2)); console.log(`Created initial data file: ${DATA_FILE}`); } // GET endpoint to retrieve data app.get('/data/weight-tracker-data.json', (req, res) => { try { console.log(`[DEBUG] GET request received for ${DATA_FILE}`); console.log(`[DEBUG] File exists: ${fs.existsSync(DATA_FILE)}`); if (fs.existsSync(DATA_FILE)) { const data = fs.readFileSync(DATA_FILE, 'utf8'); console.log(`[DEBUG] Data read from file: ${data.substring(0, 100)}...`); res.setHeader('Content-Type', 'application/json'); res.send(data); console.log(`[DEBUG] Data sent to client`); } else { console.log(`[DEBUG] Data file not found at ${DATA_FILE}`); res.status(404).send({ error: 'Data file not found' }); } } catch (error) { console.error('[DEBUG] Error reading data file:', error); res.status(500).send({ error: 'Failed to read data file' }); } }); // PUT endpoint to update data app.put('/data/weight-tracker-data.json', (req, res) => { try { console.log(`[DEBUG] PUT request received for ${DATA_FILE}`); const data = req.body; // Log request body summary console.log(`[DEBUG] Request body received:`, { hasData: !!data, hasWeights: data && !!data.weights, weightCount: data && data.weights ? data.weights.length : 0, hasMeals: data && !!data.meals, mealCount: data && data.meals ? data.meals.length : 0 }); // Validate data structure if (!data || !data.weights || !data.meals) { console.log(`[DEBUG] Invalid data structure received`); return res.status(400).send({ error: 'Invalid data structure' }); } // Ensure data directory exists if (!fs.existsSync(DATA_DIR)) { console.log(`[DEBUG] Creating data directory: ${DATA_DIR}`); fs.mkdirSync(DATA_DIR, { recursive: true }); } // Write to file console.log(`[DEBUG] Writing data to file: ${DATA_FILE}`); fs.writeFileSync(DATA_FILE, JSON.stringify(data, null, 2)); // Verify file was written const fileExists = fs.existsSync(DATA_FILE); console.log(`[DEBUG] File exists after write: ${fileExists}`); if (fileExists) { const stats = fs.statSync(DATA_FILE); console.log(`[DEBUG] File size after write: ${stats.size} bytes`); } res.send({ success: true, message: 'Data saved successfully' }); console.log(`[DEBUG] Data updated: ${new Date().toISOString()}`); } catch (error) { console.error('[DEBUG] Error writing data file:', error); res.status(500).send({ error: 'Failed to write data file' }); } }); // Start server app.listen(port, () => { console.log(`Data API server running on port ${port}`); console.log(`Data directory: ${DATA_DIR}`); console.log(`Data file: ${DATA_FILE}`); });