Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

emitter-pubsub-broker

Package Overview
Dependencies
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

emitter-pubsub-broker - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

30

CHANGELOG.md

@@ -5,2 +5,32 @@ # Change Log

<a name="0.5.0"></a>
# [0.5.0](https://github.com/an-sh/emitter-pubsub-broker/compare/v0.4.0...v0.5.0) (2017-01-06)
### Bug Fixes
* ignore broadcast errors ([e895e96](https://github.com/an-sh/emitter-pubsub-broker/commit/e895e96))
### Code Refactoring
* change getSubscriptions return type ([338a47a](https://github.com/an-sh/emitter-pubsub-broker/commit/338a47a))
* rename unsubscribeall to unsubscribeAll ([3a25f07](https://github.com/an-sh/emitter-pubsub-broker/commit/3a25f07))
### Features
* add custom serialisation support ([c3f218d](https://github.com/an-sh/emitter-pubsub-broker/commit/c3f218d))
* add getClients ([f728105](https://github.com/an-sh/emitter-pubsub-broker/commit/f728105))
* support broadcast data encoding ([392c173](https://github.com/an-sh/emitter-pubsub-broker/commit/392c173))
### BREAKING CHANGES
* Now getSubscriptions method returns a shared Set
instead of a fresh Array.
* Rename unsubscribeall to unsubscribeAll.
<a name="0.4.0"></a>

@@ -7,0 +37,0 @@ # [0.4.0](https://github.com/an-sh/emitter-pubsub-broker/compare/v0.3.0...v0.4.0) (2016-11-29)

153

lib/EmitterPubsubBroker.js

@@ -127,8 +127,47 @@ 'use strict';

/**
* Messages encoder. Encoded messages will be used to emit messages
* via event emitters. May also return promises for an asynchronous
* execution.
*
* @callback EmitterPubsubBroker.Encoder
* @param {*} args Emit arguments.
* @return {Promise<Object>|Object} Data to send.
*/
/**
* Messages serialisation. Serialised messages will be used internally
* via a communication {@link Connector}. May also return promises
* for an asynchronous execution.
*
* @callback EmitterPubsubBroker.Serialize
* @param {Object} data Data.
* @return {Promise<Object>|Object} Serialised data.
*/
/**
* Messages deserialisation. Serialised messages will be used
* internally via a communication {@link Connector}. May also return
* promises for an asynchronous execution.
*
* @callback EmitterPubsubBroker.Deserialize
* @param {Object} data Serialised data.
* @return {Promise<Object>|Object} Data.
*/
/**
* @typedef {Object} EmitterPubsubBroker.Options
*
* @property {string} connect Connect string.
* @property {string} [prefix='emitter-pubsub-broker:'] Prefix.
* @property {string} [connect] Connect string for a connector.
* @property {string} [prefix='emitter-pubsub-broker:'] Prefix for a connector.
* @property {boolean} [includeChannel=false] Include channel as the
* first argument.
* @property {EmitterPubsubBroker.Encoder} [encoder] Optional encoder
* to run before broadcasting.
* @property {string} [method='emit'] An alternative emit method.
* @property {EmitterPubsubBroker.Serialize}
* [serialize=msgpack.encode] Serialisation function to use with a
* connector.
* @property {EmitterPubsubBroker.Deserialize}
* [deserialize=msgpack.decode] Deserialisation function to use with a
* connector.
* @property {Connector} [connector] Custom connector implementation.

@@ -154,2 +193,6 @@ */

this.prefix = options.prefix || 'emitter-pubsub-broker:';
this.method = options.method || 'emit';
this.serialize = options.serialize || msgpack.encode;
this.deserialize = options.deserialize || msgpack.decode;
this.encoder = options.encoder;
this.includeChannel = options.includeChannel;

@@ -160,6 +203,6 @@ this.clientChannels = new Map();

this.connector = options.connector || new RedisConnector(options.connect);
this.serialize = true;
this.useSerialization = true;
} else {
this.connector = new MemoryConnector();
this.serialize = false;
this.useSerialization = false;
}

@@ -177,8 +220,9 @@ this.connector.on('message', this._dispatch.bind(this));

_channelAddClient(client, ch) {
let clients = this.channelClients.get(ch);
_channelAddClient(client, channel) {
let clients = this.channelClients.get(channel);
if (clients == null) {
clients = new Set();
this.channelClients.set(ch, clients);
this.channelClients.set(channel, clients);
clients.add(client);
let ch = this.prefix + channel;
return this.connector.subscribe(ch);

@@ -191,4 +235,4 @@ } else {

_channelRemoveClient(client, ch) {
let clients = this.channelClients.get(ch);
_channelRemoveClient(client, channel) {
let clients = this.channelClients.get(channel);
let nclients;

@@ -200,2 +244,3 @@ if (clients != null) {

if (nclients === 0) {
let ch = this.prefix + channel;
return this.connector.unsubscribe(ch);

@@ -208,5 +253,9 @@ } else {

_makeMessage(msg) {
return this.serialize ? msgpack.encode(msg) : msg;
return Promise.try(() => this.useSerialization ? this.serialize(msg) : msg);
}
_unpackMessage(data) {
return Promise.try(() => this.useSerialization ? this.deserialize(data) : data);
}
/**

@@ -225,5 +274,4 @@ * Subscribes emitter to a channel.

}
let ch = this.prefix + channel;
channels.add(ch);
return this._channelAddClient(client, ch);
channels.add(channel);
return this._channelAddClient(client, channel);
}

@@ -240,11 +288,10 @@

let channels = this.clientChannels.get(client);
let ch = this.prefix + channel;
if (channels) {
channels.delete(ch);
channels.delete(channel);
}
return this._channelRemoveClient(client, ch);
return this._channelRemoveClient(client, channel);
}
/**
* Unsubscribes emitter from all channel.
* Unsubscribes emitter from all channels.
*

@@ -254,3 +301,3 @@ * @param {EventEmitter} client Emitter.

*/
unsubscribeall(client) {
unsubscribeAll(client) {
let channels = this.clientChannels.get(client);

@@ -279,4 +326,3 @@ this.clientChannels.delete(client);

let ch = this.prefix + channel;
let msg = this._makeMessage({ name: name, args: args });
return this.connector.publish(ch, msg);
return this._makeMessage({ name: name, args: args }).then(msg => this.connector.publish(ch, msg));
}

@@ -301,25 +347,28 @@

let sender = client.id;
let msg = this._makeMessage({ sender: sender, name: name, args: args });
return this.connector.publish(ch, msg);
return this._makeMessage({ sender: sender, name: name, args: args }).then(msg => this.connector.publish(ch, msg));
}
/**
* Returns client subscriptions.
* Returns set of client subscriptions. The result __MUST NOT__ be
* modified.
*
* @param {EventEmitter} client Emitter.
* @return {Array<string>}
* @return {Set<string>|undefined}
*/
getSubscriptions(client) {
let channels = this.clientChannels.get(client);
let res = [];
if (channels) {
let plen = this.prefix.length;
for (let channel of channels) {
res.push(channel.slice(plen));
}
}
return res;
return this.clientChannels.get(client);
}
/**
* Returns _internal_ set of channel clients of EmitterPubsubBroker
* instance. The result __MUST NOT__ be modified.
*
* @param {string} channel Channel.
* @return {Set<EventEmitter>|undefined}
*/
getClients(channel) {
return this.channelClients.get(channel);
}
/**
* Closes broker.

@@ -336,19 +385,20 @@ *

_dispatch(ch, data) {
let channel = ch.slice(this.prefix.length);
let message = this.serialize ? msgpack.decode(data) : data;
let clients = this.channelClients.get(ch);
/* istanbul ignore else */
if (clients) {
let args;
if (this.includeChannel) {
args = [message.name, channel].concat(_toConsumableArray(message.args));
} else {
args = [message.name].concat(_toConsumableArray(message.args));
this._unpackMessage(data).then(message => {
let channel = ch.slice(this.prefix.length);
let clients = this.channelClients.get(channel);
/* istanbul ignore else */
if (clients) {
let args = this.includeChannel ? [message.name, channel].concat(_toConsumableArray(message.args)) : [message.name].concat(_toConsumableArray(message.args));
Promise.try(() => this.encoder ? this.encoder(args) : args).then(data => {
const method = this.method;
const encoder = this.encoder;
const sender = message.sender;
clients.forEach(client => {
if (!sender || client.id !== sender) {
Promise.try(() => encoder ? client[method](data) : client[method].apply(client, _toConsumableArray(data))).catchReturn();
}
});
});
}
for (let client of clients) {
if (!message.sender || client.id !== message.sender) {
client.emit.apply(client, _toConsumableArray(args));
}
}
}
});
}

@@ -358,3 +408,6 @@

// compatibility
EmitterPubsubBroker.prototype.unsubscribeall = EmitterPubsubBroker.prototype.unsubscribeAll;
module.exports = EmitterPubsubBroker;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9FbWl0dGVyUHVic3ViQnJva2VyLmpzIl0sIm5hbWVzIjpbIlByb21pc2UiLCJyZXF1aXJlIiwiUmVkaXMiLCJtc2dwYWNrIiwiRXZlbnRFbWl0dGVyIiwiUmVkaXNDb25uZWN0b3IiLCJjb25zdHJ1Y3RvciIsIm9wdGlvbnMiLCJwdWIiLCJzdWIiLCJzdWJzY3JpYmUiLCJjYXRjaFJldHVybiIsIm9uIiwiX29uTWVzc2FnZSIsImJpbmQiLCJlbWl0IiwiYnVmIiwiZGF0YSIsImNoIiwidG9TdHJpbmciLCJwdWJsaXNoIiwidW5zdWJzY3JpYmUiLCJjbG9zZSIsImFsbCIsInF1aXQiLCJNZW1vcnlDb25uZWN0b3IiLCJyZXNvbHZlIiwidGhlbiIsIkVtaXR0ZXJQdWJzdWJCcm9rZXIiLCJjb25uZWN0IiwicHJlZml4IiwiaW5jbHVkZUNoYW5uZWwiLCJjbGllbnRDaGFubmVscyIsIk1hcCIsImNoYW5uZWxDbGllbnRzIiwiY29ubmVjdG9yIiwic2VyaWFsaXplIiwiX2Rpc3BhdGNoIiwiX2NoYW5uZWxBZGRDbGllbnQiLCJjbGllbnQiLCJjbGllbnRzIiwiZ2V0IiwiU2V0Iiwic2V0IiwiYWRkIiwiX2NoYW5uZWxSZW1vdmVDbGllbnQiLCJuY2xpZW50cyIsImRlbGV0ZSIsInNpemUiLCJfbWFrZU1lc3NhZ2UiLCJtc2ciLCJlbmNvZGUiLCJjaGFubmVsIiwiY2hhbm5lbHMiLCJ1bnN1YnNjcmliZWFsbCIsImVhY2giLCJuYW1lIiwiYXJncyIsInNlbmQiLCJzZW5kZXIiLCJpZCIsImdldFN1YnNjcmlwdGlvbnMiLCJyZXMiLCJwbGVuIiwibGVuZ3RoIiwicHVzaCIsInNsaWNlIiwiY2xlYXIiLCJtZXNzYWdlIiwiZGVjb2RlIiwibW9kdWxlIiwiZXhwb3J0cyJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7QUFFQSxNQUFNQSxVQUFVQyxRQUFRLFVBQVIsQ0FBaEI7QUFDQSxNQUFNQyxRQUFRRCxRQUFRLFNBQVIsQ0FBZDtBQUNBLE1BQU1FLFVBQVVG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LElBQWhCLEVBQXNCSixPQUF0Qiw0QkFBa0NnQixRQUFRWCxJQUExQztBQUNELE9BRkQsTUFFTztBQUNMQSxnQkFBUVcsUUFBUVosSUFBaEIsNEJBQXlCWSxRQUFRWCxJQUFqQztBQUNEO0FBQ0QsV0FBSyxJQUFJbEIsTUFBVCxJQUFtQkMsT0FBbkIsRUFBNEI7QUFDMUIsWUFBSSxDQUFDNEIsUUFBUVQsTUFBVCxJQUFtQnBCLE9BQU9xQixFQUFQLEtBQWNRLFFBQVFULE1BQTdDLEVBQXFEO0FBQ25EcEIsaUJBQU94QixJQUFQLGtDQUFlMEMsSUFBZjtBQUNEO0FBQ0Y7QUFDRjtBQUNGOztBQW5NNEM7O0FBdU0vQ2EsT0FBT0MsT0FBUCxHQUFpQjNDLG1CQUFqQiIsImZpbGUiOiJFbWl0dGVyUHVic3ViQnJva2VyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnXG5cbmNvbnN0IFByb21pc2UgPSByZXF1aXJlKCdibHVlYmlyZCcpXG5jb25zdCBSZWRpcyA9IHJlcXVpcmUoJ2lvcmVkaXMnKVxuY29uc3QgbXNncGFjayA9IHJlcXVpcmUoJ21zZ3BhY2stbGl0ZScpXG5jb25zdCB7IEV2ZW50RW1pdHRlciB9ID0gcmVxdWlyZSgnZXZlbnRlbWl0dGVyMycpXG5cbi8qKlxuICogSW50ZXJmYWNlIGZvciBjb25uZWN0b3IgaW1wbGVtZW50YXRpb25zLlxuICpcbiAqIEBpbnRlcmZhY2UgQ29ubmVjdG9yXG4gKiBAZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAqL1xuXG4vKipcbiAqIEBtZXRob2RcbiAqIEBpbnN0YW5jZVxuICogQG5hbWUgcHVibGlzaFxuICogQG1lbWJlck9mIENvbm5lY3RvclxuICogQHBhcmFtIHtzdHJpbmd9IGNoYW5uZWwgQ2hhbm5lbC5cbiAqIEBwYXJhbSB7QnVmZmVyfSBkYXRhIERhdGEuXG4gKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59XG4gKi9cblxuLyoqXG4gKiBAbWV0aG9kXG4gKiBAaW5zdGFuY2VcbiAqIEBuYW1lIHN1YnNjcmliZVxuICogQG1lbWJlck9mIENvbm5lY3RvclxuICogQHBhcmFtIHtzdHJpbmd9IGNoYW5uZWwgQ2hhbm5lbC5cbiAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn1cbiAqL1xuXG4vKipcbiAqIEBtZXRob2RcbiAqIEBpbnN0YW5jZVxuICogQG5hbWUgdW5zdWJzY3JpYmVcbiAqIEBtZW1iZXJPZiBDb25uZWN0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIENoYW5uZWwuXG4gKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59XG4gKi9cblxuLyoqXG4gKiBAbWV0aG9kXG4gKiBAaW5zdGFuY2VcbiAqIEBuYW1lIGNsb3NlXG4gKiBAbWVtYmVyT2YgQ29ubmVjdG9yXG4gKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59XG4gKi9cblxuLyoqXG4gKiBAZXZlbnQgbWVzc2FnZVxuICogQG1lbWJlck9mIENvbm5lY3RvclxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50IEV2ZW50IG5hbWUuXG4gKiBAcGFyYW0ge0J1ZmZlcn0gZGF0YSBFdmVudCBkYXRhLlxuICovXG5cbi8qKlxuICogRXZlbnQgd2lsbCBiZSBsaXN0ZW5lZCBieSB7QGxpbmsgRW1pdHRlclB1YnN1YkJyb2tlcn0gaW5zdGFuY2UuXG4gKlxuICogQGV2ZW50IGVycm9yXG4gKiBAbWVtYmVyT2YgQ29ubmVjdG9yXG4gKiBAcGFyYW0ge0Vycm9yfSBlcnJvciBFcnJvci5cbiAqL1xuXG5jbGFzcyBSZWRpc0Nvbm5lY3RvciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIGNvbnN0cnVjdG9yIChvcHRpb25zKSB7XG4gICAgc3VwZXIoKVxuICAgIHRoaXMucHViID0gbmV3IFJlZGlzKG9wdGlvbnMpXG4gICAgdGhpcy5zdWIgPSBuZXcgUmVkaXMob3B0aW9ucylcbiAgICB0aGlzLnN1Yi5zdWJzY3JpYmUoKS5jYXRjaFJldHVybigpXG4gICAgdGhpcy5zdWIub24oJ21lc3NhZ2VCdWZmZXInLCB0aGlzLl9vbk1lc3NhZ2UuYmluZCh0aGlzKSlcbiAgICB0aGlzLnN1Yi5vbignZXJyb3InLCB0aGlzLmVtaXQuYmluZCh0aGlzKSlcbiAgICB0aGlzLnB1Yi5vbignZXJyb3InLCB0aGlzLmVtaXQuYmluZCh0aGlzKSlcbiAgfVxuXG4gIF9vbk1lc3NhZ2UgKGJ1ZiwgZGF0YSkge1xuICAgIGxldCBjaCA9IGJ1Zi50b1N0cmluZygpXG4gICAgdGhpcy5lbWl0KCdtZXNzYWdlJywgY2gsIGRhdGEpXG4gIH1cblxuICBwdWJsaXNoIChjaCwgZGF0YSkge1xuICAgIHJldHVybiB0aGlzLnB1Yi5wdWJsaXNoKGNoLCBkYXRhKVxuICB9XG5cbiAgc3Vic2NyaWJlIChjaCkge1xuICAgIHJldHVybiB0aGlzLnN1Yi5zdWJzY3JpYmUoY2gpXG4gIH1cblxuICB1bnN1YnNjcmliZSAoY2gpIHtcbiAgICByZXR1cm4gdGhpcy5zdWIudW5zdWJzY3JpYmUoY2gpXG4gIH1cblxuICBjbG9zZSAoKSB7XG4gICAgcmV0dXJuIFByb21pc2UuYWxsKFt0aGlzLnB1Yi5xdWl0KCksIHRoaXMuc3ViLnF1aXQoKV0pXG4gIH1cbn1cblxuY2xhc3MgTWVtb3J5Q29ubmVjdG9yIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgY29uc3RydWN0b3IgKG9wdGlvbnMpIHtcbiAgICBzdXBlcigpXG4gIH1cblxuICBwdWJsaXNoIChjaCwgZGF0YSkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgICAgLnRoZW4oKCkgPT4gdGhpcy5lbWl0KCdtZXNzYWdlJywgY2gsIGRhdGEpKVxuICB9XG5cbiAgc3Vic2NyaWJlIChjaCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG5cbiAgdW5zdWJzY3JpYmUgKGNoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cblxuICBjbG9zZSAoKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gIH1cbn1cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBFbWl0dGVyUHVic3ViQnJva2VyLk9wdGlvbnNcbiAqXG4gKiBAcHJvcGVydHkge3N0cmluZ30gY29ubmVjdCBDb25uZWN0IHN0cmluZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbcHJlZml4PSdlbWl0dGVyLXB1YnN1Yi1icm9rZXI6J10gUHJlZml4LlxuICogQHByb3BlcnR5IHtib29sZWFufSBbaW5jbHVkZUNoYW5uZWw9ZmFsc2VdIEluY2x1ZGUgY2hhbm5lbCBhcyB0aGVcbiAqIGZpcnN0IGFyZ3VtZW50LlxuICogQHByb3BlcnR5IHtDb25uZWN0b3J9IFtjb25uZWN0b3JdIEN1c3RvbSBjb25uZWN0b3IgaW1wbGVtZW50YXRpb24uXG4gKi9cblxuLyoqXG4gKiBAZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAqL1xuY2xhc3MgRW1pdHRlclB1YnN1YkJyb2tlciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgYnJva2VyLlxuICAgKlxuICAgKiBAcGFyYW0ge0VtaXR0ZXJQdWJzdWJCcm9rZXIuT3B0aW9uc3xzdHJpbmd9IG9wdGlvbnMgT3B0aW9ucyBvciBhXG4gICAqIGNvbm5lY3QgaWYgYSBzdHJpbmcuIElmIGNvbm5lY3Qgc3RyaW5nIGlzIGVtcHR5LCB0aGVuIGFuXG4gICAqIGluLW1lbW9yeSBjb25uZWN0b3IgaXMgdXNlZC5cbiAgICovXG4gIGNvbnN0cnVjdG9yIChvcHRpb25zKSB7XG4gICAgc3VwZXIoKVxuICAgIGlmIChvcHRpb25zID09IG51bGwgfHwgdHlwZW9mIG9wdGlvbnMgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zID0geyBjb25uZWN0OiBvcHRpb25zIH1cbiAgICB9XG4gICAgdGhpcy5wcmVmaXggPSBvcHRpb25zLnByZWZpeCB8fCAnZW1pdHRlci1wdWJzdWItYnJva2VyOidcbiAgICB0aGlzLmluY2x1ZGVDaGFubmVsID0gb3B0aW9ucy5pbmNsdWRlQ2hhbm5lbFxuICAgIHRoaXMuY2xpZW50Q2hhbm5lbHMgPSBuZXcgTWFwKClcbiAgICB0aGlzLmNoYW5uZWxDbGllbnRzID0gbmV3IE1hcCgpXG4gICAgaWYgKG9wdGlvbnMuY29ubmVjdCB8fCBvcHRpb25zLmNvbm5lY3Rvcikge1xuICAgICAgdGhpcy5jb25uZWN0b3IgPSBvcHRpb25zLmNvbm5lY3RvciB8fCBuZXcgUmVkaXNDb25uZWN0b3Iob3B0aW9ucy5jb25uZWN0KVxuICAgICAgdGhpcy5zZXJpYWxpemUgPSB0cnVlXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY29ubmVjdG9yID0gbmV3IE1lbW9yeUNvbm5lY3RvcigpXG4gICAgICB0aGlzLnNlcmlhbGl6ZSA9IGZhbHNlXG4gICAgfVxuICAgIHRoaXMuY29ubmVjdG9yLm9uKCdtZXNzYWdlJywgdGhpcy5fZGlzcGF0Y2guYmluZCh0aGlzKSlcbiAgICAvKipcbiAgICAgKiBDb25uZWN0b3IgZXJyb3IuIERvZXMgbm90IHRocm93IGlmIHRoZXJlIGFyZSBubyBsaXN0ZW5lcnMuXG4gICAgICpcbiAgICAgKiBAZXZlbnQgZXJyb3JcbiAgICAgKiBAbWVtYmVyT2YgRW1pdHRlclB1YnN1YkJyb2tlclxuICAgICAqIEBwYXJhbSB7RXJyb3J9IGVycm9yIEVycm9yLlxuICAgICAqL1xuICAgIHRoaXMuY29ubmVjdG9yLm9uKCdlcnJvcicsIHRoaXMuZW1pdC5iaW5kKHRoaXMpKVxuICB9XG5cbiAgX2NoYW5uZWxBZGRDbGllbnQgKGNsaWVudCwgY2gpIHtcbiAgICBsZXQgY2xpZW50cyA9IHRoaXMuY2hhbm5lbENsaWVudHMuZ2V0KGNoKVxuICAgIGlmIChjbGllbnRzID09IG51bGwpIHtcbiAgICAgIGNsaWVudHMgPSBuZXcgU2V0KClcbiAgICAgIHRoaXMuY2hhbm5lbENsaWVudHMuc2V0KGNoLCBjbGllbnRzKVxuICAgICAgY2xpZW50cy5hZGQoY2xpZW50KVxuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdG9yLnN1YnNjcmliZShjaClcbiAgICB9IGVsc2Uge1xuICAgICAgY2xpZW50cy5hZGQoY2xpZW50KVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgfVxuICB9XG5cbiAgX2NoYW5uZWxSZW1vdmVDbGllbnQgKGNsaWVudCwgY2gpIHtcbiAgICBsZXQgY2xpZW50cyA9IHRoaXMuY2hhbm5lbENsaWVudHMuZ2V0KGNoKVxuICAgIGxldCBuY2xpZW50c1xuICAgIGlmIChjbGllbnRzICE9IG51bGwpIHtcbiAgICAgIGNsaWVudHMuZGVsZXRlKGNsaWVudClcbiAgICAgIG5jbGllbnRzID0gY2xpZW50cy5zaXplXG4gICAgfVxuICAgIGlmIChuY2xpZW50cyA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdG9yLnVuc3Vic2NyaWJlKGNoKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICB9XG4gIH1cblxuICBfbWFrZU1lc3NhZ2UgKG1zZykge1xuICAgIHJldHVybiB0aGlzLnNlcmlhbGl6ZSA/IG1zZ3BhY2suZW5jb2RlKG1zZykgOiBtc2dcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWJzY3JpYmVzIGVtaXR0ZXIgdG8gYSBjaGFubmVsLlxuICAgKlxuICAgKiBAcGFyYW0ge0V2ZW50RW1pdHRlcn0gY2xpZW50IEVtaXR0ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIENoYW5uZWwuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn1cbiAgICovXG4gIHN1YnNjcmliZSAoY2xpZW50LCBjaGFubmVsKSB7XG4gICAgbGV0IGNoYW5uZWxzID0gdGhpcy5jbGllbnRDaGFubmVscy5nZXQoY2xpZW50KVxuICAgIGlmICghY2hhbm5lbHMpIHtcbiAgICAgIGNoYW5uZWxzID0gbmV3IFNldCgpXG4gICAgICB0aGlzLmNsaWVudENoYW5uZWxzLnNldChjbGllbnQsIGNoYW5uZWxzKVxuICAgIH1cbiAgICBsZXQgY2ggPSB0aGlzLnByZWZpeCArIGNoYW5uZWxcbiAgICBjaGFubmVscy5hZGQoY2gpXG4gICAgcmV0dXJuIHRoaXMuX2NoYW5uZWxBZGRDbGllbnQoY2xpZW50LCBjaClcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnN1YnNjcmliZXMgZW1pdHRlciBmcm9tIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IGNsaWVudCBFbWl0dGVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hhbm5lbCBDaGFubmVsLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59XG4gICAqL1xuICB1bnN1YnNjcmliZSAoY2xpZW50LCBjaGFubmVsKSB7XG4gICAgbGV0IGNoYW5uZWxzID0gdGhpcy5jbGllbnRDaGFubmVscy5nZXQoY2xpZW50KVxuICAgIGxldCBjaCA9IHRoaXMucHJlZml4ICsgY2hhbm5lbFxuICAgIGlmIChjaGFubmVscykge1xuICAgICAgY2hhbm5lbHMuZGVsZXRlKGNoKVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY2hhbm5lbFJlbW92ZUNsaWVudChjbGllbnQsIGNoKVxuICB9XG5cbiAgLyoqXG4gICAqIFVuc3Vic2NyaWJlcyBlbWl0dGVyIGZyb20gYWxsIGNoYW5uZWwuXG4gICAqXG4gICAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSBjbGllbnQgRW1pdHRlci5cbiAgICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fVxuICAgKi9cbiAgdW5zdWJzY3JpYmVhbGwgKGNsaWVudCkge1xuICAgIGxldCBjaGFubmVscyA9IHRoaXMuY2xpZW50Q2hhbm5lbHMuZ2V0KGNsaWVudClcbiAgICB0aGlzLmNsaWVudENoYW5uZWxzLmRlbGV0ZShjbGllbnQpXG4gICAgaWYgKGNoYW5uZWxzKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5lYWNoKFxuICAgICAgICBjaGFubmVscywgdGhpcy5fY2hhbm5lbFJlbW92ZUNsaWVudC5iaW5kKHRoaXMsIGNsaWVudCkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaXNoIGFuIGV2ZW50IHRvIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNoYW5uZWwgQ2hhbm5lbC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgRXZlbnQgbmFtZS5cbiAgICogQHBhcmFtIHsqfSBhcmdzIEFyZ3VtZW50cy5cbiAgICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fVxuICAgKi9cbiAgcHVibGlzaCAoY2hhbm5lbCwgbmFtZSwgLi4uYXJncykge1xuICAgIGxldCBjaCA9IHRoaXMucHJlZml4ICsgY2hhbm5lbFxuICAgIGxldCBtc2cgPSB0aGlzLl9tYWtlTWVzc2FnZSh7bmFtZSwgYXJnc30pXG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdG9yLnB1Ymxpc2goY2gsIG1zZylcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaXNoIGFuIGV2ZW50IHRvIGEgY2hhbm5lbCwgZXhjbHVkaW5nIHRoZSBzZW5kZXIuIFRoZSBjbGllbnRcbiAgICogb2JqZWN0IF9fTVVTVF9fIGhhdmUgYW4gdW5pcXVlIGBpZGAgZmllbGQuXG4gICAqXG4gICAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSBjbGllbnQgRW1pdHRlci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGNoYW5uZWwgQ2hhbm5lbC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgRXZlbnQgbmFtZS5cbiAgICogQHBhcmFtIHsqfSBhcmdzIEFyZ3VtZW50cy5cbiAgICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fVxuICAgKi9cbiAgc2VuZCAoY2xpZW50LCBjaGFubmVsLCBuYW1lLCAuLi5hcmdzKSB7XG4gICAgbGV0IGNoID0gdGhpcy5wcmVmaXggKyBjaGFubmVsXG4gICAgbGV0IHNlbmRlciA9IGNsaWVudC5pZFxuICAgIGxldCBtc2cgPSB0aGlzLl9tYWtlTWVzc2FnZSh7c2VuZGVyLCBuYW1lLCBhcmdzfSlcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0b3IucHVibGlzaChjaCwgbXNnKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgY2xpZW50IHN1YnNjcmlwdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSBjbGllbnQgRW1pdHRlci5cbiAgICogQHJldHVybiB7QXJyYXk8c3RyaW5nPn1cbiAgICovXG4gIGdldFN1YnNjcmlwdGlvbnMgKGNsaWVudCkge1xuICAgIGxldCBjaGFubmVscyA9IHRoaXMuY2xpZW50Q2hhbm5lbHMuZ2V0KGNsaWVudClcbiAgICBsZXQgcmVzID0gW11cbiAgICBpZiAoY2hhbm5lbHMpIHtcbiAgICAgIGxldCBwbGVuID0gdGhpcy5wcmVmaXgubGVuZ3RoXG4gICAgICBmb3IgKGxldCBjaGFubmVsIG9mIGNoYW5uZWxzKSB7XG4gICAgICAgIHJlcy5wdXNoKGNoYW5uZWwuc2xpY2UocGxlbikpXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXNcbiAgfVxuXG4gIC8qKlxuICAgKiBDbG9zZXMgYnJva2VyLlxuICAgKlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59XG4gICAqL1xuICBjbG9zZSAoKSB7XG4gICAgdGhpcy5jaGFubmVsQ2xpZW50cy5jbGVhcigpXG4gICAgdGhpcy5jbGllbnRDaGFubmVscy5jbGVhcigpXG4gICAgcmV0dXJuIHRoaXMuY29ubmVjdG9yLmNsb3NlKClcbiAgfVxuXG4gIF9kaXNwYXRjaCAoY2gsIGRhdGEpIHtcbiAgICBsZXQgY2hhbm5lbCA9IGNoLnNsaWNlKHRoaXMucHJlZml4Lmxlbmd0aClcbiAgICBsZXQgbWVzc2FnZSA9IHRoaXMuc2VyaWFsaXplID8gbXNncGFjay5kZWNvZGUoZGF0YSkgOiBkYXRhXG4gICAgbGV0IGNsaWVudHMgPSB0aGlzLmNoYW5uZWxDbGllbnRzLmdldChjaClcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChjbGllbnRzKSB7XG4gICAgICBsZXQgYXJnc1xuICAgICAgaWYgKHRoaXMuaW5jbHVkZUNoYW5uZWwpIHtcbiAgICAgICAgYXJncyA9IFttZXNzYWdlLm5hbWUsIGNoYW5uZWwsIC4uLm1lc3NhZ2UuYXJnc11cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFyZ3MgPSBbbWVzc2FnZS5uYW1lLCAuLi5tZXNzYWdlLmFyZ3NdXG4gICAgICB9XG4gICAgICBmb3IgKGxldCBjbGllbnQgb2YgY2xpZW50cykge1xuICAgICAgICBpZiAoIW1lc3NhZ2Uuc2VuZGVyIHx8IGNsaWVudC5pZCAhPT0gbWVzc2FnZS5zZW5kZXIpIHtcbiAgICAgICAgICBjbGllbnQuZW1pdCguLi5hcmdzKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBFbWl0dGVyUHVic3ViQnJva2VyXG4iXX0=
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9FbWl0dGVyUHVic3ViQnJva2VyLmpzIl0sIm5hbWVzIjpbIlByb21pc2UiLCJyZXF1aXJlIiwiUmVkaXMiLCJtc2dwYWNrIiwiRXZlbnRFbWl0dGVyIiwiUmVkaXNDb25uZWN0b3IiLCJjb25zdHJ1Y3RvciIsIm9wdGlvbnMiLCJwdWIiLCJzdWIiLCJzdWJzY3JpYmUiLCJjYXRjaFJldHVybiIsIm9uIiwiX29uTWVzc2FnZSIsImJpbmQiLCJlbWl0IiwiYnVmIiwiZGF0YSIsImNoIiwidG9TdHJpbmciLCJwdWJsaXNoIiwidW5zdWJzY3JpYmUiLCJjbG9zZSIsImFsbCIsInF1aXQiLCJNZW1vcnlDb25uZWN0b3IiLCJyZXNvbHZlIiwidGhlbiIsIkVtaXR0ZXJQdWJzdWJCcm9rZXIiLCJjb25uZWN0IiwicHJlZml4IiwibWV0aG9kIiwic2VyaWFsaXplIiwiZW5jb2RlIiwiZGVzZXJpYWxpemUiLCJkZWNvZGUiLCJlbmNvZGVyIiwiaW5jbHVkZUNoYW5uZWwiLCJjbGllbnRDaGFubmVscyIsIk1hcCIsImNoYW5uZWxDbGllbnRzIiwiY29ubmVjdG9yIiwidXNlU2VyaWFsaXphdGlvbiIsIl9kaXNwYXRjaCIsIl9jaGFubmVsQWRkQ2xpZW50IiwiY2xpZW50IiwiY2hhbm5lbCIsImNsaWVudHMiLCJnZXQiLCJTZXQiLCJzZXQiLCJhZGQiLCJfY2hhbm5lbFJlbW92ZUNsaWVudCIsIm5jbGllbnRzIiwiZGVsZXRlIiwic2l6ZSIsIl9tYWtlTWVzc2FnZSIsIm1zZyIsInRyeSIsIl91bnBhY2tNZXNzYWdlIiwiY2hhbm5lbHMiLCJ1bnN1YnNjcmliZUFsbCIsImVhY2giLCJuYW1lIiwiYXJncyIsInNlbmQiLCJzZW5kZXIiLCJpZCIsImdldFN1YnNjcmlwdGlvbnMiLCJnZXRDbGllbnRzIiwiY2xlYXIiLCJtZXNzYWdlIiwic2xpY2UiLCJsZW5ndGgiLCJmb3JFYWNoIiwicHJvdG90eXBlIiwidW5zdWJzY3JpYmVhbGwiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiQUFBQTs7OztBQUVBLE1BQU1BLFVBQVVDLFFBQVEsVUFBUixDQUFoQjtBQUNBLE1BQU1DLFFBQVFELFFBQVEsU0FBUixDQUFkO0FBQ0EsTUFBTUUsVUFBVUYsUUFBUSxjQUFSLENBQWhCOztlQUN5QkEsUUFBUSxlQUFSLEM7O01BQWpCRyxZLFlBQUFBLFk7O0FBRVI7Ozs7Ozs7QUFPQTs7Ozs7Ozs7OztBQVVBOzs7Ozs7Ozs7QUFTQTs7Ozs7Ozs7O0FBU0E7Ozs7Ozs7O0FBUUE7Ozs7Ozs7QUFPQTs7Ozs7Ozs7QUFRQSxNQUFNQyxjQUFOLFNBQTZCRCxZQUE3QixDQUEwQztBQUN4Q0UsY0FBYUMsT0FBYixFQUFzQjtBQUNwQjtBQUNBLFNBQUtDLEdBQUwsR0FBVyxJQUFJTixLQUFKLENBQVVLLE9BQVYsQ0FBWDtBQUNBLFNBQUtFLEdBQUwsR0FBVyxJQUFJUCxLQUFKLENBQVVLLE9BQVYsQ0FBWDtBQUNBLFNBQUtFLEdBQUwsQ0FBU0MsU0FBVCxHQUFxQkMsV0FBckI7QUFDQSxTQUFLRixHQUFMLENBQVNHLEVBQVQsQ0FBWSxlQUFaLEVBQTZCLEtBQUtDLFVBQUwsQ0FBZ0JDLElBQWhCLENBQXFCLElBQXJCLENBQTdCO0FBQ0EsU0FBS0wsR0FBTCxDQUFTRyxFQUFULENBQVksT0FBWixFQUFxQixLQUFLRyxJQUFMLENBQVVELElBQVYsQ0FBZSxJQUFmLENBQXJCO0FBQ0EsU0FBS04sR0FBTCxDQUFTSSxFQUFULENBQVksT0FBWixFQUFxQixLQUFLRyxJQUFMLENBQVVELElBQVYsQ0FBZSxJQUFmLENBQXJCO0FBQ0Q7O0FBRURELGFBQVlHLEdBQVosRUFBaUJDLElBQWpCLEVBQXVCO0FBQ3JCLFFBQUlDLEtBQUtGLElBQUlHLFFBQUosRUFBVDtBQUNBLFNBQUtKLElBQUwsQ0FBVSxTQUFWLEVBQXFCRyxFQUFyQixFQUF5QkQsSUFBekI7QUFDRDs7QUFFREcsVUFBU0YsRUFBVCxFQUFhRCxJQUFiLEVBQW1CO0FBQ2pCLFdBQU8sS0FBS1QsR0FBTCxDQUFTWSxPQUFULENBQWlCRixFQUFqQixFQUFxQkQsSUFBckIsQ0FBUDtBQUNEOztBQUVEUCxZQUFXUSxFQUFYLEVBQWU7QUFDYixXQUFPLEtBQUtULEdBQUwsQ0FBU0MsU0FBVCxDQUFtQlEsRUFBbkIsQ0FBUDtBQUNEOztBQUVERyxjQUFhSCxFQUFiLEVBQWlCO0FBQ2YsV0FBTyxLQUFLVCxHQUFMLENBQVNZLFdBQVQsQ0FBcUJILEVBQXJCLENBQVA7QUFDRDs7QUFFREksVUFBUztBQUNQLFdBQU90QixRQUFRdUIsR0FBUixDQUFZLENBQUMsS0FBS2YsR0FBTCxDQUFTZ0IsSUFBVCxFQUFELEVBQWtCLEtBQUtmLEdBQUwsQ0FBU2UsSUFBVCxFQUFsQixDQUFaLENBQVA7QUFDRDtBQTlCdUM7O0FBaUMxQyxNQUFNQyxlQUFOLFNBQThCckIsWUFBOUIsQ0FBMkM7QUFDekNFLGNBQWFDLE9BQWIsRUFBc0I7QUFDcEI7QUFDRDs7QUFFRGEsVUFBU0YsRUFBVCxFQUFhRCxJQUFiLEVBQW1CO0FBQ2pCLFdBQU9qQixRQUFRMEIsT0FBUixHQUNKQyxJQURJLENBQ0MsTUFBTSxLQUFLWixJQUFMLENBQVUsU0FBVixFQUFxQkcsRUFBckIsRUFBeUJELElBQXpCLENBRFAsQ0FBUDtBQUVEOztBQUVEUCxZQUFXUSxFQUFYLEVBQWU7QUFDYixXQUFPbEIsUUFBUTBCLE9BQVIsRUFBUDtBQUNEOztBQUVETCxjQUFhSCxFQUFiLEVBQWlCO0FBQ2YsV0FBT2xCLFFBQVEwQixPQUFSLEVBQVA7QUFDRDs7QUFFREosVUFBUztBQUNQLFdBQU90QixRQUFRMEIsT0FBUixFQUFQO0FBQ0Q7QUFwQndDOztBQXVCM0M7Ozs7Ozs7Ozs7QUFVQTs7Ozs7Ozs7OztBQVVBOzs7Ozs7Ozs7O0FBVUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFtQkE7OztBQUdBLE1BQU1FLG1CQUFOLFNBQWtDeEIsWUFBbEMsQ0FBK0M7QUFDN0M7Ozs7Ozs7QUFPQUUsY0FBYUMsT0FBYixFQUFzQjtBQUNwQjtBQUNBLFFBQUlBLFdBQVcsSUFBWCxJQUFtQixPQUFPQSxPQUFQLEtBQW1CLFFBQTFDLEVBQW9EO0FBQ2xEQSxnQkFBVSxFQUFFc0IsU0FBU3RCLE9BQVgsRUFBVjtBQUNEO0FBQ0QsU0FBS3VCLE1BQUwsR0FBY3ZCLFFBQVF1QixNQUFSLElBQWtCLHdCQUFoQztBQUNBLFNBQUtDLE1BQUwsR0FBY3hCLFFBQVF3QixNQUFSLElBQWtCLE1BQWhDO0FBQ0EsU0FBS0MsU0FBTCxHQUFpQnpCLFFBQVF5QixTQUFSLElBQXFCN0IsUUFBUThCLE1BQTlDO0FBQ0EsU0FBS0MsV0FBTCxHQUFtQjNCLFFBQVEyQixXQUFSLElBQXVCL0IsUUFBUWdDLE1BQWxEO0FBQ0EsU0FBS0MsT0FBTCxHQUFlN0IsUUFBUTZCLE9BQXZCO0FBQ0EsU0FBS0MsY0FBTCxHQUFzQjlCLFFBQVE4QixjQUE5QjtBQUNBLFNBQUtDLGNBQUwsR0FBc0IsSUFBSUMsR0FBSixFQUF0QjtBQUNBLFNBQUtDLGNBQUwsR0FBc0IsSUFBSUQsR0FBSixFQUF0QjtBQUNBLFFBQUloQyxRQUFRc0IsT0FBUixJQUFtQnRCLFFBQVFrQyxTQUEvQixFQUEwQztBQUN4QyxXQUFLQSxTQUFMLEdBQWlCbEMsUUFBUWtDLFNBQVIsSUFBcUIsSUFBSXBDLGNBQUosQ0FBbUJFLFFBQVFzQixPQUEzQixDQUF0QztBQUNBLFdBQUthLGdCQUFMLEdBQXdCLElBQXhCO0FBQ0QsS0FIRCxNQUdPO0FBQ0wsV0FBS0QsU0FBTCxHQUFpQixJQUFJaEIsZUFBSixFQUFqQjtBQUNBLFdBQUtpQixnQkFBTCxHQUF3QixLQUF4QjtBQUNEO0FBQ0QsU0FBS0QsU0FBTCxDQUFlN0IsRUFBZixDQUFrQixTQUFsQixFQUE2QixLQUFLK0IsU0FBTCxDQUFlN0IsSUFBZixDQUFvQixJQUFwQixDQUE3QjtBQUNBOzs7Ozs7O0FBT0EsU0FBSzJCLFNBQUwsQ0FBZTdCLEVBQWYsQ0FBa0IsT0FBbEIsRUFBMkIsS0FBS0csSUFBTCxDQUFVRCxJQUFWLENBQWUsSUFBZixDQUEzQjtBQUNEOztBQUVEOEIsb0JBQW1CQyxNQUFuQixFQUEyQkMsT0FBM0IsRUFBb0M7QUFDbEMsUUFBSUMsVUFBVSxLQUFLUCxjQUFMLENBQW9CUSxHQUFwQixDQUF3QkYsT0FBeEIsQ0FBZDtBQUNBLFFBQUlDLFdBQVcsSUFBZixFQUFxQjtBQUNuQkEsZ0JBQVUsSUFBSUUsR0FBSixFQUFWO0FBQ0EsV0FBS1QsY0FBTCxDQUFvQlUsR0FBcEIsQ0FBd0JKLE9BQXhCLEVBQWlDQyxPQUFqQztBQUNBQSxjQUFRSSxHQUFSLENBQVlOLE1BQVo7QUFDQSxVQUFJM0IsS0FBSyxLQUFLWSxNQUFMLEdBQWNnQixPQUF2QjtBQUNBLGFBQU8sS0FBS0wsU0FBTCxDQUFlL0IsU0FBZixDQUF5QlEsRUFBekIsQ0FBUDtBQUNELEtBTkQsTUFNTztBQUNMNkIsY0FBUUksR0FBUixDQUFZTixNQUFaO0FBQ0EsYUFBTzdDLFFBQVEwQixPQUFSLEVBQVA7QUFDRDtBQUNGOztBQUVEMEIsdUJBQXNCUCxNQUF0QixFQUE4QkMsT0FBOUIsRUFBdUM7QUFDckMsUUFBSUMsVUFBVSxLQUFLUCxjQUFMLENBQW9CUSxHQUFwQixDQUF3QkYsT0FBeEIsQ0FBZDtBQUNBLFFBQUlPLFFBQUo7QUFDQSxRQUFJTixXQUFXLElBQWYsRUFBcUI7QUFDbkJBLGNBQVFPLE1BQVIsQ0FBZVQsTUFBZjtBQUNBUSxpQkFBV04sUUFBUVEsSUFBbkI7QUFDRDtBQUNELFFBQUlGLGFBQWEsQ0FBakIsRUFBb0I7QUFDbEIsVUFBSW5DLEtBQUssS0FBS1ksTUFBTCxHQUFjZ0IsT0FBdkI7QUFDQSxhQUFPLEtBQUtMLFNBQUwsQ0FBZXBCLFdBQWYsQ0FBMkJILEVBQTNCLENBQVA7QUFDRCxLQUhELE1BR087QUFDTCxhQUFPbEIsUUFBUTBCLE9BQVIsRUFBUDtBQUNEO0FBQ0Y7O0FBRUQ4QixlQUFjQyxHQUFkLEVBQW1CO0FBQ2pCLFdBQU96RCxRQUFRMEQsR0FBUixDQUFZLE1BQU0sS0FBS2hCLGdCQUFMLEdBQXdCLEtBQUtWLFNBQUwsQ0FBZXlCLEdBQWYsQ0FBeEIsR0FBOENBLEdBQWhFLENBQVA7QUFDRDs7QUFFREUsaUJBQWdCMUMsSUFBaEIsRUFBc0I7QUFDcEIsV0FBT2pCLFFBQVEwRCxHQUFSLENBQVksTUFBTSxLQUFLaEIsZ0JBQUwsR0FBd0IsS0FBS1IsV0FBTCxDQUFpQmpCLElBQWpCLENBQXhCLEdBQWlEQSxJQUFuRSxDQUFQO0FBQ0Q7O0FBRUQ7Ozs7Ozs7QUFPQVAsWUFBV21DLE1BQVgsRUFBbUJDLE9BQW5CLEVBQTRCO0FBQzFCLFFBQUljLFdBQVcsS0FBS3RCLGNBQUwsQ0FBb0JVLEdBQXBCLENBQXdCSCxNQUF4QixDQUFmO0FBQ0EsUUFBSSxDQUFDZSxRQUFMLEVBQWU7QUFDYkEsaUJBQVcsSUFBSVgsR0FBSixFQUFYO0FBQ0EsV0FBS1gsY0FBTCxDQUFvQlksR0FBcEIsQ0FBd0JMLE1BQXhCLEVBQWdDZSxRQUFoQztBQUNEO0FBQ0RBLGFBQVNULEdBQVQsQ0FBYUwsT0FBYjtBQUNBLFdBQU8sS0FBS0YsaUJBQUwsQ0FBdUJDLE1BQXZCLEVBQStCQyxPQUEvQixDQUFQO0FBQ0Q7O0FBRUQ7Ozs7Ozs7QUFPQXpCLGNBQWF3QixNQUFiLEVBQXFCQyxPQUFyQixFQUE4QjtBQUM1QixRQUFJYyxXQUFXLEtBQUt0QixjQUFMLENBQW9CVSxHQUFwQixDQUF3QkgsTUFBeEIsQ0FBZjtBQUNBLFFBQUllLFFBQUosRUFBYztBQUNaQSxlQUFTTixNQUFULENBQWdCUixPQUFoQjtBQUNEO0FBQ0QsV0FBTyxLQUFLTSxvQkFBTCxDQUEwQlAsTUFBMUIsRUFBa0NDLE9BQWxDLENBQVA7QUFDRDs7QUFFRDs7Ozs7O0FBTUFlLGlCQUFnQmhCLE1BQWhCLEVBQXdCO0FBQ3RCLFFBQUllLFdBQVcsS0FBS3RCLGNBQUwsQ0FBb0JVLEdBQXBCLENBQXdCSCxNQUF4QixDQUFmO0FBQ0EsU0FBS1AsY0FBTCxDQUFvQmdCLE1BQXBCLENBQTJCVCxNQUEzQjtBQUNBLFFBQUllLFFBQUosRUFBYztBQUNaLGFBQU81RCxRQUFROEQsSUFBUixDQUNMRixRQURLLEVBQ0ssS0FBS1Isb0JBQUwsQ0FBMEJ0QyxJQUExQixDQUErQixJQUEvQixFQUFxQytCLE1BQXJDLENBREwsQ0FBUDtBQUVELEtBSEQsTUFHTztBQUNMLGFBQU83QyxRQUFRMEIsT0FBUixFQUFQO0FBQ0Q7QUFDRjs7QUFFRDs7Ozs7Ozs7QUFRQU4sVUFBUzBCLE9BQVQsRUFBa0JpQixJQUFsQixFQUFpQztBQUFBLHNDQUFOQyxJQUFNO0FBQU5BLFVBQU07QUFBQTs7QUFDL0IsUUFBSTlDLEtBQUssS0FBS1ksTUFBTCxHQUFjZ0IsT0FBdkI7QUFDQSxXQUFPLEtBQUtVLFlBQUwsQ0FBa0IsRUFBQ08sVUFBRCxFQUFPQyxVQUFQLEVBQWxCLEVBQ0pyQyxJQURJLENBQ0M4QixPQUFPLEtBQUtoQixTQUFMLENBQWVyQixPQUFmLENBQXVCRixFQUF2QixFQUEyQnVDLEdBQTNCLENBRFIsQ0FBUDtBQUVEOztBQUVEOzs7Ozs7Ozs7O0FBVUFRLE9BQU1wQixNQUFOLEVBQWNDLE9BQWQsRUFBdUJpQixJQUF2QixFQUFzQztBQUFBLHVDQUFOQyxJQUFNO0FBQU5BLFVBQU07QUFBQTs7QUFDcEMsUUFBSTlDLEtBQUssS0FBS1ksTUFBTCxHQUFjZ0IsT0FBdkI7QUFDQSxRQUFJb0IsU0FBU3JCLE9BQU9zQixFQUFwQjtBQUNBLFdBQU8sS0FBS1gsWUFBTCxDQUFrQixFQUFDVSxjQUFELEVBQVNILFVBQVQsRUFBZUMsVUFBZixFQUFsQixFQUNKckMsSUFESSxDQUNDOEIsT0FBTyxLQUFLaEIsU0FBTCxDQUFlckIsT0FBZixDQUF1QkYsRUFBdkIsRUFBMkJ1QyxHQUEzQixDQURSLENBQVA7QUFFRDs7QUFFRDs7Ozs7OztBQU9BVyxtQkFBa0J2QixNQUFsQixFQUEwQjtBQUN4QixXQUFPLEtBQUtQLGNBQUwsQ0FBb0JVLEdBQXBCLENBQXdCSCxNQUF4QixDQUFQO0FBQ0Q7O0FBRUQ7Ozs7Ozs7QUFPQXdCLGFBQVl2QixPQUFaLEVBQXFCO0FBQ25CLFdBQU8sS0FBS04sY0FBTCxDQUFvQlEsR0FBcEIsQ0FBd0JGLE9BQXhCLENBQVA7QUFDRDs7QUFFRDs7Ozs7QUFLQXhCLFVBQVM7QUFDUCxTQUFLa0IsY0FBTCxDQUFvQjhCLEtBQXBCO0FBQ0EsU0FBS2hDLGNBQUwsQ0FBb0JnQyxLQUFwQjtBQUNBLFdBQU8sS0FBSzdCLFNBQUwsQ0FBZW5CLEtBQWYsRUFBUDtBQUNEOztBQUVEcUIsWUFBV3pCLEVBQVgsRUFBZUQsSUFBZixFQUFxQjtBQUNuQixTQUFLMEMsY0FBTCxDQUFvQjFDLElBQXBCLEVBQTBCVSxJQUExQixDQUErQjRDLFdBQVc7QUFDeEMsVUFBSXpCLFVBQVU1QixHQUFHc0QsS0FBSCxDQUFTLEtBQUsxQyxNQUFMLENBQVkyQyxNQUFyQixDQUFkO0FBQ0EsVUFBSTFCLFVBQVUsS0FBS1AsY0FBTCxDQUFvQlEsR0FBcEIsQ0FBd0JGLE9BQXhCLENBQWQ7QUFDQTtBQUNBLFVBQUlDLE9BQUosRUFBYTtBQUNYLFlBQUlpQixPQUFPLEtBQUszQixjQUFMLElBQ05rQyxRQUFRUixJQURGLEVBQ1FqQixPQURSLDRCQUNvQnlCLFFBQVFQLElBRDVCLE1BRU5PLFFBQVFSLElBRkYsNEJBRVdRLFFBQVFQLElBRm5CLEVBQVg7QUFHQWhFLGdCQUFRMEQsR0FBUixDQUFZLE1BQU0sS0FBS3RCLE9BQUwsR0FBZSxLQUFLQSxPQUFMLENBQWE0QixJQUFiLENBQWYsR0FBb0NBLElBQXRELEVBQTREckMsSUFBNUQsQ0FBaUVWLFFBQVE7QUFDdkUsZ0JBQU1jLFNBQVMsS0FBS0EsTUFBcEI7QUFDQSxnQkFBTUssVUFBVSxLQUFLQSxPQUFyQjtBQUNBLGdCQUFNOEIsU0FBU0ssUUFBUUwsTUFBdkI7QUFDQW5CLGtCQUFRMkIsT0FBUixDQUFnQjdCLFVBQVU7QUFDeEIsZ0JBQUksQ0FBQ3FCLE1BQUQsSUFBV3JCLE9BQU9zQixFQUFQLEtBQWNELE1BQTdCLEVBQXFDO0FBQ25DbEUsc0JBQ0cwRCxHQURILENBQ08sTUFBTXRCLFVBQVVTLE9BQU9kLE1BQVAsRUFBZWQsSUFBZixDQUFWLEdBQWlDNEIsT0FBT2QsTUFBUCxtQ0FBa0JkLElBQWxCLEVBRDlDLEVBRUdOLFdBRkg7QUFHRDtBQUNGLFdBTkQ7QUFPRCxTQVhEO0FBWUQ7QUFDRixLQXJCRDtBQXNCRDs7QUFwTjRDOztBQXdOL0M7QUFDQWlCLG9CQUFvQitDLFNBQXBCLENBQThCQyxjQUE5QixHQUErQ2hELG9CQUFvQitDLFNBQXBCLENBQThCZCxjQUE3RTs7QUFFQWdCLE9BQU9DLE9BQVAsR0FBaUJsRCxtQkFBakIiLCJmaWxlIjoiRW1pdHRlclB1YnN1YkJyb2tlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0J1xuXG5jb25zdCBQcm9taXNlID0gcmVxdWlyZSgnYmx1ZWJpcmQnKVxuY29uc3QgUmVkaXMgPSByZXF1aXJlKCdpb3JlZGlzJylcbmNvbnN0IG1zZ3BhY2sgPSByZXF1aXJlKCdtc2dwYWNrLWxpdGUnKVxuY29uc3QgeyBFdmVudEVtaXR0ZXIgfSA9IHJlcXVpcmUoJ2V2ZW50ZW1pdHRlcjMnKVxuXG4vKipcbiAqIEludGVyZmFjZSBmb3IgY29ubmVjdG9yIGltcGxlbWVudGF0aW9ucy5cbiAqXG4gKiBAaW50ZXJmYWNlIENvbm5lY3RvclxuICogQGV4dGVuZHMgRXZlbnRFbWl0dGVyXG4gKi9cblxuLyoqXG4gKiBAbWV0aG9kXG4gKiBAaW5zdGFuY2VcbiAqIEBuYW1lIHB1Ymxpc2hcbiAqIEBtZW1iZXJPZiBDb25uZWN0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIENoYW5uZWwuXG4gKiBAcGFyYW0ge0J1ZmZlcn0gZGF0YSBEYXRhLlxuICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fVxuICovXG5cbi8qKlxuICogQG1ldGhvZFxuICogQGluc3RhbmNlXG4gKiBAbmFtZSBzdWJzY3JpYmVcbiAqIEBtZW1iZXJPZiBDb25uZWN0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIENoYW5uZWwuXG4gKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59XG4gKi9cblxuLyoqXG4gKiBAbWV0aG9kXG4gKiBAaW5zdGFuY2VcbiAqIEBuYW1lIHVuc3Vic2NyaWJlXG4gKiBAbWVtYmVyT2YgQ29ubmVjdG9yXG4gKiBAcGFyYW0ge3N0cmluZ30gY2hhbm5lbCBDaGFubmVsLlxuICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fVxuICovXG5cbi8qKlxuICogQG1ldGhvZFxuICogQGluc3RhbmNlXG4gKiBAbmFtZSBjbG9zZVxuICogQG1lbWJlck9mIENvbm5lY3RvclxuICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+fVxuICovXG5cbi8qKlxuICogQGV2ZW50IG1lc3NhZ2VcbiAqIEBtZW1iZXJPZiBDb25uZWN0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudCBFdmVudCBuYW1lLlxuICogQHBhcmFtIHtCdWZmZXJ9IGRhdGEgRXZlbnQgZGF0YS5cbiAqL1xuXG4vKipcbiAqIEV2ZW50IHdpbGwgYmUgbGlzdGVuZWQgYnkge0BsaW5rIEVtaXR0ZXJQdWJzdWJCcm9rZXJ9IGluc3RhbmNlLlxuICpcbiAqIEBldmVudCBlcnJvclxuICogQG1lbWJlck9mIENvbm5lY3RvclxuICogQHBhcmFtIHtFcnJvcn0gZXJyb3IgRXJyb3IuXG4gKi9cblxuY2xhc3MgUmVkaXNDb25uZWN0b3IgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICBjb25zdHJ1Y3RvciAob3B0aW9ucykge1xuICAgIHN1cGVyKClcbiAgICB0aGlzLnB1YiA9IG5ldyBSZWRpcyhvcHRpb25zKVxuICAgIHRoaXMuc3ViID0gbmV3IFJlZGlzKG9wdGlvbnMpXG4gICAgdGhpcy5zdWIuc3Vic2NyaWJlKCkuY2F0Y2hSZXR1cm4oKVxuICAgIHRoaXMuc3ViLm9uKCdtZXNzYWdlQnVmZmVyJywgdGhpcy5fb25NZXNzYWdlLmJpbmQodGhpcykpXG4gICAgdGhpcy5zdWIub24oJ2Vycm9yJywgdGhpcy5lbWl0LmJpbmQodGhpcykpXG4gICAgdGhpcy5wdWIub24oJ2Vycm9yJywgdGhpcy5lbWl0LmJpbmQodGhpcykpXG4gIH1cblxuICBfb25NZXNzYWdlIChidWYsIGRhdGEpIHtcbiAgICBsZXQgY2ggPSBidWYudG9TdHJpbmcoKVxuICAgIHRoaXMuZW1pdCgnbWVzc2FnZScsIGNoLCBkYXRhKVxuICB9XG5cbiAgcHVibGlzaCAoY2gsIGRhdGEpIHtcbiAgICByZXR1cm4gdGhpcy5wdWIucHVibGlzaChjaCwgZGF0YSlcbiAgfVxuXG4gIHN1YnNjcmliZSAoY2gpIHtcbiAgICByZXR1cm4gdGhpcy5zdWIuc3Vic2NyaWJlKGNoKVxuICB9XG5cbiAgdW5zdWJzY3JpYmUgKGNoKSB7XG4gICAgcmV0dXJuIHRoaXMuc3ViLnVuc3Vic2NyaWJlKGNoKVxuICB9XG5cbiAgY2xvc2UgKCkge1xuICAgIHJldHVybiBQcm9taXNlLmFsbChbdGhpcy5wdWIucXVpdCgpLCB0aGlzLnN1Yi5xdWl0KCldKVxuICB9XG59XG5cbmNsYXNzIE1lbW9yeUNvbm5lY3RvciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIGNvbnN0cnVjdG9yIChvcHRpb25zKSB7XG4gICAgc3VwZXIoKVxuICB9XG5cbiAgcHVibGlzaCAoY2gsIGRhdGEpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICAgIC50aGVuKCgpID0+IHRoaXMuZW1pdCgnbWVzc2FnZScsIGNoLCBkYXRhKSlcbiAgfVxuXG4gIHN1YnNjcmliZSAoY2gpIHtcbiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgfVxuXG4gIHVuc3Vic2NyaWJlIChjaCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG5cbiAgY2xvc2UgKCkge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKVxuICB9XG59XG5cbi8qKlxuICogTWVzc2FnZXMgZW5jb2Rlci4gRW5jb2RlZCBtZXNzYWdlcyB3aWxsIGJlIHVzZWQgdG8gZW1pdCBtZXNzYWdlc1xuICogdmlhIGV2ZW50IGVtaXR0ZXJzLiBNYXkgYWxzbyByZXR1cm4gcHJvbWlzZXMgZm9yIGFuIGFzeW5jaHJvbm91c1xuICogZXhlY3V0aW9uLlxuICpcbiAqIEBjYWxsYmFjayBFbWl0dGVyUHVic3ViQnJva2VyLkVuY29kZXJcbiAqIEBwYXJhbSB7Kn0gYXJncyBFbWl0IGFyZ3VtZW50cy5cbiAqIEByZXR1cm4ge1Byb21pc2U8T2JqZWN0PnxPYmplY3R9IERhdGEgdG8gc2VuZC5cbiAqL1xuXG4vKipcbiAqIE1lc3NhZ2VzIHNlcmlhbGlzYXRpb24uIFNlcmlhbGlzZWQgbWVzc2FnZXMgd2lsbCBiZSB1c2VkIGludGVybmFsbHlcbiAqIHZpYSBhIGNvbW11bmljYXRpb24ge0BsaW5rIENvbm5lY3Rvcn0uICBNYXkgYWxzbyByZXR1cm4gcHJvbWlzZXNcbiAqIGZvciBhbiBhc3luY2hyb25vdXMgZXhlY3V0aW9uLlxuICpcbiAqIEBjYWxsYmFjayBFbWl0dGVyUHVic3ViQnJva2VyLlNlcmlhbGl6ZVxuICogQHBhcmFtIHtPYmplY3R9IGRhdGEgRGF0YS5cbiAqIEByZXR1cm4ge1Byb21pc2U8T2JqZWN0PnxPYmplY3R9IFNlcmlhbGlzZWQgZGF0YS5cbiAqL1xuXG4vKipcbiAqIE1lc3NhZ2VzIGRlc2VyaWFsaXNhdGlvbi4gU2VyaWFsaXNlZCBtZXNzYWdlcyB3aWxsIGJlIHVzZWRcbiAqIGludGVybmFsbHkgdmlhIGEgY29tbXVuaWNhdGlvbiB7QGxpbmsgQ29ubmVjdG9yfS4gIE1heSBhbHNvIHJldHVyblxuICogcHJvbWlzZXMgZm9yIGFuIGFzeW5jaHJvbm91cyBleGVjdXRpb24uXG4gKlxuICogQGNhbGxiYWNrIEVtaXR0ZXJQdWJzdWJCcm9rZXIuRGVzZXJpYWxpemVcbiAqIEBwYXJhbSB7T2JqZWN0fSBkYXRhIFNlcmlhbGlzZWQgZGF0YS5cbiAqIEByZXR1cm4ge1Byb21pc2U8T2JqZWN0PnxPYmplY3R9IERhdGEuXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiB7T2JqZWN0fSBFbWl0dGVyUHVic3ViQnJva2VyLk9wdGlvbnNcbiAqXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2Nvbm5lY3RdIENvbm5lY3Qgc3RyaW5nIGZvciBhIGNvbm5lY3Rvci5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbcHJlZml4PSdlbWl0dGVyLXB1YnN1Yi1icm9rZXI6J10gUHJlZml4IGZvciBhIGNvbm5lY3Rvci5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW2luY2x1ZGVDaGFubmVsPWZhbHNlXSBJbmNsdWRlIGNoYW5uZWwgYXMgdGhlXG4gKiBmaXJzdCBhcmd1bWVudC5cbiAqIEBwcm9wZXJ0eSB7RW1pdHRlclB1YnN1YkJyb2tlci5FbmNvZGVyfSBbZW5jb2Rlcl0gT3B0aW9uYWwgZW5jb2RlclxuICogdG8gcnVuIGJlZm9yZSBicm9hZGNhc3RpbmcuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW21ldGhvZD0nZW1pdCddIEFuIGFsdGVybmF0aXZlIGVtaXQgbWV0aG9kLlxuICogQHByb3BlcnR5IHtFbWl0dGVyUHVic3ViQnJva2VyLlNlcmlhbGl6ZX1cbiAqIFtzZXJpYWxpemU9bXNncGFjay5lbmNvZGVdIFNlcmlhbGlzYXRpb24gZnVuY3Rpb24gdG8gdXNlIHdpdGggYVxuICogY29ubmVjdG9yLlxuICogQHByb3BlcnR5IHtFbWl0dGVyUHVic3ViQnJva2VyLkRlc2VyaWFsaXplfVxuICogW2Rlc2VyaWFsaXplPW1zZ3BhY2suZGVjb2RlXSBEZXNlcmlhbGlzYXRpb24gZnVuY3Rpb24gdG8gdXNlIHdpdGggYVxuICogY29ubmVjdG9yLlxuICogQHByb3BlcnR5IHtDb25uZWN0b3J9IFtjb25uZWN0b3JdIEN1c3RvbSBjb25uZWN0b3IgaW1wbGVtZW50YXRpb24uXG4gKi9cblxuLyoqXG4gKiBAZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAqL1xuY2xhc3MgRW1pdHRlclB1YnN1YkJyb2tlciBleHRlbmRzIEV2ZW50RW1pdHRlciB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgYnJva2VyLlxuICAgKlxuICAgKiBAcGFyYW0ge0VtaXR0ZXJQdWJzdWJCcm9rZXIuT3B0aW9uc3xzdHJpbmd9IG9wdGlvbnMgT3B0aW9ucyBvciBhXG4gICAqIGNvbm5lY3QgaWYgYSBzdHJpbmcuIElmIGNvbm5lY3Qgc3RyaW5nIGlzIGVtcHR5LCB0aGVuIGFuXG4gICAqIGluLW1lbW9yeSBjb25uZWN0b3IgaXMgdXNlZC5cbiAgICovXG4gIGNvbnN0cnVjdG9yIChvcHRpb25zKSB7XG4gICAgc3VwZXIoKVxuICAgIGlmIChvcHRpb25zID09IG51bGwgfHwgdHlwZW9mIG9wdGlvbnMgPT09ICdzdHJpbmcnKSB7XG4gICAgICBvcHRpb25zID0geyBjb25uZWN0OiBvcHRpb25zIH1cbiAgICB9XG4gICAgdGhpcy5wcmVmaXggPSBvcHRpb25zLnByZWZpeCB8fCAnZW1pdHRlci1wdWJzdWItYnJva2VyOidcbiAgICB0aGlzLm1ldGhvZCA9IG9wdGlvbnMubWV0aG9kIHx8ICdlbWl0J1xuICAgIHRoaXMuc2VyaWFsaXplID0gb3B0aW9ucy5zZXJpYWxpemUgfHwgbXNncGFjay5lbmNvZGVcbiAgICB0aGlzLmRlc2VyaWFsaXplID0gb3B0aW9ucy5kZXNlcmlhbGl6ZSB8fCBtc2dwYWNrLmRlY29kZVxuICAgIHRoaXMuZW5jb2RlciA9IG9wdGlvbnMuZW5jb2RlclxuICAgIHRoaXMuaW5jbHVkZUNoYW5uZWwgPSBvcHRpb25zLmluY2x1ZGVDaGFubmVsXG4gICAgdGhpcy5jbGllbnRDaGFubmVscyA9IG5ldyBNYXAoKVxuICAgIHRoaXMuY2hhbm5lbENsaWVudHMgPSBuZXcgTWFwKClcbiAgICBpZiAob3B0aW9ucy5jb25uZWN0IHx8IG9wdGlvbnMuY29ubmVjdG9yKSB7XG4gICAgICB0aGlzLmNvbm5lY3RvciA9IG9wdGlvbnMuY29ubmVjdG9yIHx8IG5ldyBSZWRpc0Nvbm5lY3RvcihvcHRpb25zLmNvbm5lY3QpXG4gICAgICB0aGlzLnVzZVNlcmlhbGl6YXRpb24gPSB0cnVlXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY29ubmVjdG9yID0gbmV3IE1lbW9yeUNvbm5lY3RvcigpXG4gICAgICB0aGlzLnVzZVNlcmlhbGl6YXRpb24gPSBmYWxzZVxuICAgIH1cbiAgICB0aGlzLmNvbm5lY3Rvci5vbignbWVzc2FnZScsIHRoaXMuX2Rpc3BhdGNoLmJpbmQodGhpcykpXG4gICAgLyoqXG4gICAgICogQ29ubmVjdG9yIGVycm9yLiBEb2VzIG5vdCB0aHJvdyBpZiB0aGVyZSBhcmUgbm8gbGlzdGVuZXJzLlxuICAgICAqXG4gICAgICogQGV2ZW50IGVycm9yXG4gICAgICogQG1lbWJlck9mIEVtaXR0ZXJQdWJzdWJCcm9rZXJcbiAgICAgKiBAcGFyYW0ge0Vycm9yfSBlcnJvciBFcnJvci5cbiAgICAgKi9cbiAgICB0aGlzLmNvbm5lY3Rvci5vbignZXJyb3InLCB0aGlzLmVtaXQuYmluZCh0aGlzKSlcbiAgfVxuXG4gIF9jaGFubmVsQWRkQ2xpZW50IChjbGllbnQsIGNoYW5uZWwpIHtcbiAgICBsZXQgY2xpZW50cyA9IHRoaXMuY2hhbm5lbENsaWVudHMuZ2V0KGNoYW5uZWwpXG4gICAgaWYgKGNsaWVudHMgPT0gbnVsbCkge1xuICAgICAgY2xpZW50cyA9IG5ldyBTZXQoKVxuICAgICAgdGhpcy5jaGFubmVsQ2xpZW50cy5zZXQoY2hhbm5lbCwgY2xpZW50cylcbiAgICAgIGNsaWVudHMuYWRkKGNsaWVudClcbiAgICAgIGxldCBjaCA9IHRoaXMucHJlZml4ICsgY2hhbm5lbFxuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdG9yLnN1YnNjcmliZShjaClcbiAgICB9IGVsc2Uge1xuICAgICAgY2xpZW50cy5hZGQoY2xpZW50KVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXG4gICAgfVxuICB9XG5cbiAgX2NoYW5uZWxSZW1vdmVDbGllbnQgKGNsaWVudCwgY2hhbm5lbCkge1xuICAgIGxldCBjbGllbnRzID0gdGhpcy5jaGFubmVsQ2xpZW50cy5nZXQoY2hhbm5lbClcbiAgICBsZXQgbmNsaWVudHNcbiAgICBpZiAoY2xpZW50cyAhPSBudWxsKSB7XG4gICAgICBjbGllbnRzLmRlbGV0ZShjbGllbnQpXG4gICAgICBuY2xpZW50cyA9IGNsaWVudHMuc2l6ZVxuICAgIH1cbiAgICBpZiAobmNsaWVudHMgPT09IDApIHtcbiAgICAgIGxldCBjaCA9IHRoaXMucHJlZml4ICsgY2hhbm5lbFxuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdG9yLnVuc3Vic2NyaWJlKGNoKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICB9XG4gIH1cblxuICBfbWFrZU1lc3NhZ2UgKG1zZykge1xuICAgIHJldHVybiBQcm9taXNlLnRyeSgoKSA9PiB0aGlzLnVzZVNlcmlhbGl6YXRpb24gPyB0aGlzLnNlcmlhbGl6ZShtc2cpIDogbXNnKVxuICB9XG5cbiAgX3VucGFja01lc3NhZ2UgKGRhdGEpIHtcbiAgICByZXR1cm4gUHJvbWlzZS50cnkoKCkgPT4gdGhpcy51c2VTZXJpYWxpemF0aW9uID8gdGhpcy5kZXNlcmlhbGl6ZShkYXRhKSA6IGRhdGEpXG4gIH1cblxuICAvKipcbiAgICogU3Vic2NyaWJlcyBlbWl0dGVyIHRvIGEgY2hhbm5lbC5cbiAgICpcbiAgICogQHBhcmFtIHtFdmVudEVtaXR0ZXJ9IGNsaWVudCBFbWl0dGVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gY2hhbm5lbCBDaGFubmVsLlxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHVuZGVmaW5lZD59XG4gICAqL1xuICBzdWJzY3JpYmUgKGNsaWVudCwgY2hhbm5lbCkge1xuICAgIGxldCBjaGFubmVscyA9IHRoaXMuY2xpZW50Q2hhbm5lbHMuZ2V0KGNsaWVudClcbiAgICBpZiAoIWNoYW5uZWxzKSB7XG4gICAgICBjaGFubmVscyA9IG5ldyBTZXQoKVxuICAgICAgdGhpcy5jbGllbnRDaGFubmVscy5zZXQoY2xpZW50LCBjaGFubmVscylcbiAgICB9XG4gICAgY2hhbm5lbHMuYWRkKGNoYW5uZWwpXG4gICAgcmV0dXJuIHRoaXMuX2NoYW5uZWxBZGRDbGllbnQoY2xpZW50LCBjaGFubmVsKVxuICB9XG5cbiAgLyoqXG4gICAqIFVuc3Vic2NyaWJlcyBlbWl0dGVyIGZyb20gYSBjaGFubmVsLlxuICAgKlxuICAgKiBAcGFyYW0ge0V2ZW50RW1pdHRlcn0gY2xpZW50IEVtaXR0ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIENoYW5uZWwuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn1cbiAgICovXG4gIHVuc3Vic2NyaWJlIChjbGllbnQsIGNoYW5uZWwpIHtcbiAgICBsZXQgY2hhbm5lbHMgPSB0aGlzLmNsaWVudENoYW5uZWxzLmdldChjbGllbnQpXG4gICAgaWYgKGNoYW5uZWxzKSB7XG4gICAgICBjaGFubmVscy5kZWxldGUoY2hhbm5lbClcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NoYW5uZWxSZW1vdmVDbGllbnQoY2xpZW50LCBjaGFubmVsKVxuICB9XG5cbiAgLyoqXG4gICAqIFVuc3Vic2NyaWJlcyBlbWl0dGVyIGZyb20gYWxsIGNoYW5uZWxzLlxuICAgKlxuICAgKiBAcGFyYW0ge0V2ZW50RW1pdHRlcn0gY2xpZW50IEVtaXR0ZXIuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn1cbiAgICovXG4gIHVuc3Vic2NyaWJlQWxsIChjbGllbnQpIHtcbiAgICBsZXQgY2hhbm5lbHMgPSB0aGlzLmNsaWVudENoYW5uZWxzLmdldChjbGllbnQpXG4gICAgdGhpcy5jbGllbnRDaGFubmVscy5kZWxldGUoY2xpZW50KVxuICAgIGlmIChjaGFubmVscykge1xuICAgICAgcmV0dXJuIFByb21pc2UuZWFjaChcbiAgICAgICAgY2hhbm5lbHMsIHRoaXMuX2NoYW5uZWxSZW1vdmVDbGllbnQuYmluZCh0aGlzLCBjbGllbnQpKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaCBhbiBldmVudCB0byBhIGNoYW5uZWwuXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIENoYW5uZWwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIEV2ZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7Kn0gYXJncyBBcmd1bWVudHMuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn1cbiAgICovXG4gIHB1Ymxpc2ggKGNoYW5uZWwsIG5hbWUsIC4uLmFyZ3MpIHtcbiAgICBsZXQgY2ggPSB0aGlzLnByZWZpeCArIGNoYW5uZWxcbiAgICByZXR1cm4gdGhpcy5fbWFrZU1lc3NhZ2Uoe25hbWUsIGFyZ3N9KVxuICAgICAgLnRoZW4obXNnID0+IHRoaXMuY29ubmVjdG9yLnB1Ymxpc2goY2gsIG1zZykpXG4gIH1cblxuICAvKipcbiAgICogUHVibGlzaCBhbiBldmVudCB0byBhIGNoYW5uZWwsIGV4Y2x1ZGluZyB0aGUgc2VuZGVyLiBUaGUgY2xpZW50XG4gICAqIG9iamVjdCBfX01VU1RfXyBoYXZlIGFuIHVuaXF1ZSBgaWRgIGZpZWxkLlxuICAgKlxuICAgKiBAcGFyYW0ge0V2ZW50RW1pdHRlcn0gY2xpZW50IEVtaXR0ZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIENoYW5uZWwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIEV2ZW50IG5hbWUuXG4gICAqIEBwYXJhbSB7Kn0gYXJncyBBcmd1bWVudHMuXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn1cbiAgICovXG4gIHNlbmQgKGNsaWVudCwgY2hhbm5lbCwgbmFtZSwgLi4uYXJncykge1xuICAgIGxldCBjaCA9IHRoaXMucHJlZml4ICsgY2hhbm5lbFxuICAgIGxldCBzZW5kZXIgPSBjbGllbnQuaWRcbiAgICByZXR1cm4gdGhpcy5fbWFrZU1lc3NhZ2Uoe3NlbmRlciwgbmFtZSwgYXJnc30pXG4gICAgICAudGhlbihtc2cgPT4gdGhpcy5jb25uZWN0b3IucHVibGlzaChjaCwgbXNnKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHNldCBvZiBjbGllbnQgc3Vic2NyaXB0aW9ucy4gVGhlIHJlc3VsdCBfX01VU1QgTk9UX18gYmVcbiAgICogbW9kaWZpZWQuXG4gICAqXG4gICAqIEBwYXJhbSB7RXZlbnRFbWl0dGVyfSBjbGllbnQgRW1pdHRlci5cbiAgICogQHJldHVybiB7U2V0PHN0cmluZz58dW5kZWZpbmVkfVxuICAgKi9cbiAgZ2V0U3Vic2NyaXB0aW9ucyAoY2xpZW50KSB7XG4gICAgcmV0dXJuIHRoaXMuY2xpZW50Q2hhbm5lbHMuZ2V0KGNsaWVudClcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIF9pbnRlcm5hbF8gc2V0IG9mIGNoYW5uZWwgY2xpZW50cyBvZiBFbWl0dGVyUHVic3ViQnJva2VyXG4gICAqIGluc3RhbmNlLiBUaGUgcmVzdWx0IF9fTVVTVCBOT1RfXyBiZSBtb2RpZmllZC5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGNoYW5uZWwgQ2hhbm5lbC5cbiAgICogQHJldHVybiB7U2V0PEV2ZW50RW1pdHRlcj58dW5kZWZpbmVkfVxuICAgKi9cbiAgZ2V0Q2xpZW50cyAoY2hhbm5lbCkge1xuICAgIHJldHVybiB0aGlzLmNoYW5uZWxDbGllbnRzLmdldChjaGFubmVsKVxuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlcyBicm9rZXIuXG4gICAqXG4gICAqIEByZXR1cm4ge1Byb21pc2U8dW5kZWZpbmVkPn1cbiAgICovXG4gIGNsb3NlICgpIHtcbiAgICB0aGlzLmNoYW5uZWxDbGllbnRzLmNsZWFyKClcbiAgICB0aGlzLmNsaWVudENoYW5uZWxzLmNsZWFyKClcbiAgICByZXR1cm4gdGhpcy5jb25uZWN0b3IuY2xvc2UoKVxuICB9XG5cbiAgX2Rpc3BhdGNoIChjaCwgZGF0YSkge1xuICAgIHRoaXMuX3VucGFja01lc3NhZ2UoZGF0YSkudGhlbihtZXNzYWdlID0+IHtcbiAgICAgIGxldCBjaGFubmVsID0gY2guc2xpY2UodGhpcy5wcmVmaXgubGVuZ3RoKVxuICAgICAgbGV0IGNsaWVudHMgPSB0aGlzLmNoYW5uZWxDbGllbnRzLmdldChjaGFubmVsKVxuICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgIGlmIChjbGllbnRzKSB7XG4gICAgICAgIGxldCBhcmdzID0gdGhpcy5pbmNsdWRlQ2hhbm5lbFxuICAgICAgICAgID8gW21lc3NhZ2UubmFtZSwgY2hhbm5lbCwgLi4ubWVzc2FnZS5hcmdzXVxuICAgICAgICAgIDogW21lc3NhZ2UubmFtZSwgLi4ubWVzc2FnZS5hcmdzXVxuICAgICAgICBQcm9taXNlLnRyeSgoKSA9PiB0aGlzLmVuY29kZXIgPyB0aGlzLmVuY29kZXIoYXJncykgOiBhcmdzKS50aGVuKGRhdGEgPT4ge1xuICAgICAgICAgIGNvbnN0IG1ldGhvZCA9IHRoaXMubWV0aG9kXG4gICAgICAgICAgY29uc3QgZW5jb2RlciA9IHRoaXMuZW5jb2RlclxuICAgICAgICAgIGNvbnN0IHNlbmRlciA9IG1lc3NhZ2Uuc2VuZGVyXG4gICAgICAgICAgY2xpZW50cy5mb3JFYWNoKGNsaWVudCA9PiB7XG4gICAgICAgICAgICBpZiAoIXNlbmRlciB8fCBjbGllbnQuaWQgIT09IHNlbmRlcikge1xuICAgICAgICAgICAgICBQcm9taXNlXG4gICAgICAgICAgICAgICAgLnRyeSgoKSA9PiBlbmNvZGVyID8gY2xpZW50W21ldGhvZF0oZGF0YSkgOiBjbGllbnRbbWV0aG9kXSguLi5kYXRhKSlcbiAgICAgICAgICAgICAgICAuY2F0Y2hSZXR1cm4oKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG59XG5cbi8vIGNvbXBhdGliaWxpdHlcbkVtaXR0ZXJQdWJzdWJCcm9rZXIucHJvdG90eXBlLnVuc3Vic2NyaWJlYWxsID0gRW1pdHRlclB1YnN1YkJyb2tlci5wcm90b3R5cGUudW5zdWJzY3JpYmVBbGxcblxubW9kdWxlLmV4cG9ydHMgPSBFbWl0dGVyUHVic3ViQnJva2VyXG4iXX0=
{
"name": "emitter-pubsub-broker",
"version": "0.4.0",
"version": "0.5.0",
"private": false,

@@ -5,0 +5,0 @@ "description": "An utility for connecting EventEmitters via a pubsub.",

@@ -49,3 +49,3 @@

[API](https://an-sh.github.io/emitter-pubsub-broker/0.4/index.html)
[API](https://an-sh.github.io/emitter-pubsub-broker/0.5/index.html)
documentation is available online.

@@ -52,0 +52,0 @@

@@ -123,8 +123,47 @@ 'use strict'

/**
* Messages encoder. Encoded messages will be used to emit messages
* via event emitters. May also return promises for an asynchronous
* execution.
*
* @callback EmitterPubsubBroker.Encoder
* @param {*} args Emit arguments.
* @return {Promise<Object>|Object} Data to send.
*/
/**
* Messages serialisation. Serialised messages will be used internally
* via a communication {@link Connector}. May also return promises
* for an asynchronous execution.
*
* @callback EmitterPubsubBroker.Serialize
* @param {Object} data Data.
* @return {Promise<Object>|Object} Serialised data.
*/
/**
* Messages deserialisation. Serialised messages will be used
* internally via a communication {@link Connector}. May also return
* promises for an asynchronous execution.
*
* @callback EmitterPubsubBroker.Deserialize
* @param {Object} data Serialised data.
* @return {Promise<Object>|Object} Data.
*/
/**
* @typedef {Object} EmitterPubsubBroker.Options
*
* @property {string} connect Connect string.
* @property {string} [prefix='emitter-pubsub-broker:'] Prefix.
* @property {string} [connect] Connect string for a connector.
* @property {string} [prefix='emitter-pubsub-broker:'] Prefix for a connector.
* @property {boolean} [includeChannel=false] Include channel as the
* first argument.
* @property {EmitterPubsubBroker.Encoder} [encoder] Optional encoder
* to run before broadcasting.
* @property {string} [method='emit'] An alternative emit method.
* @property {EmitterPubsubBroker.Serialize}
* [serialize=msgpack.encode] Serialisation function to use with a
* connector.
* @property {EmitterPubsubBroker.Deserialize}
* [deserialize=msgpack.decode] Deserialisation function to use with a
* connector.
* @property {Connector} [connector] Custom connector implementation.

@@ -150,2 +189,6 @@ */

this.prefix = options.prefix || 'emitter-pubsub-broker:'
this.method = options.method || 'emit'
this.serialize = options.serialize || msgpack.encode
this.deserialize = options.deserialize || msgpack.decode
this.encoder = options.encoder
this.includeChannel = options.includeChannel

@@ -156,6 +199,6 @@ this.clientChannels = new Map()

this.connector = options.connector || new RedisConnector(options.connect)
this.serialize = true
this.useSerialization = true
} else {
this.connector = new MemoryConnector()
this.serialize = false
this.useSerialization = false
}

@@ -173,8 +216,9 @@ this.connector.on('message', this._dispatch.bind(this))

_channelAddClient (client, ch) {
let clients = this.channelClients.get(ch)
_channelAddClient (client, channel) {
let clients = this.channelClients.get(channel)
if (clients == null) {
clients = new Set()
this.channelClients.set(ch, clients)
this.channelClients.set(channel, clients)
clients.add(client)
let ch = this.prefix + channel
return this.connector.subscribe(ch)

@@ -187,4 +231,4 @@ } else {

_channelRemoveClient (client, ch) {
let clients = this.channelClients.get(ch)
_channelRemoveClient (client, channel) {
let clients = this.channelClients.get(channel)
let nclients

@@ -196,2 +240,3 @@ if (clients != null) {

if (nclients === 0) {
let ch = this.prefix + channel
return this.connector.unsubscribe(ch)

@@ -204,5 +249,9 @@ } else {

_makeMessage (msg) {
return this.serialize ? msgpack.encode(msg) : msg
return Promise.try(() => this.useSerialization ? this.serialize(msg) : msg)
}
_unpackMessage (data) {
return Promise.try(() => this.useSerialization ? this.deserialize(data) : data)
}
/**

@@ -221,5 +270,4 @@ * Subscribes emitter to a channel.

}
let ch = this.prefix + channel
channels.add(ch)
return this._channelAddClient(client, ch)
channels.add(channel)
return this._channelAddClient(client, channel)
}

@@ -236,11 +284,10 @@

let channels = this.clientChannels.get(client)
let ch = this.prefix + channel
if (channels) {
channels.delete(ch)
channels.delete(channel)
}
return this._channelRemoveClient(client, ch)
return this._channelRemoveClient(client, channel)
}
/**
* Unsubscribes emitter from all channel.
* Unsubscribes emitter from all channels.
*

@@ -250,3 +297,3 @@ * @param {EventEmitter} client Emitter.

*/
unsubscribeall (client) {
unsubscribeAll (client) {
let channels = this.clientChannels.get(client)

@@ -272,4 +319,4 @@ this.clientChannels.delete(client)

let ch = this.prefix + channel
let msg = this._makeMessage({name, args})
return this.connector.publish(ch, msg)
return this._makeMessage({name, args})
.then(msg => this.connector.publish(ch, msg))
}

@@ -290,25 +337,29 @@

let sender = client.id
let msg = this._makeMessage({sender, name, args})
return this.connector.publish(ch, msg)
return this._makeMessage({sender, name, args})
.then(msg => this.connector.publish(ch, msg))
}
/**
* Returns client subscriptions.
* Returns set of client subscriptions. The result __MUST NOT__ be
* modified.
*
* @param {EventEmitter} client Emitter.
* @return {Array<string>}
* @return {Set<string>|undefined}
*/
getSubscriptions (client) {
let channels = this.clientChannels.get(client)
let res = []
if (channels) {
let plen = this.prefix.length
for (let channel of channels) {
res.push(channel.slice(plen))
}
}
return res
return this.clientChannels.get(client)
}
/**
* Returns _internal_ set of channel clients of EmitterPubsubBroker
* instance. The result __MUST NOT__ be modified.
*
* @param {string} channel Channel.
* @return {Set<EventEmitter>|undefined}
*/
getClients (channel) {
return this.channelClients.get(channel)
}
/**
* Closes broker.

@@ -325,19 +376,24 @@ *

_dispatch (ch, data) {
let channel = ch.slice(this.prefix.length)
let message = this.serialize ? msgpack.decode(data) : data
let clients = this.channelClients.get(ch)
/* istanbul ignore else */
if (clients) {
let args
if (this.includeChannel) {
args = [message.name, channel, ...message.args]
} else {
args = [message.name, ...message.args]
this._unpackMessage(data).then(message => {
let channel = ch.slice(this.prefix.length)
let clients = this.channelClients.get(channel)
/* istanbul ignore else */
if (clients) {
let args = this.includeChannel
? [message.name, channel, ...message.args]
: [message.name, ...message.args]
Promise.try(() => this.encoder ? this.encoder(args) : args).then(data => {
const method = this.method
const encoder = this.encoder
const sender = message.sender
clients.forEach(client => {
if (!sender || client.id !== sender) {
Promise
.try(() => encoder ? client[method](data) : client[method](...data))
.catchReturn()
}
})
})
}
for (let client of clients) {
if (!message.sender || client.id !== message.sender) {
client.emit(...args)
}
}
}
})
}

@@ -347,2 +403,5 @@

// compatibility
EmitterPubsubBroker.prototype.unsubscribeall = EmitterPubsubBroker.prototype.unsubscribeAll
module.exports = EmitterPubsubBroker

@@ -6,2 +6,4 @@ 'use strict'

const eventToPromise = require('event-to-promise')
const msgpack = require('msgpack-lite')
const Promise = require('bluebird')
const { expect } = require('chai')

@@ -46,2 +48,32 @@ const { EventEmitter } = require('events')

it('should emit published encoded messages', function (done) {
broker = new EmitterPubsubBroker({connect, encoder: JSON.stringify, method: 'send'})
let client = new EventEmitter()
client.send = function (args) {
let [ev, x, y] = JSON.parse(args)
expect(ev).equal('myEvent')
expect(x).equal(1)
expect(y).equal('2')
done()
}
broker.subscribe(client, 'my-channel').then(() => {
broker.publish('my-channel', 'myEvent', 1, '2')
})
})
it('should use custom serialisation', function () {
let serialize = (data) => Promise.try(() => msgpack.encode(data))
let deserialize = (data) => Promise.try(() => msgpack.decode(data))
broker = new EmitterPubsubBroker({connect, serialize, deserialize})
let client = new EventEmitter()
return broker.subscribe(client, 'my-channel').then(() => {
broker.publish('my-channel', 'myEvent', 1, '2')
return eventToPromise(client, 'myEvent', {array: true}).then(args => {
let [x, y] = args
expect(x).equal(1)
expect(y).equal('2')
})
})
})
it('should prepend a channel argument', function () {

@@ -87,4 +119,5 @@ broker = new EmitterPubsubBroker({connect, includeChannel: true})

eventToPromise(client1, 'myEvent').then(notReachable)
return Promise.all([eventToPromise(client2, 'myEvent'),
new Promise(resolve => setTimeout(resolve, 1000))])
return Promise.all([
eventToPromise(client2, 'myEvent'),
new Promise(resolve => setTimeout(resolve, 1000))])
})

@@ -96,12 +129,28 @@ })

let client1 = new EventEmitter()
return Promise.all([broker.subscribe(client1, 'my-channel'),
broker.subscribe(client1, 'channel')])
return Promise.all([
broker.subscribe(client1, 'my-channel'),
broker.subscribe(client1, 'channel')])
.then(() => {
let subs = broker.getSubscriptions(client1)
expect(subs).lengthOf(2)
expect(subs).include('my-channel')
expect(subs).include('channel')
expect(subs.size).equal(2)
expect(subs.has('my-channel')).true
expect(subs.has('channel')).true
})
})
it('should get clients set', function () {
broker = new EmitterPubsubBroker(connect)
let client1 = new EventEmitter()
let client2 = new EventEmitter()
return Promise.all([
broker.subscribe(client1, 'channel'),
broker.subscribe(client2, 'channel')])
.then(() => {
let subs = broker.getClients('channel')
expect(subs.size).equal(2)
expect(subs.has(client1)).true
expect(subs.has(client2)).true
})
})
it('should unsubscribe all', function () {

@@ -112,5 +161,6 @@ this.timeout(4000)

let client1 = new EventEmitter()
return Promise.all([broker.subscribe(client1, 'my-channel'),
broker.subscribe(client1, 'channel')])
.then(() => broker.unsubscribeall(client1))
return Promise.all([
broker.subscribe(client1, 'my-channel'),
broker.subscribe(client1, 'channel')])
.then(() => broker.unsubscribeAll(client1))
.then(() => {

@@ -130,8 +180,8 @@ expect(broker.getSubscriptions(client1)).empty

it('should handle non-existent unsubscribeall', function () {
it('should handle non-existent unsubscribeAll', function () {
broker = new EmitterPubsubBroker(connect)
let client1 = new EventEmitter()
return broker.unsubscribeall(client1)
return broker.unsubscribeAll(client1)
})
}))
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc