npm package: @jaquinones45/jaquilogs-sdk
Description: SDK oficial de JaquiLogs - Cliente de logs, componentes React embebibles y dashboard analytics para monitoreo de aplicaciones
Author: JaquiSoft
Latest version: 1.2.0

# @jaquinones45/jaquilogs-sdk

SDK oficial de **JaquiLogs** - Plataforma de monitoreo y gestión de logs.

Incluye:
- **Cliente SDK** para enviar logs desde cualquier aplicación Node.js/Browser
- **Componentes React** embebibles con dashboard, tabla de logs y gráficos
- **Hooks** de React Query para consumo de datos
- **Sistema de temas y labels** completamente personalizable
- **Soporte i18n** (Español e Inglés)

---

## Instalación

```bash
# Con pnpm
pnpm add @jaquinones45/jaquilogs-sdk

# Con npm
npm install @jaquinones45/jaquilogs-sdk

# Con yarn
yarn add @jaquinones45/jaquilogs-sdk
```

### Peer Dependencies (solo si usas componentes React)

```bash
pnpm add react react-dom @tanstack/react-query recharts
```

---

## 1. Cliente SDK (Enviar Logs)

El cliente funciona en **cualquier entorno JavaScript** (Node.js, Browser, Edge Functions).
No requiere React.

### Configuración Básica

```typescript
import { createClient } from "@jaquinones45/jaquilogs-sdk";

const logger = createClient({
  apiKey: "tu-api-key",
  baseUrl: "https://api.jaquilogs.com", // Opcional, este es el default
  applicationId: "app-id-opcional",      // Se aplica a todos los logs
  debug: true,                           // Logs de debug en consola
});
```

### Enviar Logs

```typescript
// Método genérico
logger.log({
  level: "INFO",
  message: "Usuario autenticado exitosamente",
  request_url: "/api/auth/login",
  request_method: "POST",
  status_code: 200,
  response_time_ms: 45,
  custom_fields: { user_id: "abc123", region: "latam" },
});

// Shortcuts por nivel
logger.success("Pago procesado", {
  request_url: "/api/payments",
  request_method: "POST",
  status_code: 201,
  response_time_ms: 320,
});

logger.error("Fallo en la base de datos", {
  request_url: "/api/users",
  request_method: "GET",
  status_code: 500,
  response_time_ms: 5000,
});

logger.warn("Rate limit alcanzado", {
  request_url: "/api/search",
  request_method: "GET",
  status_code: 429,
  response_time_ms: 12,
});

logger.info("Health check OK", {
  request_url: "/health",
  request_method: "GET",
  status_code: 200,
  response_time_ms: 3,
});

logger.debug("Cache miss para key users:list", {
  request_url: "/api/users",
  request_method: "GET",
  status_code: 200,
  response_time_ms: 150,
});
```

### Middleware Express

Loguea automáticamente todas las peticiones HTTP:

```typescript
import express from "express";
import { createClient } from "@jaquinones45/jaquilogs-sdk";

const app = express();
const logger = createClient({ apiKey: "tu-api-key" });

// Agrega el middleware - ¡y listo!
app.use(logger.middleware());

app.get("/api/users", (req, res) => {
  res.json({ users: [] });
  // Se logueará automáticamente: GET /api/users 200
});
```

### Fetch Wrapper

Loguea automáticamente llamadas fetch:

```typescript
const logger = createClient({ apiKey: "tu-api-key" });

// En lugar de fetch(), usa logger.fetch()
const response = await logger.fetch("https://api.example.com/data", {
  method: "POST",
  body: JSON.stringify({ query: "test" }),
});
// Se logueará automáticamente con level, status, response_time
```

### Batching y Flush

Los logs se acumulan en batch y se envían periódicamente:

```typescript
const logger = createClient({
  apiKey: "tu-api-key",
  batchSize: 50,       // Flush automático al llegar a 50 logs
  flushInterval: 5000, // O cada 5 segundos
  maxRetries: 3,       // Reintentos con backoff exponencial
  timeout: 10000,      // Timeout por request
});

// Flush manual
await logger.flush();

// Ver cuántos logs están en cola
console.log(logger.pendingCount);

// Destruir (flush + limpiar timer)
await logger.destroy();
```

### Leer Datos

