---
sidebar_position: 3
---

# Transform

[Event Bus Input Transforms](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-transform-target-input.html) transform events matched by [Rules](./rule). Transforms supports a loosely coupled application by allowing the rule to normalize an event before sending it to a target with it's own expected payload schema.

Functionless allows Typescript to be used when defining an input transform. It transforms the code given into Event Bridge's [Input Transform](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-transform-target-input.html) JSON schema, while maintaining the contract provided by the [Typescript Syntax](./syntax#event-transforms).

```ts
const bus = new EventBus(stack, 'bus');
const func = new Function<string, void>(stack, 'func', (input) => console.log(input));

// an event bridge rule made with Functionless
const lambdaEventsRule = bus
  // For all events
  .all();
  // send only the `id` string to the target.
  .map(event => event.id)
  // send all matched events to the given function.
  .pipe(func);
```

The above is equal to the below in CDK:

```ts
declare const func: aws_lambda.IFunction;
const bus = aws_events.EventBus(stack, "bus");
const lambdaEventsRule = aws_events.Rule(bus, "lambdaEvents", {
  eventBus: bus,
  // matches all events. equivalent to .all() or .when(event => true)
  eventPattern: { source: [{ prefix: "" }] },
});
lambdaEventsRule.addTarget(
  new aws_event_targets.LambdaFunction(func, {
    // equivalent to .map(event => event.id)
    event: aws_events.RuleTargetInput.fromEventPath("$.id"),
  })
);
```

:::info
Where does the `{ source: [{ prefix: "" }] }` syntax come from?

Rules have no explicit way to send all events, this hack was proposed on [StackOverflow](https://stackoverflow.com/a/62407802/968011).

Why does this work?

- The `source` field is always required and is always a string.
- `{ prefix: "" }` ([Prefix Matching](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns-content-based-filtering.html#eb-filtering-prefix-matching)) will match any string.
  :::

:::info
For more details on the supported schema for `Transform`s see [syntax](./syntax#event-transforms)
:::

:::caution
[Bus to bus targets (`.pipe`) cannot be transformed](./limitations#bus-to-bus-rules-cannot-be-transformed).
:::

## Utilities

EventBridge provides [predefined variables](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-transform-target-input.html#eb-transform-input-predefined) to inject additional information when transforming events.

Most of the predefined variables can be accessed using the second parameter to the `.map` function's callback.

```ts
const bus = new EventBus(stack, "bus")
  .all()
  // send the rule name to a lambda for each event on the bus
  .map((event, $utils) => $utils.context.ruleName)
  .pipe(
    new Function(stack, "func", (ruleName) =>
      console.log(`rule name: ${ruleName}`)
    )
  );
```

| Variable       | Functionless                                      | Description                                                                                                                  |
| -------------- | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Rule Arn       | `(event, $utils) => $utils.context.ruleName`      | The Amazon Resource Name (ARN) of the EventBridge rule.                                                                      |
| Rule Name      | `(event, $utils) => $utils.context.ruleName`      | The Name of the EventBridge rule.                                                                                            |
| Ingestion Time | `(event, $utils) => $utils.context.ingestionTime` | The time at which the event was received by EventBridge. This variable is generated by EventBridge and can't be overwritten. |
| Event Json     | `(event, $utils) => $utils.context.eventJson`     | The exact payload of an event as a string.                                                                                   |
| Event          | `(event) => event`                                | A copy of the original event.                                                                                                |

### Whole Event

To make use of the whole event predefined variable `aws.events.event`, use the event object when transforming.

```ts
const bus = new EventBus(stack, "bus")
  .all()
  // send the whole event to a lambda
  .map((event, $utils) => ({
    eventId: event.id,
    // uses the `aws.events.event` predefined variable to send to whole event.
    event: event,
  }))
  .pipe(
    new Function(stack, "func", ({ eventId, event }) =>
      console.log(`event id: ${eventId}`, event)
    )
  );
```
