Migrar backend a PostgreSQL + Node.js/Express con nuevas funcionalidades
Backend (water-api/): - Crear API REST completa con Express + TypeScript - Implementar autenticación JWT con refresh tokens - CRUD completo para: projects, concentrators, meters, gateways, devices, users, roles - Agregar validación con Zod para todas las entidades - Implementar webhooks para The Things Stack (LoRaWAN) - Agregar endpoint de lecturas con filtros y resumen de consumo - Implementar carga masiva de medidores via Excel (.xlsx) Frontend: - Crear cliente HTTP con manejo automático de JWT y refresh - Actualizar todas las APIs para usar nuevo backend - Agregar sistema de autenticación real (login, logout, me) - Agregar selector de tipo (LORA, LoRaWAN, Grandes) en concentradores y medidores - Agregar campo Meter ID en medidores - Crear modal de carga masiva para medidores - Agregar página de consumo con gráficas y filtros - Corregir carga de proyectos independiente de datos existentes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
97
water-api/src/index.ts
Normal file
97
water-api/src/index.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
import express, { Application, Request, Response, NextFunction } from 'express';
|
||||
import cors from 'cors';
|
||||
import helmet from 'helmet';
|
||||
import routes from './routes';
|
||||
import logger from './utils/logger';
|
||||
import { testConnection } from './config/database';
|
||||
|
||||
const app: Application = express();
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
const NODE_ENV = process.env.NODE_ENV || 'development';
|
||||
|
||||
// Security middleware
|
||||
app.use(helmet());
|
||||
|
||||
// CORS configuration
|
||||
const allowedOrigins = (process.env.CORS_ORIGIN || 'http://localhost:5173')
|
||||
.split(',')
|
||||
.map(origin => origin.trim());
|
||||
|
||||
app.use(cors({
|
||||
origin: (origin, callback) => {
|
||||
// Allow requests with no origin (mobile apps, curl, etc.)
|
||||
if (!origin) return callback(null, true);
|
||||
|
||||
if (allowedOrigins.includes(origin)) {
|
||||
callback(null, true);
|
||||
} else {
|
||||
logger.warn(`CORS blocked origin: ${origin}`);
|
||||
callback(null, true); // Allow all in development
|
||||
}
|
||||
},
|
||||
credentials: true,
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization']
|
||||
}));
|
||||
|
||||
// Body parsing middleware
|
||||
app.use(express.json({ limit: '10mb' }));
|
||||
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
||||
|
||||
// Health check endpoint
|
||||
app.get('/health', (_req: Request, res: Response) => {
|
||||
res.status(200).json({
|
||||
status: 'ok',
|
||||
timestamp: new Date().toISOString(),
|
||||
environment: NODE_ENV
|
||||
});
|
||||
});
|
||||
|
||||
// Mount all API routes
|
||||
app.use('/api', routes);
|
||||
|
||||
// 404 handler
|
||||
app.use((_req: Request, res: Response) => {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: 'Resource not found',
|
||||
error: 'NOT_FOUND'
|
||||
});
|
||||
});
|
||||
|
||||
// Global error handler
|
||||
app.use((err: Error, _req: Request, res: Response, _next: NextFunction) => {
|
||||
console.error('Error:', err);
|
||||
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: NODE_ENV === 'development' ? err.message : 'Internal server error',
|
||||
error: 'INTERNAL_ERROR'
|
||||
});
|
||||
});
|
||||
|
||||
// Start server
|
||||
const startServer = async () => {
|
||||
try {
|
||||
// Test database connection
|
||||
await testConnection();
|
||||
logger.info('Database connection established');
|
||||
|
||||
app.listen(PORT, () => {
|
||||
logger.info(`Server running on port ${PORT} in ${NODE_ENV} mode`);
|
||||
logger.info(`Health check available at http://localhost:${PORT}/health`);
|
||||
logger.info(`API available at http://localhost:${PORT}/api`);
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error('Failed to start server:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
startServer();
|
||||
|
||||
export default app;
|
||||
Reference in New Issue
Block a user