> ## Documentation Index
> Fetch the complete documentation index at: https://docs.insforge.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Referencia de SDK de Base de Datos

> Operaciones de base de datos seguras en tipos con el SDK de TypeScript para InsForge

## Instalación

<CodeGroup>
  ```bash npm theme={null}
  npm install @insforge/sdk@latest
  ```

  ```bash yarn theme={null}
  yarn add @insforge/sdk@latest
  ```

  ```bash pnpm theme={null}
  pnpm add @insforge/sdk@latest
  ```
</CodeGroup>

```javascript theme={null}
import { createClient } from '@insforge/sdk';

const insforge = createClient({
  baseUrl: 'https://your-app.insforge.app',
  anonKey: 'your-anon-key'  // Optional: for public/unauthenticated requests
});
```

Find the anon key with `npx @insforge/cli secrets get ANON_KEY`, or in the dashboard: click **Install** and open **API Keys**.

## insert()

Inserta nuevos registros en una tabla.

### Parámetros

* `values` (object | Array, required) - Datos a insertar. Un único objeto o matriz para inserción masiva
* `options.count` ('exact' | 'planned' | 'estimated', optional) - Incluye conteo de filas insertadas

### Devoluciones

```typescript theme={null}
{
  data: Array<object> | null,
  error: Error | null,
  count?: number
}
```

<Note>
  Encadena `.select()` después de `.insert()` para devolver los datos insertados
</Note>

### Ejemplos

<CodeGroup>
  ```javascript Single insert theme={null}
  const { data, error } = await insforge.database
    .from('posts')
    .insert({ title: 'Hello World', content: 'My first post!' })
    .select()
  ```

  ```javascript Bulk insert theme={null}
  const { data, error } = await insforge.database
    .from('posts')
    .insert([
      { title: 'First Post', content: 'Hello everyone!' },
      { title: 'Second Post', content: 'Another update.' }
    ])
    .select()
  ```
</CodeGroup>

### Salida de Ejemplo

```json theme={null}
{
  "data": [
    { "id": "789", "title": "Hello World", "content": "My first post!", "created_at": "2024-01-15T10:30:00Z" }
  ],
  "error": null
}
```

***

## update()

Actualiza registros existentes en una tabla. Debe usar filtros para apuntar a filas específicas.

### Parámetros

* `values` (object, required) - Campos a actualizar
* `options.count` ('exact' | 'planned' | 'estimated', optional) - Incluye conteo de filas actualizadas

### Devoluciones

```typescript theme={null}
{
  data: Array<object> | null,
  error: Error | null,
  count?: number
}
```

<Warning>
  Siempre usa filtros como `.eq()` o `.in()` para especificar qué filas actualizar
</Warning>

### Ejemplos

<CodeGroup>
  ```javascript Update by ID theme={null}
  const { data, error } = await insforge.database
    .from('posts')
    .update({ title: 'Updated Title' })
    .eq('id', postId)
    .select()
  ```

  ```javascript Update multiple theme={null}
  const { data, error } = await insforge.database
    .from('tasks')
    .update({ status: 'completed' })
    .in('id', ['task-1', 'task-2'])
    .select()
  ```
</CodeGroup>

### Salida de Ejemplo

```json theme={null}
{
  "data": [
    { "id": "123", "title": "Updated Title", "content": "My first post!", "updated_at": "2024-01-15T11:00:00Z" }
  ],
  "error": null
}
```

***

## delete()

Elimina registros de una tabla. Debe usar filtros para apuntar a filas específicas.

### Parámetros

* `options.count` ('exact' | 'planned' | 'estimated', optional) - Incluye conteo de filas eliminadas

### Devoluciones

```typescript theme={null}
{
  data: Array<object> | null,
  error: Error | null,
  count?: number
}
```

<Warning>
  Siempre usa filtros para especificar qué filas eliminar
</Warning>

### Ejemplos

<CodeGroup>
  ```javascript Delete by ID theme={null}
  const { error } = await insforge.database
    .from('posts')
    .delete()
    .eq('id', postId)
  ```

  ```javascript Delete with filter theme={null}
  const { error } = await insforge.database
    .from('sessions')
    .delete()
    .lt('expires_at', new Date())
  ```
</CodeGroup>

### Salida de Ejemplo

```json theme={null}
{
  "data": null,
  "error": null
}
```

***

## select()

Consulta registros de una tabla o vista.

### Parámetros

* `columns` (string, optional) - Nombres de columnas separados por comas. Usa `*` para todas las columnas
* `options.count` ('exact' | 'planned' | 'estimated', optional) - Incluye conteo de fila total
* `options.head` (boolean, optional) - Devuelve solo el conteo, sin datos

### Devoluciones

```typescript theme={null}
{
  data: Array<object> | null,
  error: Error | null,
  count?: number
}
```

### Ejemplos

<CodeGroup>
  ```javascript Get all theme={null}
  const { data, error } = await insforge.database
    .from('posts')
    .select()
  ```

  ```javascript Specific columns theme={null}
  const { data, error } = await insforge.database
    .from('posts')
    .select('id, title, content')
  ```

  ```javascript With relationships theme={null}
  const { data, error } = await insforge.database
    .from('posts')
    .select('*, comments(id, content)')
  ```
</CodeGroup>

### Salida de Ejemplo

```json theme={null}
{
  "data": [
    { "id": "123", "title": "Hello World", "content": "My first post!" },
    { "id": "456", "title": "Second Post", "content": "Another update." }
  ],
  "error": null
}
```

***

## rpc()

Llama a funciones almacenadas de PostgreSQL (RPC - Llamada de Procedimiento Remoto).

### Parámetros

* `functionName` (string, required) - Nombre de la función PostgreSQL a llamar
* `args` (object, optional) - Argumentos a pasar a la función

