npm package: @jamx-framework/server
Description: JAMX Framework â€” HTTP Server
Author: Stiven-21
Latest version: 1.0.0

# @jamx-framework/server

## Descripción
Servidor HTTP de JAMX Framework. Proporciona una base ligera y modular para construir aplicaciones server-side, con pipeline de middlewares, soporte para HMR (Hot Module Replacement), validación de requests, rate limiting, seguridad (CSRF, headers), y manejo de archivos estáticos. Está construido sobre `node:http` nativo sin dependencias externas pesadas.

## Cómo funciona
El servidor implementa un modelo de pipeline de middlewares:

1. **Request → Middleware Pipeline**: Cada request pasa por una cadena de middlewares
2. **Request Dispatcher**: El dispatcher (ej: FileRouter) enruta al handler correcto
3. **Response**: El handler envía la respuesta a través de `JamxResponse`
4. **Eventos**: El servidor emite eventos para logging, monitoreo, HMR

## Componentes principales

### JamxServer (`src/http/server.ts`)
Servidor HTTP principal:
- `create(options)`: Factory method para crear instancia
- `start()`: Inicia el servidor
- `stop()`: Detiene gracefulmente
- `use(middleware)`: Añade middleware dinámicamente
- `on(event, handler)`: Suscribe a eventos
- `httpServer`: Acceso al `http.Server` nativo

### JamxRequest (`src/http/request.ts`)
Wrapper de `http.IncomingMessage` con utilidades:
- `method`, `url`, `path`, `query`, `params`, `headers`
- `body`: Parseado automáticamente por `bodyParser`
- `locals`: Objeto para datos entre middlewares

### JamxResponse (`src/http/response.ts`)
Wrapper de `http.ServerResponse` con API fluida:
- `status(code)`, `header(name, value)`, `json(body)`, `text(body)`
- `send(body)`, `redirect(url)`, `notFound()`, `noContent()`
- `raw`: Acceso al `ServerResponse` nativo

### MiddlewarePipeline (`src/middleware/pipeline.ts`)
Gestiona la cadena de ejecución de middlewares:
- `use(middleware)`: Añade middleware
- `clone()`: Crea copia para aislamiento por request
- `execute(req, res)`: Ejecuta pipeline completo

### Middlewares built-in
- `bodyParser`: Parse JSON, URL-encoded, text bodies
- `cors`: Configura CORS headers
- `requestId`: Añade `X-Request-ID` único
- `staticFiles`: Sirve archivos estáticos
- `globalErrorHandler`: Captura errores no manejados
- `rateLimit`: Limita requests por IP/cliente

### HMR (Hot Module Replacement)
- `HmrServer`: Coordina HMR entre servidor y cliente
- `FileWatcher`: Observa cambios en archivos
- `HmrWebSocketServer`: WebSocket para push de cambios
- `generateClientScript`: Genera script de cliente para HMR

### Request Dispatcher (`src/router/dispatcher.ts`)
Interface para enrutadores:
- `dispatch(req, res)`: Método que deben implementar routers como FileRouter

### Validación (`src/validation/parse-body.ts`)
- `parseBody(req)`: Parsea body según Content-Type
- `parseQuery(url)`: Parsea query string
- `parseParams(route, path)`: Extrae params de ruta

### Webhooks (`src/webhooks/`)
- `WebhookSender`: Envía webhooks con retry
- `webhookVerifier`: Verifica signatures de webhooks

## Uso básico

### Servidor simple
```typescript
import { JamxServer } from '@jamx-framework/server';

const server = await JamxServer.create();

server.use(async (req, res) => {
  res.json({ message: 'Hello World' });
});

await server.start();
console.log(`Server running on http://${server.address.host}:${server.address.port}`);

await server.stop();
```

### Con middleware de body parsing
```typescript
import { JamxServer, bodyParser } from '@jamx-framework/server';

const server = await JamxServer.create();

server.use(bodyParser()); // parsea req.body automáticamente

server.use(async (req, res) => {
  if (req.method === 'POST') {
    const data = req.body as { name: string };
    res.json({ received: data.name });
  }
});

await server.start();
```

### Con CORS
```typescript
import { JamxServer, cors } from '@jamx-framework/server';

const server = await JamxServer.create();

