# SLM Framework - API REST (Node.js + Express)

Sistema de API REST versionado construido con Node.js y Express.js, con routing dinámico, hot-reload y middlewares de seguridad.

## 🚀 Características

- ✅ **Node.js + Express.js**: Backend moderno y performante
- ✅ **Routing Dinámico**: Configuración de endpoints mediante JSON (path-to-regexp)
- ✅ **Hot Reload Automático**: Detecta cambios en `endpoints.slm` y recarga sin reiniciar
- ✅ **Versionamiento**: Soporte para múltiples versiones de API (v1, v2, etc.)
- ✅ **Autenticación**: Middleware de API Key con validación
- ✅ **Rate Limiting**: Control de límites de peticiones (preparado para implementar)
- ✅ **CORS**: Configuración de Cross-Origin Resource Sharing
- ✅ **Elasticsearch**: Integración completa con ES
- ✅ **Error Handling**: Manejo global de errores y excepciones
- ✅ **Cache**: Sistema de cache con NodeCache (15s TTL)
- ✅ **Moment.js**: Manejo avanzado de fechas y zonas horarias
- ✅ **Logging Estructurado**: Sistema de logs con archivos separados (logs/error)
- ✅ **Constants & Utils**: Códigos HTTP y funciones auxiliares centralizadas
- ✅ **Elasticsearch Service**: Servicio completo de ES con axios (CRUD + búsquedas)
- ✅ **Memory Monitoring**: Monitoreo automático de memoria con detección de fugas
- ✅ **Email Notifications**: Sistema de notificaciones multi-canal (Email implementado, Slack/WhatsApp preparados)

## 📁 Estructura

```
api/
├── server.js                       # Servidor principal (Express.js)
├── package.json                    # Dependencias Node.js
├── .env                            # Variables de entorno
├── .env.example                    # Plantilla de variables
├── .gitignore                      # Exclusiones de Git
├── README.md                       # Esta documentación
├── ELASTICSEARCH.md                # Documentación servicio Elasticsearch
├── MEMORY-MONITORING.md            # Documentación sistema de monitoreo de memoria
├── logs/                           # Carpeta para logs (auto-creada)
├── error/                          # Carpeta para errores (auto-creada)
└── slm.framework/
    ├── system/
    │   ├── slmapi.slm              # Configuración centralizada
    │   ├── endpoints.slm           # Registro de endpoints (JSON)
    │   ├── elasticsearch.slm       # Servicio Elasticsearch (axios)
    │   ├── logger.slm              # Sistema de logging estructurado
    │   ├── constants.slm           # Códigos HTTP y mensajes de error
    │   ├── utils.slm               # Funciones auxiliares
    │   ├── memory-monitor.slm      # Monitoreo de memoria y detección de fugas
    │   └── notifications.slm       # Sistema de notificaciones multi-canal
    └── modules/
        └── v1/                     # API versión 1
            ├── status.slm          # GET /v1/status
            ├── auth/
            │   └── login.slm       # POST /v1/auth/login
            ├── users/
            │   ├── list.slm        # GET /v1/users
            │   └── get.slm         # GET /v1/users/:id
            ├── example/
            │   ├── test.slm        # GET /v1/example/test
            │   └── elasticsearch-demo.slm  # GET /v1/example/es-demo
            └── debug/
                ├── memory.slm              # GET /v1/debug/memory
                ├── memory-stats.slm        # GET /v1/debug/memory/stats
                ├── memory-leak-detection.slm  # GET /v1/debug/memory/leak-detection
                ├── heap-snapshot.slm       # GET /v1/debug/heap-snapshot
                └── gc.slm                  # POST /v1/debug/gc
```

## 🛠️ Instalación

### 1. Instalar Dependencias

```bash
cd api
npm install
```

### 2. Configurar Variables de Entorno

El API tiene su propio archivo `.env` en la carpeta `api/`:

