169 lines
5.6 KiB
JavaScript
169 lines
5.6 KiB
JavaScript
/**
|
|
* 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}`);
|
|
});
|