server.use(cors({
  origin: ['https://example.com', 'http://localhost:3000'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  headers: ['Content-Type', 'Authorization'],
}));

await server.start();
```

### Con archivos estáticos
```typescript
import { JamxServer, staticFiles } from '@jamx-framework/server';

const server = await JamxServer.create();

// Servir archivos estáticos desde /public
server.use(staticFiles({
  root: './public',
  cacheControl: 'public, max-age=3600',
}));

// API después de estáticos
server.use(async (req, res) => {
  res.json({ api: true });
});

await server.start();
```

### Con rate limiting
```typescript
import { JamxServer, rateLimit } from '@jamx-framework/server';

const server = await JamxServer.create();

server.use(rateLimit({
  max: 100, // 100 requests por ventana
  window: '1m', // 1 minuto
  keyBy: 'ip', // o 'user-id', 'session-id', etc.
}));

await server.start();
```

### Con FileRouter
```typescript
import { JamxServer, FileRouter } from '@jamx-framework/server';

const server = await JamxServer.create();

const router = new FileRouter({ projectRoot: './' });
server.use(router.dispatch.bind(router));

await server.start();
```

### Con middleware personalizado
```typescript
import { JamxServer } from '@jamx-framework/server';

const server = await JamxServer.create();

// Logging middleware
server.use(async (req, res, next) => {
  console.log(`${req.method} ${req.path}`);
  const start = Date.now();

  // Capturar respuesta
  const originalSend = res.send.bind(res);
  res.send = (body) => {
    const duration = Date.now() - start;
    console.log(`${req.method} ${req.path} ${res.statusCode} ${duration}ms`);
    return originalSend(body);
  };

  next();
});

// Auth middleware
server.use(async (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1];
  if (token) {
    try {
      const user = await verifyToken(token);
      req.locals.user = user;
    } catch (err) {
      // token inválido, continuar sin usuario
    }
  }
  next();
});

// Handler principal
server.use(async (req, res) => {
  const user = req.locals.user;
  res.json({ user: user?.id ?? null });
});

await server.start();
```

### Con error handling
```typescript
import { JamxServer, globalErrorHandler } from '@jamx-framework/server';

const server = await JamxServer.create();

// Middleware que puede lanzar errores
server.use(async (req, res) => {
  if (Math.random() > 0.5) {
    throw new Error('Random error');
  }
  res.json({ ok: true });
});

// Error handler (debe ser el último)
server.use(globalErrorHandler({
  // En desarrollo, retorna stack trace
  // En producción, retorna mensaje genérico
  showStackTrace: process.env.NODE_ENV === 'development',
}));

await server.start();
```

### Con HMR (desarrollo)
```typescript
import { JamxServer, HmrServer } from '@jamx-framework/server';

const server = await JamxServer.create({
  isDev: true,
});

const hmr = new HmrServer({
  server,
  projectRoot: './',
  port: 3000,
});

await hmr.start();
await server.start();
```

### Eventos del servidor
```typescript
import { JamxServer } from '@jamx-framework/server';

const server = await JamxServer.create();

server.on('listening', (event) => {
  console.log(`Server listening on ${event.host}:${event.port}`);
});

server.on('request', (event) => {
  console.log(`${event.method} ${event.path} → ${event.status} (${event.durationMs}ms)`);
});

server.on('error', (event) => {
  console.error('Server error:', event.error);
});

server.on('stopped', () => {
  console.log('Server stopped');
});

await server.start();
```

### Graceful shutdown
```typescript
import { JamxServer } from '@jamx-framework/server';

const server = await JamxServer.create({
  shutdownTimeout: 10000, // 10 segundos
});

await server.start();

// Manejar señales de terminación
process.on('SIGTERM', async () => {
  console.log('SIGTERM received, shutting down gracefully...');
  await server.stop();
  process.exit(0);
});