### Devoluciones

```typescript theme={null}
{
  data: T | T[] | null,
  error: Error | null
}
```

### Ejemplos

<CodeGroup>
  ```javascript With parameters theme={null}
  const { data, error } = await insforge.database
    .rpc('get_user_stats', { user_id: '123' })
  ```

  ```javascript Without parameters theme={null}
  const { data, error } = await insforge.database
    .rpc('get_all_active_users')
  ```
</CodeGroup>

***

## Filtros

Encadena filtros para reducir los resultados de la consulta. Todos los filtros toman `(column, value)` como parámetros.

| Filtro                    | Descripción                                                        | Ejemplo                                |
| ------------------------- | ------------------------------------------------------------------ | -------------------------------------- |
| `.eq(column, value)`      | Igual a                                                            | `.eq('status', 'active')`              |
| `.neq(column, value)`     | No igual a                                                         | `.neq('status', 'banned')`             |
| `.gt(column, value)`      | Mayor que                                                          | `.gt('age', 18)`                       |
| `.gte(column, value)`     | Mayor o igual que                                                  | `.gte('price', 100)`                   |
| `.lt(column, value)`      | Menor que                                                          | `.lt('stock', 10)`                     |
| `.lte(column, value)`     | Menor o igual que                                                  | `.lte('priority', 3)`                  |
| `.like(column, pattern)`  | Patrón que distingue mayúsculas de minúsculas (usa `%` comodín)    | `.like('name', '%Widget%')`            |
| `.ilike(column, pattern)` | Patrón que no distingue mayúsculas de minúsculas (usa `%` comodín) | `.ilike('email', '%@gmail.com')`       |
| `.in(column, array)`      | Valor en matriz                                                    | `.in('status', ['pending', 'active'])` |
| `.is(column, value)`      | Exactamente igual (para comprobaciones nulas)                      | `.is('deleted_at', null)`              |

```javascript theme={null}
// Example: Chain multiple filters
const { data } = await insforge.database
  .from('products')
  .select()
  .eq('category', 'electronics')
  .gte('price', 50)
  .lte('price', 500)
  .is('in_stock', true)
```

***

## Modificadores

Controla cómo se devuelven los resultados de la consulta.

| Modificador               | Descripción                                                                          | Ejemplo                                      |
| ------------------------- | ------------------------------------------------------------------------------------ | -------------------------------------------- |
| `.order(column, options)` | Ordena los resultados. Opciones: `{ ascending: true/false, nullsFirst: true/false }` | `.order('created_at', { ascending: false })` |
| `.limit(count)`           | Limita el número de filas                                                            | `.limit(10)`                                 |
| `.range(from, to)`        | Obtén filas entre índices (paginación)                                               | `.range(0, 9)`                               |
| `.single()`               | Devuelve objeto en lugar de matriz (lanza si hay múltiples)                          | `.single()`                                  |
| `.maybeSingle()`          | Devuelve objeto o null (sin error)                                                   | `.maybeSingle()`                             |

```javascript theme={null}
// Example: Pagination with sorting
const { data } = await insforge.database
  .from('posts')
  .select()
  .order('created_at', { ascending: false })
  .range(0, 9)
```

***

## Patrones Comunes

### Paginación con Conteo

```javascript theme={null}
const page = 1;
const pageSize = 10;
const from = (page - 1) * pageSize;
const to = from + pageSize - 1;

const { data, count } = await insforge.database
  .from('posts')
  .select('*', { count: 'exact' })
  .range(from, to)
  .order('created_at', { ascending: false })

console.log(`Page ${page}: ${data.length} of ${count} total`)
```

**Salida:**

```json theme={null}
{
  "data": [
    { "id": "1", "title": "Post 1", "created_at": "2024-01-15T10:00:00Z" },
    { "id": "2", "title": "Post 2", "created_at": "2024-01-14T10:00:00Z" }
  ],
  "count": 50,
  "error": null
}
```

### Búsqueda Filtrada

```javascript theme={null}
const { data } = await insforge.database
  .from('products')
  .select('id, name, price, category')
  .eq('category', 'electronics')
  .gte('price', 50)
  .lte('price', 500)
  .order('price', { ascending: true })
  .limit(20)
```

**Salida:**

```json theme={null}
{
  "data": [
    { "id": "101", "name": "USB Cable", "price": 59.99, "category": "electronics" },
    { "id": "102", "name": "Keyboard", "price": 89.99, "category": "electronics" }
  ],
  "error": null
}
```

### Usar con Ganchos de Autenticación

Combina consultas de base de datos con ganchos `useUser()` o `useAuth()` para obtener datos específicos del usuario:

```tsx theme={null}
import { useUser } from '@insforge/react'; // or '@insforge/react-router'
import { insforge } from './lib/insforge';
import { useEffect, useState } from 'react';

function MyProfile() {
  const { user, isLoaded } = useUser();
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    if (user) {
      // Fetch user's posts from database
      insforge.database
        .from('posts')
        .select('*')
        .eq('user_id', user.id)
        .then(({ data }) => setPosts(data));
    }
  }, [user]);

  if (!isLoaded) return <div>Loading...</div>;
  if (!user) return <div>Not signed in</div>;

  return (
    <div>
      <h1>{user.profile?.name}</h1>
      <p>{user.email}</p>
      <h2>My Posts: {posts.length}</h2>
      {posts.map(post => (
        <div key={post.id}>{post.title}</div>
      ))}
    </div>
  );
}
```

**Puntos clave:**

* Usa `user.id` para filtrar datos del usuario autenticado
* Comprueba `isLoaded` antes de acceder a `user` para evitar condiciones de carrera
* Comprueba `!user` para manejar el estado no autenticado
