# Exchange messages with the Total Messaging Service

> Enable the TMS WebSocket endpoint and let external clients receive published messages, send messages to your app and call its functions.

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

TMS (Total Messaging Service) is a small message bus on top of a WebSocket. Turn it on in the `config` file with `$tms : true`; the endpoint is `/$tms/` and `secret_tms` is the token that every client must send in the `x-token` header (a wrong token closes the connection with code 4001, and an address that fails more than 5 times is blocked for a while). When a client connects it receives a `meta` message that lists what the app publishes, what it accepts and what it can do.

Three things can be exposed, each one described by a schema in the same `name:Type` format as an action `input`:

- `NEWPUBLISH(name, schema)` declares a message the app **sends**; `PUBLISH(name, value)` sends it to every client that asked for it by sending `{ type: 'subscribers', subscribers: [name] }`.
- `NEWSUBSCRIBE(name, schema, callback)` declares a message the app **receives**: a client sends `{ type: 'subscribe', id: name, data: {...} }` and `callback(message, client)` runs only when the data is valid. The validated data is in `message.response` (`message.error` is always `null` there) and `client` is the sender.
- `NEWCALL(name, schema, callback)` declares a function the client **calls**: the client sends `{ type: 'call', id: name, data: {...}, callbackid: '1' }`, and the app answers with the same message carrying `success: true` and the result in `data`, or `error: true` when the data is invalid. `callback(data, done, client)` produces the result with `done(null, result)`.

Passing `null` as the schema of `NEWPUBLISH` or `NEWSUBSCRIBE` removes the declaration. The official client of Total.js (`TMSCLIENT`) speaks this protocol for you from another Total.js app; any WebSocket client works.

`UNSUBSCRIBE(name, [callback])` removes the listeners of a message that the app receives: only `callback` when you pass it, all of them when you do not. It returns `true` when it removed something and `false` when there was nothing to remove.

```text config
$tms : true
secret_tms : my-tms-token
```

```js definitions/tms.js
NEWPUBLISH('news', 'title:String');

NEWSUBSCRIBE('orders', 'id:String, qty:Number', function(message, client) {
	MAIN.orders.push(message.response);
});

NEWCALL('sum', 'a:Number, b:Number', function(data, done) {
	done(null, { total: data.a + data.b });
});

MAIN.orders = [];
```

```js controllers/tms.js
exports.install = function() {
	ROUTE('POST /news/ @json', news);
	ROUTE('GET /orders/', orders);
	ROUTE('GET /unsubscribe/', unsubscribe);
};

function news($) {
	PUBLISH('news', { title: $.body.title });
	$.success();
}

function orders($) {
	$.json(MAIN.orders);
}

function unsubscribe($) {
	const first = UNSUBSCRIBE('orders');
	const second = UNSUBSCRIBE('orders');
	$.json({ first: first, second: second });
}
```