process.on('SIGINT', async () => {
  console.log('SIGINT received, shutting down gracefully...');
  await server.stop();
  process.exit(0);
});
```

## API Reference

### JamxServer

#### Factory method
```typescript
static async create(options?: ServerOptions): Promise<JamxServer>
```
Crea una nueva instancia del servidor.

**ServerOptions:**
```typescript
interface ServerOptions {
  port?: number;              // Puerto (default: 3000)
  host?: string;              // Host (default: 'localhost')
  dispatcher?: RequestDispatcher; // Enrutador (default: StubDispatcher)
  middlewares?: Middleware[]; // Middlewares adicionales
  isDev?: boolean;            // Modo desarrollo (default: false)
  shutdownTimeout?: number;   // Timeout de shutdown en ms (default: 5000)
}
```

#### Métodos de ciclo de vida
```typescript
start(): Promise<void>
```
Inicia el servidor. Retorna una promesa que se resuelve cuando el servidor está escuchando.

```typescript
stop(): Promise<void>
```
Detiene el servidor gracefulmente. Espera a que las requests en curso terminen antes de cerrar.

#### Middleware management
```typescript
use(middleware: Middleware): this
```
Añade un middleware al pipeline. Puede llamarse antes o después de `start()`.

```typescript
on(handler: ServerEventHandler): this
```
Suscribe un handler a eventos del servidor.

#### Getters
```typescript
readonly isListening: boolean
```
`true` si el servidor está escuchando conexiones.

```typescript
readonly address: { port: number; host: string }
```
Dirección en la que el servidor está escuchando.

```typescript
readonly httpServer: http.Server | null
```
Instancia subyacente de `http.Server` de Node.js.

### JamxRequest

#### Propiedades
```typescript
method: string;           // Método HTTP (GET, POST, etc.)
url: string;             // URL completa con query string
path: string;            // Solo el path (sin query)
query: Record<string, string>; // Query parameters parseados
params: Record<string, string>; // Parámetros de ruta (por dispatcher)
headers: Record<string, string>; // Headers (normalizados a minúsculas)
body: unknown;           // Cuerpo parseado (por bodyParser)
locals: Record<string, unknown>; // Datos para middlewares
```

#### Métodos
```typescript
getHeader(name: string): string | undefined
```
Obtiene un header específico (case-insensitive).

### JamxResponse

#### Métodos de respuesta
```typescript
status(code: number): this
```
Establece el código de estado HTTP.

```typescript
header(name: string, value: string): this
```
Añade un header a la respuesta.

```typescript
json(body: unknown, status?: number): void
```
Envía respuesta JSON. Establece `Content-Type: application/json`.

```typescript
text(body: string, status?: number): void
```
Envía respuesta de texto plano.

```typescript
send(body: string | Buffer, status?: number): void
```
Envía cuerpo crudo (string o Buffer).

```typescript
redirect(url: string, status?: number): void
```
Redirige a otra URL (por defecto 302).

```typescript
notFound(message?: string): void
```
Responde con 404 Not Found.

```typescript
noContent(): void
```
Responde con 204 No Content.

```typescript
raw: http.ServerResponse
```
Acceso directo al `ServerResponse` nativo de Node.js.

#### Getters
```typescript
readonly sent: boolean
```
`true` si ya se envió una respuesta.

### Middleware

#### Tipo
```typescript
type Middleware = (
  req: JamxRequest,
  res: JamxResponse,
  next: NextFn
) => Promise<void> | void;
```

#### NextFn
```typescript
type NextFn = () => Promise<void> | void;
```
Función que debe llamarse para continuar al siguiente middleware.

#### Ejemplo de middleware
```typescript
function loggingMiddleware(req: JamxRequest, res: JamxResponse, next: NextFn) {
  console.log(`${req.method} ${req.path}`);
  next();
}