```env
# api/.env

# Node Environment
NODE_ENV=development

# Server Configuration
API_PORT=3000

# Elasticsearch Configuration
ES_SERVER=http://elasticsearch:9200
DEV_ES_INDEX=slm-app-dev

# API Security
API_KEY_DEV=dev-key-12345
API_KEY_TEST=test-key-67890

# Rate Limiting
RATE_LIMIT_ENABLED=true
RATE_LIMIT_MAX=100
RATE_LIMIT_WINDOW=60

# Timezone
TZ=America/Mexico_City

# Memory Monitoring
MEMORY_ALERT_THRESHOLD=0.80
MEMORY_CRITICAL_THRESHOLD=0.90
MEMORY_MONITOR_INTERVAL=300000
MEMORY_EMAIL_ALERTS=true
MEMORY_ALERT_EMAIL=admin@example.com

# Email Notifications (Nodemailer)
NOTIFICATIONS_EMAIL_ENABLED=true
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_SECURE=false
SMTP_FROM=noreply@slm-framework.local
```

**Nota:** El archivo `.env` ya viene incluido con valores por defecto. Ajustar según necesidades.

**Para notificaciones por email en producción**, configurar SMTP:
```env
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=true
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password
```

### 3. Iniciar el Servidor

```bash
# Modo producción
npm start

# Modo desarrollo (con nodemon para auto-restart)
npm run dev
```

El servidor estará disponible en: `http://localhost:3000`

### 4. Iniciar con Docker (Alternativa)

**Opción A: Con docker-compose (recomendado):**

Desde la raíz del proyecto:
```bash
# Iniciar todos los servicios (PHP + Node.js + Elasticsearch)
docker-compose up -d

# Solo API + Elasticsearch
docker-compose up api elasticsearch -d

# Ver logs del API
docker-compose logs -f api
```

**Opción B: Docker standalone:**

```bash
# Build de la imagen
docker build -t slm-api:latest .

# Ejecutar contenedor
docker run -d \
  --name slm-api \
  -p 3000:3000 \
  -e NODE_ENV=production \
  -e ES_SERVER=http://elasticsearch:9200 \
  -e DEV_ES_INDEX=slm-app-dev \
  slm-api:latest
```

**Opción C: Producción:**

Desde la raíz del proyecto:
```bash
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up --build -d
```

## ⚙️ Configuración

### API Keys

Editar `slm.framework/system/slmapi.slm`:

```javascript
const api_keys = [
    'dev-key-12345',         // Desarrollo
    'prod-key-67890',        // Producción
    'your-custom-key-here'   // Personalizado
];
```

**⚠️ Importante:** En producción, usar variables de entorno para las API Keys.

### Rate Limiting

```javascript
const rate_limit_enabled = true;
const rate_limit_max = 100;      // Requests por ventana
const rate_limit_window = 60;    // Segundos
```

### CORS

En `server.js`:

```javascript
app.use(cors({
    origin: ['https://tudominio.com'], // Dominios permitidos
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key']
}));
```

## 🔌 Endpoints Disponibles

### Root & Status

```http
GET /
GET /about
GET /status
GET /version
```

**Headers:**
```
X-API-Key: dev-key-12345
```

**Response:**
```json
{
  "name": "SLM Framework API",
  "version": "1.0.0",
  "status": "operational",
  "timestamp": 1234567890000
}
```

---

### API Status (v1)

```http
GET /v1/status
```

**Headers:**
```
X-API-Key: dev-key-12345
```

**Response:**
```json
{
  "error": false,
  "message": "API is operational",
  "data": {
    "name": "SLM Framework API",
    "version": "1.0.0",
    "status": "operational",
    "uptime": 123.456,
    "environment": "development",
    "elasticsearch": {
      "server": "http://elasticsearch:9200",
      "index": "slm-app-dev"
    },
    "features": {
      "authentication": true,
      "rate_limiting": true,
      "hot_reload": true
    },
    "memory": {
      "rss": "45MB",
      "heapTotal": "20MB",
      "heapUsed": "15MB"
    }
  },
  "timestamp": 1234567890000
}
```

---

### Login

```http
POST /v1/auth/login
```

**Headers:**
```
X-API-Key: dev-key-12345
Content-Type: application/json
```

**Body:**
```json
{
  "email": "admin@example.com",
  "password": "admin123"
}
```

**Response Success (200):**
```json
{
  "error": false,
  "message": "Login successful",
  "data": {
    "token": "abc123def456...",
    "user": {
      "id": "user-id-123",
      "name": "John",
      "lastname": "Doe",
      "email": "admin@example.com",
      "profile": "profile-id"
    },
    "expires_in": 3600
  },
  "timestamp": 1234567890000
}
```

**Response Error (401):**
```json
{
  "error": true,
  "message": "Invalid credentials",
  "timestamp": 1234567890000
}
```

---

### List Users

