Files
ocean-cleanup/server/src/index.ts
Paul Bailey 3d487a468e feat: implement external API integration with static tide tables (task 32)
- Add in-memory caching for external API responses (6-hour expiration)
- Implement OpenWeatherMap integration for weather data
- Create static tide tables for 22 Irish coastal stations
- Add tide calculation based on semi-diurnal patterns and lunar cycles
- Implement water quality, beach quality, and biodiversity placeholder endpoints
- Add comprehensive API documentation (EXTERNAL_API_SETUP.md)
- Fix frontend WaterQualityIndicator crash
- Remove Redis dependency (using in-memory cache instead)
- All external data endpoints functional and tested
2025-11-16 23:24:42 +00:00

81 lines
2.2 KiB
TypeScript

import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import dotenv from 'dotenv';
import path from 'path';
import reportRoutes from './routes/reportRoutes';
import eventRoutes from './routes/eventRoutes';
import userRoutes from './routes/userRoutes';
import externalDataRoutes from './routes/externalDataRoutes';
// Load environment variables
dotenv.config();
const app = express();
const PORT = process.env.PORT || 3005;
// Middleware
app.use(helmet({
crossOriginResourcePolicy: { policy: "cross-origin" },
contentSecurityPolicy: false, // Disable CSP for development
}));
app.use(cors({
origin: [
'http://localhost:5173',
'http://localhost:5174',
process.env.CORS_ORIGIN || ''
].filter(Boolean),
credentials: true,
}));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Serve uploaded files - use process.cwd() to get the correct path
const uploadDir = process.env.UPLOAD_DIR || path.join(process.cwd(), 'uploads');
app.use('/uploads', express.static(uploadDir));
// Health check
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// API Routes
app.use('/api/reports', reportRoutes);
app.use('/api/events', eventRoutes);
app.use('/api/users', userRoutes);
app.use('/api/external', externalDataRoutes);
// Error handling middleware
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
console.error('Error:', err);
if (err.name === 'MulterError') {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.status(400).json({
error: {
code: 'FILE_TOO_LARGE',
message: 'File size exceeds the maximum limit of 5MB',
timestamp: new Date().toISOString(),
},
});
}
}
res.status(500).json({
error: {
code: 'INTERNAL_SERVER_ERROR',
message: err.message || 'An unexpected error occurred',
timestamp: new Date().toISOString(),
},
});
});
// Start server
app.listen(PORT, () => {
console.log(`🚀 Server running on port ${PORT}`);
console.log(`📍 Environment: ${process.env.NODE_ENV || 'development'}`);
console.log(`🔗 API: http://localhost:${PORT}/api`);
});
export default app;