function authMiddleware(req: JamxRequest, res: JamxResponse, next: NextFn) {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) {
    res.json({ error: 'Unauthorized' }, 401);
    return;
  }
  // verificar token...
  next();
}
```

### MiddlewarePipeline

#### Métodos
```typescript
use(middleware: Middleware): void
```
Añade un middleware al final del pipeline.

```typescript
clone(): MiddlewarePipeline
```
Crea una copia del pipeline con los mismos middlewares. Usado para aislar cada request.

```typescript
execute(req: JamxRequest, res: JamxResponse): Promise<void>
```
Ejecuta todos los middlewares en secuencia.

### RequestDispatcher

#### Interface
```typescript
interface RequestDispatcher {
  dispatch(req: JamxRequest, res: JamxResponse): Promise<void>;
}
```
Cualquier router (FileRouter, StubDispatcher) implementa esta interface.

### StubDispatcher
Dispatcher por defecto que responde 404 a todo. Útil para tests o como fallback.

### Built-in Middlewares

#### bodyParser
```typescript
function bodyParser(options?: {
  limit?: string | number;  // límite de tamaño (default: '1mb')
  json?: boolean;           // parsear JSON (default: true)
  urlencoded?: boolean;     // parsear URL-encoded (default: true)
  text?: boolean;           // parsear texto (default: false)
}): Middleware
```
Parsea el cuerpo de la request según `Content-Type`.

**Content-Type soportados:**
- `application/json` → `req.body` = objeto parseado
- `application/x-www-form-urlencoded` → `req.body` = objeto
- `text/plain` → `req.body` = string

#### cors
```typescript
function cors(options?: {
  origin: string | string[];  // orígenes permitidos
  methods?: string[];         // métodos permitidos
  headers?: string[];         // headers permitidos
  credentials?: boolean;      // Access-Control-Allow-Credentials
}): Middleware
```
Configura CORS headers.

#### requestId
```typescript
function requestId(): Middleware
```
Añade header `X-Request-ID` con UUID único a cada request.

#### staticFiles
```typescript
function staticFiles(options?: {
  root: string;                // directorio raíz
  cacheControl?: string;       // Cache-Control header
  index?: boolean | string;    // servir index.html por defecto
  extensions?: string[];       // extensiones a probar
}): Middleware
```
Sirve archivos estáticos desde disco.

#### globalErrorHandler
```typescript
function globalErrorHandler(options?: {
  showStackTrace?: boolean;    // mostrar stack en respuesta
  logger?: (err: unknown) => void; // logger personalizado
}): Middleware
```
Captura errores no manejados y responde con 500.

#### rateLimit
```typescript
function rateLimit(options?: {
  max: number;                 // max requests por ventana
  window: string | number;     // ventana de tiempo ('1m', '1h', etc.)
  keyBy: 'ip' | 'user-id' | 'session-id' | ((req) => string); // clave
  storage?: 'memory' | 'redis'; // backend de almacenamiento
}): Middleware
```
Limita el número de requests por cliente.

### HMR

#### HmrServer
```typescript
class HmrServer {
  constructor(options: HmrServerOptions);
  start(): Promise<void>;
  stop(): Promise<void>;
}
```
Coordina Hot Module Replacement.

**HmrServerOptions:**
```typescript
interface HmrServerOptions {
  server: JamxServer;       // instancia del servidor
  projectRoot: string;      // raíz del proyecto
  port: number;             // puerto del servidor
  wsPort?: number;          // puerto WebSocket (default: port+1)
}
```

#### FileWatcher
```typescript
class FileWatcher {
  constructor(projectRoot: string);
  onChange(handler: (changes: FileChange[]) => void): void;
  start(): void;
  stop(): void;
}
```
Observa cambios en archivos.

**FileChange:**
```typescript
interface FileChange {
  path: string;
  kind: ChangeKind; // 'create' | 'modify' | 'delete' | 'rename'
}
```

#### HmrWebSocketServer
```typescript
class HmrWebSocketServer {
  constructor(server: http.Server, port: number);
  broadcast(message: HmrMessage): void;
  start(): void;
  stop(): void;
}
```
WebSocket server para push de cambios a clientes.

**HmrMessage:**
```typescript
interface HmrMessage {
  type: 'reload' | 'update' | 'error';
  path?: string;
  data?: unknown;
}
```

#### generateClientScript
```typescript
function generateClientScript(options: {
  wsUrl: string;
  projectRoot: string;
  isDev: boolean;
}): string
```
Genera el script JavaScript que el cliente ejecuta para HMR.

### Webhooks

#### WebhookSender
```typescript
class WebhookSender {
  constructor(options: {
    url: string;
    secret?: string;          // para verificar signature
    retries?: number;         // reintentos (default: 3)
    timeout?: number;         // timeout en ms (default: 5000)
  });

  async send(payload: unknown, options?: SendWebhookOptions): Promise<WebhookDelivery>;
}
```
Envía webhooks con retry automático.

**WebhookDelivery:**
```typescript
interface WebhookDelivery {
  id: string;
  status: 'pending' | 'sent' | 'failed';
  attempts: number;
  response?: http.IncomingMessage;
  error?: Error;
}
```

#### webhookVerifier
```typescript
function webhookVerifier(secret: string): (req: JamxRequest) => boolean
```
Retorna un middleware que verifica la signature de un webhook.

## Flujo interno

### Ciclo de vida de una request
```typescript
// 1. Servidor recibe conexión HTTP
server = http.createServer(async (rawReq, rawRes) => handleRequest(rawReq, rawRes));

// 2. handleRequest crea wrappers JAMX
const req = new JamxRequest(rawReq);
const res = new JamxResponse(rawRes);

// 3. Clonar pipeline (aislamiento por request)
const pipeline = this.pipeline.clone();

// 4. Añadir dispatcher como último middleware
pipeline.use(async (req, res) => {
  await this.dispatcher.dispatch(req, res);
});

// 5. Ejecutar pipeline
await pipeline.execute(req, res);

// 6. Si no se respondió → 404
if (!res.sent && !rawRes.writableEnded) {
  res.notFound();
}

// 7. Emitir evento de request
this.emit({
  type: 'request',
  method: req.method,
  path: req.path,
  status: rawRes.statusCode,
  durationMs: Date.now() - startTime,
});
```

### Pipeline de middlewares
```typescript
class MiddlewarePipeline {
  private middlewares: Middleware[] = [];