```http
GET /v1/users?page=1&limit=10&search=john&status=active
```

**Headers:**
```
X-API-Key: dev-key-12345
```

**Query Parameters:**
- `page`: Número de página (default: 1)
- `limit`: Registros por página (default: 10, max: 100)
- `search`: Búsqueda por nombre o email
- `status`: Filtrar por estado (active, inactive)

**Response:**
```json
{
  "error": false,
  "data": {
    "users": [
      {
        "id": "user-id-123",
        "name": "John",
        "lastname": "Doe",
        "email": "john@example.com",
        "status": "active",
        "profile": "profile-id",
        "created_at": 1234567890000
      }
    ],
    "pagination": {
      "page": 1,
      "limit": 10,
      "total": 50,
      "pages": 5
    }
  },
  "timestamp": 1234567890000
}
```

---

### Get User

```http
GET /v1/users/:id
```

**Headers:**
```
X-API-Key: dev-key-12345
```

**Response:**
```json
{
  "error": false,
  "data": {
    "id": "user-id-123",
    "name": "John",
    "lastname": "Doe",
    "email": "john@example.com",
    "status": "active",
    "profile": "profile-id",
    "profile_info": {
      "id": "profile-id",
      "name": "Administrator",
      "description": "Full access"
    },
    "created_at": 1234567890000,
    "last_login": 1234567890000,
    "last_login_ip": "127.0.0.1"
  },
  "timestamp": 1234567890000
}
```

---

### Test Endpoint

```http
GET /v1/example/test?echo=hello
```

**Headers:**
```
X-API-Key: dev-key-12345
```

**Response:**
```json
{
  "error": false,
  "message": "Test endpoint executed successfully",
  "data": {
    "api_info": {
      "name": "SLM Framework API",
      "version": "1.0.0",
      "uptime": 123.456
    },
    "request_info": {
      "method": "GET",
      "path": "/v1/example/test",
      "ip": "127.0.0.1"
    },
    "echo": "hello"
  },
  "timestamp": 1234567890000
}
```

---

### Elasticsearch Demo

```http
GET /v1/example/es-demo
```

**Headers:**
```
X-API-Key: dev-key-12345
```

**Descripción:** Demuestra todas las capacidades del servicio de Elasticsearch:
- Crear objeto
- Obtener por ID
- Actualizar con doc
- Actualizar con script
- Buscar por tipo
- Contar documentos
- Búsqueda compleja
- Verificar existencia
- Obtener por valor de campo
- Eliminar objeto

**Response:**
```json
{
  "error": false,
  "message": "Demo de Elasticsearch ejecutado",
  "data": {
    "message": "Elasticsearch demo completado exitosamente",
    "operations": {
      "create": { "success": true, "id": "demo-xxx", "result": "created" },
      "getById": { "success": true, "object": {...} },
      "update": { "success": true, "result": "updated" },
      "updateWithScript": { "success": true, "result": "updated" },
      "searchByType": { "success": true, "found": 5 },
      "count": { "success": true, "total": 10 },
      "complexSearch": { "success": true, "total": 10, "hits": 5 },
      "exists": { "success": true, "exists": true },
      "getObjectWithValue": { "success": true, "found": true },
      "delete": { "success": true, "result": "deleted" }
    },
    "summary": {
      "totalOperations": 10,
      "allSuccessful": true
    }
  },
  "timestamp": 1234567890000
}
```

## 🔥 Hot Reload Automático

El sistema detecta cambios en `endpoints.slm` automáticamente. **No es necesario reiniciar el servidor.**

### Cómo funciona

1. **Caché inteligente**: El sistema verifica el timestamp del archivo `endpoints.slm` en cada petición
2. **Recarga automática**: Si detecta cambios, recarga las rutas automáticamente
3. **Por entorno**:
   - **Desarrollo**: Hot-reload de handlers + endpoints habilitado
   - **Producción**: Solo hot-reload de endpoints (handlers en caché para performance)

### Agregar Nuevos Endpoints

**Paso 1:** Editar `slm.framework/system/endpoints.slm`

**⚠️ Nuevo formato:** Método HTTP + ruta en la misma key

```json
{
  "GET /v1/products/:id": {
    "handler": "./slm.framework/modules/v1/products/get.slm"
  },
  "POST /v1/products": {
    "handler": "./slm.framework/modules/v1/products/create.slm"
  },
  "PUT /v1/products/:id": {
    "handler": "./slm.framework/modules/v1/products/update.slm"
  },
  "DELETE /v1/products/:id": {
    "handler": "./slm.framework/modules/v1/products/delete.slm"
  }
}
```

