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

# Transform

> MAPPER, VALIDATE and CONTENT-FILTER: plugins that reshape, check and trim payloads.

These three processors are always part of the server, except that the `SCRIPT` mode of `MAPPER` needs the optional `script-js` module (see [Built-in plugins](/plugins/overview)).

Options marked "expression" take the expression language described in [Variables and expressions](/building/variables-and-expressions). Inside an expression the message is the root, so `payload.price` reads a payload field. These plugins do not resolve `${...}` variables in their options. Unless a section says otherwise, the default timeout is the engine default of 30 seconds idle.

## MAPPER

Rebuilds the payload of each message. It has three modes.

| Option | Type | Default | Meaning |
| - | - | - | - |
| `mode` | `PROJECTION`, `TEMPLATE` or `SCRIPT` | none, required | How the mapping is applied |
| `mapping` | map or string | none, required | See the table below |
| `dropOriginal` | boolean | `true` | `true` keeps only what the mapping builds. `false` keeps the original payload and adds or overwrites the mapped fields |
| `strictMode` | boolean | `true` | Fail the message when evaluation fails. When `false`, the failure is logged and processing goes on |

Output port: `default`. The message keeps its id and metadata; only the payload changes.

| Mode | `mapping` is | Result |
| - | - | - |
| `PROJECTION` | A map of target field to expression. A dot in the target nests the value: `user.id` builds `{"user": {"id": ...}}` | An object with the mapped fields |
| `TEMPLATE` | A map of target field to a template, or one template string | With a map, an object whose values are the rendered text. With a string, the payload becomes the rendered text |
| `SCRIPT` | A JavaScript string | The value of the script's last expression |

A template uses double-brace placeholders such as `hi {{payload.name}}`. A payload that is not an object is wrapped as `{"value": <payload>}` when `dropOriginal` is `false` in `PROJECTION` mode.

With `strictMode` off, a projection field whose expression gives null is left out, and a failing script gives an empty payload (or the original payload when `dropOriginal` is `false`). With `strictMode` on, a null result is written as null and any evaluation error fails the message.

### SCRIPT mode

A script sees three values: `message`, `payload` and `metadata`. Its result is the value of its last expression, converted to plain objects, lists and scalars. An object literal needs parentheses:

```text theme={"system"}
({ total: payload.items.length, label: 'order-' + payload.id })
```

Scripts are limited:

| Limit | Value |
| - | - |
| Run time | 10 seconds, then the script is cancelled |
| Statements | 50 million, then the script is stopped |
| Types a script can load | A short list of value types, such as `Math`, `String`, `UUID`, `Base64`, lists, maps and the date-time types. Anything else is refused |
| Memory | not limited |

The run-time and statement limits are server start-up settings, `yukta.script.timeout-ms` (10000) and `yukta.script.max-statements` (50000000).

A `SCRIPT` node is rejected at validation when the `script-js` module is not in the build. Prefer `PROJECTION` for simple reshaping: it is faster and cannot reach anything outside the message.

```json theme={"system"}
{
  "nodeId": "shape",
  "type": "MAPPER",
  "config": {
    "mode": "PROJECTION",
    "mapping": { "userId": "payload.id", "label": "'user:' + payload.name" }
  }
}
```

With the payload `{"id": 1, "name": "Ada", "active": true}` this node emits `{"userId": 1, "label": "user:Ada"}`.

This node writes a text payload from a template:

```json theme={"system"}
{
  "nodeId": "message-text",
  "type": "MAPPER",
  "config": { "mode": "TEMPLATE", "mapping": "Build {{payload.build}} finished: {{payload.status}}" }
}
```

## VALIDATE

Checks required fields and field types on the payload and routes bad messages to the `invalid` port, so bad input can be set aside instead of failing a later node.

| Option | Type | Default | Meaning |
| - | - | - | - |
| `required` | list | none | Field names that must be present and not null |
| `types` | map | none | Field name to one of `string`, `number`, `boolean`, `object` or `array` |

At least one of `required` and `types` must be set. A field listed in `types` that is absent or null passes the type check; list it in `required` as well to insist on it.

Output ports: `default` for valid messages and `invalid` for the rest. An invalid message carries every reason found, such as `missing field: email; field qty is not number`, as its failure reason. A payload that is not an object is invalid with the reason `payload is not an object`.

```json theme={"system"}
{
  "nodeId": "check-order",
  "type": "VALIDATE",
  "config": {
    "required": ["orderId", "email"],
    "types": { "orderId": "string", "qty": "number", "items": "array" }
  }
}
```

```json theme={"system"}
[
  { "source": "check-order", "target": "process-order" },
  { "source": "check-order", "target": "quarantine", "sourcePort": "invalid" }
]
```

## CONTENT-FILTER

Keeps or removes parts of a message. Use it to strip sensitive or unimportant fields before logging or sending a payload on. The type string is written with a hyphen.

| Option | Type | Default | Meaning |
| - | - | - | - |
| `mode` | `INCLUDE` or `EXCLUDE` | `INCLUDE` | `INCLUDE` keeps only the listed paths. `EXCLUDE` removes the listed paths |
| `paths` | list | none, required | The paths. See below |
| `flatten` | boolean | `false` | Turn nested objects in the result payload into one level with dotted keys, so `{"a": {"b": 1}}` becomes `{"a.b": 1}` |
| `strictMode` | boolean | `true` | `INCLUDE` mode: fail when a listed payload path is missing. When `false`, a failure passes the message on unchanged |
| `errorPort` | string | none | Port for messages that fail, with the failure details attached |

Output ports: `default`, plus `errorPort` when set.

Paths:

* A plain path such as `user.name` refers to the payload.
* A path starting with `metadata.` or `headers.` refers to the message metadata.
* In `INCLUDE` mode a path may also be an expression. A path that starts with `#` is evaluated as one.
* In `EXCLUDE` mode paths are plain dotted names. Missing paths are ignored.

With `INCLUDE`, the new payload holds only the listed paths, nested as written. When any listed path targets metadata, the metadata is replaced by the listed entries plus the message's core identifiers (message id, trace id, correlation id, timestamp, sequence fields and reply address).

If the payload is a list, each item is filtered on its own and emitted as a separate message.

This node removes secrets before a payload goes on:

```json theme={"system"}
{
  "nodeId": "redact",
  "type": "CONTENT-FILTER",
  "config": {
    "mode": "EXCLUDE",
    "paths": ["user.password", "user.token", "metadata.apiKey"]
  }
}
```

## Limits and defaults

| Item | Value |
| - | - |
| `MAPPER` `dropOriginal`, `strictMode` | `true`, `true` |
| Script run time and statements | 10 seconds, 50 million |
| Script memory | not limited |
| `CONTENT-FILTER` `mode` | `INCLUDE` |
| Default timeout, all three plugins | 30 seconds idle |

## Related

* [Variables and expressions](/building/variables-and-expressions)
* [Routing and flow](/plugins/routing-and-flow)
* [Messages](/concepts/messages)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.