emitter-pubsub-broker
Advanced tools
Comparing version 0.4.0 to 0.5.0
@@ -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) |
@@ -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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9FbWl0dGVyUHVic3ViQnJva2VyLmpzIl0sIm5hbWVzIjpbIlByb21pc2UiLCJyZXF1aXJlIiwiUmVkaXMiLCJtc2dwYWNrIiwiRXZlbnRFbWl0dGVyIiwiUmVkaXNDb25uZWN0b3IiLCJjb25zdHJ1Y3RvciIsIm9wdGlvbnMiLCJwdWIiLCJzdWIiLCJzdWJzY3JpYmUiLCJjYXRjaFJldHVybiIsIm9uIiwiX29uTWVzc2FnZSIsImJpbmQiLCJlbWl0IiwiYnVmIiwiZGF0YSIsImNoIiwidG9TdHJpbmciLCJwdWJsaXNoIiwidW5zdWJzY3JpYmUiLCJjbG9zZSIsImFsbCIsInF1aXQiLCJNZW1vcnlDb25uZWN0b3IiLCJyZXNvbHZlIiwidGhlbiIsIkVtaXR0ZXJQdWJzdWJCcm9rZXIiLCJjb25uZWN0IiwicHJlZml4IiwibWV0aG9kIiwic2VyaWFsaXplIiwiZW5jb2RlIiwiZGVzZXJpYWxpemUiLCJkZWNvZGUiLCJlbmNvZGVyIiwiaW5jbHVkZUNoYW5uZWwiLCJjbGllbnRDaGFubmVscyIsIk1hcCIsImNoYW5uZWxDbGllbnRzIiwiY29ubmVjdG9yIiwidXNlU2VyaWFsaXphdGlvbiIsIl9kaXNwYXRjaCIsIl9jaGFubmVsQWRkQ2xpZW50IiwiY2xpZW50IiwiY2hhbm5lbCIsImNsaWVudHMiLCJnZXQiLCJTZXQiLCJzZXQiLCJhZGQiLCJfY2hhbm5lbFJlbW92ZUNsaWVudCIsIm5jbGllbnRzIiwiZGVsZXRlIiwic2l6ZSIsIl9tYWtlTWVzc2FnZSIsIm1zZyIsInRyeSIsIl91bnBhY2tNZXNzYWdlIiwiY2hhbm5lbHMiLCJ1bnN1YnNjcmliZUFsbCIsImVhY2giLCJuYW1lIiwiYXJncyIsInNlbmQiLCJzZW5kZXIiLCJpZCIsImdldFN1YnNjcmlwdGlvbnMiLCJnZXRDbGllbnRzIiwiY2xlYXIiLCJtZXNzYWdlIiwic2xpY2UiLCJsZW5ndGgiLCJmb3JFYWNoIiwicHJvdG90eXBlIiwidW5zdWJzY3JpYmVhbGwiLCJtb2R1bGUiLCJleHBv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QUFDRixLQXJCRDtBQXNCRDs7QUFwTjRDOztBQXdOL0M7QUFDQWlCLG9CQUFvQitDLFNBQXBCLENBQThCQyxjQUE5QixHQUErQ2hELG9CQUFvQitDLFNBQXBCLENBQThCZCxjQUE3RTs7QUFFQWdCLE9BQU9DLE9BQVAsR0FBaUJsRCxtQkFBakIiLCJmaWxlIjoiRW1pdHRlclB1YnN1YkJyb2tlci5qcyIsInNvdXJjZXNDb250ZW50IjpbIid1c2Ugc3RyaWN0J1xuXG5jb25zdCBQcm9taXNlID0gcmVxdWlyZSgnYmx1ZWJpcmQnKVxuY29uc3QgUmVkaXMgPSByZXF1aXJlKCdpb3JlZGlzJylcbmNvbnN0IG1zZ3BhY2sgPSByZXF1aXJlKCdtc2dwYWNrLWxpdGUnKVxuY29uc3QgeyBFdmVudEVtaXR0ZXIgfSA9IHJlcXVpcmUoJ2V2ZW50ZW1pdHRlcjMnKVxuXG4vKipcbiAqIEludGVyZmFjZSBmb3IgY29ubmVjdG9yIGltcGxlbWVudGF0aW9ucy5cbiAqXG4gKiBAaW50ZXJmYWNlIENvbm5lY3RvclxuICogQGV4dGVuZHMgRXZlbnRFbWl0dGVyXG4gKi9cblxuLyoqXG4gKiBAbWV0aG9kXG4gKiBAaW5zdGFuY2VcbiAqIEBuYW1lIHB1Ymxpc2hcbiAqIEBtZW1iZXJPZiBDb25uZWN0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBjaGFubmVsIENoYW5uZWwuXG4gKiBAcGFyYW0ge0J1ZmZlcn0gZGF0YSBEYXRhLlxuICogQHJldHVybiB7UHJvbWlzZTx1bmRlZmluZWQ+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) | ||
}) | ||
})) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
59703
912