Matecito.devmatecito.dev
Matecito

Documentación

Introducción

MatecitoDB es un Backend-as-a-Service (BaaS) con autenticación, bases de datos en tiempo real, storage y más. Soporta JavaScript/TypeScript y Flutter/Dart. El SDK soporta API v1 (default) y v2 (recomendada).

npm install matecitodb
Flutter: matecitodb_flutter: ^4.0.0
v1: default · v2: recomendada

API v1 vs v2

El SDK soporta ambas versiones. Por defecto usa v1 para compatibilidad. Activá v2 para Functions, Analytics, AI, Remote Config, Forms, filtros avanzados y fixes de seguridad.

v1: CRUD, Auth, Storage, Realtime, Webhooks
v2: v1 + Functions, Analytics, AI, Config, Forms, Notifications, vector search

Compatible con todos los proyectos existentes.

API v1 (default)typescript
// API v1 (default) — Compatibilidad con proyectos existentes
export const db = createClient<Database>({
  url:        process.env.MATECITODB_URL!,
  apiKey:     process.env.MATECITODB_API_KEY!,
  apiVersion: 'v1',  // default, no hace falta especificarlo
})

Incluye todos los módulos nuevos y security hardening.

API v2 (recomendada)typescript
// API v2 (recomendada) — Features avanzadas + security fixes
export const db = createClient<Database>({
  url:        process.env.MATECITODB_URL!,
  apiKey:     process.env.MATECITODB_API_KEY!,
  apiVersion: 'v2',
})

// Con serviceKey (server-side / admin)
export const dbAdmin = createClient<Database>({
  url:        process.env.MATECITODB_URL!,
  serviceKey: process.env.MATECITODB_SERVICE_KEY!,
  apiVersion: 'v2',
})

Inicialización

Inicializá el cliente con tus variables de entorno. Nunca expongas serviceKey en el cliente.

lib/db.tstypescript
import { createClient } from 'matecitodb'
import type { Database } from '@/matecito/database'

export const db = createClient<Database>({
  url:    process.env.MATECITODB_URL!,
  apiKey: process.env.NEXT_PUBLIC_MATECITODB_API_KEY!,
  // serviceKey: process.env.MATECITODB_SERVICE_KEY!,  // server-side
  // apiVersion: 'v2',  // descomentá para v2
})

Auth — Básico

Registro, login, logout y perfil del usuario actual.

Auth básicotypescript
// Registro
const { user } = await db.auth.signUp({
  email:    'user@example.com',
  password: 'secure-password',
  name:     'Juan Pérez',
})

// Login
const { token, user } = await db.auth.signIn({
  email:    'user@example.com',
  password: 'secure-password',
})

// Logout
await db.auth.signOut()

// Usuario actual
const me = await db.auth.getMe()

Auth — Sesión

Gestión de tokens, refresh y listener de cambios de sesión.

Session & onAuthChangetypescript
// Persistir sesión manualmente
await db.auth.setSession(token)

// Refresh de token expirado
const { token: newToken } = await db.auth.refreshSession()

// Escuchar cambios de sesión
const unsub = db.auth.onAuthChange((event, session) => {
  // event: 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED'
  if (event === 'SIGNED_IN') console.log('User:', session?.user)
  if (event === 'SIGNED_OUT') router.push('/login')
})
// unsub() para dejar de escuchar

Auth — Contraseña

Reset & verificacióntypescript
// Solicitar reset de contraseña
await db.auth.requestPasswordReset('user@example.com')

// Confirmar reset (con token del email)
await db.auth.resetPassword({ token: 'reset-token', newPassword: 'new-pass' })

// Verificar email
await db.auth.verifyEmail(token)
await db.auth.resendVerification('user@example.com')

// Actualizar perfil
await db.auth.updateProfile({ name: 'New Name', avatar_url: 'https://...' })

Auth — OAuth (v2)

Login con Google, GitHub, Discord y Apple. Solo disponible en proyectos v2.

OAuth flowtypescript
// Obtener URL OAuth (v2)
const { url } = await db.auth.getOAuthUrl('google')
window.location.href = url

// Manejar callback en /auth/callback
const { token, user } = await db.auth.handleOAuthCallback(window.location.href)

Auth — TOTP / 2FA (v2)

Autenticación de dos factores con Google Authenticator, Authy o cualquier app TOTP.

TOTP setup & verifytypescript
// TOTP / 2FA (v2 only)
// 1. Setup — devuelve secret + QR URL
const { secret, qr_url } = await db.auth.totpSetup()

// 2. Confirmar con código del authenticator
await db.auth.totpConfirm({ code: '123456' })

// 3. Verificar en cada login
await db.auth.totpVerify({ code: '123456' })

// 4. Desactivar 2FA
await db.auth.totpDisable({ password: 'current-password' })

Auth — Admin & Roles

Gestión de usuarios y roles desde el servidor. Requiere serviceKey.