```typescript
// Obtener logs
const logs = await logger.getLogs({
  level: "ERROR",
  application_id: "mi-app",
  limit: 100,
});

// Obtener un log específico
const log = await logger.getLog("log-id-aqui");

// Obtener estadísticas
const stats = await logger.getStats({
  period: "day",
  level: ["ERROR", "WARNING"],
});

// Obtener aplicaciones
const apps = await logger.getApplications();
```

---

## 2. Componentes React

### Setup: JaquiLogsProvider

Envuelve tu aplicación (o sección) con el provider:

```tsx
import { JaquiLogsProvider } from "@jaquinones45/jaquilogs-sdk";
// O import más específico:
// import { JaquiLogsProvider } from "@jaquinones45/jaquilogs-sdk/react";

function App() {
  return (
    <JaquiLogsProvider
      config={{
        baseUrl: "https://api.jaquilogs.com",
        apiKey: "tu-api-key",
        locale: "es",              // "es" | "en"
        refreshInterval: 10000,    // Polling cada 10s
        labels: {
          dashboardTitle: "Mi Panel de Monitoreo",
          totalLogs: "Registros Totales",
          // ... cualquier label que quieras personalizar
        },
        theme: {
          primaryColor: "#6366f1",
          mode: "dark",
          borderRadius: 12,
          levelColors: {
            ERROR: "#ff0000",
          },
        },
      }}
    >
      <MyDashboard />
    </JaquiLogsProvider>
  );
}
```

#### Si ya usas React Query

Pasa tu propio `QueryClient` para evitar conflictos:

```tsx
import { QueryClient } from "@tanstack/react-query";

const queryClient = new QueryClient();

<JaquiLogsProvider config={config} queryClient={queryClient}>
  {children}
</JaquiLogsProvider>
```

---

### Dashboard Completo

El componente todo-en-uno con stats, gráficos y tabla:

```tsx
import { JaquiLogsDashboard } from "@jaquinones45/jaquilogs-sdk";

function MonitorPage() {
  return (
    <JaquiLogsDashboard
      title="Sistema de Monitoreo"
      sections={["stats", "logsByLevel", "logsByHour", "recentLogs"]}
      onLogClick={(log) => console.log("Log seleccionado:", log)}
    />
  );
}
```

**Props disponibles:**

| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| `title` | `string` | `labels.dashboardTitle` | Título del dashboard |
| `sections` | `string[]` | Todas | Secciones visibles |
| `filters` | `DashboardStatsFilters` | - | Filtros iniciales |
| `onLogClick` | `(log) => void` | - | Callback al hacer clic en un log |
| `className` | `string` | - | Clase CSS personalizada |

**Secciones disponibles:** `stats`, `logsByLevel`, `logsByHour`, `logsByMethod`, `topUrls`, `recentLogs`

---

### Cards de Estadísticas

```tsx
import { JaquiLogsStatsCards } from "@jaquinones45/jaquilogs-sdk";

<JaquiLogsStatsCards
  cards={["totalLogs", "totalErrors", "avgResponseTime", "successRate"]}
  filters={{ period: "day" }}
/>
```

**Cards disponibles:** `totalLogs`, `totalErrors`, `totalWarnings`, `applications`, `avgResponseTime`, `successRate`, `errorRate`

---

### Tabla de Logs

```tsx
import { JaquiLogsTable } from "@jaquinones45/jaquilogs-sdk";

<JaquiLogsTable
  searchable
  level="ERROR"
  limit={100}
  columns={["timestamp", "level", "message", "statusCode", "responseTime"]}
  maxHeight="500px"
  onRowClick={(log) => openModal(log)}
/>
```

**Props:**

| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| `applicationId` | `string` | - | Filtrar por app |
| `level` | `LogLevel` | - | Filtrar por nivel |
| `limit` | `number` | - | Máximo de logs |
| `columns` | `string[]` | Todas | Columnas visibles |
| `searchable` | `boolean` | `false` | Habilitar buscador |
| `maxHeight` | `string` | `600px` | Altura máxima con scroll |
| `onRowClick` | `(log) => void` | - | Click en fila |

---

### Gráficos

```tsx
import { JaquiLogsChart } from "@jaquinones45/jaquilogs-sdk";

// Gráfico de barras por nivel
<JaquiLogsChart chartType="bar" dataKey="logsByLevel" height={300} />

// Gráfico de líneas por hora (tráfico)
<JaquiLogsChart chartType="line" dataKey="logsByHour" title="Tráfico por Hora" />

// Gráfico de torta por método HTTP
<JaquiLogsChart chartType="pie" dataKey="logsByMethod" />

// Top URLs con errores
<JaquiLogsChart chartType="bar" dataKey="topUrls" height={400} />
```

