Data mapping
The data mapper draws how data in one shape becomes another: a shop's order into your invoice, a CRM export into your customer table, a partner's API into yours. The source and target fields are two trees, from sample data or a JSON Schema, with a line for every mapping. Drag to connect, or pick a field with Space and press Enter on its target.
A field can be copied, worked out with the library's spreadsheet formulas, passed through a lookup table and given a default; a list becomes a list, item by item, with a filter. Auto-map matches by name and synonym; problems are listed as you go; the preview runs the map over sample records. The map is plain JSON, and the same engine runs it in a bundle, a worker or Node.
Shop orders to invoices
An online shop's orders become invoices. The customer's name is worked out with a formula, the country passes through a lookup table, the invoice lines are made from the order's items (skipping any of quantity zero), and the total is a formula over the whole list. Open the Preview tab to see each order's invoice.
Get the code
<script src="/assets/bmx-components.min.js"></script> <bmx-data-mapper id="dm-orders" label="Shop order to invoice" style="inline-size: 100%"></bmx-data-mapper>
A CRM export, auto-mapped
Contacts exported from another system, mapped to your customer table's schema. Nothing is mapped yet:
press Auto-map and the fields that mean the same thing are joined by name and synonym —
mail to email, org to company. The required fields
left over are listed as problems.
Get the code
<script src="/assets/bmx-components.min.js"></script> <bmx-data-mapper id="dm-crm" label="CRM contacts to customers" style="inline-size: 100%"></bmx-data-mapper>
Run it anywhere
People draw the map in the page; your import job or API gateway runs it. The same engine is a module for a worker or Node, with no page needed. Here it runs the first map over ten thousand orders.
// Node 18 or later: the mapper's engine, from the Gold package.
import { checkDataMap, runMapMany } from './dist/node/bmx-data-mapper.mjs';
const map = await db.map('orders-to-invoices'); // the JSON the page saved
const problems = checkDataMap(map).filter(p => p.severity === 'error');
if (problems.length) throw new Error(problems[0].message);
const { output, issues } = runMapMany(map, await shop.ordersSince(lastRun));
await invoices.insertMany(output);
for (const issue of issues) log.warn(`order ${issue.record}: ${issue.path} - ${issue.message}`);