Admin APItypescript
// Auth Admin (serviceKey requerida)
// Listar usuarios
const { users } = await db.auth.admin.listUsers({ page: 1, limit: 50 })

// Crear usuario como admin
const { user } = await db.auth.admin.createUser({
  email: 'user@example.com', password: 'pass', name: 'Juan',
})

// Banear / desbanear
await db.auth.admin.banUser(userId)
await db.auth.admin.unbanUser(userId)

// Eliminar usuario
await db.auth.admin.deleteUser(userId)

// Roles
await db.auth.roles.assign(userId, 'moderator')
await db.auth.roles.revoke(userId, 'moderator')
Invitacionestypescript
// Invitaciones
const { link } = await db.auth.invitations.create({
  email: 'nuevo@example.com',
  role:  'editor',
  expiresInHours: 48,
})

// Listar invitaciones pendientes
const { invitations } = await db.auth.invitations.list()

// Revocar
await db.auth.invitations.revoke(invitationId)

QueryBuilder — Filtros

API fluida y tipada para consultar datos. Todos los métodos son encadenables.

Filtros básicostypescript
// QueryBuilder — API fluida y tipada
const posts = await db
  .from('posts')
  .eq('status', 'published')
  .order('created_at', 'desc')
  .limit(20)
  .get()

// Múltiples filtros
const results = await db
  .from('products')
  .gte('price', 100)
  .lte('price', 500)
  .like('name', '%laptop%')
  .in('category', ['tech', 'gaming'])
  .notIn('status', ['draft', 'archived'])
  .limit(10)
  .get()

// Búsqueda por campo nullable
const noPhone = await db.from('users').isNull('phone').get()

// Contiene en array (v2)
const tagged = await db.from('posts').has('tags', 'javascript').get()

QueryBuilder — Avanzado

Full-text search, vector search, OR conditions, relaciones y más.

Filtros avanzadostypescript
// Full-text search (v2)
const articles = await db
  .from('articles')
  .search('base de datos')
  .order('relevance', 'desc')
  .get()

// Vector / semántico (v2)
const similar = await db
  .from('documents')
  .searchFullText('machine learning')
  .limit(5)
  .get()

// Between
const recent = await db
  .from('orders')
  .between('created_at', '2024-01-01', '2024-12-31')
  .get()

// OR conditions
const active = await db
  .from('users')
  .or([{ field: 'status', op: 'eq', value: 'active' }, { field: 'role', op: 'eq', value: 'admin' }])
  .get()

// Relaciones (populate)
const withAuthor = await db
  .from('posts')
  .populate('author_id', 'users')
  .limit(10)
  .get()

// Soft-deleted + expirados
const all = await db.from('items').includeDeleted().includeExpired().get()

QueryBuilder — Mutaciones

Insert, upsert, update, merge, delete, hard delete y restore.

CRUD con QueryBuildertypescript
// Crear
const post = await db.from('posts').insert({ title: 'Hola', status: 'draft' })

// Crear múltiples
const posts = await db.from('posts').insertMany([
  { title: 'Post 1' }, { title: 'Post 2' },
])

// Upsert (insert o update por clave única)
await db.from('users').upsert({ email: 'j@ex.com', name: 'Juan' }, 'email')

// Actualizar filtrado
await db.from('posts').eq('status', 'draft').update({ status: 'published' })

// Merge (actualización parcial con ID)
await db.from('products').merge(productId, { price: 299 })

// Soft delete
await db.from('posts').eq('id', postId).delete()

// Hard delete (permanente)
await db.from('posts').eq('id', postId).hardDelete()

// Restaurar soft-deleted
await db.from('posts').eq('id', postId).restore()

QueryBuilder — Paginación

paginate(), findOne(), count(), select() y export().

Paginación & utilidadestypescript
// Paginación fluida
const page = await db
  .from('products')
  .eq('category', 'tech')
  .order('price', 'asc')
  .paginate(1, 20) // página 1, 20 por página

// Devuelve:
// { data: [...], total: 150, page: 1, limit: 20, pages: 8 }

// findOne
const user = await db.from('users').eq('email', 'j@ex.com').findOne()

// count
const total = await db.from('posts').eq('status', 'published').count()

// Seleccionar campos
const names = await db
  .from('users')
  .select(['id', 'name', 'email'])
  .limit(100)
  .get()

// Exportar (v2)
const csv = await db.from('orders').export('csv')
const json = await db.from('orders').export('json')

QueryBuilder — Realtime

subscribe() y watch() directamente desde el QueryBuilder.

Realtime desde QBtypescript
// Realtime desde QueryBuilder
const unsubscribe = await db
  .from('messages')
  .eq('room_id', 'room-123')
  .subscribe((event) => {
    // event.action: 'create' | 'update' | 'delete'
    console.log('Nuevo evento:', event.action, event.record)
  })

