# Options of NEWACTION and the object an action receives

> Configure NEWACTION and use the action context to handle requests.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: en
Content-SHA256: f1ffd2184b29e3078bcf6ecaeeb9ef9f5f0c5e6e808b6ea368164415466f662b
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`NEWACTION(name, options)` declares an action. `name` is its id (`Users/insert`): routes use it with `--> *Users/insert` and your code with `ACTION('Users/insert', payload)`.

## Options

| Option | Value | What it does |
|---|---|---|
| `name` | text | A description of the action; it is also available as `$.name`. |
| `action` | `function($, model)` | The code of the action. `model` is the validated input. |
| `input` | text | The fields of the body, as `name:Type` separated by commas; a `*` before the name makes it required. See the input types page. |
| `output` | text | The fields of the answer; fields that are not listed are removed. |
| `params` | text | The `{name}` segments of the route, validated like `input`. |
| `query` | text | The query string, validated like `input`. |
| `partial` | `true` | Only the fields that were sent reach the action. Use it for `PATCH`. |
| `user` | `true` or `false` | `true` answers 401 when there is no signed-in user; `false` accepts only anonymous requests. |
| `permissions` | text or array | `'read,write'`: the user needs one of them (or to be a super administrator). |
| `route` | text | Declares the route of the action here: `'GET /products/'`, or `true` for an `API` route. |
| `middleware` | text | Names of middleware that run before the action, separated by spaces or commas. |
| `timeout` | milliseconds | When the action does not answer in time, the request fails with the error `Timeout.`. |
| `cache` | `true` or an object | Keep the result of an action with `CACHE`. |
| `config` | object | Values that the action reads from `$.config`. |
| `audit` | text | Records an automatic event after successful completion; see the dedicated recipe for tested boundaries. [action-audit](/en/total5/action-audit/) |
| `csrf`, `encrypt`, `compress`, `publish` | - | [action-transport-boundaries](/en/total5/action-transport-boundaries/) |
| `sa`, `su` | true | Either requires a user with either administrator flag. [action-hooks-and-admin](/en/total5/action-hooks-and-admin/) |
| `oninput`, `onoutput` | function | Before the handler after validation; successful completion hook after output processing. [action-hooks-and-admin](/en/total5/action-hooks-and-admin/) |
| `extend` | path | Adds the result under this path in the validated input and returns the extended payload. [action-hooks-and-admin](/en/total5/action-hooks-and-admin/) |

## The object `$` of an action

| Member | What it is |
|---|---|
| `$.query`, `$.params` | The validated query string and route segments. |
| `$.payload` | The validated input; it is the same object as the second argument of `action`. |
| `$.user` | The signed-in user. |
| `$.config` | The `config` option. |
| `$.name`, `$.id` | The `name` option and the id of the action. |
| `$.controller` | The `$` of the route when the action was called from a route, so `$.controller.body` is the raw body. It does not exist when the action is called with `ACTION()`. |
| `$.callback(value)` | Answers with a value; it is filtered by `output`. Without arguments it returns a function `(err, response)`. |
| `$.success(value)` | Answers `{ success: true }`. |
| `$.invalid(error)` | Answers with an error: a text, a status code or an `ErrorBuilder`. |
| `$.done(arg)`, `$.successful(fn)` | Return callbacks for functions that report an error as their first argument. |
| `$.cookie(name, value, expiration)` | Reads or writes a cookie of the request. |
| `$.redirect(url)` | Redirects the request. |
| `$.output(name)` | Chooses how a route answers: `json`, `html`, `xml`, `text`, `redirect`, `binary`, `jsonstring`, `empty` or `file`. |
| `$.unauthorized(...permissions)` | Answers 401 and returns `true` when the user has none of the permissions. |
| `$.action(name, payload)` | Runs another action with the same request. |
| `$.hostname(path)` | The address of this server. |

```js definitions/options.js
MIDDLEWARE('tag', function($, next) {
	$.response.headers['x-tag'] = 'on';
	next();
});

var counter = { cached: 0 };
MAIN.counter = counter;

NEWACTION('Options/named', {
	name: 'The name',
	config: { limit: 3 },
	action: function($) {
		$.callback({ name: $.name, id: $.id, limit: $.config.limit });
	}
});

NEWACTION('Options/guarded', {
	name: 'Needs a user',
	user: true,
	permissions: 'read',
	action: function($) {
		$.success();
	}
});

NEWACTION('Options/slow', {
	name: 'Never answers',
	timeout: 300,
	action: function($) {}
});

NEWACTION('Options/cached', {
	name: 'The cache option',
	query: 'page:Number',
	cache: { expire: '1 minute', query: 'page' },
	action: function($) {
		counter.cached++;
		$.callback({ page: $.query.page, runs: counter.cached });
	}
});

NEWACTION('Options/routed', {
	name: 'Declares its own route',
	route: 'GET /routed/ #tag',
	action: function($) {
		$.callback({ routed: true });
	}
});

NEWACTION('Options/output', {
	name: 'Chooses how to answer',
	action: function($) {
		$.output('plain');
		$.callback('plain text');
	}
});

AUTH(function($) {
	if ($.headers['x-user'])
		$.success({ id: '1', permissions: $.headers['x-user'].split(',') });
	else
		$.invalid();
});
```

```js controllers/options.js
exports.install = function() {
	ROUTE('GET /named/ --> *Options/named');
	ROUTE('GET /guarded/ --> *Options/guarded');
	ROUTE('GET /slow/ --> *Options/slow');
	ROUTE('GET /cached/ --> *Options/cached');
	ROUTE('GET /output/ --> *Options/output');
};
```
