Templates & versions
There are three layers. They sound redundant at first; each does a specific job.
Mapping template
A template is a named recipe scoped to one source platform and one resource type. For example, Magento → Products v1 is a template. Every tenant sees the same default templates as read-only seeds.
Templates ship with sensible defaults for every resource Graftport knows how to move. You don’t create templates from scratch — you fork existing ones.
Mapping version
A version is an immutable snapshot of the JSONata text. Every save creates a new version. Past versions stick around so you can always trace exactly which version produced a given Shopify record.
A template has a current version that new migrations pin to by default. Changing the current version doesn’t retroactively re-pin existing migrations — they keep their pinned version unless you bump them explicitly.
Mapping
A mapping is the link between a (migration, resource) pair and a
specific template version. There’s exactly one per pair.
The mapping carries:
- The pinned version — the source of truth for what this resource produces.
- A pointer back to the template it came from.
- Whether the mapping uses a default template or a tenant-owned fork.
Why this many layers
Three concerns are kept clean:
| Concern | Layer that owns it |
|---|---|
| ”What’s the canonical mapping for Magento products?” | Template + its current version. |
| ”What did this specific run produce?” | The mapping version it was pinned to at run time. |
| ”Which version is this migration on?” | Mapping. |
That separation lets you upgrade one merchant’s mapping without touching the others, and lets you audit a year-old run by looking at its pinned version directly.