// watch — escucha todos los eventos de una colección
const stop = db.from('notifications').watch((event) => {
  if (event.action === 'create') showToast(event.record.message)
})

unsubscribe() // o stop()

Records (API clásica)

API imperativa con db.records.*. Compatible con v1 y v2.

db.records.*typescript
// API clásica (db.records)
const record = await db.records.create('users', {
  name: 'Juan', email: 'juan@example.com',
})

const { records, pagination } = await db.records.list('users', {
  page: 1, limit: 50, sort: '-created_at',
})

await db.records.update(record.id, { name: 'Juan Updated' })
await db.records.delete(record.id)
await db.records.hardDelete(record.id)

Realtime

Suscripción a eventos en tiempo real. v1 usa /ws, v2 usa /realtime (con presence).

db.realtime.subscribe()typescript
// Suscripción básica
const unsubscribe = db.realtime.subscribe('users', (event) => {
  console.log('Acción:', event.action) // create | update | delete
  console.log('Registro:', event.record)
})

// Con filtro
db.realtime.subscribe('posts', (event) => {
  setFeed(prev => [event.record, ...prev])
}, { status: 'published' })

unsubscribe()

Almacenamiento

Storagetypescript
// Subir archivo
const file = await db.storage.upload('avatar.png', fileData, {
  collection: 'users',
  recordId:   'user-id-123',
  public:     true,
})

// Obtener URL pública
const url = db.storage.getUrl(file.path)

// Listar archivos
const { files } = await db.storage.list({ collection: 'users', recordId: 'user-id-123' })

// Eliminar
await db.storage.delete(file.id)

Email (SMTP)

SMTPtypescript
// Configurar SMTP
await db.emails.saveSmtp({
  host:     'smtp.gmail.com',
  port:     587,
  username: 'noreply@myapp.com',
  password: 'app-password',
  secure:   false,
})

// Enviar
await db.emails.send({
  to:      ['user@example.com'],
  subject: 'Bienvenido a mi app',
  html:    '<h1>¡Hola!</h1><p>Gracias por registrarte.</p>',
})

Functions (v2)

Ejecutar y gestionar serverless functions. Requiere proyecto v2.

db.functions.*typescript
// Invocar una function (v2)
const { result, duration_ms } = await db.functions.invoke('send-welcome', {
  args: { email: 'user@example.com', name: 'Juan' },
})

// Crear function
await db.functions.create({
  name:       'process-order',
  code:       `const { args, db } = context; return { ok: true }`,
  timeout_ms: 5000,
  is_public:  false,
})

// Listar
const { functions } = await db.functions.list()

// Historial de ejecuciones
const { executions } = await db.functions.history('send-welcome')

Analytics (v2)

Eventos, funnels y métricas de uso. Requiere proyecto v2.

db.analytics.*typescript
// Trackear evento (v2)
await db.analytics.track('page_view', {
  user_id:    currentUser.id,
  properties: { page: '/pricing', source: 'google' },
})

// Obtener eventos agrupados
const { results } = await db.analytics.events({
  group_by: 'event',
  days:     30,
})

// Funnel de conversión
const { funnel } = await db.analytics.funnel({
  steps: ['page_view', 'signup', 'checkout', 'purchase'],
})

AI Gateway (v2)

Integrá OpenAI, Anthropic o Groq sin exponer API keys al cliente.

db.ai.*typescript
// Configurar AI (v2)
await db.ai.setConfig({
  provider: 'openai', // 'anthropic' | 'groq'
  model:    'gpt-4o-mini',
  api_key:  'sk-...',
})

// Chat completion
const { content } = await db.ai.chat([
  { role: 'user', content: '¿Cómo implemento auth con matecitodb?' },
])

// Con system prompt
const { content } = await db.ai.chat(messages, {
  system:     'Sos un asistente técnico de MatecitoDB.',
  max_tokens: 500,
})

Remote Config (v2)

Feature flags y configuración remota en tiempo real.

db.config.*typescript
// Remote Config (v2)
// Obtener todos los valores
const { configs } = await db.config.getAll()

// Obtener uno
const mode = await db.config.get('maintenance_mode')

// Crear / actualizar
await db.config.set('maintenance_mode', false, {
  description: 'Desactiva el acceso público',
})

// Eliminar
await db.config.delete('old_flag')

Notificaciones (v2)

Push notifications a dispositivos iOS, Android y Web.

db.notifications.*typescript
// Notificaciones push (v2)
// Registrar dispositivo
await db.notifications.registerDevice({
  token:    fcmToken,
  platform: 'android', // 'ios' | 'web'
})

// Enviar notificación
await db.notifications.send({
  user_ids: [userId],
  title:    '¡Nueva actualización!',
  body:     'Revisá las novedades de la app.',
  data:     { screen: 'updates' },
})

// Enviar a todos
await db.notifications.broadcast({
  title: 'Mantenimiento programado',
  body:  'El servicio estará caído el sábado 02:00-04:00 AM.',
})