# Venice JS

> *Manage your JS channels like a pro Venetian gondolier!*

![](venice-img.jpg)

## Installation

```npm install --save @spindox/venice```

## Usage 

Use venice instance in your application:

```import venice from '@spindox/venice';```

or create your own instance with the exported classes:

```import { Venice, VeniceChannel } from '@spindox/venice';```

## Classes

<dl>
<dt><a href="#VeniceChannel">VeniceChannel</a></dt>
<dd><p>A Venice channel.</p>
<p>An abstraction layer on top of <a href="http://mozilla.github.io/jschannel/docs/">js-channel</a> instance.</p>
</dd>
<dt><a href="#Venice">Venice</a></dt>
<dd><p>Contains all Venice channels of the application.</p>
</dd>
</dl>

<a name="VeniceChannel"></a>

## VeniceChannel
A Venice channel.

An abstraction layer on top of [js-channel](http://mozilla.github.io/jschannel/docs/) instance.

**Kind**: global class  

* [VeniceChannel](#VeniceChannel)
    * [new VeniceChannel(key, options)](#new_VeniceChannel_new)
    * [.publish(topic, data, callback)](#VeniceChannel+publish)
    * [.subscribe(topic, handler)](#VeniceChannel+subscribe)
    * [.unsubscribe(topic)](#VeniceChannel+unsubscribe)
    * [.disconnect()](#VeniceChannel+disconnect)

<a name="new_VeniceChannel_new"></a>

### new VeniceChannel(key, options)

| Param | Type | Description |
| --- | --- | --- |
| key | <code>string</code> | The channel identifier |
| options | [<code>ChannelOptions</code>](#ChannelOptions) | The channel configuration options |

<a name="VeniceChannel+publish"></a>

### veniceChannel.publish(topic, data, callback)
Publishes a message related to the specified topic.

**Kind**: instance method of [<code>VeniceChannel</code>](#VeniceChannel)  

Param | Type | Description
--- | --- | ---
topic | <code>string</code> | The message topic
data | <code>\*</code> | Data to be sent to the other window. The data is serialized using [the structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm). This means you can pass a broad variety of data objects safely to the destination window without having to serialize them yourself
callback | [<code>VeniceCallback</code>](#VeniceCallback) | The message publication callback

**Example**  

	const payload = { type: 'geolocation' };
	channel.publish('event.hardware', payload, (err, data) => {
	  if (err) return err;
	  console.log('position', data);
	});

<a name="VeniceChannel+subscribe"></a>

### veniceChannel.subscribe(topic, handler)
Subscribes a message handler for the specified topic.

**Kind**: instance method of [<code>VeniceChannel</code>](#VeniceChannel)  

| Param | Type | Description |
| --- | --- | --- |
| topic | <code>string</code> | The message topic |
| handler | [<code>SubscriptionHandler</code>](#SubscriptionHandler) | The message handler |

**Example**  

	channel.subscribe('event.hardware', (data, tx) => {
	  if (data.type === 'geolocation') {
	    // async
	    getCurrentPosition()
	      .then((position) => {
	        tx.complete(position);
	      })
	      .catch((ex) => {
	        tx.error('fail', ex);
	      });
	      tx.delayReturn(true);
	  } else {
	    // sync
	    return 'Sync data';
	  }
	});

<a name="VeniceChannel+unsubscribe"></a>

### veniceChannel.unsubscribe(topic)
Unsubscribes the handler for the specified topic.

**Kind**: instance method of [<code>VeniceChannel</code>](#VeniceChannel)  

| Param | Type | Description |
| --- | --- | --- |
| topic | <code>string</code> | The message topic |

**Example**  

	channel.unsubscribe('event.hardware');

<a name="VeniceChannel+disconnect"></a>

### veniceChannel.disconnect()
Destroys the channel

**Kind**: instance method of [<code>VeniceChannel</code>](#VeniceChannel)  
**Example**  

	channel.disconnect();

<a name="Venice"></a>

## Venice
Contains all Venice channels of the application.

**Kind**: global class  

* [Venice](#Venice)
    * [.channel(key, options)](#Venice+channel) ⇒ <code>object</code>
    * [.publish(params)](#Venice+publish)
    * [.subscribe(params)](#Venice+subscribe)
    * [.unsubscribe(params)](#Venice+unsubscribe)
    * [.disconnect(key)](#Venice+disconnect)

<a name="Venice+channel"></a>

### venice.channel(key, options) ⇒ <code>object</code>
Creates a communication channel between the parent window and the iframe.
If it's invoked without options, returns an existing channel.

**Kind**: instance method of [<code>Venice</code>](#Venice)  
**Returns**: <code>object</code> - - A VeniceChannel instance  

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| key | <code>string</code> |  | The channel identifier |
| options | [<code>ChannelOptions</code>](#ChannelOptions) | <code></code> | The channel configuration options |

**Example**  

	// Set Venice channel on parent
	const channel = venice.channel('channel.sample', {
	  window: iframe.contentWindow,
	  onReady: () => {
	    console.log('channel is ready!');
	  },
	});

**Example**  

	// Set Venice channel on iframe
	const channel = venice.channel('channel.sample', {});

**Example**  

	// Get Venice channel
	const channel = venice.channel('channel.sample');

<a name="Venice+publish"></a>

### venice.publish(params)
Publishes a message related to the specified topic on the specified channel.

**Kind**: instance method of [<code>Venice</code>](#Venice)  

| Param | Type | Description |
| --- | --- | --- |
| params | <code>object</code> |  |
| params.channel | <code>string</code> | The Venice channel identifier |
| params.topic | <code>string</code> | The message topic |
| params.data | <code>\*</code> | Data to be sent to the other window. The data is serialized using [the structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm). This means you can pass a broad variety of data objects safely to the destination window without having to serialize them yourself |
| params.callback | [<code>VeniceCallback</code>](#VeniceCallback) | The message publication callback |

**Example**

	venice.publish({  
	  channel: 'channel.sample',  
	  topic: 'event.hardware',  
	  data: { type: 'geolocation' },  
	  callback: (err, data) => {  
	    if (err) return err;  
	    console.log('position', data);  
	  });  
	});  
	
<a name="Venice+subscribe"></a>

### venice.subscribe(params)
Subscribes a message handler for the specified topic on the specified channel.

**Kind**: instance method of [<code>Venice</code>](#Venice)  

| Param | Type | Description |
| --- | --- | --- |
| params | <code>object</code> |  |
| params.channel | <code>string</code> | The Venice channel identifier |
| params.topic | <code>string</code> | The message topic |
| params.handler | [<code>SubscriptionHandler</code>](#SubscriptionHandler) | The message handler |

**Example**  

	venice.subscribe({  
	  channel: 'channel.sample',  
	  topic: 'event.hardware',  
	  handler: (data, tx) => {  
	    if (data.type === 'geolocation') {  
	      // async  
	      getCurrentPosition()  
	        .then((position) => {  
	          tx.complete(position);  
	        })  
	        .catch((ex) => {  
	          tx.error('fail', ex);  
	        });  
	        tx.delayReturn(true);  
	    } else {  
	      // sync  
	      return 'Sync data';  
	    }  
	  }  
	});  

<a name="Venice+unsubscribe"></a>

### venice.unsubscribe(params)
Unsubscribes the handler for the specified topic on the specified channel.

**Kind**: instance method of [<code>Venice</code>](#Venice)  

| Param | Type | Description |
| --- | --- | --- |
| params | <code>object</code> |  |
| params.channel | <code>string</code> | The Venice channel identifier |
| params.topic | <code>string</code> | The message topic |

**Example**  

	venice.unsubscribe({
	  channel: 'channel.sample',  
	  topic: 'event.hardware',  
	});

<a name="Venice+disconnect"></a>

### venice.disconnect(key)
Destroys the specified Venice channel.

**Kind**: instance method of [<code>Venice</code>](#Venice)  

| Param | Type | Description |
| --- | --- | --- |
| key | <code>string</code> | The Venice channel identifier |

**Example**  

	venice.disconnect('venice.channel');


## Functions

<dl>
<dt><a href="#SubscriptionHandler">SubscriptionHandler(data, transaction)</a></dt>
<dd><p>This method is invoked by the message topic listener. It receives data as the first argument.</p>
<p>If your implementation is asychronous, you&#39;ll have to use the transaction object that&#39;s automatically passed as the second argument.</p>
</dd>
</dl>

## Typedefs

<dl>
<dt><a href="#ChannelOptions">ChannelOptions</a> : <code>object</code></dt>
<dd><p>Venice channel options.</p>
<p>By defaul <em>window</em> is equal to <strong>window.parent</strong>, <em>origin</em> is equal to <strong>*</strong>, and <em>scope</em> has the same value of <em>key</em> parameter.</p>
</dd>
<dt><a href="#VeniceCallback">VeniceCallback</a> : <code>function</code></dt>
<dd><p>This callback is invoked after that the subscribed listener received the message data, handled it, and, eventually, returned a response.</p>
<p>It&#39;s a node-style method, whit the error (or <em>null</em>) as the first argument and the response data as the second argument.</p>
</dd>
<dt><a href="#Transaction">Transaction</a> : <code>object</code></dt>
<dd><p>Transaction object for asychronous implementations of message.</p>
</dd>
</dl>

<a name="SubscriptionHandler"></a>

## SubscriptionHandler(data, transaction)
This method is invoked by the message topic listener. It receives data as the first argument.

If your implementation is asychronous, you'll have to use the transaction object that's automatically passed as the second argument.

**Kind**: global function  

| Param | Type | Description |
| --- | --- | --- |
| data | <code>\*</code> | The message data |
| transaction | [<code>Transaction</code>](#Transaction) | The transaction object |

<a name="ChannelOptions"></a>

## ChannelOptions: <code>object</code>
Venice channel options.

By defaul *window* is equal to **window.parent**, *origin* is equal to *****, and *scope* has the same value of *key* parameter.

**Kind**: global typedef  
**Properties**

| Name | Type | Description |
| --- | --- | --- |
| window | <code>element</code> | A reference to the window to communicate with |
| origin | <code>string</code> | Specifies what the origin of other window must be for the event to be dispatched |
| scope | <code>string</code> | All messages will be safely tucked under the namespace you provide. If omitted, it's equal to the channel key |
| onReady | <code>function</code> | Callback called once actual communication has been established between the parent page and child frame. If the child frame hadn't set up its end of the channel, for instance, onReady would never get called |

<a name="VeniceCallback"></a>

## VeniceCallback: <code>function</code>
This callback is invoked after that the subscribed listener received the message data, handled it, and, eventually, returned a response.

It's a node-style method, whit the error (or *null*) as the first argument and the response data as the second argument.

**Kind**: global typedef  

| Param | Type |
| --- | --- |
| error | <code>string</code> | 
| result | <code>\*</code> | 

<a name="Transaction"></a>

## Transaction: <code>object</code>
Transaction object for asychronous implementations of message.

**Kind**: global typedef  
**Properties**

| Name | Type | Description |
| --- | --- | --- |
| complete | <code>function</code> | Resolves transaction with data passed as argument |
| completed | <code>function</code> |  |
| delayReturn | <code>function</code> | Indicates that the handler implementation is asynchronous |
| error | <code>function</code> | Rejects transaction with error (code and message) passed as argument. ```e.g. tx.error('mega_fail', 'I could not get your stuff.');``` |
| invoke | <code>function</code> |  |
| origin | <code>string</code> | Contains the origin of the message |

##Licence: MPL2.0
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
