npm package: @skailan/tenant-manager
Description: Gestión optimizada de multitenancy para Skailan
Author: Skailan Team
Latest version: 1.0.0

# @skailan/tenant-manager

Gestión optimizada de multitenancy para Skailan. Esta librería proporciona una solución robusta para manejar múltiples tenants en aplicaciones Node.js con Express.

## 🚀 Instalación

```bash
npm install @skailan/tenant-manager
```

## 📖 Uso Básico

### Configuración Inicial

```typescript
import { TenantManager, createTenantResolver } from "@skailan/tenant-manager";

const tenantManager = new TenantManager({
  database: {
    type: "postgresql",
    host: "localhost",
    port: 5432,
    username: "postgres",
    password: "password",
    database: "skailan",
  },
  cache: {
    type: "redis",
    host: "localhost",
    port: 6379,
    ttl: 300000, // 5 minutos
  },
  isolation: "database-per-tenant",
  autoScaling: true,
});
```

### Middleware Express

```typescript
import express from "express";
import { createTenantResolver } from "@skailan/tenant-manager";

const app = express();

// Crear middleware de resolución de tenants
const tenantResolver = createTenantResolver(tenantManager);

// Usar middleware
app.use(tenantResolver);

// Ahora todas las requests tienen acceso a req.tenant
app.get("/api/data", (req, res) => {
  console.log("Tenant ID:", req.tenant?.id);
  console.log("Tenant Name:", req.tenant?.name);

  res.json({
    tenant: req.tenant,
    data: "Your data here",
  });
});
```

### Uso Manual

```typescript
import { TenantManager } from "@skailan/tenant-manager";

const tenantManager = new TenantManager(config);

// Resolver tenant manualmente
const tenant = await tenantManager.resolveTenant("empresa1.skailan.com");
console.log(tenant.id); // 'empresa1'
console.log(tenant.name); // 'Empresa1'

// Obtener base de datos del tenant
const db = await tenantManager.getTenantDatabase(tenant.id);
```

## 🔧 Configuración

### Opciones de Base de Datos

```typescript
{
  database: {
    type: 'postgresql' | 'mysql',
    host: string,
    port: number,
    username: string,
    password: string,
    database: string,
    ssl?: boolean
  }
}
```

### Opciones de Cache

```typescript
{
  cache: {
    type: 'redis' | 'memory',
    host?: string,        // Solo para Redis
    port?: number,        // Solo para Redis
    password?: string,    // Solo para Redis
    ttl?: number         // Tiempo de vida en ms
  }
}
```

### Opciones de Aislamiento

- `database-per-tenant`: Cada tenant tiene su propia base de datos
- `schema-per-tenant`: Cada tenant usa un schema diferente en la misma base de datos

## 🛠️ API

### TenantManager

#### `resolveTenant(host: string): Promise<Tenant>`

Resuelve un tenant basado en el hostname.

#### `getTenantDatabase(tenantId: string): Promise<PrismaClient>`

Obtiene la conexión de base de datos para un tenant específico.

#### `createTenant(tenantData: Partial<Tenant>): Promise<Tenant>`

Crea un nuevo tenant.

#### `invalidateTenantCache(host: string): Promise<void>`

Invalida el cache para un host específico.

#### `getStats(): Promise<Stats>`

Obtiene estadísticas del cache y conexiones.

### Middlewares

#### `createTenantResolver(tenantManager: TenantManager)`

Crea un middleware Express que resuelve automáticamente el tenant.

#### `requireTenant(req: Request, res: Response, next: NextFunction)`

Middleware que requiere que exista un tenant en la request.

#### `getTenantDatabase(tenantManager: TenantManager)`

Middleware que obtiene la base de datos del tenant.

## 📊 Ejemplos de Uso

### Ejemplo Completo

```typescript
import express from "express";
import {
  TenantManager,
  createTenantResolver,
  requireTenant,
  getTenantDatabase,
} from "@skailan/tenant-manager";

const app = express();

// Configurar TenantManager
const tenantManager = new TenantManager({
  database: {
    type: "postgresql",
    host: process.env.DB_HOST || "localhost",
    port: parseInt(process.env.DB_PORT || "5432"),
    username: process.env.DB_USER || "postgres",
    password: process.env.DB_PASSWORD || "",
    database: process.env.DB_NAME || "skailan",
  },
  cache: {
    type: "redis",
    host: process.env.REDIS_HOST || "localhost",
    port: parseInt(process.env.REDIS_PORT || "6379"),
    ttl: 300000,
  },
  isolation: "database-per-tenant",
  autoScaling: true,
});

// Middlewares
app.use(express.json());
app.use(createTenantResolver(tenantManager));

// Rutas que requieren tenant
app.get("/api/contacts", requireTenant, async (req, res) => {
  const db = await tenantManager.getTenantDatabase(req.tenant!.id);

  const contacts = await db.contact.findMany({
    where: { tenantId: req.tenant!.id },
  });

  res.json(contacts);
});

// Ruta con middleware de base de datos
app.get(
  "/api/users",
  requireTenant,
  getTenantDatabase(tenantManager),
  async (req, res) => {
    const users = await req.tenantDatabase!.user.findMany();
    res.json(users);
  }
);

app.listen(3000, () => {
  console.log("🚀 Server running on port 3000");
});
```

### Ejemplo con Configuración por Defecto

```typescript
import { createTenantManager } from "@skailan/tenant-manager";

// Usar configuración por defecto
const tenantManager = createTenantManager();

// O personalizar solo algunas opciones
const tenantManager = createTenantManager({
  database: {
    host: "my-db-host.com",
    password: "my-password",
  },
  cache: {
    type: "redis",
    host: "my-redis-host.com",
  },
});
```

## 🧪 Testing

```bash
# Ejecutar tests
npm test

# Ejecutar tests en modo watch
npm run test:watch

# Ver coverage
npm test -- --coverage
```

## 📈 Performance

- **Cache Hit Rate**: > 95% con Redis
- **Latencia de Resolución**: < 10ms con cache
- **Conexiones de BD**: Pooling automático por tenant
- **Memory Usage**: Optimizado con lazy loading

## 🔒 Seguridad

- Aislamiento completo entre tenants
- Validación de hostnames
- Timeout en conexiones de base de datos
- Rate limiting por tenant (configurable)

## 🤝 Contribuir

1. Fork el proyecto
2. Crear una rama para tu feature (`git checkout -b feature/amazing-feature`)
3. Commit tus cambios (`git commit -m 'Add amazing feature'`)
4. Push a la rama (`git push origin feature/amazing-feature`)
5. Abrir un Pull Request

## 📄 Licencia

MIT License - ver [LICENSE](LICENSE) para detalles.

## 🆘 Soporte

Para soporte técnico, contacta al equipo de Skailan o abre un issue en el repositorio.