## Transmit

`npm install transmit`

Transmit is two things:

+ Abstractions on top of the [ws](https://github.com/einaros/ws) library
+ A similar set of abstractions for the client, automatically exposed

Features:

+ Callback behavior
+ Integration with sessions
+ Client grouping
+ Broadcasting

*Incompatible with Express beta, make sure that you are using Express 2.5.x*

## Basic example

### Server

*server.js*

```js

var express = require('express')
,   app     = express.createServer()

var lactate = require('lactate')

app.get('/', function(req, res) {
  return lactate.file('index.html', req, res)
})

app.listen(8080)

var transmit = require('transmit')()
transmit.listen(app, function(socket) {
    socket.on('request', data, cb) {
        cb('Greetings')
    })
})

```

### Client

*index.html*

```html

<!doctype html>
<html>
  <head>
    <title>Transmit example</title>
    <script src='/transmit'></script>
  </head>
  <body>
    <script>
    var $t = transmit()
    $t.on('open', function() {
        $t.send('request', 'asdf', function(res) {
            alert(res) /* 'Greetings' */
        })
    })
    </script>
  </body>
</html>

```


## Integrating with express sessions

To integrate express sessions with Transmit, first make sure you have `node_redis` and `connect-redis` modules installed.

`npm install redis hiredis connect-redis`

Then simply set `sessions` to `true` in the Transmit options.

```js
var express = require('express')
var app = express.createServer()

var RedisStore = require('connect-redis')(express)

app.use(express.cookieParser())
app.use(express.session({
    store:new RedisStore()
    secret:'somn'
})

app.get('/', function(req, res) {
    req.session.user = Math.random().toString(36).substring(2)
    res.end(landingPage)
})

app.listen(8080)

var transmit = require('transmit')({
    sessions:true
})

transmit.on('connection', function(socket) {
    var user = socket.session.user
})

transmit.listen(app)
```

Transmit parses incoming connection headers to find the connect session ID, queries Redis for the session data, and JSON parses it. Transmit is then loosely-coupled to your express app.

To query Redis for sessions after the client has connected:

```js
transmit.on('connection', function(con) {
    transmit.getSession(con, function(err, session) {

    })
})
```

## Grouping clients

Transmit allows you to group clients any way you like, by exposing a mapping function. Combined with Express sessions this can be quite convenient. Example.

```js

function attachURL(req, res, next) {
    req.session.url = req.url
    return next()
}

app.get('/', attachURL, function(req, res) {
    /* Send landing page with Transmit script */
})

var transmit = require('transmit')({
    sessions:true
})

transmit.group(function(client) {
    return client.session.url
})

transmit.listen(app, function(client) {
    client.peers(function(peer) {
        peer.send('greet', 'Greetings')
    })
})

```

## Server methods

### on (event *string*, callback *function*)

Applicable events

+ `connection` socket
+ `error` error
+ `close`

### listen (server *http(s).Server*, callback *function*)

Callback function is executed for every connection with one argument: the connecting socket

### broadcast (event *string*, message *stringifiable*)

### group (fn *function*)

This method will map your clients into groups, using `fn`. In the following example your clients will be grouped by the `someProperty` property of their session object (assuming sessions have been enabled). To access a group you may use either Transmit's `of` method or the `peers` method attached to Transmit clients.

```js

transmit.group(function(client) {
    return client.session.someProperty
})

```

### of (group *string*)

Returns an array of clients by group name.

### close

Close the server

## Socket methods

These methods exist on both the client and server-side.

### on (event *string*, callback *function*)

Applicable events

+ `error` error
+ `close`

### send (event *string*, message *stringifiable*, callback *function*)

The `send` method automatically stringifies your second argument. An optional third argument is for callback function.

Transmit's stringification format is: `JSON.stringify([event, data])`

*Server* 

```js
    socket.on('requestMilk', function(req, res) {
        res('Try again soon')
    })
```

*Client*

```js
    transmit.send('requestMilk, 'please', function(res) {
        alert(res === 'Try again soon') /* true */
    })
```

### sendBinary (data *buffer*)

### peers (fn *function*)

Without a callback this function returns an array containing the client's peers. Otherwise, your callback will be executed for every peer.

While using a callback to broadcast to a peer group, note that to avoid Transmit's automatic stringification you may use the native `send` method attached to the `socket` property. At this level Transmit behaves just like the `ws` module. However, note also that Transmit stringifies in the format described above.

```js
    var ids = socket.peers().map(function(i) { return i.clientId })

    var dataString = JSON.stringify([
        'someEvent',
        'someData'
    ])

    socket.peers(function(peer) {
        peer.socket.send(dataString)
    })
```

### close

Close the client


## Options

+ `Transmit` options

The `client_name` option refers to the  name with which to expose our client script. By default, the client script is accessed from `/transmit`. 

```js
var id = 'to_defy_the_laws_of_tradition_is_a_crusade_only_of_the_brave'

var transmit = require('transmit')({
    'client_name':id
})

/*
    The script can now be accessed from 
    /to_defy_the_laws_of_tradition_is_a_crusade_only_of_the_brave
*/
```

To prevent the client script from being served, use `no_client`

```js
var transmit = require('transmit')({
    no_client:true
})
```

To integrate with express sessions using connect-redis, set `sessions` to true.
This will automatically fetch sessions from connect-redis and attach the `session` property to incoming sockets.

```js
var transmit = require('transmit')({
    sessions:true
})
```

+ `ws` options

To set `ws` options, you may pass them to the initialization function like so

```js
var transmit = require('transmit')({port:2112})
```

You can find all of the available `ws` options [here](https://github.com/einaros/ws/blob/master/doc/ws.md#class-wsserver)

+ `node_redis` options

Transmit uses Redis (node_redis) to fetch sessions from a `connect-redis` session store. If you don't care about sessions, these options don't apply to you. If you do care about integrating sessions, see the section above on that topic.

You may pass options to node_redis by way of the `redis` property. See available options [here](https://github.com/mranney/node_redis#rediscreateclientport-host-options)

```js
var transmit = require('transmit')({
    redis: {

    }
})
```

+ `Lactate` options

For serving the client script, Transmit relies on [Lactate](https://github.com/Weltschmerz/Lactate).
You may set Lactate options using `lactate` like so

```js
var _transmit = require('transmit')({
    lactate: {
        expires:'one year'
    }
})
```


A complex options example:

```js

var options = {
    port:2112,
    client_name:'MyScript',
    sessions:false,

    lactate: {
        expires:'two days',
        cache:false
    },

    redis:{
        parser:'javascript',
        no_ready_check:true
    }
}

var transmit = require('transmit')(options)
```
