Shared classes / Forms SDK
MintJams Commerce provides server-side shared classes (Groovy) and a Forms SDK (client JS). They collapse repeated logic into one place so each script and each form can focus on its own business logic.
Shared classes (commerce.*)
- Location:
content/WEB-INF/classes/commerce/<Name>.groovy(package commerce) - Import:
import commerce.Money - Call: all static methods (no state). E.g.
Money.format(total) - Rules: classes never use script globals — they take
session/log/configas parameters; the error policy is explicit ("pure" = caller handles, or "defensive" = caught and logged)
Changed classes are picked up on workspace deploy.
Main classes (excerpt)
| Class | Role |
|---|---|
Money |
parse/format money (toNumber / format) |
Jcr |
read/write JSON documents (getOrCreateFile / readMap / toJson) |
SimpleYaml |
dependency-free simple YAML reader (parse) |
Notifications / NotificationMessage / NotificationChannel |
multi-channel notifications (Slack/Discord/Teams/LINE/Webhook/Email); build a channel-agnostic message and dispatch |
ReviewReasons |
order/refund screening "review reason" descriptors (render is for notifications; forms localize via i18n) |
Orders / Refunds |
interpret order / refund payloads |
ShopifyAdmin / ShopifyWrite |
Shopify Admin API (token, GraphQL) and write-back (inventory, price, publish, metafields) |
Pim |
product information overlay (multi-language, rich descriptions, metafields) |
Reconciliation |
CMS↔Shopify drift detection and healing |
Inventory / InventoryRules / SalesVelocity / Replenishment |
inventory thresholds, sales velocity, auto-reorder |
Locations / Allocation |
multi-location inventory and allocation planning |
Backorders / Events / Customers / Checkouts |
backorders, event ingestion, CRM, abandoned carts |
Catalog / Pages |
public projections for the storefront |
Health / Alerts / TaskSla / WorkflowStatus / Reports / Dashboard |
monitoring, alerts, SLA, status writes, reports, aggregations |
Example
import commerce.Jcr
import commerce.Money
def order = Jcr.readMap(repositorySession, "/content/commerce/orders/raw/2026/06/order_123.json")
def total = Money.format(Money.toNumber(order.total_price))
Forms SDK (forms-sdk.js)
A client-side SDK shared by Shopify task forms. It handles form ↔ host (Webtop) communication, i18n, theme/localization, and lifecycle, so a form only writes its own business logic.
Loading & initializing
<script src="./forms-sdk.js?v=1"></script>
const sdk = window.createTasksForm();
- it publishes
window.createTasksFormandwindow.TasksFormSDK - the ICU engine (
intl-messageformat) is dynamically imported inside the SDK and surfaced viatranslate()/formatMessage() - the form iframe runs without
allow-same-origin, so the SDK is loaded with a classic<script>(an ESM import would be blocked by CORS)
Lifecycle & events
sdk.start()/sdk.stop()— start / tear downsdk.on(type, fn)— subscribe to'context'/'localization'/'theme'/'standalone'/'ready'sdk.whenReady()— the ICU engine is ready
sdk.on('context', p => this.handleContext(p))
.on('localization', loc => this.applyLocalization(loc))
.on('ready', () => { this.i18n.revision++; })
.start();
RPC (host operations)
The postMessage details are hidden; you call named methods (excerpt).
- user:
getCurrentUser()/getUser(username) - start mode:
getProcessDefinition()/startProcess({ variables, businessKey }) - task:
getTask()/getTaskWithVariables()/setTaskVariables(...)/completeTask(variables?) - assignment:
claimTask()/unclaimTask()/setAssignee(assignee) - CMS:
getNode(path)/listChildren(path, {first, after})/setNodeProperty(path, name, value)/readNodeText(path) - i18n:
getI18nMessages(prefix?)
i18n & formatting (pure)
translate(messages, locale, id, params, fallback)/formatMessage(template, locale, params)formatNumber(value, localization)/formatMoney(value, localization)/formatDate(value, localization)- node read helpers:
getProp(node, name)/getStringProp(node, name)/readYamlScalar(yamlText, key)
The SDK holds no reactive UI state. Keep
localizationandi18nin the form'sdata()and repaint on'ready'.