**Paso 2:** Crear el handler `slm.framework/modules/v1/products/get.slm`

```javascript
const axios = require('axios');
const constants = require('../../system/constants.slm');
const utils = require('../../system/utils.slm');
const logger = require('../../system/logger.slm');

module.exports = async (req, res, next, slmapi) => {
    const productId = req.params.id;

    try {
        const query = `${slmapi.es_server}/${slmapi.es_index}/_doc/${productId}`;
        const request = await axios.get(query);

        if (!request.data.found) {
            return res.status(constants.HTTP.NOT_FOUND).json(
                utils.errorResponse('Product not found', constants.HTTP.NOT_FOUND)
            );
        }

        return res.status(constants.HTTP.OK).json(
            utils.successResponse(request.data._source, 'Product retrieved successfully')
        );

    } catch (error) {
        logger.error('Error retrieving product', {
            productId,
            error: error.message
        });

        return res.status(constants.HTTP.INTERNAL_ERROR).json(
            utils.errorResponse(constants.ERRORS.INTERNAL_ERROR)
        );
    }
};
```

**Paso 3:** ¡Listo! El endpoint está disponible inmediatamente

```bash
# Probar el nuevo endpoint
curl -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/products/product-123
```

El sistema detectará el cambio en `endpoints.slm` automáticamente en la siguiente petición.

## 📝 Formato de endpoints.slm

### Estructura del archivo

```json
{
  "MÉTODO /ruta/completa": {
    "handler": "./path/relativo/al/handler.slm"
  }
}
```

### Ejemplos

```json
{
  "GET /v1/users": {
    "handler": "./slm.framework/modules/v1/users/list.slm"
  },
  "GET /v1/users/:id": {
    "handler": "./slm.framework/modules/v1/users/get.slm"
  },
  "POST /v1/users": {
    "handler": "./slm.framework/modules/v1/users/create.slm"
  },
  "PUT /v1/users/:id": {
    "handler": "./slm.framework/modules/v1/users/update.slm"
  },
  "DELETE /v1/users/:id": {
    "handler": "./slm.framework/modules/v1/users/delete.slm"
  },
  "GET /v1/users/:id/posts/:postId": {
    "handler": "./slm.framework/modules/v1/users/posts/get.slm"
  }
}
```

### Métodos HTTP soportados

- `GET` - Obtener recursos
- `POST` - Crear recursos
- `PUT` - Actualizar recursos completos
- `PATCH` - Actualizar recursos parcialmente
- `DELETE` - Eliminar recursos
- `OPTIONS` - Opciones de CORS
- `HEAD` - Headers sin body

### Parámetros de ruta

Usar `:nombre` para parámetros dinámicos:

```json
{
  "GET /v1/products/:id": {
    "handler": "./slm.framework/modules/v1/products/get.slm"
  },
  "GET /v1/categories/:category/products/:productId": {
    "handler": "./slm.framework/modules/v1/products/get-by-category.slm"
  }
}
```

En el handler, acceder via `req.params`:

```javascript
module.exports = async (req, res, next, slmapi) => {
    const { id, category, productId } = req.params;
    // ...
};
```

### Query parameters

No se declaran en `endpoints.slm`, se acceden directamente:

```javascript
// GET /v1/users?page=1&limit=10&search=john
module.exports = async (req, res, next, slmapi) => {
    const { page, limit, search } = req.query;
    // ...
};
```

## 📦 Estructura de Módulos

Cada módulo debe exportar una función con esta firma:

```javascript
module.exports = async (req, res, next, slmapi) => {
    // req  = Express request object
    // res  = Express response object
    // next = Express next function
    // slmapi = Configuración compartida (ES, timestamps, etc.)

    try {
        // Tu lógica aquí

        return res.status(200).json({
            error: false,
            data: { ... },
            timestamp: slmapi.timestamp()
        });

    } catch (error) {
        return res.status(500).json({
            error: true,
            message: 'Error message',
            timestamp: slmapi.timestamp()
        });
    }
};
```

## 🛠️ Utilidades de slmapi

El objeto `slmapi` proporciona utilidades comunes para todos los módulos:

### Gestión de Fechas (Moment.js)

