UNPKG

blast-graph-angular2

Version:

![Alt text](./resources/images/b-circle-trans-100.png) **with** ![Alt text](./resources/images/angular.png)

437 lines (436 loc) 36.2 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { BlastHelpers } from './blast-helpers'; import { Subject } from 'rxjs/index'; /** @type {?} */ export const BLAST_VERSION = '0.0.1'; /** @type {?} */ export const LOG_LEVEL = { DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3 }; /** * @record */ export function BlastServiceConfig() { } /** @type {?} */ BlastServiceConfig.prototype.initialTimeout; /** @type {?} */ BlastServiceConfig.prototype.maxTimeout; /** @type {?} */ BlastServiceConfig.prototype.reconnectIfNotNormalClose; export class BlastService { /** * @param {?} url * @param {?=} connectNow * @param {?=} protocols * @param {?=} config */ constructor(url, connectNow, protocols, config) { this.url = url; this.protocols = protocols; this.config = config; this.reconnectAttempts = 0; this.sendQueue = []; this.onMessageCallbacks = []; this.onOpenCallbacks = []; this.onErrorCallbacks = []; this.onCloseCallbacks = []; this.readyStateConstants = { 'CONNECTING': 0, 'OPEN': 1, 'CLOSING': 2, 'CLOSED': 3, 'RECONNECT_ABORTED': 4 }; this.normalCloseCode = 1000; this.reconnectableStatusCodes = [4000]; this.logLevel = LOG_LEVEL.ERROR; /** @type {?} */ const match = new RegExp('wss?:\/\/').test(url); if (!match) { throw new Error('Invalid url provided'); } this.config = config || { initialTimeout: 500, maxTimeout: 300000, reconnectIfNotNormalClose: true }; this.dataStream = new Subject(); if (connectNow === undefined || connectNow) { this.connect(true); } } /** * @param {?=} force * @return {?} */ connect(force = false) { /** @type {?} */ const self = this; if (force || !this.socket || this.socket.readyState !== this.readyStateConstants.OPEN) { self.socket = this.protocols ? new WebSocket(this.url, this.protocols) : new WebSocket(this.url); self.socket.onopen = (ev) => { this.onOpenHandler(ev); }; self.socket.onmessage = (ev) => { if (BlastHelpers.isJson(ev.data)) { /** @type {?} */ const message = JSON.parse(ev.data); this.debug('BlastService', 'jsonMessage', 'passing to handlers', ev.data); // call a json message handler - if true, then message handled mustn't carry on if (self.handleJsonMessage(message) === true) { return; } } self.onMessageHandler(ev.data); this.dataStream.next(ev.data); }; this.socket.onclose = (ev) => { self.onCloseHandler(ev); }; this.socket.onerror = (ev) => { self.onErrorHandler(ev); this.dataStream.error(ev); }; } } /** * Run in Block Mode * Return true when can send and false in socket closed * @param {?} data * @param {?=} binary * @return {?} */ sendMessage(data, binary) { /** @type {?} */ const self = this; if (this.getReadyState() !== this.readyStateConstants.OPEN && this.getReadyState() !== this.readyStateConstants.CONNECTING) { this.connect(); } this.debug('BlastService', 'sendMessage', data); self.sendQueue.push({ message: data, binary: binary }); if (self.socket.readyState === self.readyStateConstants.OPEN) { self.fireQueue(); return true; } else { return false; } } /** * Use {mode} mode to send {data} data * If no specify, Default SendMode is Observable mode * @param {?} data * @param {?=} binary * @return {?} */ send(data, binary) { return this.sendMessage(data, binary); } /** * @return {?} */ getDataStream() { return this.dataStream; } /** * @param {?} event * @return {?} */ notifyOpenCallbacks(event) { for (let i = 0; i < this.onOpenCallbacks.length; i++) { this.onOpenCallbacks[i].call(this, event); } } /** * @return {?} */ fireQueue() { while (this.sendQueue.length && this.socket.readyState === this.readyStateConstants.OPEN) { /** @type {?} */ const data = this.sendQueue.shift(); if (data.binary) { this.socket.send(data.message); } else { this.socket.send(BlastHelpers.isString(data.message) ? data.message : JSON.stringify(data.message)); } } } /** * @param {?} event * @return {?} */ notifyCloseCallbacks(event) { for (let i = 0; i < this.onCloseCallbacks.length; i++) { this.onCloseCallbacks[i].call(this, event); } } /** * @param {?} event * @return {?} */ notifyErrorCallbacks(event) { for (let i = 0; i < this.onErrorCallbacks.length; i++) { this.onErrorCallbacks[i].call(this, event); } } /** * @param {?} cb * @return {?} */ onOpen(cb) { this.onOpenCallbacks.push(cb); return this; } ; /** * @param {?} cb * @return {?} */ onClose(cb) { this.onCloseCallbacks.push(cb); return this; } /** * @param {?} cb * @return {?} */ onError(cb) { this.onErrorCallbacks.push(cb); return this; } ; /** * @param {?} callback * @param {?=} options * @return {?} */ onMessage(callback, options) { if (!BlastHelpers.isFunction(callback)) { throw new Error('Callback must be a function'); } this.onMessageCallbacks.push({ fn: callback, pattern: options ? options.filter : undefined, autoApply: options ? options.autoApply : true }); return this; } /** * @param {?} message * @return {?} */ handleJsonMessage(message) { // as a default return false i.e. don't change message flow // enables extended classes to override this function return false; } /** * @param {?} message * @return {?} */ onMessageHandler(message) { this.debug('BlastService', 'onMessageHandler', message.data); /** @type {?} */ const self = this; /** @type {?} */ let currentCallback; for (let i = 0; i < self.onMessageCallbacks.length; i++) { currentCallback = self.onMessageCallbacks[i]; currentCallback.fn.apply(self, [message]); } } ; /** * @param {?} event * @return {?} */ onOpenHandler(event) { this.debug('BlastService', 'connected'); this.reconnectAttempts = 0; this.notifyOpenCallbacks(event); this.fireQueue(); } /** * @param {?} event * @return {?} */ onCloseHandler(event) { this.debug('BlastService', 'closed'); this.notifyCloseCallbacks(event); if ((this.config.reconnectIfNotNormalClose && event.code !== this.normalCloseCode) || this.reconnectableStatusCodes.indexOf(event.code) > -1) { this.reconnect(); } else { this.sendQueue = []; this.dataStream.complete(); } } ; /** * @param {?} event * @return {?} */ onErrorHandler(event) { this.debug('BlastService', 'onErrorHandler', event); this.notifyErrorCallbacks(event); } ; /** * @return {?} */ reconnect() { this.close(true); /** @type {?} */ const backoffDelay = this.getBackoffDelay(++this.reconnectAttempts); // let backoffDelaySeconds = backoffDelay / 1000; // // console.log('Reconnecting in ' + backoffDelaySeconds + ' seconds'); this.debug('BlastService', 'reconnectDelay', backoffDelay); setTimeout(() => this.connect(), backoffDelay); return this; } /** * @param {?=} force * @return {?} */ close(force = false) { if (force || !this.socket.bufferedAmount) { this.socket.close(this.normalCloseCode); } return this; } ; /** * @param {?} attempt * @return {?} */ getBackoffDelay(attempt) { /** @type {?} */ const R = Math.random() + 1; /** @type {?} */ const T = this.config.initialTimeout; /** @type {?} */ const F = 2; /** @type {?} */ const N = attempt; /** @type {?} */ const M = this.config.maxTimeout; return Math.floor(Math.min(R * T * Math.pow(F, N), M)); } ; /** * @param {?} state * @return {?} */ setInternalState(state) { if (Math.floor(state) !== state || state < 0 || state > 4) { throw new Error('state must be an integer between 0 and 4, got: ' + state); } this.internalConnectionState = state; } /** * Could be -1 if not initzialized yet * @return {?} */ getReadyState() { if (this.socket == null) { return -1; } return this.internalConnectionState || this.socket.readyState; } /** * @return {?} */ getVersion() { return BLAST_VERSION; } /** * @return {?} */ hasConsole() { if (console === undefined) { return false; } return true; } /** * @param {...?} args * @return {?} */ debug(...args) { if (this.hasConsole() && this.logLevel < 1) { console.debug.apply(console, args); } } /** * @param {...?} args * @return {?} */ info(...args) { if (this.hasConsole() && this.logLevel < 2) { console.debug.apply(console, args); } } /** * @param {...?} args * @return {?} */ warn(...args) { if (this.hasConsole() && this.logLevel < 4) { console.debug.apply(console, args); } } /** * @param {...?} args * @return {?} */ error(...args) { console.error.apply(console, args); } /** * @param {?} level * @return {?} */ setLogLevel(level) { this.logLevel = level; } } if (false) { /** @type {?} */ BlastService.prototype.reconnectAttempts; /** @type {?} */ BlastService.prototype.sendQueue; /** @type {?} */ BlastService.prototype.onMessageCallbacks; /** @type {?} */ BlastService.prototype.onOpenCallbacks; /** @type {?} */ BlastService.prototype.onErrorCallbacks; /** @type {?} */ BlastService.prototype.onCloseCallbacks; /** @type {?} */ BlastService.prototype.readyStateConstants; /** @type {?} */ BlastService.prototype.normalCloseCode; /** @type {?} */ BlastService.prototype.reconnectableStatusCodes; /** @type {?} */ BlastService.prototype.socket; /** @type {?} */ BlastService.prototype.dataStream; /** @type {?} */ BlastService.prototype.internalConnectionState; /** @type {?} */ BlastService.prototype.logLevel; /** @type {?} */ BlastService.prototype.url; /** @type {?} */ BlastService.prototype.protocols; /** @type {?} */ BlastService.prototype.config; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmxhc3QtYW5ndWxhcjIuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9ibGFzdC1ncmFwaC1hbmd1bGFyMi8iLCJzb3VyY2VzIjpbInNyYy9ibGFzdC1hbmd1bGFyMi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBSUEsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzdDLE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSxZQUFZLENBQUM7O0FBRW5DLGFBQWEsYUFBYSxHQUFHLE9BQU8sQ0FBQzs7QUFFckMsYUFBYSxTQUFTLEdBQUc7SUFDckIsS0FBSyxFQUFFLENBQUM7SUFDUixJQUFJLEVBQUUsQ0FBQztJQUNQLElBQUksRUFBRSxDQUFDO0lBQ1AsS0FBSyxFQUFFLENBQUM7Q0FDWCxDQUFDOzs7Ozs7Ozs7OztBQVNGLE1BQU07Ozs7Ozs7SUF3QkYsWUFBb0IsR0FBVyxFQUMzQixVQUFvQixFQUNaLFdBQ0E7UUFIUSxRQUFHLEdBQUgsR0FBRyxDQUFRO1FBRW5CLGNBQVMsR0FBVCxTQUFTO1FBQ1QsV0FBTSxHQUFOLE1BQU07aUNBekJVLENBQUM7eUJBQ0YsRUFBRTtrQ0FDTyxFQUFFOytCQUNBLEVBQUU7Z0NBQ0QsRUFBRTtnQ0FDRixFQUFFO21DQUNYO1lBQzFCLFlBQVksRUFBRSxDQUFDO1lBQ2YsTUFBTSxFQUFFLENBQUM7WUFDVCxTQUFTLEVBQUUsQ0FBQztZQUNaLFFBQVEsRUFBRSxDQUFDO1lBQ1gsbUJBQW1CLEVBQUUsQ0FBQztTQUN6QjsrQkFFeUIsSUFBSTt3Q0FDSyxDQUFDLElBQUksQ0FBQzt3QkFLdkIsU0FBUyxDQUFDLEtBQUs7O1FBUTdCLE1BQU0sS0FBSyxHQUFHLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNoRCxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDVCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFD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LElBQVc7UUFDZixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3pDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztTQUN0QztLQUNKOzs7OztJQUNELElBQUksQ0FBQyxHQUFHLElBQVc7UUFDZixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3pDLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztTQUN0QztLQUNKOzs7OztJQUNELEtBQUssQ0FBQyxHQUFHLElBQVc7UUFDaEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ3RDOzs7OztJQUVELFdBQVcsQ0FBQyxLQUFhO1FBQ3JCLElBQUksQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO0tBQ3pCO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGUsIE9wdGlvbmFsfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbi8qKlxuICogYmxhc3QtYW5ndWxhcjJcbiAqL1xuaW1wb3J0IHtCbGFzdEhlbHBlcnN9IGZyb20gJy4vYmxhc3QtaGVscGVycyc7XG5pbXBvcnQge1N1YmplY3R9IGZyb20gJ3J4anMvaW5kZXgnO1xuXG5leHBvcnQgY29uc3QgQkxBU1RfVkVSU0lPTiA9ICcwLjAuMSc7XG5cbmV4cG9ydCBjb25zdCBMT0dfTEVWRUwgPSB7XG4gICAgREVCVUc6IDAsXG4gICAgSU5GTzogMSxcbiAgICBXQVJOOiAyLFxuICAgIEVSUk9SOiAzXG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIEJsYXN0U2VydmljZUNvbmZpZyB7XG4gICAgaW5pdGlhbFRpbWVvdXQ6IG51bWJlcjtcbiAgICBtYXhUaW1lb3V0OiBudW1iZXI7XG4gICAgcmVjb25uZWN0SWZOb3ROb3JtYWxDbG9zZTogYm9vbGVhbjtcbn1cblxuLy9ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQmxhc3RTZXJ2aWNlIHtcblxuICAgIHByaXZhdGUgcmVjb25uZWN0QXR0ZW1wdHMgPSAwO1xuICAgIHByaXZhdGUgc2VuZFF1ZXVlOiBhbnlbXSA9IFtdO1xuICAgIHByaXZhdGUgb25NZXNzYWdlQ2FsbGJhY2tzOiBhbnlbXSA9IFtdO1xuICAgIHByaXZhdGUgb25PcGVuQ2FsbGJhY2tzOiBGdW5jdGlvbltdID0gW107XG4gICAgcHJpdmF0ZSBvbkVycm9yQ2FsbGJhY2tzOiBGdW5jdGlvbltdID0gW107XG4gICAgcHJpdmF0ZSBvbkNsb3NlQ2FsbGJhY2tzOiBGdW5jdGlvbltdID0gW107XG4gICAgcHJpdmF0ZSByZWFkeVN0YXRlQ29uc3RhbnRzID0ge1xuICAgICAgICAnQ09OTkVDVElORyc6IDAsXG4gICAgICAgICdPUEVOJzogMSxcbiAgICAgICAgJ0NMT1NJTkcnOiAyLFxuICAgICAgICAnQ0xPU0VEJzogMyxcbiAgICAgICAgJ1JFQ09OTkVDVF9BQk9SVEVEJzogNFxuICAgIH07XG5cbiAgICBwcml2YXRlIG5vcm1hbENsb3NlQ29kZSA9IDEwMDA7XG4gICAgcHJpdmF0ZSByZWNvbm5lY3RhYmxlU3RhdHVzQ29kZXMgPSBbNDAwMF07XG4gICAgcHJpdmF0ZSBzb2NrZXQ6IFdlYlNvY2tldDtcbiAgICBwcml2YXRlIGRhdGFTdHJlYW06IFN1YmplY3Q8YW55PjtcbiAgICBwcml2YXRlIGludGVybmFsQ29ubmVjdGlvblN0YXRlOiBudW1iZXI7XG5cbiAgICBwdWJsaWMgbG9nTGV2ZWwgPSBMT0dfTEVWRUwuRVJST1I7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHVybDogc3RyaW5nLFxuICAgICAgICBjb25uZWN0Tm93PzogYm9vbGVhbixcbiAgICAgICAgcHJpdmF0ZSBwcm90b2NvbHM/OiBBcnJheTxzdHJpbmc+LFxuICAgICAgICBwcml2YXRlIGNvbmZpZz86IEJsYXN0U2VydmljZUNvbmZpZ1xuICAgICkge1xuXG4gICAgICAgIGNvbnN0IG1hdGNoID0gbmV3IFJlZ0V4cCgnd3NzPzpcXC9cXC8nKS50ZXN0KHVybCk7XG4gICAgICAgIGlmICghbWF0Y2gpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB1cmwgcHJvdmlkZWQnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZyB8fCB7aW5pdGlhbFRpbWVvdXQ6IDUwMCwgbWF4VGltZW91dDogMzAwMDAwLCByZWNvbm5lY3RJZk5vdE5vcm1hbENsb3NlOiB0cnVlfTtcbiAgICAgICAgdGhpcy5kYXRhU3RyZWFtID0gbmV3IFN1YmplY3QoKTtcblxuICAgICAgICBpZiAoY29ubmVjdE5vdyA9PT0gdW5kZWZpbmVkIHx8IGNvbm5lY3ROb3cpIHtcbiAgICAgICAgICAgIHRoaXMuY29ubmVjdCh0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGNvbm5lY3QoZm9yY2UgPSBmYWxzZSkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKGZvcmNlIHx8ICF0aGlzLnNvY2tldCB8fCB0aGlzLnNvY2tldC5yZWFkeVN0YXRlICE9PSB0aGlzLnJlYWR5U3RhdGVDb25zdGFudHMuT1BFTikge1xuICAgICAgICAgICAgc2VsZi5zb2NrZXQgPSB0aGlzLnByb3RvY29scyA/IG5ldyBXZWJTb2NrZXQodGhpcy51cmwsIHRoaXMucHJvdG9jb2xzKSA6IG5ldyBXZWJTb2NrZXQodGhpcy51cmwpO1xuXG4gICAgICAgICAgICBzZWxmLnNvY2tldC5vbm9wZW4gPSAoZXY6IEV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5vbk9wZW5IYW5kbGVyKGV2KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBzZWxmLnNvY2tldC5vbm1lc3NhZ2UgPSAoZXY6IE1lc3NhZ2VFdmVudCkgPT4ge1xuXG4gICAgICAgICAgICAgICAgaWYgKEJsYXN0SGVscGVycy5pc0pzb24oZXYuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IEpTT04ucGFyc2UoZXYuZGF0YSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGVidWcoJ0JsYXN0U2VydmljZScsICdqc29uTWVzc2FnZScsICdwYXNzaW5nIHRvIGhhbmRsZXJzJywgZXYuZGF0YSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gY2FsbCBhIGpzb24gbWVzc2FnZSBoYW5kbGVyIC0gaWYgdHJ1ZSwgdGhlbiBtZXNzYWdlIGhhbmRsZWQgbXVzdG4ndCBjYXJyeSBvblxuICAgICAgICAgICAgICAgICAgICBpZiAoc2VsZi5oYW5kbGVKc29uTWVzc2FnZShtZXNzYWdlKSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNlbGYub25NZXNzYWdlSGFuZGxlcihldi5kYXRhKTtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFTdHJlYW0ubmV4dChldi5kYXRhKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc29ja2V0Lm9uY2xvc2UgPSAoZXY6IENsb3NlRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBzZWxmLm9uQ2xvc2VIYW5kbGVyKGV2KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc29ja2V0Lm9uZXJyb3IgPSAoZXY6IEVycm9yRXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBzZWxmLm9uRXJyb3JIYW5kbGVyKGV2KTtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFTdHJlYW0uZXJyb3IoZXYpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUnVuIGluIEJsb2NrIE1vZGVcbiAgICAgKiBSZXR1cm4gdHJ1ZSB3aGVuIGNhbiBzZW5kIGFuZCBmYWxzZSBpbiBzb2NrZXQgY2xvc2VkXG4gICAgICogQHBhcmFtIGRhdGFcbiAgICAgKiBAcmV0dXJucyBcbiAgICAgKi9cbiAgICBwcml2YXRlIHNlbmRNZXNzYWdlKGRhdGE6IGFueSwgYmluYXJ5PzogYm9vbGVhbik6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMuZ2V0UmVhZHlTdGF0ZSgpICE9PSB0aGlzLnJlYWR5U3RhdGVDb25zdGFudHMuT1BFTlxuICAgICAgICAgICAgJiYgdGhpcy5nZXRSZWFkeVN0YXRlKCkgIT09IHRoaXMucmVhZHlTdGF0ZUNvbnN0YW50cy5DT05ORUNUSU5HKSB7XG4gICAgICAgICAgICB0aGlzLmNvbm5lY3QoKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRlYnVnKCdCbGFzdFNlcnZpY2UnLCAnc2VuZE1lc3NhZ2UnLCBkYXRhKTtcbiAgICAgICAgc2VsZi5zZW5kUXVldWUucHVzaCh7bWVzc2FnZTogZGF0YSwgYmluYXJ5OiBiaW5hcnl9KTtcbiAgICAgICAgaWYgKHNlbGYuc29ja2V0LnJlYWR5U3RhdGUgPT09IHNlbGYucmVhZHlTdGF0ZUNvbnN0YW50cy5PUEVOKSB7XG4gICAgICAgICAgICBzZWxmLmZpcmVRdWV1ZSgpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2Uge21vZGV9IG1vZGUgdG8gc2VuZCB7ZGF0YX0gZGF0YVxuICAgICAqIElmIG5vIHNwZWNpZnksIERlZmF1bHQgU2VuZE1vZGUgaXMgT2JzZXJ2YWJsZSBtb2RlXG4gICAgICogQHBhcmFtIGRhdGFcbiAgICAgKiBAcGFyYW0gbW9kZVxuICAgICAqIEBwYXJhbSBiaW5hcnlcbiAgICAgKiBAcmV0dXJucyBcbiAgICAgKi9cbiAgICBzZW5kKGRhdGE6IGFueSwgYmluYXJ5PzogYm9vbGVhbik6IGFueSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbmRNZXNzYWdlKGRhdGEsIGJpbmFyeSk7XG4gICAgfVxuXG4gICAgZ2V0RGF0YVN0cmVhbSgpOiBTdWJqZWN0PGFueT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRhU3RyZWFtO1xuICAgIH1cblxuXG4gICAgbm90aWZ5T3BlbkNhbGxiYWNrcyhldmVudDogRXZlbnQpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm9uT3BlbkNhbGxiYWNrcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5vbk9wZW5DYWxsYmFja3NbaV0uY2FsbCh0aGlzLCBldmVudCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmaXJlUXVldWUoKSB7XG4gICAgICAgIHdoaWxlICh0aGlzLnNlbmRRdWV1ZS5sZW5ndGggJiYgdGhpcy5zb2NrZXQucmVhZHlTdGF0ZSA9PT0gdGhpcy5yZWFkeVN0YXRlQ29uc3RhbnRzLk9QRU4pIHtcbiAgICAgICAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLnNlbmRRdWV1ZS5zaGlmdCgpO1xuXG4gICAgICAgICAgICBpZiAoZGF0YS5iaW5hcnkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNvY2tldC5zZW5kKGRhdGEubWVzc2FnZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc29ja2V0LnNlbmQoXG4gICAgICAgICAgICAgICAgICAgIEJsYXN0SGVscGVycy5pc1N0cmluZyhkYXRhLm1lc3NhZ2UpID8gZGF0YS5tZXNzYWdlIDogSlNPTi5zdHJpbmdpZnkoZGF0YS5tZXNzYWdlKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBub3RpZnlDbG9zZUNhbGxiYWNrcyhldmVudDogRXZlbnQpIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLm9uQ2xvc2VDYWxsYmFja3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRoaXMub25DbG9zZUNhbGxiYWNrc1tpXS5jYWxsKHRoaXMsIGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5vdGlmeUVycm9yQ2FsbGJhY2tzKGV2ZW50OiBFdmVudCkge1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMub25FcnJvckNhbGxiYWNrcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgdGhpcy5vbkVycm9yQ2FsbGJhY2tzW2ldLmNhbGwodGhpcywgZXZlbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25PcGVuKGNiOiBGdW5jdGlvbikge1xuICAgICAgICB0aGlzLm9uT3BlbkNhbGxiYWNrcy5wdXNoKGNiKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcblxuICAgIG9uQ2xvc2UoY2I6IEZ1bmN0aW9uKSB7XG4gICAgICAgIHRoaXMub25DbG9zZUNhbGxiYWNrcy5wdXNoKGNiKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgb25FcnJvcihjYjogRnVuY3Rpb24pIHtcbiAgICAgICAgdGhpcy5vbkVycm9yQ2FsbGJhY2tzLnB1c2goY2IpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9O1xuXG4gICAgb25NZXNzYWdlKGNhbGxiYWNrOiBGdW5jdGlvbiwgb3B0aW9ucz8pIHtcbiAgICAgICAgaWYgKCFCbGFzdEhlbHBlcnMuaXNGdW5jdGlvbihjYWxsYmFjaykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm9uTWVzc2FnZUNhbGxiYWNrcy5wdXNoKHtcbiAgICAgICAgICAgIGZuOiBjYWxsYmFjayxcbiAgICAgICAgICAgIHBhdHRlcm46IG9wdGlvbnMgPyBvcHRpb25zLmZpbHRlciA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIGF1dG9BcHBseTogb3B0aW9ucyA/IG9wdGlvbnMuYXV0b0FwcGx5IDogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgaGFuZGxlSnNvbk1lc3NhZ2UobWVzc2FnZTogYW55KTogYm9vbGVhbiB7XG4gICAgICAgIC8vIGFzIGEgZGVmYXVsdCByZXR1cm4gZmFsc2UgaS5lLiBkb24ndCBjaGFuZ2UgbWVzc2FnZSBmbG93XG4gICAgICAgIC8vIGVuYWJsZXMgZXh0ZW5kZWQgY2xhc3NlcyB0byBvdmVycmlkZSB0aGlzIGZ1bmN0aW9uXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBvbk1lc3NhZ2VIYW5kbGVyKG1lc3NhZ2U6IE1lc3NhZ2VFdmVudCkge1xuICAgICAgICB0aGlzLmRlYnVnKCdCbGFzdFNlcnZpY2UnLCAnb25NZXNzYWdlSGFuZGxlcicsIG1lc3NhZ2UuZGF0YSk7XG5cbiAgICAgICAgY29uc3Qgc2VsZiA9IHRoaXM7XG4gICAgICAgIGxldCBjdXJyZW50Q2FsbGJhY2s7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZi5vbk1lc3NhZ2VDYWxsYmFja3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGN1cnJlbnRDYWxsYmFjayA9IHNlbGYub25NZXNzYWdlQ2FsbGJhY2tzW2ldO1xuICAgICAgICAgICAgY3VycmVudENhbGxiYWNrLmZuLmFwcGx5KHNlbGYsIFttZXNzYWdlXSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgb25PcGVuSGFuZGxlcihldmVudDogRXZlbnQpIHtcbiAgICAgICAgdGhpcy5kZWJ1ZygnQmxhc3RTZXJ2aWNlJywgJ2Nvbm5lY3RlZCcpO1xuICAgICAgICB0aGlzLnJlY29ubmVjdEF0dGVtcHRzID0gMDtcbiAgICAgICAgdGhpcy5ub3RpZnlPcGVuQ2FsbGJhY2tzKGV2ZW50KTtcbiAgICAgICAgdGhpcy5maXJlUXVldWUoKTtcbiAgICB9XG5cbiAgICBvbkNsb3NlSGFuZGxlcihldmVudDogQ2xvc2VFdmVudCkge1xuICAgICAgICB0aGlzLmRlYnVnKCdCbGFzdFNlcnZpY2UnLCAnY2xvc2VkJyk7XG4gICAgICAgIHRoaXMubm90aWZ5Q2xvc2VDYWxsYmFja3MoZXZlbnQpO1xuICAgICAgICBpZiAoKHRoaXMuY29uZmlnLnJlY29ubmVjdElmTm90Tm9ybWFsQ2xvc2UgJiYgZXZlbnQuY29kZSAhPT0gdGhpcy5ub3JtYWxDbG9zZUNvZGUpXG4gICAgICAgICAgICB8fCB0aGlzLnJlY29ubmVjdGFibGVTdGF0dXNDb2Rlcy5pbmRleE9mKGV2ZW50LmNvZGUpID4gLTEpIHtcbiAgICAgICAgICAgIHRoaXMucmVjb25uZWN0KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNlbmRRdWV1ZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5kYXRhU3RyZWFtLmNvbXBsZXRlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgb25FcnJvckhhbmRsZXIoZXZlbnQ6IEVycm9yRXZlbnQpIHtcbiAgICAgICAgdGhpcy5kZWJ1ZygnQmxhc3RTZXJ2aWNlJywgJ29uRXJyb3JIYW5kbGVyJywgZXZlbnQpO1xuICAgICAgICB0aGlzLm5vdGlmeUVycm9yQ2FsbGJhY2tzKGV2ZW50KTtcbiAgICB9O1xuXG4gICAgcmVjb25uZWN0KCkge1xuICAgICAgICB0aGlzLmNsb3NlKHRydWUpO1xuICAgICAgICBjb25zdCBiYWNrb2ZmRGVsYXkgPSB0aGlzLmdldEJhY2tvZmZEZWxheSgrK3RoaXMucmVjb25uZWN0QXR0ZW1wdHMpO1xuICAgICAgICAvLyAgICAgICAgIGxldCBiYWNrb2ZmRGVsYXlTZWNvbmRzID0gYmFja29mZkRlbGF5IC8gMTAwMDtcbiAgICAgICAgLy8gICAgICAgICAvLyBjb25zb2xlLmxvZygnUmVjb25uZWN0aW5nIGluICcgKyBiYWNrb2ZmRGVsYXlTZWNvbmRzICsgJyBzZWNvbmRzJyk7XG4gICAgICAgIHRoaXMuZGVidWcoJ0JsYXN0U2VydmljZScsICdyZWNvbm5lY3REZWxheScsIGJhY2tvZmZEZWxheSk7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5jb25uZWN0KCksIGJhY2tvZmZEZWxheSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGNsb3NlKGZvcmNlOiBib29sZWFuID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKGZvcmNlIHx8ICF0aGlzLnNvY2tldC5idWZmZXJlZEFtb3VudCkge1xuICAgICAgICAgICAgdGhpcy5zb2NrZXQuY2xvc2UodGhpcy5ub3JtYWxDbG9zZUNvZGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICBnZXRCYWNrb2ZmRGVsYXkoYXR0ZW1wdDogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IFIgPSBNYXRoLnJhbmRvbSgpICsgMTtcbiAgICAgICAgY29uc3QgVCA9IHRoaXMuY29uZmlnLmluaXRpYWxUaW1lb3V0O1xuICAgICAgICBjb25zdCBGID0gMjtcbiAgICAgICAgY29uc3QgTiA9IGF0dGVtcHQ7XG4gICAgICAgIGNvbnN0IE0gPSB0aGlzLmNvbmZpZy5tYXhUaW1lb3V0O1xuXG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKE1hdGgubWluKFIgKiBUICogTWF0aC5wb3coRiwgTiksIE0pKTtcbiAgICB9O1xuXG4gICAgc2V0SW50ZXJuYWxTdGF0ZShzdGF0ZTogbnVtYmVyKSB7XG4gICAgICAgIGlmIChNYXRoLmZsb29yKHN0YXRlKSAhPT0gc3RhdGUgfHwgc3RhdGUgPCAwIHx8IHN0YXRlID4gNCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzdGF0ZSBtdXN0IGJlIGFuIGludGVnZXIgYmV0d2VlbiAwIGFuZCA0LCBnb3Q6ICcgKyBzdGF0ZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5pbnRlcm5hbENvbm5lY3Rpb25TdGF0ZSA9IHN0YXRlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvdWxkIGJlIC0xIGlmIG5vdCBpbml0emlhbGl6ZWQgeWV0XG4gICAgICogQHJldHVybnMgXG4gICAgICovXG4gICAgZ2V0UmVhZHlTdGF0ZSgpOiBudW1iZXIge1xuICAgICAgICBpZiAodGhpcy5zb2NrZXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmludGVybmFsQ29ubmVjdGlvblN0YXRlIHx8IHRoaXMuc29ja2V0LnJlYWR5U3RhdGU7XG4gICAgfVxuXG4gICAgZ2V0VmVyc2lvbigpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gQkxBU1RfVkVSU0lPTjtcbiAgICB9XG5cblxuICAgIHByaXZhdGUgaGFzQ29uc29sZSgpOiBib29sZWFuIHtcbiAgICAgICAgaWYgKGNvbnNvbGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBwcml2YXRlIGRlYnVnKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgICAgIGlmICh0aGlzLmhhc0NvbnNvbGUoKSAmJiB0aGlzLmxvZ0xldmVsIDwgMSkge1xuICAgICAgICAgICAgY29uc29sZS5kZWJ1Zy5hcHBseShjb25zb2xlLCBhcmdzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGluZm8oLi4uYXJnczogYW55W10pIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzQ29uc29sZSgpICYmIHRoaXMubG9nTGV2ZWwgPCAyKSB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnLmFwcGx5KGNvbnNvbGUsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHdhcm4oLi4uYXJnczogYW55W10pIHtcbiAgICAgICAgaWYgKHRoaXMuaGFzQ29uc29sZSgpICYmIHRoaXMubG9nTGV2ZWwgPCA0KSB7XG4gICAgICAgICAgICBjb25zb2xlLmRlYnVnLmFwcGx5KGNvbnNvbGUsIGFyZ3MpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVycm9yKC4uLmFyZ3M6IGFueVtdKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IuYXBwbHkoY29uc29sZSwgYXJncyk7XG4gICAgfVxuXG4gICAgc2V0TG9nTGV2ZWwobGV2ZWw6IG51bWJlcikge1xuICAgICAgICB0aGlzLmxvZ0xldmVsID0gbGV2ZWw7XG4gICAgfVxufVxuXG4iXX0=