Skip to main content
Every node in a JDM file has a type that determines its behavior and content structure.

Available node types

TypeDescription
inputNodeEntry point for decision input
outputNodeExit point returning the result
decisionTableNodeSpreadsheet-style conditional logic
expressionNodeZEN expression transformations
functionNodeCustom JavaScript logic
switchNodeConditional branching
decisionNodeSub-decision reference

Common node properties

All nodes share these properties:
PropertyTypeDescription
idstringUnique identifier
typestringNode type
namestringDisplay name
positionobjectCanvas position { x, y }
contentobjectType-specific configuration

Input node

The entry point for every decision. Receives the data you pass to evaluate().
{
  "id": "input",
  "type": "inputNode",
  "name": "Request",
  "position": { "x": 0, "y": 100 },
  "content": {
    "schema": ""
  }
}
PropertyTypeDescription
schemastringOptional JSON Schema for input validation

Output node

The exit point that returns the decision result.
{
  "id": "output",
  "type": "outputNode",
  "name": "Response",
  "position": { "x": 600, "y": 100 },
  "content": {
    "schema": ""
  }
}
PropertyTypeDescription
schemastringOptional JSON Schema for output validation

Decision table node

Spreadsheet-style conditional logic with inputs, outputs, and rules.
{
  "type": "decisionTableNode",
  "content": {
    "hitPolicy": "first",
    "inputs": [
      { "id": "i1", "name": "Customer Tier", "field": "customer.tier" },
      { "id": "i2", "name": "Order Total", "field": "order.total" }
    ],
    "outputs": [
      { "id": "o1", "name": "Discount", "field": "discount" }
    ],
    "rules": [
      { "_id": "r1", "i1": "\"gold\"", "i2": ">= 100", "o1": "0.15" },
      { "_id": "r2", "i1": "", "i2": "", "o1": "0" }
    ],
    "passThrough": true,
    "inputField": null,
    "outputPath": null,
    "executionMode": "single"
  }
}

Content properties

PropertyTypeDefaultDescription
hitPolicy"first" | "collect""first"Return first match or all matches
inputsarrayInput column definitions
outputsarrayOutput column definitions
rulesarrayRule rows (keyed by column id)
passThroughbooleantrueInclude input data in output
inputFieldstring | nullnullArray field to iterate (for loop mode)
outputPathstring | nullnullPath to store output
executionMode"single" | "loop""single"Process once or iterate array

Input column

PropertyTypeDescription
idstringUnique identifier (used in rules)
namestringDisplay label
fieldstringPath to input value (enables unary mode)
defaultValuestringDefault if field is null

Output column

PropertyTypeDescription
idstringUnique identifier (used in rules)
namestringDisplay label
fieldstringOutput field name
defaultValuestringDefault if no rule matches

Rules format

Each rule is an object with _id and entries keyed by column id:
{ "_id": "rule-1", "i1": ">= 100", "i2": "\"gold\"", "o1": "0.15" }
Leave a cell empty ("") to match any value.

Expression node

Transform data using ZEN expressions.
{
  "type": "expressionNode",
  "content": {
    "expressions": [
      { "id": "e1", "key": "subtotal", "value": "sum(map(items, #.price * #.qty))" },
      { "id": "e2", "key": "tax", "value": "$.subtotal * 0.08" },
      { "id": "e3", "key": "total", "value": "$.subtotal + $.tax" }
    ],
    "passThrough": true,
    "inputField": null,
    "outputPath": null,
    "executionMode": "single"
  }
}

Content properties

PropertyTypeDefaultDescription
expressionsarrayKey-value expression pairs
passThroughbooleantrueInclude input data in output
inputFieldstring | nullnullArray field to iterate (for loop mode)
outputPathstring | nullnullPath to store output
executionMode"single" | "loop""single"Process once or iterate array

Expression entry

PropertyTypeDescription
idstringUnique identifier
keystringOutput field name
valuestringZEN expression
Use $ to reference values calculated earlier in the same node.

Function node

Custom JavaScript for complex logic.
{
  "type": "functionNode",
  "content": {
    "source": "/** @type {Handler} */\nexport const handler = async (input) => {\n  return { loyaltyPoints: Math.floor(input.total * 1.5) };\n}"
  }
}
PropertyTypeDescription
sourcestringJavaScript function code
Function nodes support:
  • ES6+ JavaScript syntax
  • async/await for asynchronous operations
  • Built-in libraries: dayjs, big.js, zod

Switch node

Route data through different paths based on conditions.
{
  "type": "switchNode",
  "content": {
    "hitPolicy": "first",
    "statements": [
      { "id": "s1", "condition": "customer.tier == 'enterprise'", "isDefault": false },
      { "id": "s2", "condition": "customer.tier == 'business'", "isDefault": false },
      { "id": "s3", "condition": "", "isDefault": true }
    ]
  }
}

Content properties

PropertyTypeDefaultDescription
hitPolicy"first" | "collect""first"Execute first match or all matches
statementsarrayBranch conditions

Statement

PropertyTypeDescription
idstringUnique identifier (used as edge sourceHandle)
conditionstringZEN expression evaluating to boolean
isDefaultbooleanTrue for the fallback branch

Connecting switch outputs

Each statement id becomes a source handle for edges:
{
  "edges": [
    { "id": "e1", "sourceId": "switch-1", "targetId": "enterprise-node", "sourceHandle": "s1", "type": "edge" },
    { "id": "e2", "sourceId": "switch-1", "targetId": "business-node", "sourceHandle": "s2", "type": "edge" },
    { "id": "e3", "sourceId": "switch-1", "targetId": "default-node", "sourceHandle": "s3", "type": "edge" }
  ]
}

Decision node

Reference another decision (sub-decision).
{
  "type": "decisionNode",
  "content": {
    "key": "pricing/calculate-discount",
    "passThrough": true,
    "inputField": null,
    "outputPath": null,
    "executionMode": "single"
  }
}
PropertyTypeDefaultDescription
keystringPath to the referenced decision
passThroughbooleantrueInclude input data in output
inputFieldstring | nullnullArray field to iterate (for loop mode)
outputPathstring | nullnullPath to store output
executionMode"single" | "loop""single"Process once or iterate array

Edge schema

Edges connect nodes in the graph:
{
  "id": "edge-1",
  "sourceId": "node-a",
  "targetId": "node-b",
  "sourceHandle": null,
  "type": "edge"
}
PropertyTypeDescription
idstringUnique identifier
sourceIdstringSource node id
targetIdstringTarget node id
sourceHandlestring | nullOutput handle (for switch nodes)
type"edge"Always “edge”