---
description: Anatomy of an Action.
---

# Action

## Introduction

An action deals with the business part, it is the layer between an incoming call (request, event or process call) and a Datasource (DB, File, External Service). It means **there is no Response concepts** in an Action.

The simplest form of an action is :

```javascript
const Action = require('idylle').Action;
module.exports = app => {
    Action({
        execute: context => { return 'Hello World' }
    });
};
```

{% hint style="warning" %}
The Action **must** have an `execute` property which must be a **function** whereas it will throw an `InvalidExecuteFunctionError`
{% endhint %}

1. Fetching the 'Constructor' of the action from the library
2. The execute property is the only mandatory property of an Action. It is used when an action is invoked from another part of your application, when an HTTP request is routed to it or an Socket Event is routed to it.
3. The Action mechanism will insert your execute property in a **Promise Chain** meaning if your function  is **synchronous** the next part will be executed directly at the end of your action. If instead, your action returns a `Promise`, the system **will wait** for your `execute` property to `resolve/reject` the **Promise** before executing the next part of the mechanism.&#x20;

## Input sources

When an action is executed, a [Context](context) is built and normalized/sanitized. This context, defined as the **input** of an **Action** can comes from 3 different sources.&#x20;

* An HTTP Request

![Scheme explaining how a context is generated from an HTTP Request.](https://3050976882-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LBVxReILYCHpYSQFFV6%2F-LB_GeXLI_DOmXqVGzrJ%2F-LB_wyw23oK9t_T8MmO-%2FHTTP.png?alt=media\&token=845ad76a-8f35-438e-b5ff-cf1aa9ffd47f)

{% hint style="info" %}
In this example we see when the dependency `CriteriaBuilder` is used. Remember that you can override this `CriteriaBuilder` during the [initialization phase](../../the-flows#customizing-the-flow).&#x20;
{% endhint %}

* An IO Event

![Scheme explaining how a context is generated from a process call.](https://3050976882-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LBVxReILYCHpYSQFFV6%2F-LB_GeXLI_DOmXqVGzrJ%2F-LB_wv86eui4aZ3rns7W%2FIO.png?alt=media\&token=dfb039b8-e42d-4426-ae1d-afff4fb34edc)

* An Process invocation

![Scheme explaining how a context is generated of a process call.](https://3050976882-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LBVxReILYCHpYSQFFV6%2F-LB_GeXLI_DOmXqVGzrJ%2F-LB_xIyux7yGg8WyVBZ_%2FProcess.png?alt=media\&token=a15a58ab-94ae-46a9-a9d4-0bbca8392043)

## Rules - Validating | Sanitizing

* **Validation** checks if the input meets a set of criteria (such as a string contains no standalone single quotation marks).
* **Sanitization** modifies the input to ensure that it is valid (such as doubling single quotes).&#x20;

You would normally combine these two techniques to provide in-depth defense to your application. For example, you might change all single quotation marks in a string to double quotation marks (sanitize) and then check that all the quotation marks were actually changed to double quotation marks (validate).

Validation checks include testing for the length, format, range, and allowable characters. For example, if your application expects positive integer input, you need to validate that any string input consists only of the digits 0 through 9.

To do so, Actions have an extra property called rules which represent an array of function. Each of them are also included in the Promise chain mechanism.

Below an example of three validators :

```javascript
const Action = require('idylle').Action;

module.exports = app => {
    const League = app.models.League;

    return Action({
        rules: [
            context => (context.user && context.user.id) || context.error(400, 'missing.user'),
            context => (context.data.name) || context.error(400, 'missing.name'),
            context => (context.data.competition_id) || context.error(400, 'missing.competition_id')
        ],
        execute: context => {
            context.data.owner = context.user;

            return getCompetitionDetails()
                .then(c => c || context.error(400, 'invalid competition'))
                .then(create);

            function getCompetitionDetails() {
                return app.actions.remote.competitions
                    .show({ 'params.id': context.data.competition_id });
            }

            function create(competition) {
                context.data.competition = competition;
                context.data.players = [context.user.id];

                return League
                    .create(context.data);
            }
        }
    });
};
```

This example demonstrate the ability to validate the context of an Action before actually executing its body. Moreover, line 20, we see that another actions `remote.competitions.show()` is used inside the current action.&#x20;
