> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gorules.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Node types

> Reference for all JDM node types and their content schemas.

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

## Available node types

| Type                | Description                         |
| ------------------- | ----------------------------------- |
| `inputNode`         | Entry point for decision input      |
| `outputNode`        | Exit point returning the result     |
| `decisionTableNode` | Spreadsheet-style conditional logic |
| `expressionNode`    | ZEN expression transformations      |
| `functionNode`      | Custom JavaScript logic             |
| `switchNode`        | Conditional branching               |
| `decisionNode`      | Sub-decision reference              |

## Common node properties

All nodes share these properties:

| Property   | Type   | Description                 |
| ---------- | ------ | --------------------------- |
| `id`       | string | Unique identifier           |
| `type`     | string | Node type                   |
| `name`     | string | Display name                |
| `position` | object | Canvas position `{ x, y }`  |
| `content`  | object | Type-specific configuration |

## Input node

The entry point for every decision. Receives the data you pass to `evaluate()`.

```json theme={null}
{
  "id": "input",
  "type": "inputNode",
  "name": "Request",
  "position": { "x": 0, "y": 100 },
  "content": {
    "schema": ""
  }
}
```

| Property | Type   | Description                               |
| -------- | ------ | ----------------------------------------- |
| `schema` | string | Optional JSON Schema for input validation |

## Output node

The exit point that returns the decision result.

```json theme={null}
{
  "id": "output",
  "type": "outputNode",
  "name": "Response",
  "position": { "x": 600, "y": 100 },
  "content": {
    "schema": ""
  }
}
```

| Property | Type   | Description                                |
| -------- | ------ | ------------------------------------------ |
| `schema` | string | Optional JSON Schema for output validation |

## Decision table node

Spreadsheet-style conditional logic with inputs, outputs, and rules.

```json theme={null}
{
  "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

| Property        | Type                     | Default    | Description                            |
| --------------- | ------------------------ | ---------- | -------------------------------------- |
| `hitPolicy`     | `"first"` \| `"collect"` | `"first"`  | Return first match or all matches      |
| `inputs`        | array                    |            | Input column definitions               |
| `outputs`       | array                    |            | Output column definitions              |
| `rules`         | array                    |            | Rule rows (keyed by column id)         |
| `passThrough`   | boolean                  | `true`     | Include input data in output           |
| `inputField`    | string \| null           | `null`     | Array field to iterate (for loop mode) |
| `outputPath`    | string \| null           | `null`     | Path to store output                   |
| `executionMode` | `"single"` \| `"loop"`   | `"single"` | Process once or iterate array          |

### Input column

| Property       | Type   | Description                              |
| -------------- | ------ | ---------------------------------------- |
| `id`           | string | Unique identifier (used in rules)        |
| `name`         | string | Display label                            |
| `field`        | string | Path to input value (enables unary mode) |
| `defaultValue` | string | Default if field is null                 |

### Output column

| Property       | Type   | Description                       |
| -------------- | ------ | --------------------------------- |
| `id`           | string | Unique identifier (used in rules) |
| `name`         | string | Display label                     |
| `field`        | string | Output field name                 |
| `defaultValue` | string | Default if no rule matches        |

### Rules format

Each rule is an object with `_id` and entries keyed by column id:

```json theme={null}
{ "_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.

```json theme={null}
{
  "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

| Property        | Type                   | Default    | Description                            |
| --------------- | ---------------------- | ---------- | -------------------------------------- |
| `expressions`   | array                  |            | Key-value expression pairs             |
| `passThrough`   | boolean                | `true`     | Include input data in output           |
| `inputField`    | string \| null         | `null`     | Array field to iterate (for loop mode) |
| `outputPath`    | string \| null         | `null`     | Path to store output                   |
| `executionMode` | `"single"` \| `"loop"` | `"single"` | Process once or iterate array          |

### Expression entry

| Property | Type   | Description       |
| -------- | ------ | ----------------- |
| `id`     | string | Unique identifier |
| `key`    | string | Output field name |
| `value`  | string | ZEN expression    |

Use `$` to reference values calculated earlier in the same node.

## Function node

Custom JavaScript for complex logic.

```json theme={null}
{
  "type": "functionNode",
  "content": {
    "source": "/** @type {Handler} */\nexport const handler = async (input) => {\n  return { loyaltyPoints: Math.floor(input.total * 1.5) };\n}"
  }
}
```

| Property | Type   | Description              |
| -------- | ------ | ------------------------ |
| `source` | string | JavaScript 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.

```json theme={null}
{
  "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

| Property     | Type                     | Default   | Description                        |
| ------------ | ------------------------ | --------- | ---------------------------------- |
| `hitPolicy`  | `"first"` \| `"collect"` | `"first"` | Execute first match or all matches |
| `statements` | array                    |           | Branch conditions                  |

### Statement

| Property    | Type    | Description                                   |
| ----------- | ------- | --------------------------------------------- |
| `id`        | string  | Unique identifier (used as edge sourceHandle) |
| `condition` | string  | ZEN expression evaluating to boolean          |
| `isDefault` | boolean | True for the fallback branch                  |

### Connecting switch outputs

Each statement id becomes a source handle for edges:

```json theme={null}
{
  "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).

```json theme={null}
{
  "type": "decisionNode",
  "content": {
    "key": "pricing/calculate-discount",
    "passThrough": true,
    "inputField": null,
    "outputPath": null,
    "executionMode": "single"
  }
}
```

| Property        | Type                   | Default    | Description                            |
| --------------- | ---------------------- | ---------- | -------------------------------------- |
| `key`           | string                 |            | Path to the referenced decision        |
| `passThrough`   | boolean                | `true`     | Include input data in output           |
| `inputField`    | string \| null         | `null`     | Array field to iterate (for loop mode) |
| `outputPath`    | string \| null         | `null`     | Path to store output                   |
| `executionMode` | `"single"` \| `"loop"` | `"single"` | Process once or iterate array          |

## Edge schema

Edges connect nodes in the graph:

```json theme={null}
{
  "id": "edge-1",
  "sourceId": "node-a",
  "targetId": "node-b",
  "sourceHandle": null,
  "type": "edge"
}
```

| Property       | Type           | Description                      |
| -------------- | -------------- | -------------------------------- |
| `id`           | string         | Unique identifier                |
| `sourceId`     | string         | Source node id                   |
| `targetId`     | string         | Target node id                   |
| `sourceHandle` | string \| null | Output handle (for switch nodes) |
| `type`         | `"edge"`       | Always "edge"                    |