**Props:**

| Prop | Tipo | Default | Descripción |
|------|------|---------|-------------|
| `chartType` | `"bar" \| "line" \| "pie"` | `"bar"` | Tipo de gráfico |
| `dataKey` | `string` | `"logsByLevel"` | Fuente de datos |
| `title` | `string` | Auto (i18n) | Título del gráfico |
| `height` | `number` | `300` | Altura en pixeles |
| `filters` | `DashboardStatsFilters` | - | Filtros |

**dataKeys disponibles:** `logsByLevel`, `logsByMethod`, `logsByHour`, `logsByStatus`, `logsByApplication`, `topUrls`, `topApplicationsByLogCount`

---

## 3. Hooks de React

Usa los hooks directamente para construir tus propios componentes:

```tsx
import { useLogs, useDashboardStats, useApplications, useLog } from "@jaquinones45/jaquilogs-sdk";

function MyComponent() {
  // Lista de logs con auto-refresh
  const { data: logs, isLoading } = useLogs({
    level: "ERROR",
    application_id: "mi-app",
  });

  // Estadísticas del dashboard
  const { data: stats } = useDashboardStats({
    period: "day",
    level: ["ERROR", "WARNING"],
  });

  // Aplicaciones
  const { data: apps } = useApplications();

  // Un log específico
  const { data: log } = useLog("log-id");

  return (
    <div>
      <p>Errores hoy: {stats?.totalErrors}</p>
      <ul>
        {logs?.map((log) => (
          <li key={log.id}>{log.message}</li>
        ))}
      </ul>
    </div>
  );
}
```

---

## 4. Personalización

### Labels / Títulos

Cambia cualquier texto visible en los componentes:

```tsx
<JaquiLogsProvider
  config={{
    baseUrl: "...",
    apiKey: "...",
    labels: {
      // Cambia el título del dashboard
      dashboardTitle: "Centro de Control ACME Corp",

      // Cambia los KPIs
      totalLogs: "Registros del Sistema",
      totalErrors: "Incidentes",
      avgResponseTime: "Latencia Promedio",

      // Cambia la tabla
      logViewerTitle: "Historial de Eventos",
      searchPlaceholder: "Buscar eventos...",
      noLogsFound: "Sin eventos registrados",

      // Cambia encabezados
      timestamp: "Fecha",
      message: "Descripción",
      statusCode: "Estado HTTP",
      responseTime: "Duración",

      // Cambia gráficos
      logsByLevel: "Eventos por Severidad",
      logsByHour: "Volumen por Hora",

      // Labels completamente custom
      myCustomLabel: "Mi label personalizado",
    },
  }}
>
```

### Temas

```tsx
// Tema claro personalizado
const miTema = {
  mode: "light" as const,
  primaryColor: "#0066cc",
  backgroundColor: "#fafafa",
  surfaceColor: "#ffffff",
  textColor: "#1a1a1a",
  borderRadius: 12,
  fontFamily: "'Inter', sans-serif",
  levelColors: {
    SUCCESS: "#10b981",
    INFO: "#0ea5e9",
    WARNING: "#f59e0b",
    ERROR: "#dc2626",
    DEBUG: "#a855f7",
  },
  chartColors: ["#0066cc", "#10b981", "#f59e0b", "#dc2626", "#a855f7"],
};

// Tema oscuro
const temaOscuro = {
  mode: "dark" as const,
  primaryColor: "#818cf8",
  backgroundColor: "#0f172a",
  surfaceColor: "#1e293b",
  textColor: "#f1f5f9",
  borderColor: "#334155",
};

<JaquiLogsProvider config={{ ...config, theme: miTema }}>
```

### Idioma

```tsx
// Español (default)
<JaquiLogsProvider config={{ ...config, locale: "es" }}>

// Inglés
<JaquiLogsProvider config={{ ...config, locale: "en" }}>

// Inglés con overrides específicos
<JaquiLogsProvider
  config={{
    ...config,
    locale: "en",
    labels: { dashboardTitle: "My Custom Title" },
  }}
>
```

---

## 5. Ejemplos Completos

### Next.js App

