# Build a processing pipeline with transforms

> Register several steps under one name with NEWTRANSFORM() and run a value through them in order with TRANSFORM().

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

A transform is a named chain of steps. `NEWTRANSFORM(name, fn, [id])` adds a step to the chain `name`; steps run in the order they were registered, and each one receives the options object `$` and the current value. Change the value with `$.value = ...` and call `$.next()` to continue with the next step. `$.invalid(message)` adds an error. `TRANSFORM(name, value)` starts the chain and returns a promise with the final value; the promise rejects when a step has reported an error. With a callback instead, `TRANSFORM(name, value, function(err, value) {})`. A name without any step returns the value as it is.

Use it for work that has to be extended from several places, such as cleaning a comment before it is saved: a spam filter, a trimmer and a link checker can each live in their own file and be added or removed without touching the code that calls `TRANSFORM()`. The optional `id` lets you remove one step later with `NEWTRANSFORM(name, null, id)`.

```js definitions/transforms.js
NEWTRANSFORM('comment', function($, value) {
	$.value = value.trim();
	$.next();
}, 'trim');

NEWTRANSFORM('comment', function($, value) {
	if (/spam/i.test(value))
		$.invalid('Spam is not allowed');
	$.next();
}, 'spam');

NEWTRANSFORM('comment', function($, value) {
	$.value = value.replace(/\s+/g, ' ');
	$.next();
}, 'spaces');
```

```js controllers/comments.js
exports.install = function() {
	ROUTE('POST /comment/ @json', comment);
	ROUTE('DELETE /comment/spaces/', remove_step);
};

async function comment($) {
	try {
		var text = await TRANSFORM('comment', $.body.text);
		$.json({ text: text });
	} catch (err) {
		$.json({ error: true });
	}
}

function remove_step($) {
	NEWTRANSFORM('comment', null, 'spaces');
	$.success();
}
```