  use(mw: Middleware) {
    this.middlewares.push(mw);
  }

  clone(): MiddlewarePipeline {
    const clone = new MiddlewarePipeline();
    clone.middlewares = [...this.middlewares];
    return clone;
  }

  async execute(req: JamxRequest, res: JamxResponse) {
    let index = 0;

    const next = (): Promise<void> => {
      if (index >= this.middlewares.length) return Promise.resolve();

      const mw = this.middlewares[index++];
      return Promise.resolve(mw(req, res, next)).then(next);
    };

    await next();
  }
}
```

### Construcción del pipeline
```typescript
private buildPipeline(extraMiddlewares: Middleware[]): MiddlewarePipeline {
  const pipeline = new MiddlewarePipeline();

  // 1. Middlewares built-in
  pipeline.use(requestId());      // X-Request-ID
  pipeline.use(bodyParser());     // parse body

  // 2. Middlewares del usuario
  for (const mw of extraMiddlewares) {
    pipeline.use(mw);
  }

  return pipeline;
}
```

### Request lifecycle completo
```typescript
// Ejemplo con todos los componentes

const server = await JamxServer.create({
  port: 3000,
  middlewares: [
    cors({ origin: '*' }),
    rateLimit({ max: 100, window: '1m' }),
  ],
});

// 1. Request entra
// 2. requestId → añade X-Request-ID
// 3. bodyParser → parsea body
// 4. cors → configura CORS headers
// 5. rateLimit → verifica límite
// 6. user middlewares (logging, auth, etc.)
// 7. dispatcher.dispatch → enruta a handler
// 8. handler envía respuesta
// 9. Si no se respondió → 404
// 10. Emitir evento 'request'
```

## Configuración

### Opciones del servidor
```typescript
const server = await JamxServer.create({
  port: 8080,
  host: '0.0.0.0',
  isDev: true,
  shutdownTimeout: 10000,
  middlewares: [customMiddleware],
  dispatcher: fileRouter,
});
```

### Variables de entorno
- `PORT`: Puerto del servidor (sobreescribe `options.port`)
- `HOST`: Host del servidor (sobreescribe `options.host`)
- `NODE_ENV`: Modo desarrollo/producción (afecta logs, errores)

## Testing

### Tests unitarios
```typescript
import { JamxServer, bodyParser } from '@jamx-framework/server';
import { describe, it, expect, beforeEach, afterEach } from 'vitest';

describe('Server', () => {
  let server: JamxServer;

  beforeEach(async () => {
    server = await JamxServer.create({
      port: 0, // puerto aleatorio
    });
  });

  afterEach(async () => {
    await server.stop();
  });

  it('should start and stop', async () => {
    await server.start();
    expect(server.isListening).toBe(true);

    await server.stop();
    expect(server.isListening).toBe(false);
  });

  it('should handle requests', async () => {
    server.use(async (req, res) => {
      res.json({ method: req.method, path: req.path });
    });

    await server.start();
    const port = server.address.port;

    const response = await fetch(`http://localhost:${port}/test`);
    const data = await response.json();

    expect(data.method).toBe('GET');
    expect(data.path).toBe('/test');
  });

  it('should emit events', async () => {
    const events: any[] = [];

    server.on('listening', (e) => events.push(e));
    server.on('request', (e) => events.push(e));
    server.on('stopped', (e) => events.push(e));

    await server.start();
    await fetch(`http://localhost:${server.address.port}/ping`);
    await server.stop();

    expect(events.some(e => e.type === 'listening')).toBe(true);
    expect(events.some(e => e.type === 'request')).toBe(true);
    expect(events.some(e => e.type === 'stopped')).toBe(true);
  });
});
```

### Tests con TestServer
```typescript
import { createTestServer } from '@jamx-framework/testing';

const testServer = createTestServer();

testServer.get('/api/test', (req, res) => {
  res.writeHead(200, { 'Content-Type': 'application/json' });
  res.end(JSON.stringify({ ok: true }));
});

await testServer.start();
const client = new TestClient(testServer.url);

const response = await client.get('/api/test');
expect(response.status).toBe(200);
expect(response.json()).toEqual({ ok: true });