```tsx
// app/monitoring/page.tsx
"use client";

import {
  JaquiLogsProvider,
  JaquiLogsDashboard,
} from "@jaquinones45/jaquilogs-sdk";

export default function MonitoringPage() {
  return (
    <JaquiLogsProvider
      config={{
        baseUrl: process.env.NEXT_PUBLIC_JAQUILOGS_URL!,
        apiKey: process.env.NEXT_PUBLIC_JAQUILOGS_KEY!,
        locale: "es",
        theme: { mode: "dark", primaryColor: "#6366f1" },
        labels: { dashboardTitle: "Monitor de Producción" },
      }}
    >
      <div style={{ maxWidth: 1200, margin: "0 auto", padding: 24 }}>
        <JaquiLogsDashboard
          sections={["stats", "logsByLevel", "logsByHour", "recentLogs"]}
        />
      </div>
    </JaquiLogsProvider>
  );
}
```

### React + Vite (Componentes Individuales)

```tsx
import {
  JaquiLogsProvider,
  JaquiLogsStatsCards,
  JaquiLogsChart,
  JaquiLogsTable,
} from "@jaquinones45/jaquilogs-sdk";

function App() {
  return (
    <JaquiLogsProvider config={{ baseUrl: "...", apiKey: "...", locale: "es" }}>
      <div className="grid gap-6 p-6">
        {/* Solo los KPIs */}
        <JaquiLogsStatsCards cards={["totalLogs", "totalErrors"]} />

        {/* Un gráfico específico */}
        <JaquiLogsChart
          chartType="line"
          dataKey="logsByHour"
          title="Tráfico en tiempo real"
          height={300}
        />

        {/* Tabla de errores recientes */}
        <JaquiLogsTable
          level="ERROR"
          searchable
          columns={["timestamp", "message", "statusCode"]}
          limit={20}
        />
      </div>
    </JaquiLogsProvider>
  );
}
```

### Node.js Backend (Solo Cliente)

```typescript
import { createClient } from "@jaquinones45/jaquilogs-sdk/client";

const logger = createClient({
  apiKey: process.env.JAQUILOGS_API_KEY!,
  applicationId: "backend-api",
});

// Express middleware
app.use(logger.middleware());

// En un catch de error
app.use((err, req, res, next) => {
  logger.error(`Unhandled error: ${err.message}`, {
    request_url: req.originalUrl,
    request_method: req.method,
    status_code: 500,
    response_time_ms: 0,
    custom_fields: { stack: err.stack },
  });
  res.status(500).json({ error: "Internal Server Error" });
});

// Cleanup al cerrar
process.on("SIGTERM", async () => {
  await logger.destroy();
  process.exit(0);
});
```

---

## 6. Referencia de Tipos

```typescript
// Niveles de log
type LogLevel = "SUCCESS" | "INFO" | "WARNING" | "ERROR" | "DEBUG";

// Métodos HTTP
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD";

// Períodos de tiempo
type Period = "minute" | "hour" | "day" | "week" | "quarter" | "semester" | "annual";

// Filtros de dashboard
interface DashboardStatsFilters {
  period?: Period;
  application_id?: string[];
  level?: LogLevel[];
  method?: HttpMethod[];
  status?: ("2xx" | "3xx" | "4xx" | "5xx")[];
  date_from?: string;  // ISO 8601
  date_to?: string;    // ISO 8601
}

// Payload para crear un log
interface CreateLogPayload {
  timestamp?: string;           // Auto-generado si no se envía
  level: LogLevel;
  request_url: string;
  request_method: HttpMethod;
  status_code: number;
  response_time_ms: number;
  message: string;
  application_id?: string;      // Override del default
  custom_fields?: Record<string, unknown>;
}
```

---

## 7. Utilidades Exportadas

```typescript
import {
  formatTimestamp, // "2024-02-15T10:30:00Z" → "15/2/2024, 10:30:00"
  formatMs,        // 1500 → "1.50s", 45 → "45ms"
  formatNumber,    // 15000 → "15.0K", 1500000 → "1.5M"
  formatPercent,   // 98.5 → "98.5%"
  defaultTheme,    // Tema claro por defecto
  darkTheme,       // Tema oscuro por defecto
  labelsEs,        // Labels en español
  labelsEn,        // Labels en inglés
} from "@jaquinones45/jaquilogs-sdk";
```

---

## Licencia

MIT - JaquiSoft