```javascript
// Timestamp en milisegundos
const ts = slmapi.timestamp(); // 1234567890000

// Fecha actual formateada
const now = slmapi.now(); // "2026-01-25T10:30:00.000Z"
const nowMx = slmapi.now('mx'); // "2026-01-25 04:30:00" (zona horaria México)

// Formatear cualquier fecha
const formatted = slmapi.formatDate(Date.now()); // "2026-01-25 10:30:00"
const custom = slmapi.formatDate(Date.now(), 'DD/MM/YYYY'); // "25/01/2026"

// Tiempo relativo (español)
const relative = slmapi.fromNow('2026-01-24'); // "hace un día"

// Uso directo de moment
const weekStart = slmapi.moment().startOf('week').format('YYYY-MM-DD');
const nextMonth = slmapi.moment().add(1, 'month').format('MMMM YYYY');
```

### Seguridad

```javascript
// Hash MD5
const hash = slmapi.md5('texto'); // "098f6bcd4621d373cade4e832627b4f6"

// Bcrypt (asíncrono)
const hashedPassword = await slmapi.bcrypt.hash('password123', 10);
const isValid = await slmapi.bcrypt.compare('password123', hashedPassword);
```

### Elasticsearch

**Configuración:**
```javascript
console.log(slmapi.es_server); // "http://elasticsearch:9200"
console.log(slmapi.es_index);  // "slm-app-dev"
console.log(slmapi.es_index_log); // "slm-app-dev-api-log"
```

**Operaciones CRUD:**
```javascript
// Crear documento
const result = await slmapi.setNewObject({
    slm: { type: 'user' },
    name: 'John Doe',
    email: 'john@example.com'
}, 'user-123'); // ID opcional

// Obtener documento por ID
const user = await slmapi.getObjectById('user-123');
if (user) {
    console.log(user.name); // "John Doe"
}

// Actualizar documento
await slmapi.updateObjectByID('user-123', {
    name: 'Jane Doe',
    lastUpdate: Date.now()
});

// Eliminar documento
await slmapi.deleteObjectByID('user-123');
```

**Búsquedas:**
```javascript
// Buscar por tipo y filtros
const users = await slmapi.searchByType('user', { 'status.keyword': 'active' }, 10, 0);

// Buscar por valor de campo
const user = await slmapi.getObjectWithValue('user', 'email.keyword', 'john@example.com');

// Búsqueda con query DSL
const results = await slmapi.search({
    query: {
        bool: {
            must: [
                { term: { 'slm.type': 'user' } },
                { match: { name: 'john' } }
            ]
        }
    },
    size: 10
});

// Contar documentos
const count = await slmapi.countDocuments({
    query: { term: { 'slm.type': 'user' } }
});

// Verificar existencia
const exists = await slmapi.existsDocument('user-123');
```

📚 **Documentación completa:** [ELASTICSEARCH.md](ELASTICSEARCH.md)

### Información del API

```javascript
console.log(slmapi.api_name);    // "SLM Framework API"
console.log(slmapi.api_version); // "1.0.0"
console.log(slmapi.api_keys);    // ["dev-key-12345", "test-key-67890"]
```

### Otras Utilidades

```javascript
// Sistema de archivos
const data = slmapi.fs.readFileSync('file.txt', 'utf8');

// Ejecutar comandos del sistema
slmapi.exec('ls -la', (error, stdout, stderr) => {
    console.log(stdout);
});
```

## 🧪 Testing

### Con cURL

```bash
# Status (sin autenticación)
curl http://localhost:3000/status

# Health check (sin autenticación)
curl http://localhost:3000/health

# API Status (requiere API Key)
curl -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/status

# Login
curl -X POST \
  -H "X-API-Key: dev-key-12345" \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@example.com","password":"admin123"}' \
  http://localhost:3000/v1/auth/login

# Get User
curl -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/users/user-id-123

# List Users with pagination
curl -H "X-API-Key: dev-key-12345" \
  "http://localhost:3000/v1/users?page=1&limit=10&search=john"

# Elasticsearch Demo (prueba todas las funciones de ES)
curl -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/example/es-demo

# Test Endpoint
curl -H "X-API-Key: dev-key-12345" \
  "http://localhost:3000/v1/example/test?echo=hello"
```

### Con Postman

1. Crear colección "SLM API"
2. Agregar header global: `X-API-Key: dev-key-12345`
3. Importar endpoints desde ejemplos