await testServer.stop();
```

## Consideraciones de rendimiento

### Pipeline optimizado
- Los middlewares se ejecutan en secuencia, no en paralelo
- `pipeline.clone()` crea una copia ligera por request (shallow copy de array)
- No hay overhead significativo por request

### Sin dependencias externas
- Solo usa `node:http` nativo
- Sin Express/Fastify → menos memoria, menos CPU
- Ideal para serverless (Lambda, Cloudflare Workers via adapters)

### HMR overhead
- En desarrollo, HMR agrega WebSocket server y file watcher
- En producción, HMR está deshabilitado
- El overhead es mínimo (~1-2MB de memoria)

### Body parsing
- `bodyParser` carga el body completo en memoria
- Para uploads grandes, usar `staticFiles` o streaming
- Límite por defecto: 1MB (configurable)

### Rate limiting
- Por defecto usa memoria (Map)
- Para múltiples instancias, usar Redis storage
- Limpia automáticamente entradas expiradas

## Seguridad

### Headers de seguridad
El servidor no agrega security headers por defecto. Usar middleware:

```typescript
import { helmet } from '@jamx-framework/security'; // (hipotético)

server.use(helmet());
```

O manualmente:
```typescript
server.use((req, res, next) => {
  res.header('X-Content-Type-Options', 'nosniff');
  res.header('X-Frame-Options', 'DENY');
  res.header('X-XSS-Protection', '1; mode=block');
  next();
});
```

### CSRF
No incluido en core. Usar `@jamx-framework/auth` o middleware externo.

### Validación de input
El servidor no valida automáticamente. Usar `@jamx-framework/validator`:

```typescript
import { validate } from '@jamx-framework/validator';

server.use(async (req, res, next) => {
  if (req.method === 'POST') {
    const result = validate(req.body, userSchema);
    if (!result.valid) {
      res.json({ errors: result.errors }, 400);
      return;
    }
    req.body = result.value; // datos validados y casteados
  }
  next();
});
```

## Limitaciones

### Sin soporte nativo para:
- WebSockets (usar `@jamx-framework/realtime` con adapter)
- HTTP/2 (solo HTTP/1.1)
- TLS/SSL (usir reverse proxy como Nginx)
- Sessions (usar `@jamx-framework/auth` con JWT o DB)

### Single-threaded
- Node.js es single-threaded
- Para CPU-intensive tasks, usar Worker Threads o external services
- Para I/O, Node.js es no-blocking por defecto

### No incluye:
- ORM (usar `@jamx-framework/db`)
- Template engine (usar `@jamx-framework/renderer`)
- Authentication (usar `@jamx-framework/auth`)

## Integración con otros paquetes

### Con `@jamx-framework/router`
```typescript
import { FileRouter } from '@jamx-framework/router';

const router = new FileRouter({ projectRoot: './' });
const server = await JamxServer.create();
server.use(router.dispatch.bind(router));
```

### Con `@jamx-framework/config`
```typescript
import { ConfigManager } from '@jamx-framework/config';

const configManager = new ConfigManager();
await configManager.load('./');

const server = await JamxServer.create({
  port: configManager.section('server').port,
  host: configManager.section('server').host,
});
```

### Con `@jamx-framework/auth`
```typescript
import { authMiddleware } from '@jamx-framework/auth';

server.use(authMiddleware());
```

### Con `@jamx-framework/metrics`
```typescript
import { Metrics } from '@jamx-framework/metrics';

server.on('request', (event) => {
  Metrics.histogram('http.request.duration', event.durationMs, {
    method: event.method,
    path: event.path,
    status: event.status,
  });
});
```

## Ejemplo completo

```typescript
// server/index.ts
import { JamxServer, bodyParser, cors, rateLimit, staticFiles, requestId } from '@jamx-framework/server';
import { FileRouter } from '@jamx-framework/router';
import { ConfigManager } from '@jamx-framework/config';
import { Metrics } from '@jamx-framework/metrics';

