On this page
Guides / Sync your system into collections

Sync your system into collections

Mirror a catalog, an inventory or a price list inside Meteor so your Mets can read it without you writing an endpoint per question.

Updated View .md
StackNode · TypeScript SDK · any cron
Endpointscollections.create · collections.addField · items.iterate · items.create · items.patchField

Your Met answers better when it knows your business. A collection is a workspace table the Met reads and writes on its own: mirror your catalog, your inventory or your price list there, and stop writing an endpoint for every question someone might ask.

This recipe syncs an external system into a collection, nightly, without duplicating anything.

Before you start

Your key needs collections:write, items:read and items:write.

1. Create the collection and its fields

Once. Each field's name is the key the value lives under inside the item and never changes; the label is what shows on screen and you can change it.

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

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

const catalog = await met.collections.create({ name: 'Catalog' });

for (const field of [
  { name: 'sku',    label: 'SKU',    type: 'text',     required: true },
  { name: 'name',   label: 'Name',   type: 'text',     required: true },
  { name: 'price',  label: 'Price',  type: 'currency' },
  { name: 'stock',  label: 'Stock',  type: 'number' },
  { name: 'active', label: 'Active', type: 'boolean' },
] as const) {
  await met.collections.addField(catalog.id, field);
}

The available types are text, number, currency, email, date, datetime, boolean, url, select, prompt, usuario, contact, page, sitio, image and file.

2. Sync without duplicating

The collection won't enforce uniqueness for you. The pattern that works is to pull what's already there, index it by your own business key — the sku here — and decide between create and update.

// What already lives in Meteor, indexed by SKU.
const bySku = new Map<string, number>();
for await (const item of met.items.iterate(catalog.id)) {
  bySku.set(item.data.sku, item.id);
}

for (const product of await pullFromYourSystem()) {
  const existing = bySku.get(product.sku);

  if (!existing) {
    await met.items.create(catalog.id, {
      sku: product.sku,
      name: product.name,
      price: product.price,
      stock: product.stock,
      active: true,
    });
    continue;
  }

  // Only what moves often: one patch per field avoids stomping on
  // whatever someone edited by hand in the dashboard.
  await met.items.patchField(catalog.id, existing, 'price', product.price);
  await met.items.patchField(catalog.id, existing, 'stock', product.stock);
  bySku.delete(product.sku);
}

// Whatever is left in the map is gone from your system.
for (const [, itemId] of bySku) {
  await met.items.patchField(catalog.id, itemId, 'active', false);
}

Notice that what disappeared gets marked active: false instead of deleted. A deleted item takes with it every reference other Mets or tasks made to it; an inactive one can be filtered out and still explains why an old conversation talks about it.

3. Check the Met is seeing it

const found = await met.items.search('blue bike');

search looks across the content of the workspace's items. If your Met says "I don't have that information" and this does find it, the data isn't the problem: the Met doesn't have the collection among its own. You set that per Met — see Mets and their tools.

Running it nightly

met items list --collection 12 --limit 5   # quick check from the terminal

Any cron works. If you already use GitHub Actions, the run Meteor from CI recipe has the workflow ready.

Next