## 🚨 Códigos de Error

| Código | Significado |
|--------|-------------|
| 200 | OK - Éxito |
| 400 | Bad Request - Parámetros inválidos |
| 401 | Unauthorized - API Key faltante |
| 403 | Forbidden - API Key inválida |
| 404 | Not Found - Endpoint o recurso no encontrado |
| 500 | Internal Server Error - Error del servidor |

## 📚 Sistema de Módulos Auxiliares

### Logger (logger.slm)

Sistema de logging estructurado con archivos separados:

```javascript
const logger = require('./slm.framework/system/logger.slm');

// Log de información
logger.info('Operation successful', { userId: '123', action: 'login' });

// Log de error
logger.error('Database connection failed', { error: err.message });

// Log de seguridad
logger.security('Invalid API Key', { apiKey: 'xxx...', ip: '127.0.0.1' });

// Log de advertencia
logger.warning('Rate limit approaching', { requests: 95, limit: 100 });
```

**Características:**
- Archivos por fecha: `logs/2026-01-25.log`
- Errores separados: `error/2026-01-25.log`
- Formato JSON estructurado
- Colores en desarrollo
- Middleware HTTP automático

### Constants (constants.slm)

Códigos HTTP y mensajes de error centralizados:

```javascript
const constants = require('./slm.framework/system/constants.slm');

// Usar códigos HTTP
res.status(constants.HTTP.OK).json(data);
res.status(constants.HTTP.NOT_FOUND).json(error);
res.status(constants.HTTP.UNAUTHORIZED).json(error);

// Usar mensajes de error estándar
utils.errorResponse(constants.ERRORS.INVALID_APIKEY);
utils.errorResponse(constants.ERRORS.ENDPOINT_NOT_FOUND);
utils.errorResponse(constants.ERRORS.MISSING_PARAMETERS);
```

### Utils (utils.slm)

Funciones auxiliares para respuestas y validaciones:

```javascript
const utils = require('./slm.framework/system/utils.slm');

// Respuesta de éxito
return res.status(200).json(
    utils.successResponse({ users: [...] }, 'Users retrieved')
);

// Respuesta de error
return res.status(400).json(
    utils.errorResponse('Validation failed', 400, { missing: ['email'] })
);

// Validar campos requeridos
const validation = utils.validateRequiredFields(req.body, ['email', 'password']);
if (!validation.valid) {
    return res.status(400).json(
        utils.errorResponse('Missing fields', 400, { missing: validation.missing })
    );
}

// Otras utilidades
const sanitized = utils.sanitizeForLog(apiKey); // Para logs seguros
const id = utils.generateId('user'); // Generar IDs únicos
const bytes = utils.formatBytes(1024000); // "1000 KB"
```

## 🧠 Sistema de Monitoreo de Memoria

El API incluye un sistema completo de monitoreo de memoria con detección automática de fugas (memory leaks) y notificaciones por email.

### Características

- ✅ **Monitoreo Automático**: Mide memoria cada 5 minutos (configurable)
- ✅ **Detección de Fugas**: Análisis de regresión lineal para detectar tendencias
- ✅ **Alertas por Niveles**: Warning (80%) y Critical (90%)
- ✅ **Notificaciones por Email**: Alertas automáticas vía SMTP
- ✅ **Heap Snapshots**: Generación de snapshots para análisis detallado
- ✅ **Estadísticas Históricas**: Métricas guardadas para análisis
- ✅ **Garbage Collection**: Limpieza manual cuando se detecta uso alto

### Endpoints de Debug

#### GET /v1/debug/memory

Obtiene métricas actuales de memoria:

```bash
curl -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/debug/memory
```

**Respuesta:**
```json
{
  "error": false,
  "data": {
    "timestamp": 1737849600000,
    "uptime": 3600,
    "rssMB": 150,
    "heapTotalMB": 120,
    "heapUsedMB": 80,
    "heapPercentage": 67,
    "status": "healthy",
    "isAlert": false,
    "isCritical": false
  }
}
```

#### GET /v1/debug/memory/stats

Obtiene estadísticas históricas:

```bash
curl -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/debug/memory/stats
```

#### GET /v1/debug/memory/leak-detection

Ejecuta detección de fugas:

```bash
curl -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/debug/memory/leak-detection
```