async function main() {
  // Cargar configuración
  const configManager = new ConfigManager();
  await configManager.load('./');

  const config = configManager.get();

  // Crear servidor
  const server = await JamxServer.create({
    port: config.server?.port ?? 3000,
    host: config.server?.host ?? 'localhost',
    isDev: configManager.isDev,
    middlewares: [
      // CORS
      cors({
        origin: config.server?.cors?.origins ?? ['http://localhost:3000'],
        credentials: true,
      }),

      // Rate limiting
      rateLimit({
        max: config.security?.rateLimit?.max ?? 100,
        window: config.security?.rateLimit?.window ?? '1m',
        keyBy: 'ip',
      }),

      // Logging con métricas
      async (req, res, next) => {
        const start = Date.now();
        res.on('finish', () => {
          const duration = Date.now() - start;
          Metrics.histogram('http.request.duration', duration, {
            method: req.method,
            path: req.path,
            status: res.statusCode,
          });
        });
        next();
      },

      // Autenticación (si está configurada)
      ...(config.auth ? [authMiddleware(config.auth)] : []),
    ],
  });

  // Eventos
  server.on('listening', () => {
    console.log(`Server listening on http://${server.address.host}:${server.address.port}`);
  });

  server.on('error', (err) => {
    console.error('Server error:', err);
  });

  // Archivos estáticos
  server.use(staticFiles({
    root: './public',
    cacheControl: 'public, max-age=3600',
  }));

  // API routes con FileRouter
  const router = new FileRouter({ projectRoot: './' });
  server.use(router.dispatch.bind(router));

  // Graceful shutdown
  process.on('SIGTERM', async () => {
    console.log('SIGTERM received, shutting down...');
    await server.stop();
    process.exit(0);
  });

  process.on('SIGINT', async () => {
    console.log('SIGINT received, shutting down...');
    await server.stop();
    process.exit(0);
  });

  // Iniciar
  await server.start();
}

main().catch(console.error);
```

## Referencia rápida

### Crear servidor
```typescript
const server = await JamxServer.create(options);
```

### Middlewares comunes
```typescript
server.use(bodyParser());
server.use(cors({ origin: '*' }));
server.use(rateLimit({ max: 100, window: '1m' }));
server.use(staticFiles({ root: './public' }));
server.use(requestId());
server.use(globalErrorHandler());
```

### Añadir middleware personalizado
```typescript
server.use(async (req, res, next) => {
  // lógica
  next();
});
```

### Eventos
```typescript
server.on('listening', (e) => console.log(`Listening on ${e.port}`));
server.on('request', (e) => console.log(`${e.method} ${e.path}`));
server.on('error', (e) => console.error(e.error));
server.on('stopped', () => console.log('Stopped'));
```

### Control
```typescript
await server.start();
await server.stop();
```

### Acceso a http.Server nativo
```typescript
const httpServer = server.httpServer;
// puedes añadir listeners personalizados, etc.
```

## Archivos importantes
- `src/http/server.ts` - JamxServer principal
- `src/http/request.ts` - JamxRequest
- `src/http/response.ts` - JamxResponse
- `src/middleware/pipeline.ts` - MiddlewarePipeline
- `src/middleware/built-in/` - Middlewares incluidos
- `src/router/dispatcher.ts` - RequestDispatcher interface
- `src/hmr/` - Hot Module Replacement
- `tests/unit/http/server.test.ts` - Tests del servidor
- `tests/unit/middleware/` - Tests de middlewares

## Dependencias
- `@jamx-framework/core` - Para `NotFoundException` y tipos
- `@jamx-framework/cache` - Para rate limit con Redis
- `@jamx-framework/config` - Para configuración
- `@jamx-framework/storage` - Para static files con S3
- `@jamx-framework/validator` - Para validación
- `@types/node` - Tipos de Node.js
- `vitest` - Testing
- `rimraf` - Limpieza

## Scripts del paquete
- `pnpm build` - Compila TypeScript a JavaScript
- `pnpm dev` - Compilación en watch mode
- `pnpm test` - Ejecuta tests unitarios
- `pnpm test:watch` - Tests en watch mode
- `pnpm type-check` - Verifica tipos sin compilar
- `pnpm clean` - Limpia archivos compilados

## Comparación con Express/Fastify

| Característica | JAMX Server | Express | Fastify |
|----------------|-------------|---------|---------|
| Peso | ~50KB | ~200KB | ~150KB |
| Dependencias | Solo core | muchas | moderadas |
| Pipeline | Sí (explicito) | Sí (implícito) | Sí |
| TypeScript | Nativo | opcional | opcional |
| HMR | Sí (integrado) | No | No |
| Validación | Externa | Externa | Externa |
| ORM | Externa | Externa | Externa |
| Rendimiento | Muy alto | Medio | Alto |
| Aprendizaje | Moderado | Fácil | Moderado |

## Buenas prácticas

### 1. Orden de middlewares
```typescript
// Correcto: bodyParser antes de handlers que usen req.body
server.use(bodyParser());
server.use(async (req, res) => {
  // req.body disponible aquí
});

// Incorrecto: bodyParser después
server.use(async (req, res) => {
  // req.body undefined aquí
});
server.use(bodyParser());
```

### 2. Error handling al final
```typescript
// Middlewares primero
server.use(bodyParser());
server.use(cors());
server.use(auth);

