WeightTracker/data-api.js

82 lines
2.9 KiB
JavaScript

const express = require('express');
const bodyParser = require('body-parser');
const fs = require('fs').promises;
const path = require('path');
const app = express();
const PORT = 3000;
const DATA_DIR = process.env.DATA_DIR || '/data'; // Fallback for local dev, Docker will set via supervisord
const DATA_FILE_NAME = 'weight-tracker-data.json';
const DATA_FILE_PATH = path.join(DATA_DIR, DATA_FILE_NAME);
const DEFAULT_DATA = { weights: [], meals: [] };
app.use(bodyParser.json({ limit: '2mb' })); // Use body-parser to handle JSON POST requests, limit size
// Middleware for basic logging
app.use((req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
});
// GET endpoint to retrieve data
app.get('/', async (req, res) => {
try {
await fs.access(DATA_FILE_PATH);
const fileContent = await fs.readFile(DATA_FILE_PATH, 'utf8');
res.json(JSON.parse(fileContent));
} catch (error) {
if (error.code === 'ENOENT') {
// File doesn't exist, return default data
console.log(`Data file not found at ${DATA_FILE_PATH}, returning default data.`);
res.json(DEFAULT_DATA);
} else {
console.error('Error reading data file:', error);
res.status(500).json({ message: 'Error reading data file', error: error.message });
}
}
});
// PUT endpoint to save data
app.put('/', async (req, res) => {
const newData = req.body;
// Basic Input Validation
if (typeof newData !== 'object' || newData === null) {
return res.status(400).json({ message: 'Invalid data format: body must be an object.' });
}
if (!Array.isArray(newData.weights)) {
return res.status(400).json({ message: 'Invalid data format: weights must be an array.' });
}
if (!Array.isArray(newData.meals)) {
return res.status(400).json({ message: 'Invalid data format: meals must be an array.' });
}
// Add more specific validation for array items if needed
try {
await fs.writeFile(DATA_FILE_PATH, JSON.stringify(newData, null, 2), 'utf8');
res.status(200).json({ message: 'Data saved successfully.' });
} catch (error) {
console.error('Error writing data file:', error);
res.status(500).json({ message: 'Error writing data file', error: error.message });
}
});
app.listen(PORT, '0.0.0.0', () => {
console.log(`Data API server listening on port ${PORT}`);
console.log(`Expecting data file at: ${DATA_FILE_PATH}`);
});
// Basic error handling for uncaught exceptions
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
// Optionally, exit the process or perform other cleanup
// process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// Optionally, exit the process or perform other cleanup
// process.exit(1);
});