**Respuesta (fuga detectada):**
```json
{
  "error": false,
  "data": {
    "detected": true,
    "slope": 2.5,
    "recommendation": "Create a heap snapshot and analyze with Chrome DevTools",
    "measurements": 50
  }
}
```

#### GET /v1/debug/heap-snapshot

Genera un heap snapshot para análisis con Chrome DevTools:

```bash
curl -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/debug/heap-snapshot
```

**Descargar y analizar:**
```bash
# Descargar del contenedor
docker cp slm-api:/app/api/heap-1737849600000.heapsnapshot ./

# Abrir Chrome DevTools > Memory > Load
```

#### POST /v1/debug/gc

Fuerza garbage collection (requiere `--expose-gc`):

```bash
curl -X POST \
  -H "X-API-Key: dev-key-12345" \
  http://localhost:3000/v1/debug/gc
```

### Configuración

Variables de entorno en `api/.env`:

```env
# Memory Monitoring
MEMORY_ALERT_THRESHOLD=0.80
MEMORY_CRITICAL_THRESHOLD=0.90
MEMORY_MONITOR_INTERVAL=300000
MEMORY_EMAIL_ALERTS=true
MEMORY_ALERT_EMAIL=admin@example.com
MEMORY_LEAK_SLOPE=2

# Email Notifications
NOTIFICATIONS_EMAIL_ENABLED=true
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_FROM=noreply@slm-framework.local
```

### Notificaciones por Email

El sistema envía automáticamente emails cuando:

1. **Warning Alert**: Heap usage > 80%
2. **Critical Alert**: Heap usage > 90%
3. **Memory Leak Detected**: Tendencia creciente detectada

**Para configurar email en producción:**

```env
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=true
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password
```

### Mejores Prácticas Anti-Memory-Leak

Ver documentación completa: [`MEMORY-MONITORING.md`](./MEMORY-MONITORING.md)

**Principales causas de fugas:**

1. ❌ Event listeners no removidos
2. ❌ Closures con referencias a objetos grandes
3. ❌ Timers y intervals no limpiados
4. ❌ Variables globales que crecen indefinidamente
5. ❌ Promesas no manejadas correctamente
6. ❌ Streams no cerrados
7. ❌ Referencias circulares
8. ❌ Caché sin límite o TTL

**Soluciones:**

- ✅ Usar `once()` en vez de `on()` para event listeners
- ✅ Implementar caché con TTL y límite de tamaño (node-cache)
- ✅ Siempre limpiar timers con `clearInterval()`/`clearTimeout()`
- ✅ Limitar arrays/objects globales
- ✅ Cerrar streams explícitamente
- ✅ Usar timeouts en requests HTTP

## 📝 Mejores Prácticas

1. **Versionamiento**: Usar `/v1/`, `/v2/` para endpoints
2. **API Keys**: Rotar keys regularmente en producción
3. **Hot Reload**: Es automático, solo editar `endpoints.slm`
4. **Logging**: Usar `logger.*` en lugar de `console.log`
5. **Errores**: Usar `constants.ERRORS` y `utils.errorResponse()`
6. **Códigos HTTP**: Usar `constants.HTTP.*` en lugar de números
7. **Cache**: Ajustar TTL según necesidades de cada endpoint
8. **Validación**: Validar todos los inputs con `utils.validateRequiredFields()`
9. **Async/Await**: Siempre usar try-catch en funciones async
10. **Formato endpoints.slm**: Usar formato "MÉTODO /ruta" en keys

## 🔄 Próximas Mejoras

- [ ] JWT Authentication
- [ ] Refresh tokens
- [ ] Redis para cache distribuido
- [ ] Rate limiting con redis (implementado en memoria)
- [ ] WebSockets para real-time
- [ ] Swagger/OpenAPI documentation
- [ ] Metrics con Prometheus
- [ ] Request validation con Joi/Zod
- [ ] Unit tests con Jest
- [ ] Clustering para multi-core

## 📚 Recursos

- [Documentación Principal](../docs/es_MX/README.md)
- [Express.js Docs](https://expressjs.com/)
- [Moment.js Docs](https://momentjs.com/docs/)
- [Moment Timezone](https://momentjs.com/timezone/)
- [Elasticsearch Client](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html)

---

**Versión:** 1.0.0
**Última actualización:** Enero 2026
**Stack:** Node.js + Express.js + Moment.js + Elasticsearch + Nodemailer