// Error handler al final
server.use(globalErrorHandler());
```

### 3. Usar async/await
```typescript
// ✅ Bien
server.use(async (req, res, next) => {
  try {
    const data = await fetchData();
    res.json(data);
  } catch (err) {
    next(err); // pasar al error handler
  }
});

// ❌ No usar callbacks
server.use((req, res, next) => {
  fetchData((err, data) => {
    if (err) return next(err);
    res.json(data);
  });
});
```

### 4. Llamar next() o responder
```typescript
// ✅ Una de las dos, no ambas
server.use(async (req, res, next) => {
  // O respondes:
  res.json({ ok: true });

  // O llamas next():
  // next();
});

// ❌ No hagas ambas
server.use(async (req, res, next) => {
  res.json({ ok: true });
  next(); // error: headers ya enviados
});
```

### 5. Usar locals para datos compartidos
```typescript
// Middleware de autenticación
server.use(async (req, res, next) => {
  const user = await verifyToken(req.headers.authorization);
  req.locals.user = user; // guardar para siguientes middlewares
  next();
});

// Handler
server.use(async (req, res) => {
  const user = req.locals.user; // disponible aquí
  res.json({ user });
});
```

## Preguntas frecuentes

### ¿Cómo manejar 404?
El servidor responde 404 automáticamente si ningún middleware envía respuesta.

```typescript
// Para custom 404, añadir middleware al final
server.use(async (req, res) => {
  res.notFound('Page not found');
});
```

### ¿Cómo manejar errores 500?
Usar `globalErrorHandler` al final del pipeline:

```typescript
server.use(globalErrorHandler({
  showStackTrace: process.env.NODE_ENV === 'development',
}));
```

### ¿Puedo usar Express middleware?
No directamente. Los middlewares de Express tienen una API diferente (3 args vs 4 args, `next` como callback). Necesitas un adapter.

### ¿Cómo servir HTTPS?
El servidor solo soporta HTTP. Usar reverse proxy (Nginx, Caddy) o `spdy`/`http2` externamente.

### ¿Cómo escalar horizontalmente?
- Usar balanceador de carga (Nginx, HAProxy)
- Asegurar que el estado sea externo (Redis, DB)
- No guardar estado en memoria del servidor

### ¿Cómo añadir WebSocket?
El servidor no incluye WebSocket. Usar `@jamx-framework/realtime`:

```typescript
import { WebSocketServer } from '@jamx-framework/realtime';

const wsServer = new WebSocketServer({ server });
wsServer.on('connection', (socket) => {
  socket.on('message', (msg) => {
    // manejar mensaje
  });
});
```

### ¿Cómo subir archivos?
Usar `busboy` o `multer` externamente, o el middleware `multipart` de JAMX (si existe).

```typescript
import { multipart } from '@jamx-framework/server';

server.use(multipart({ limits: { fileSize: 10 * 1024 * 1024 } }));

server.use(async (req, res) => {
  const file = req.files?.[0];
  if (file) {
    await saveFile(file);
  }
  res.json({ ok: true });
});
```

### ¿Cómo usar sesiones?
El servidor no incluye sesiones. Usar `@jamx-framework/auth` con JWT o sesiones en DB.

```typescript
import { session } from '@jamx-framework/auth';

server.use(session({
  secret: process.env.SESSION_SECRET,
  store: new RedisStore(),
}));
```

## Limitaciones conocidas

### No incluye:
- Template rendering (usar `@jamx-framework/renderer`)
- ORM/database (usar `@jamx-framework/db`)
- Authentication (usar `@jamx-framework/auth`)
- Validation (usar `@jamx-framework/validator`)
- Rate limiting con Redis (solo memoria por defecto)
- WebSockets (usar `@jamx-framework/realtime`)

### Diseñado para:
- APIs REST/GraphQL
- SSR con renderer
- Microservicios
- Serverless functions (via adapters)

### No diseñado para:
- Aplicaciones monolíticas pesadas (usar Next.js/Nuxt)
- WebSockets puros (usar Socket.io)
- FTP/SFTP (usar servidores especializados)

## Futuras mejoras
- Soporte para HTTP/2
- WebSocket integrado
- Sesiones nativas
- Template engine integrado
- Metrics integradas (Prometheus endpoint)
- Graceful shutdown mejorado (drenar conexiones)
- Request timeout configurable
- Compression (gzip/brotli)
- Caching (CDN, browser)

## Conclusión
`@jamx-framework/server` es un servidor HTTP minimalista pero potente, ideal para aplicaciones JAMX que necesitan control total sobre el stack. Su diseño modular permite añadir solo las funcionalidades necesarias, manteniendo el footprint pequeño y el rendimiento alto.