# Sincronizar tu sistema con colecciones

Tu Met contesta mejor cuando conoce tu negocio. Una **colección** es una tabla del
workspace que el Met lee y escribe sola: espejas ahí tu catálogo, tu inventario o tu lista
de precios, y dejas de escribir un endpoint por cada pregunta que alguien le pueda hacer.

Esta receta sincroniza un sistema externo hacia una colección, cada noche, sin duplicar
nada.

## Antes de empezar

Tu key necesita `collections:write`, `items:read` e `items:write`.

## 1. Crea la colección y sus campos

Una sola vez. El `name` de cada campo es la **clave** con la que el valor vive dentro del
ítem y no cambia nunca; el `label` es lo que se ve en pantalla y sí puedes cambiarlo.

```ts
import Met from '@meteor.ia/sdk';

const met = new Met(process.env.MET_API_KEY!, {
  workspaceId: Number(process.env.MET_WORKSPACE_ID),
});

const catalogo = await met.collections.create({ name: 'Catálogo' });

for (const campo of [
  { name: 'sku',       label: 'SKU',       type: 'text',     required: true },
  { name: 'nombre',    label: 'Nombre',    type: 'text',     required: true },
  { name: 'precio',    label: 'Precio',    type: 'currency' },
  { name: 'stock',     label: 'Stock',     type: 'number' },
  { name: 'activo',    label: 'Activo',    type: 'boolean' },
] as const) {
  await met.collections.addField(catalogo.id, campo);
}
```

Los tipos disponibles son `text`, `number`, `currency`, `email`, `date`, `datetime`,
`boolean`, `url`, `select`, `prompt`, `usuario`, `contact`, `page`, `sitio`, `image` y
`file`.

## 2. Sincroniza, sin duplicar

La colección no impone unicidad por ti. El patrón que funciona es traerte lo que ya está,
indexarlo por tu propia clave de negocio —aquí el `sku`— y decidir crear o actualizar.

```ts
// Lo que ya vive en Meteor, indexado por SKU.
const porSku = new Map<string, number>();
for await (const item of met.items.iterate(catalogo.id)) {
  porSku.set(item.data.sku, item.id);
}

for (const producto of await traerDeTuSistema()) {
  const existente = porSku.get(producto.sku);

  if (!existente) {
    await met.items.create(catalogo.id, {
      sku: producto.sku,
      nombre: producto.nombre,
      precio: producto.precio,
      stock: producto.stock,
      activo: true,
    });
    continue;
  }

  // Solo lo que se mueve seguido: un patch por campo evita pisar
  // lo que alguien haya editado a mano en el panel.
  await met.items.patchField(catalogo.id, existente, 'precio', producto.precio);
  await met.items.patchField(catalogo.id, existente, 'stock', producto.stock);
  porSku.delete(producto.sku);
}

// Lo que quedó en el mapa ya no está en tu sistema.
for (const [, itemId] of porSku) {
  await met.items.patchField(catalogo.id, itemId, 'activo', false);
}
```

Fíjate que lo que se fue se marca `activo: false` en vez de borrarse. Un ítem borrado se
lleva las referencias que otros Mets o tareas le hayan hecho; uno inactivo se puede filtrar
y sigue explicando por qué una conversación vieja habla de él.

## 3. Comprueba que el Met lo está viendo

```ts
const encontrados = await met.items.search('bicicleta azul');
```

`search` busca sobre el contenido de los ítems del workspace. Si tu Met responde "no
tengo esa información" y aquí sí aparece, el problema no es el dato: es que el Met no tiene
la colección entre las suyas. Eso se ajusta por Met — mira
[Mets y sus herramientas](mets-y-herramientas.html).

## Correrlo cada noche

```bash
met items list --collection 12 --limit 5   # comprobación rápida desde la terminal
```

Cualquier cron sirve. Si ya usas GitHub Actions, la receta de
[ejecutar Meteor desde CI](receta-github-actions.html) tiene el workflow armado.

## Y después

- Vistas, carpetas y el modelo completo: [Datos: colecciones e ítems](colecciones-e-items.html).
- Si lo que quieres espejar son personas y no productos, va en el CRM y no en una
  colección: [CRM y contactos](contactos.html).
