UNPKG

@tsclean/core

Version:

Plugin for API Rest Full development, based on Clean Architecture, IoC and Dependency Injection.

192 lines 25.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WsAdapter = void 0; const http = __importStar(require("http")); const rxjs_1 = require("rxjs"); const services_1 = require("../services"); const websockets_1 = require("../websockets"); const utils_1 = require("../utils"); const helpers_1 = require("../helpers"); const load_package_util_1 = require("../utils/load-package.util"); const url_1 = require("url"); let wsPackage = {}; var READY_STATE; (function (READY_STATE) { READY_STATE[READY_STATE["CONNECTING_STATE"] = 0] = "CONNECTING_STATE"; READY_STATE[READY_STATE["OPEN_STATE"] = 1] = "OPEN_STATE"; READY_STATE[READY_STATE["CLOSING_STATE"] = 2] = "CLOSING_STATE"; READY_STATE[READY_STATE["CLOSED_STATE"] = 3] = "CLOSED_STATE"; })(READY_STATE || (READY_STATE = {})); const UNDERLYING_HTTP_SERVER_PORT = 0; /** * @publicApi */ class WsAdapter extends websockets_1.AbstractWsAdapter { constructor(appOrHttpServer) { super(appOrHttpServer); this.logger = new services_1.Logger(WsAdapter.name); this.httpServersRegistry = new Map(); this.wsServersRegistry = new Map(); wsPackage = (0, load_package_util_1.loadPackage)('ws', 'WsAdapter', () => require('ws')); } create(port, options) { const { server, path } = options, wsOptions = __rest(options, ["server", "path"]); if (wsOptions === null || wsOptions === void 0 ? void 0 : wsOptions.namespace) { const error = new Error('"WsAdapter" does not support namespaces. If you need namespaces in your project, consider using the "@nestjs/platform-socket.io" package instead.'); this.logger.error(error); throw error; } if (port === UNDERLYING_HTTP_SERVER_PORT && this.httpServer) { this.ensureHttpServerExists(port, this.httpServer); const wsServer = this.bindErrorHandler(new wsPackage.Server(Object.assign({ noServer: true }, wsOptions))); this.addWsServerToRegistry(wsServer, port, path); return wsServer; } if (server) { return server; } if (path && port !== UNDERLYING_HTTP_SERVER_PORT) { // Multiple servers with different paths // sharing a single HTTP/S server running on different port // than a regular HTTP application const httpServer = this.ensureHttpServerExists(port); httpServer === null || httpServer === void 0 ? void 0 : httpServer.listen(port); const wsServer = this.bindErrorHandler(new wsPackage.Server(Object.assign({ noServer: true }, wsOptions))); this.addWsServerToRegistry(wsServer, port, path); return wsServer; } const wsServer = this.bindErrorHandler(new wsPackage.Server(Object.assign({ port, path }, wsOptions))); return wsServer; } bindMessageHandlers(client, handlers, transform) { const handlersMap = new Map(); handlers.forEach(handler => handlersMap.set(handler.message, handler)); const close$ = (0, rxjs_1.fromEvent)(client, helpers_1.CLOSE_EVENT).pipe((0, rxjs_1.share)(), (0, rxjs_1.first)()); const source$ = (0, rxjs_1.fromEvent)(client, 'message').pipe((0, rxjs_1.mergeMap)(data => this.bindMessageHandler(data, handlersMap, transform).pipe((0, rxjs_1.filter)(result => !(0, utils_1.isNil)(result)))), (0, rxjs_1.takeUntil)(close$)); const onMessage = (response) => { if (client.readyState !== READY_STATE.OPEN_STATE) { return; } client.send(JSON.stringify(response)); }; source$.subscribe(onMessage); } bindMessageHandler(buffer, handlersMap, transform) { try { const message = JSON.parse(buffer.data); const messageHandler = handlersMap.get(message.event); const { callback } = messageHandler; return transform(callback(message.data, message.event)); } catch (_a) { return rxjs_1.EMPTY; } } bindErrorHandler(server) { server.on(helpers_1.CONNECTION_EVENT, (ws) => ws.on(helpers_1.ERROR_EVENT, (err) => this.logger.error(err))); server.on(helpers_1.ERROR_EVENT, (err) => this.logger.error(err)); return server; } bindClientDisconnect(client, callback) { client.on(helpers_1.CLOSE_EVENT, callback); } async close(server) { const closeEventSignal = new Promise((resolve, reject) => server.close(err => (err ? reject(err) : resolve(undefined)))); for (const ws of server.clients) { ws.terminate(); } await closeEventSignal; } async dispose() { const closeEventSignals = Array.from(this.httpServersRegistry) .filter(([port]) => port !== UNDERLYING_HTTP_SERVER_PORT) .map(([_, server]) => new Promise(resolve => server.close(resolve))); await Promise.all(closeEventSignals); this.httpServersRegistry.clear(); this.wsServersRegistry.clear(); } ensureHttpServerExists(port, httpServer = http.createServer()) { if (this.httpServersRegistry.has(port)) { return; } this.httpServersRegistry.set(port, httpServer); httpServer.on('upgrade', (request, socket, head) => { try { const baseUrl = 'ws://' + request.headers.host + '/'; const pathname = new url_1.URL(request.url, baseUrl).pathname; const wsServersCollection = this.wsServersRegistry.get(port); let isRequestDelegated = false; for (const wsServer of wsServersCollection) { if (pathname === wsServer.path) { wsServer.handleUpgrade(request, socket, head, (ws) => { wsServer.emit('connection', ws, request); }); isRequestDelegated = true; break; } } if (!isRequestDelegated) { socket.destroy(); } } catch (err) { socket.end('HTTP/1.1 400\r\n' + err.message); } }); return httpServer; } addWsServerToRegistry(wsServer, port, path) { var _a; const entries = (_a = this.wsServersRegistry.get(port)) !== null && _a !== void 0 ? _a : []; entries.push(wsServer); wsServer.path = (0, utils_1.normalizePath)(path); this.wsServersRegistry.set(port, entries); } } exports.WsAdapter = WsAdapter; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3MtYWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2ZXIvd3MtYWRhcHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDJDQUE2QjtBQUM3QiwrQkFBOEY7QUFFOUYsMENBQW9DO0FBQ3BDLDhDQUEyRTtBQUMzRSxvQ0FBK0M7QUFDL0Msd0NBQXVFO0FBQ3ZFLGtFQUF5RDtBQUN6RCw2QkFBMEI7QUFFMUIsSUFBSSxTQUFTLEdBQVEsRUFBRSxDQUFBO0FBRXZCLElBQUssV0FLSjtBQUxELFdBQUssV0FBVztJQUNkLHFFQUFvQixDQUFBO0lBQ3BCLHlEQUFjLENBQUE7SUFDZCwrREFBaUIsQ0FBQTtJQUNqQiw2REFBZ0IsQ0FBQTtBQUNsQixDQUFDLEVBTEksV0FBVyxLQUFYLFdBQVcsUUFLZjtBQU9ELE1BQU0sMkJBQTJCLEdBQUcsQ0FBQyxDQUFBO0FBRXJDOztHQUVHO0FBQ0gsTUFBYSxTQUFVLFNBQVEsOEJBQWlCO0lBVzlDLFlBQWEsZUFBbUQ7UUFDOUQsS0FBSyxDQUFDLGVBQWUsQ0FBQyxDQUFBO1FBWEwsV0FBTSxHQUFHLElBQUksaUJBQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDbkMsd0JBQW1CLEdBQUcsSUFBSSxHQUFHLEVBRzdDLENBQUE7UUFDZ0Isc0JBQWlCLEdBQUcsSUFBSSxHQUFHLEVBRzNDLENBQUE7UUFJRCxTQUFTLEdBQUcsSUFBQSwrQkFBVyxFQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7SUFDakUsQ0FBQztJQUVNLE1BQU0sQ0FDWCxJQUFZLEVBQ1osT0FJQztRQUVELE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxLQUFtQixPQUFPLEVBQXJCLFNBQVMsVUFBSyxPQUFPLEVBQXhDLGtCQUE4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Q0QsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7b0JBQ3hCLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQTtnQkFDbEIsQ0FBQztZQUNILENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLE1BQU0sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQzlDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQTtRQUNGLE9BQU8sVUFBVSxDQUFBO0lBQ25CLENBQUM7SUFFUyxxQkFBcUIsQ0FDN0IsUUFBVyxFQUNYLElBQVksRUFDWixJQUFZOztRQUVaLE1BQU0sT0FBTyxHQUFHLE1BQUEsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsbUNBQUksRUFBRSxDQUFBO1FBQ3RELE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7UUFFdEIsUUFBUSxDQUFDLElBQUksR0FBRyxJQUFBLHFCQUFhLEVBQUMsSUFBSSxDQUFDLENBQUE7UUFDbkMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUE7SUFDM0MsQ0FBQztDQUNGO0FBbE1ELDhCQWtNQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGh0dHAgZnJvbSAnaHR0cCc7XG5pbXBvcnQgeyBFTVBUWSwgZmlsdGVyLCBmaXJzdCwgZnJvbUV2ZW50LCBtZXJnZU1hcCwgT2JzZXJ2YWJsZSwgc2hhcmUsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnXG5pbXBvcnQgeyBBcHBsaWNhdGlvbkNvbnRleHRJbnRlcmZhY2UgfSBmcm9tICcuLi9jb250cmFjdHMnXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9zZXJ2aWNlcydcbmltcG9ydCB7IEFic3RyYWN0V3NBZGFwdGVyLCBNZXNzYWdlTWFwcGluZ1Byb3BlcnRpZXMgfSBmcm9tICcuLi93ZWJzb2NrZXRzJ1xuaW1wb3J0IHsgaXNOaWwsIG5vcm1hbGl6ZVBhdGggfSBmcm9tICcuLi91dGlscydcbmltcG9ydCB7IENMT1NFX0VWRU5ULCBDT05ORUNUSU9OX0VWRU5ULCBFUlJPUl9FVkVOVCB9IGZyb20gJy4uL2hlbHBlcnMnXG5pbXBvcnQgeyBsb2FkUGFja2FnZSB9IGZyb20gJy4uL3V0aWxzL2xvYWQtcGFja2FnZS51dGlsJztcbmltcG9ydCB7IFVSTCB9IGZyb20gJ3VybCc7XG5cbmxldCB3c1BhY2thZ2U6IGFueSA9IHt9XG5cbmVudW0gUkVBRFlfU1RBVEUge1xuICBDT05ORUNUSU5HX1NUQVRFID0gMCxcbiAgT1BFTl9TVEFURSA9IDEsXG4gIENMT1NJTkdfU1RBVEUgPSAyLFxuICBDTE9TRURfU1RBVEUgPSAzXG59XG5cbnR5cGUgSHR0cFNlcnZlclJlZ2lzdHJ5S2V5ID0gbnVtYmVyXG50eXBlIEh0dHBTZXJ2ZXJSZWdpc3RyeUVudHJ5ID0gYW55XG50eXBlIFdzU2VydmVyUmVnaXN0cnlLZXkgPSBudW1iZXJcbnR5cGUgV3NTZXJ2ZXJSZWdpc3RyeUVudHJ5ID0gYW55W11cblxuY29uc3QgVU5ERVJMWUlOR19IVFRQX1NFUlZFUl9QT1JUID0gMFxuXG4vKipcbiAqIEBwdWJsaWNBcGlcbiAqL1xuZXhwb3J0IGNsYXNzIFdzQWRhcHRlciBleHRlbmRzIEFic3RyYWN0V3NBZGFwdGVyIHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGxvZ2dlciA9IG5ldyBMb2dnZXIoV3NBZGFwdGVyLm5hbWUpXG4gIHByb3RlY3RlZCByZWFkb25seSBodHRwU2VydmVyc1JlZ2lzdHJ5ID0gbmV3IE1hcDxcbiAgICBIdHRwU2VydmVyUmVnaXN0cnlLZXksXG4gICAgSHR0cFNlcnZlclJlZ2lzdHJ5RW50cnlcbiAgPigpXG4gIHByb3RlY3RlZCByZWFkb25seSB3c1NlcnZlcnNSZWdpc3RyeSA9IG5ldyBNYXA8XG4gICAgV3NTZXJ2ZXJSZWdpc3RyeUtleSxcbiAgICBXc1NlcnZlclJlZ2lzdHJ5RW50cnlcbiAgPigpXG5cbiAgY29uc3RydWN0b3IgKGFwcE9ySHR0cFNlcnZlcj86IEFwcGxpY2F0aW9uQ29udGV4dEludGVyZmFjZSB8IGFueSkge1xuICAgIHN1cGVyKGFwcE9ySHR0cFNlcnZlcilcbiAgICB3c1BhY2thZ2UgPSBsb2FkUGFja2FnZSgnd3MnLCAnV3NBZGFwdGVyJywgKCkgPT4gcmVxdWlyZSgnd3MnKSlcbiAgfVxuXG4gIHB1YmxpYyBjcmVhdGUgKFxuICAgIHBvcnQ6IG51bWJlcixcbiAgICBvcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55PiAmIHtcbiAgICAgIG5hbWVzcGFjZT86IHN0cmluZ1xuICAgICAgc2VydmVyPzogYW55XG4gICAgICBwYXRoPzogc3RyaW5nXG4gICAgfVxuICApIHtcbiAgICBjb25zdCB7IHNlcnZlciwgcGF0aCwgLi4ud3NPcHRpb25zIH0gPSBvcHRpb25zXG4gICAgaWYgKHdzT3B0aW9ucz8ubmFtZXNwYWNlKSB7XG4gICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihcbiAgICAgICAgJ1wiV3NBZGFwdGVyXCIgZG9lcyBub3Qgc3VwcG9ydCBuYW1lc3BhY2VzLiBJZiB5b3UgbmVlZCBuYW1lc3BhY2VzIGluIHlvdXIgcHJvamVjdCwgY29uc2lkZXIgdXNpbmcgdGhlIFwiQG5lc3Rqcy9wbGF0Zm9ybS1zb2NrZXQuaW9cIiBwYWNrYWdlIGluc3RlYWQuJ1xuICAgICAgKVxuICAgICAgdGhpcy5sb2dnZXIuZXJyb3IoZXJyb3IpXG4gICAgICB0aHJvdyBlcnJvclxuICAgIH1cblxuICAgIGlmIChwb3J0ID09PSBVTkRFUkxZSU5HX0hUVFBfU0VSVkVSX1BPUlQgJiYgdGhpcy5odHRwU2VydmVyKSB7XG4gICAgICB0aGlzLmVuc3VyZUh0dHBTZXJ2ZXJFeGlzdHMocG9ydCwgdGhpcy5odHRwU2VydmVyKVxuICAgICAgY29uc3Qgd3NTZXJ2ZXIgPSB0aGlzLmJpbmRFcnJvckhhbmRsZXIoXG4gICAgICAgIG5ldyB3c1BhY2thZ2UuU2VydmVyKHtcbiAgICAgICAgICBub1NlcnZlcjogdHJ1ZSxcbiAgICAgICAgICAuLi53c09wdGlvbnNcbiAgICAgICAgfSlcbiAgICAgIClcblxuICAgICAgdGhpcy5hZGRXc1NlcnZlclRvUmVnaXN0cnkod3NTZXJ2ZXIsIHBvcnQsIHBhdGgpXG4gICAgICByZXR1cm4gd3NTZXJ2ZXJcbiAgICB9XG5cbiAgICBpZiAoc2VydmVyKSB7XG4gICAgICByZXR1cm4gc2VydmVyXG4gICAgfVxuICAgIGlmIChwYXRoICYmIHBvcnQgIT09IFVOREVSTFlJTkdfSFRUUF9TRVJWRVJfUE9SVCkge1xuICAgICAgLy8gTXVsdGlwbGUgc2VydmVycyB3aXRoIGRpZmZlcmVudCBwYXRoc1xuICAgICAgLy8gc2hhcmluZyBhIHNpbmdsZSBIVFRQL1Mgc2VydmVyIHJ1bm5pbmcgb24gZGlmZmVyZW50IHBvcnRcbiAgICAgIC8vIHRoYW4gYSByZWd1bGFyIEhUVFAgYXBwbGljYXRpb25cbiAgICAgIGNvbnN0IGh0dHBTZXJ2ZXIgPSB0aGlzLmVuc3VyZUh0dHBTZXJ2ZXJFeGlzdHMocG9ydClcbiAgICAgIGh0dHBTZXJ2ZXI/Lmxpc3Rlbihwb3J0KVxuXG4gICAgICBjb25zdCB3c1NlcnZlciA9IHRoaXMuYmluZEVycm9ySGFuZGxlcihcbiAgICAgICAgbmV3IHdzUGFja2FnZS5TZXJ2ZXIoe1xuICAgICAgICAgIG5vU2VydmVyOiB0cnVlLFxuICAgICAgICAgIC4uLndzT3B0aW9uc1xuICAgICAgICB9KVxuICAgICAgKVxuICAgICAgdGhpcy5hZGRXc1NlcnZlclRvUmVnaXN0cnkod3NTZXJ2ZXIsIHBvcnQsIHBhdGgpXG4gICAgICByZXR1cm4gd3NTZXJ2ZXJcbiAgICB9XG4gICAgY29uc3Qgd3NTZXJ2ZXIgPSB0aGlzLmJpbmRFcnJvckhhbmRsZXIoXG4gICAgICBuZXcgd3NQYWNrYWdlLlNlcnZlcih7XG4gICAgICAgIHBvcnQsXG4gICAgICAgIHBhdGgsXG4gICAgICAgIC4uLndzT3B0aW9uc1xuICAgICAgfSlcbiAgICApXG4gICAgcmV0dXJuIHdzU2VydmVyXG4gIH1cblxuICBwdWJsaWMgYmluZE1lc3NhZ2VIYW5kbGVycyAoXG4gICAgY2xpZW50OiBhbnksXG4gICAgaGFuZGxlcnM6IE1lc3NhZ2VNYXBwaW5nUHJvcGVydGllc1tdLFxuICAgIHRyYW5zZm9ybTogKGRhdGE6IGFueSkgPT4gT2JzZXJ2YWJsZTxhbnk+XG4gICkge1xuICAgIGNvbnN0IGhhbmRsZXJzTWFwID0gbmV3IE1hcDxzdHJpbmcsIE1lc3NhZ2VNYXBwaW5nUHJvcGVydGllcz4oKVxuICAgIGhhbmRsZXJzLmZvckVhY2goaGFuZGxlciA9PiBoYW5kbGVyc01hcC5zZXQoaGFuZGxlci5tZXNzYWdlLCBoYW5kbGVyKSlcblxuICAgIGNvbnN0IGNsb3NlJCA9IGZyb21FdmVudChjbGllbnQsIENMT1NFX0VWRU5UKS5waXBlKHNoYXJlKCksIGZpcnN0KCkpXG4gICAgY29uc3Qgc291cmNlJCA9IGZyb21FdmVudChjbGllbnQsICdtZXNzYWdlJykucGlwZShcbiAgICAgIG1lcmdlTWFwKGRhdGEgPT5cbiAgICAgICAgdGhpcy5iaW5kTWVzc2FnZUhhbmRsZXIoZGF0YSwgaGFuZGxlcnNNYXAsIHRyYW5zZm9ybSkucGlwZShcbiAgICAgICAgICBmaWx0ZXIocmVzdWx0ID0+ICFpc05pbChyZXN1bHQpKVxuICAgICAgICApXG4gICAgICApLFxuICAgICAgdGFrZVVudGlsKGNsb3NlJClcbiAgICApXG4gICAgY29uc3Qgb25NZXNzYWdlID0gKHJlc3BvbnNlOiBhbnkpID0+IHtcbiAgICAgIGlmIChjbGllbnQucmVhZHlTdGF0ZSAhPT0gUkVBRFlfU1RBVEUuT1BFTl9TVEFURSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIGNsaWVudC5zZW5kKEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlKSlcbiAgICB9XG4gICAgc291cmNlJC5zdWJzY3JpYmUob25NZXNzYWdlKVxuICB9XG5cbiAgcHVibGljIGJpbmRNZXNzYWdlSGFuZGxlciAoXG4gICAgYnVmZmVyOiBhbnksXG4gICAgaGFuZGxlcnNNYXA6IE1hcDxzdHJpbmcsIE1lc3NhZ2VNYXBwaW5nUHJvcGVydGllcz4sXG4gICAgdHJhbnNmb3JtOiAoZGF0YTogYW55KSA9PiBPYnNlcnZhYmxlPGFueT5cbiAgKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgbWVzc2FnZSA9IEpTT04ucGFyc2UoYnVmZmVyLmRhdGEpXG4gICAgICBjb25zdCBtZXNzYWdlSGFuZGxlciA9IGhhbmRsZXJzTWFwLmdldChtZXNzYWdlLmV2ZW50KVxuICAgICAgY29uc3QgeyBjYWxsYmFjayB9ID0gbWVzc2FnZUhhbmRsZXJcbiAgICAgIHJldHVybiB0cmFuc2Zvcm0oY2FsbGJhY2sobWVzc2FnZS5kYXRhLCBtZXNzYWdlLmV2ZW50KSlcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiBFTVBUWVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBiaW5kRXJyb3JIYW5kbGVyIChzZXJ2ZXI6IGFueSkge1xuICAgIHNlcnZlci5vbihDT05ORUNUSU9OX0VWRU5ULCAod3M6IGFueSkgPT5cbiAgICAgIHdzLm9uKEVSUk9SX0VWRU5ULCAoZXJyOiBhbnkpID0+IHRoaXMubG9nZ2VyLmVycm9yKGVycikpXG4gICAgKVxuICAgIHNlcnZlci5vbihFUlJPUl9FVkVOVCwgKGVycjogYW55KSA9PiB0aGlzLmxvZ2dlci5lcnJvcihlcnIpKVxuICAgIHJldHVybiBzZXJ2ZXJcbiAgfVxuXG4gIHB1YmxpYyBiaW5kQ2xpZW50RGlzY29ubmVjdCAoY2xpZW50OiBhbnksIGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICAgIGNsaWVudC5vbihDTE9TRV9FVkVOVCwgY2FsbGJhY2spXG4gIH1cblxuICBwdWJsaWMgYXN5bmMgY2xvc2UgKHNlcnZlcjogYW55KSB7XG4gICAgY29uc3QgY2xvc2VFdmVudFNpZ25hbCA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+XG4gICAgICBzZXJ2ZXIuY2xvc2UoZXJyID0+IChlcnIgPyByZWplY3QoZXJyKSA6IHJlc29sdmUodW5kZWZpbmVkKSkpXG4gICAgKVxuICAgIGZvciAoY29uc3Qgd3Mgb2Ygc2VydmVyLmNsaWVudHMpIHtcbiAgICAgIHdzLnRlcm1pbmF0ZSgpXG4gICAgfVxuICAgIGF3YWl0IGNsb3NlRXZlbnRTaWduYWxcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBkaXNwb3NlICgpIHtcbiAgICBjb25zdCBjbG9zZUV2ZW50U2lnbmFscyA9IEFycmF5LmZyb20odGhpcy5odHRwU2VydmVyc1JlZ2lzdHJ5KVxuICAgICAgLmZpbHRlcigoW3BvcnRdKSA9PiBwb3J0ICE9PSBVTkRFUkxZSU5HX0hUVFBfU0VSVkVSX1BPUlQpXG4gICAgICAubWFwKChbXywgc2VydmVyXSkgPT4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiBzZXJ2ZXIuY2xvc2UocmVzb2x2ZSkpKVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoY2xvc2VFdmVudFNpZ25hbHMpXG4gICAgdGhpcy5odHRwU2VydmVyc1JlZ2lzdHJ5LmNsZWFyKClcbiAgICB0aGlzLndzU2VydmVyc1JlZ2lzdHJ5LmNsZWFyKClcbiAgfVxuXG4gIHByb3RlY3RlZCBlbnN1cmVIdHRwU2VydmVyRXhpc3RzIChcbiAgICBwb3J0OiBudW1iZXIsXG4gICAgaHR0cFNlcnZlciA9IGh0dHAuY3JlYXRlU2VydmVyKClcbiAgKSB7XG4gICAgaWYgKHRoaXMuaHR0cFNlcnZlcnNSZWdpc3RyeS5oYXMocG9ydCkpIHtcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICB0aGlzLmh0dHBTZXJ2ZXJzUmVnaXN0cnkuc2V0KHBvcnQsIGh0dHBTZXJ2ZXIpXG5cbiAgICBodHRwU2VydmVyLm9uKCd1cGdyYWRlJywgKHJlcXVlc3QsIHNvY2tldCwgaGVhZCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgYmFzZVVybCA9ICd3czovLycgKyByZXF1ZXN0LmhlYWRlcnMuaG9zdCArICcvJ1xuICAgICAgICBjb25zdCBwYXRobmFtZSA9IG5ldyBVUkwocmVxdWVzdC51cmwsIGJhc2VVcmwpLnBhdGhuYW1lXG4gICAgICAgIGNvbnN0IHdzU2VydmVyc0NvbGxlY3Rpb24gPSB0aGlzLndzU2VydmVyc1JlZ2lzdHJ5LmdldChwb3J0KVxuXG4gICAgICAgIGxldCBpc1JlcXVlc3REZWxlZ2F0ZWQgPSBmYWxzZVxuICAgICAgICBmb3IgKGNvbnN0IHdzU2VydmVyIG9mIHdzU2VydmVyc0NvbGxlY3Rpb24pIHtcbiAgICAgICAgICBpZiAocGF0aG5hbWUgPT09IHdzU2VydmVyLnBhdGgpIHtcbiAgICAgICAgICAgIHdzU2VydmVyLmhhbmRsZVVwZ3JhZGUocmVxdWVzdCwgc29ja2V0LCBoZWFkLCAod3M6IHVua25vd24pID0+IHtcbiAgICAgICAgICAgICAgd3NTZXJ2ZXIuZW1pdCgnY29ubmVjdGlvbicsIHdzLCByZXF1ZXN0KVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIGlzUmVxdWVzdERlbGVnYXRlZCA9IHRydWVcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICghaXNSZXF1ZXN0RGVsZWdhdGVkKSB7XG4gICAgICAgICAgc29ja2V0LmRlc3Ryb3koKVxuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgc29ja2V0LmVuZCgnSFRUUC8xLjEgNDAwXFxyXFxuJyArIGVyci5tZXNzYWdlKVxuICAgICAgfVxuICAgIH0pXG4gICAgcmV0dXJuIGh0dHBTZXJ2ZXJcbiAgfVxuXG4gIHByb3RlY3RlZCBhZGRXc1NlcnZlclRvUmVnaXN0cnk8VCBleHRlbmRzIFJlY29yZDwncGF0aCcsIHN0cmluZz4gPSBhbnk+IChcbiAgICB3c1NlcnZlcjogVCxcbiAgICBwb3J0OiBudW1iZXIsXG4gICAgcGF0aDogc3RyaW5nXG4gICkge1xuICAgIGNvbnN0IGVudHJpZXMgPSB0aGlzLndzU2VydmVyc1JlZ2lzdHJ5LmdldChwb3J0KSA/PyBbXVxuICAgIGVudHJpZXMucHVzaCh3c1NlcnZlcilcblxuICAgIHdzU2VydmVyLnBhdGggPSBub3JtYWxpemVQYXRoKHBhdGgpXG4gICAgdGhpcy53c1NlcnZlcnNSZWdpc3RyeS5zZXQocG9ydCwgZW50cmllcylcbiAgfVxufVxuIl19