@nodefony/monitoring-bundle
Version:
18 lines (16 loc) • 335 kB
JavaScript
"use strict";
/*
* ATTENTION: An "eval-source-map" devtool has been used.
* This devtool is neither made for production nor for readable output files.
* It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools.
* If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
* or disable the default devtool with "devtool: false".
* If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
*/
(self["webpackChunk_nodefony_monitoring_bundle"] = self["webpackChunk_nodefony_monitoring_bundle"] || []).push([["node_modules_graphql-ws_lib_index_mjs"],{
/***/ "./node_modules/graphql-ws/lib/client.mjs":
/*!************************************************!*\
!*** ./node_modules/graphql-ws/lib/client.mjs ***!
\************************************************/
/***/ (function(__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ CloseCode: function() { return /* reexport safe */ _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode; },\n/* harmony export */ DEPRECATED_GRAPHQL_WS_PROTOCOL: function() { return /* reexport safe */ _common_mjs__WEBPACK_IMPORTED_MODULE_0__.DEPRECATED_GRAPHQL_WS_PROTOCOL; },\n/* harmony export */ GRAPHQL_TRANSPORT_WS_PROTOCOL: function() { return /* reexport safe */ _common_mjs__WEBPACK_IMPORTED_MODULE_0__.GRAPHQL_TRANSPORT_WS_PROTOCOL; },\n/* harmony export */ MessageType: function() { return /* reexport safe */ _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType; },\n/* harmony export */ TerminatedCloseEvent: function() { return /* binding */ TerminatedCloseEvent; },\n/* harmony export */ createClient: function() { return /* binding */ createClient; },\n/* harmony export */ isMessage: function() { return /* reexport safe */ _common_mjs__WEBPACK_IMPORTED_MODULE_0__.isMessage; },\n/* harmony export */ parseMessage: function() { return /* reexport safe */ _common_mjs__WEBPACK_IMPORTED_MODULE_0__.parseMessage; },\n/* harmony export */ stringifyMessage: function() { return /* reexport safe */ _common_mjs__WEBPACK_IMPORTED_MODULE_0__.stringifyMessage; },\n/* harmony export */ validateMessage: function() { return /* reexport safe */ _common_mjs__WEBPACK_IMPORTED_MODULE_0__.validateMessage; }\n/* harmony export */ });\n/* harmony import */ var _common_mjs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./common.mjs */ \"./node_modules/graphql-ws/lib/common.mjs\");\n/* harmony import */ var _utils_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.mjs */ \"./node_modules/graphql-ws/lib/utils.mjs\");\n/**\n *\n * client\n *\n */\nvar __await = (undefined && undefined.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }\nvar __asyncGenerator = (undefined && undefined.__asyncGenerator) || function (thisArg, _arguments, generator) {\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\n function fulfill(value) { resume(\"next\", value); }\n function reject(value) { resume(\"throw\", value); }\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\n};\n\n\n/** This file is the entry point for browsers, re-export common elements. */\n\n/**\n * Creates a disposable GraphQL over WebSocket client.\n *\n * @category Client\n */\nfunction createClient(options) {\n const { url, connectionParams, lazy = true, onNonLazyError = console.error, lazyCloseTimeout: lazyCloseTimeoutMs = 0, keepAlive = 0, disablePong, connectionAckWaitTimeout = 0, retryAttempts = 5, retryWait = async function randomisedExponentialBackoff(retries) {\n let retryDelay = 1000; // start with 1s delay\n for (let i = 0; i < retries; i++) {\n retryDelay *= 2;\n }\n await new Promise((resolve) => setTimeout(resolve, retryDelay +\n // add random timeout from 300ms to 3s\n Math.floor(Math.random() * (3000 - 300) + 300)));\n }, shouldRetry = isLikeCloseEvent, isFatalConnectionProblem, on, webSocketImpl, \n /**\n * Generates a v4 UUID to be used as the ID using `Math`\n * as the random number generator. Supply your own generator\n * in case you need more uniqueness.\n *\n * Reference: https://gist.github.com/jed/982883\n */\n generateID = function generateUUID() {\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }, jsonMessageReplacer: replacer, jsonMessageReviver: reviver, } = options;\n let ws;\n if (webSocketImpl) {\n if (!isWebSocket(webSocketImpl)) {\n throw new Error('Invalid WebSocket implementation provided');\n }\n ws = webSocketImpl;\n }\n else if (typeof WebSocket !== 'undefined') {\n ws = WebSocket;\n }\n else if (typeof global !== 'undefined') {\n ws =\n global.WebSocket ||\n // @ts-expect-error: Support more browsers\n global.MozWebSocket;\n }\n else if (typeof window !== 'undefined') {\n ws =\n window.WebSocket ||\n // @ts-expect-error: Support more browsers\n window.MozWebSocket;\n }\n if (!ws)\n throw new Error(\"WebSocket implementation missing; on Node you can `import WebSocket from 'ws';` and pass `webSocketImpl: WebSocket` to `createClient`\");\n const WebSocketImpl = ws;\n // websocket status emitter, subscriptions are handled differently\n const emitter = (() => {\n const message = (() => {\n const listeners = {};\n return {\n on(id, listener) {\n listeners[id] = listener;\n return () => {\n delete listeners[id];\n };\n },\n emit(message) {\n var _a;\n if ('id' in message)\n (_a = listeners[message.id]) === null || _a === void 0 ? void 0 : _a.call(listeners, message);\n },\n };\n })();\n const listeners = {\n connecting: (on === null || on === void 0 ? void 0 : on.connecting) ? [on.connecting] : [],\n opened: (on === null || on === void 0 ? void 0 : on.opened) ? [on.opened] : [],\n connected: (on === null || on === void 0 ? void 0 : on.connected) ? [on.connected] : [],\n ping: (on === null || on === void 0 ? void 0 : on.ping) ? [on.ping] : [],\n pong: (on === null || on === void 0 ? void 0 : on.pong) ? [on.pong] : [],\n message: (on === null || on === void 0 ? void 0 : on.message) ? [message.emit, on.message] : [message.emit],\n closed: (on === null || on === void 0 ? void 0 : on.closed) ? [on.closed] : [],\n error: (on === null || on === void 0 ? void 0 : on.error) ? [on.error] : [],\n };\n return {\n onMessage: message.on,\n on(event, listener) {\n const l = listeners[event];\n l.push(listener);\n return () => {\n l.splice(l.indexOf(listener), 1);\n };\n },\n emit(event, ...args) {\n // we copy the listeners so that unlistens dont \"pull the rug under our feet\"\n for (const listener of [...listeners[event]]) {\n // @ts-expect-error: The args should fit\n listener(...args);\n }\n },\n };\n })();\n // invokes the callback either when an error or closed event is emitted,\n // first one that gets called prevails, other emissions are ignored\n function errorOrClosed(cb) {\n const listening = [\n // errors are fatal and more critical than close events, throw them first\n emitter.on('error', (err) => {\n listening.forEach((unlisten) => unlisten());\n cb(err);\n }),\n // closes can be graceful and not fatal, throw them second (if error didnt throw)\n emitter.on('closed', (event) => {\n listening.forEach((unlisten) => unlisten());\n cb(event);\n }),\n ];\n }\n let connecting, locks = 0, lazyCloseTimeout, retrying = false, retries = 0, disposed = false;\n async function connect() {\n // clear the lazy close timeout immediatelly so that close gets debounced\n // see: https://github.com/enisdenjo/graphql-ws/issues/388\n clearTimeout(lazyCloseTimeout);\n const [socket, throwOnClose] = await (connecting !== null && connecting !== void 0 ? connecting : (connecting = new Promise((connected, denied) => (async () => {\n if (retrying) {\n await retryWait(retries);\n // subscriptions might complete while waiting for retry\n if (!locks) {\n connecting = undefined;\n return denied({ code: 1000, reason: 'All Subscriptions Gone' });\n }\n retries++;\n }\n emitter.emit('connecting', retrying);\n const socket = new WebSocketImpl(typeof url === 'function' ? await url() : url, _common_mjs__WEBPACK_IMPORTED_MODULE_0__.GRAPHQL_TRANSPORT_WS_PROTOCOL);\n let connectionAckTimeout, queuedPing;\n function enqueuePing() {\n if (isFinite(keepAlive) && keepAlive > 0) {\n clearTimeout(queuedPing); // in case where a pong was received before a ping (this is valid behaviour)\n queuedPing = setTimeout(() => {\n if (socket.readyState === WebSocketImpl.OPEN) {\n socket.send((0,_common_mjs__WEBPACK_IMPORTED_MODULE_0__.stringifyMessage)({ type: _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.Ping }));\n emitter.emit('ping', false, undefined);\n }\n }, keepAlive);\n }\n }\n errorOrClosed((errOrEvent) => {\n connecting = undefined;\n clearTimeout(connectionAckTimeout);\n clearTimeout(queuedPing);\n denied(errOrEvent);\n if (errOrEvent instanceof TerminatedCloseEvent) {\n socket.close(4499, 'Terminated'); // close event is artificial and emitted manually, see `Client.terminate()` below\n socket.onerror = null;\n socket.onclose = null;\n }\n });\n socket.onerror = (err) => emitter.emit('error', err);\n socket.onclose = (event) => emitter.emit('closed', event);\n socket.onopen = async () => {\n try {\n emitter.emit('opened', socket);\n const payload = typeof connectionParams === 'function'\n ? await connectionParams()\n : connectionParams;\n // connectionParams might take too long causing the server to kick off the client\n // the necessary error/close event is already reported - simply stop execution\n if (socket.readyState !== WebSocketImpl.OPEN)\n return;\n socket.send((0,_common_mjs__WEBPACK_IMPORTED_MODULE_0__.stringifyMessage)(payload\n ? {\n type: _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.ConnectionInit,\n payload,\n }\n : {\n type: _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.ConnectionInit,\n // payload is completely absent if not provided\n }, replacer));\n if (isFinite(connectionAckWaitTimeout) &&\n connectionAckWaitTimeout > 0) {\n connectionAckTimeout = setTimeout(() => {\n socket.close(_common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.ConnectionAcknowledgementTimeout, 'Connection acknowledgement timeout');\n }, connectionAckWaitTimeout);\n }\n enqueuePing(); // enqueue ping (noop if disabled)\n }\n catch (err) {\n emitter.emit('error', err);\n socket.close(_common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.InternalClientError, (0,_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.limitCloseReason)(err instanceof Error ? err.message : new Error(err).message, 'Internal client error'));\n }\n };\n let acknowledged = false;\n socket.onmessage = ({ data }) => {\n try {\n const message = (0,_common_mjs__WEBPACK_IMPORTED_MODULE_0__.parseMessage)(data, reviver);\n emitter.emit('message', message);\n if (message.type === 'ping' || message.type === 'pong') {\n emitter.emit(message.type, true, message.payload); // received\n if (message.type === 'pong') {\n enqueuePing(); // enqueue next ping (noop if disabled)\n }\n else if (!disablePong) {\n // respond with pong on ping\n socket.send((0,_common_mjs__WEBPACK_IMPORTED_MODULE_0__.stringifyMessage)(message.payload\n ? {\n type: _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.Pong,\n payload: message.payload,\n }\n : {\n type: _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.Pong,\n // payload is completely absent if not provided\n }));\n emitter.emit('pong', false, message.payload);\n }\n return; // ping and pongs can be received whenever\n }\n if (acknowledged)\n return; // already connected and acknowledged\n if (message.type !== _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.ConnectionAck)\n throw new Error(`First message cannot be of type ${message.type}`);\n clearTimeout(connectionAckTimeout);\n acknowledged = true;\n emitter.emit('connected', socket, message.payload, retrying); // connected = socket opened + acknowledged\n retrying = false; // future lazy connects are not retries\n retries = 0; // reset the retries on connect\n connected([\n socket,\n new Promise((_, reject) => errorOrClosed(reject)),\n ]);\n }\n catch (err) {\n socket.onmessage = null; // stop reading messages as soon as reading breaks once\n emitter.emit('error', err);\n socket.close(_common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.BadResponse, (0,_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.limitCloseReason)(err instanceof Error ? err.message : new Error(err).message, 'Bad response'));\n }\n };\n })())));\n // if the provided socket is in a closing state, wait for the throw on close\n if (socket.readyState === WebSocketImpl.CLOSING)\n await throwOnClose;\n let release = () => {\n // releases this connection\n };\n const released = new Promise((resolve) => (release = resolve));\n return [\n socket,\n release,\n Promise.race([\n // wait for\n released.then(() => {\n if (!locks) {\n // and if no more locks are present, complete the connection\n const complete = () => socket.close(1000, 'Normal Closure');\n if (isFinite(lazyCloseTimeoutMs) && lazyCloseTimeoutMs > 0) {\n // if the keepalive is set, allow for the specified calmdown time and\n // then complete if the socket is still open.\n lazyCloseTimeout = setTimeout(() => {\n if (socket.readyState === WebSocketImpl.OPEN)\n complete();\n }, lazyCloseTimeoutMs);\n }\n else {\n // otherwise complete immediately\n complete();\n }\n }\n }),\n // or\n throwOnClose,\n ]),\n ];\n }\n /**\n * Checks the `connect` problem and evaluates if the client should retry.\n */\n function shouldRetryConnectOrThrow(errOrCloseEvent) {\n // some close codes are worth reporting immediately\n if (isLikeCloseEvent(errOrCloseEvent) &&\n (isFatalInternalCloseCode(errOrCloseEvent.code) ||\n [\n _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.InternalServerError,\n _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.InternalClientError,\n _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.BadRequest,\n _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.BadResponse,\n _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.Unauthorized,\n // CloseCode.Forbidden, might grant access out after retry\n _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.SubprotocolNotAcceptable,\n // CloseCode.ConnectionInitialisationTimeout, might not time out after retry\n // CloseCode.ConnectionAcknowledgementTimeout, might not time out after retry\n _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.SubscriberAlreadyExists,\n _common_mjs__WEBPACK_IMPORTED_MODULE_0__.CloseCode.TooManyInitialisationRequests,\n // 4499, // Terminated, probably because the socket froze, we want to retry\n ].includes(errOrCloseEvent.code)))\n throw errOrCloseEvent;\n // client was disposed, no retries should proceed regardless\n if (disposed)\n return false;\n // normal closure (possibly all subscriptions have completed)\n // if no locks were acquired in the meantime, shouldnt try again\n if (isLikeCloseEvent(errOrCloseEvent) && errOrCloseEvent.code === 1000)\n return locks > 0;\n // retries are not allowed or we tried to many times, report error\n if (!retryAttempts || retries >= retryAttempts)\n throw errOrCloseEvent;\n // throw non-retryable connection problems\n if (!shouldRetry(errOrCloseEvent))\n throw errOrCloseEvent;\n // @deprecated throw fatal connection problems immediately\n if (isFatalConnectionProblem === null || isFatalConnectionProblem === void 0 ? void 0 : isFatalConnectionProblem(errOrCloseEvent))\n throw errOrCloseEvent;\n // looks good, start retrying\n return (retrying = true);\n }\n // in non-lazy (hot?) mode always hold one connection lock to persist the socket\n if (!lazy) {\n (async () => {\n locks++;\n for (;;) {\n try {\n const [, , throwOnClose] = await connect();\n await throwOnClose; // will always throw because releaser is not used\n }\n catch (errOrCloseEvent) {\n try {\n if (!shouldRetryConnectOrThrow(errOrCloseEvent))\n return;\n }\n catch (errOrCloseEvent) {\n // report thrown error, no further retries\n return onNonLazyError === null || onNonLazyError === void 0 ? void 0 : onNonLazyError(errOrCloseEvent);\n }\n }\n }\n })();\n }\n function subscribe(payload, sink) {\n const id = generateID(payload);\n let done = false, errored = false, releaser = () => {\n // for handling completions before connect\n locks--;\n done = true;\n };\n (async () => {\n locks++;\n for (;;) {\n try {\n const [socket, release, waitForReleaseOrThrowOnClose] = await connect();\n // if done while waiting for connect, release the connection lock right away\n if (done)\n return release();\n const unlisten = emitter.onMessage(id, (message) => {\n switch (message.type) {\n case _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.Next: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- payload will fit type\n sink.next(message.payload);\n return;\n }\n case _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.Error: {\n (errored = true), (done = true);\n sink.error(message.payload);\n releaser();\n return;\n }\n case _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.Complete: {\n done = true;\n releaser(); // release completes the sink\n return;\n }\n }\n });\n socket.send((0,_common_mjs__WEBPACK_IMPORTED_MODULE_0__.stringifyMessage)({\n id,\n type: _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.Subscribe,\n payload,\n }, replacer));\n releaser = () => {\n if (!done && socket.readyState === WebSocketImpl.OPEN)\n // if not completed already and socket is open, send complete message to server on release\n socket.send((0,_common_mjs__WEBPACK_IMPORTED_MODULE_0__.stringifyMessage)({\n id,\n type: _common_mjs__WEBPACK_IMPORTED_MODULE_0__.MessageType.Complete,\n }, replacer));\n locks--;\n done = true;\n release();\n };\n // either the releaser will be called, connection completed and\n // the promise resolved or the socket closed and the promise rejected.\n // whatever happens though, we want to stop listening for messages\n await waitForReleaseOrThrowOnClose.finally(unlisten);\n return; // completed, shouldnt try again\n }\n catch (errOrCloseEvent) {\n if (!shouldRetryConnectOrThrow(errOrCloseEvent))\n return;\n }\n }\n })()\n .then(() => {\n // delivering either an error or a complete terminates the sequence\n if (!errored)\n sink.complete();\n }) // resolves on release or normal closure\n .catch((err) => {\n sink.error(err);\n }); // rejects on close events and errors\n return () => {\n // dispose only of active subscriptions\n if (!done)\n releaser();\n };\n }\n return {\n on: emitter.on,\n subscribe,\n iterate(request) {\n const pending = [];\n const deferred = {\n done: false,\n error: null,\n resolve: () => {\n // noop\n },\n };\n const dispose = subscribe(request, {\n next(val) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n pending.push(val);\n deferred.resolve();\n },\n error(err) {\n deferred.done = true;\n deferred.error = err;\n deferred.resolve();\n },\n complete() {\n deferred.done = true;\n deferred.resolve();\n },\n });\n const iterator = (function iterator() {\n return __asyncGenerator(this, arguments, function* iterator_1() {\n for (;;) {\n if (!pending.length) {\n // only wait if there are no pending messages available\n yield __await(new Promise((resolve) => (deferred.resolve = resolve)));\n }\n // first flush\n while (pending.length) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n yield yield __await(pending.shift());\n }\n // then error\n if (deferred.error) {\n throw deferred.error;\n }\n // or complete\n if (deferred.done) {\n return yield __await(void 0);\n }\n }\n });\n })();\n iterator.throw = async (err) => {\n if (!deferred.done) {\n deferred.done = true;\n deferred.error = err;\n deferred.resolve();\n }\n return { done: true, value: undefined };\n };\n iterator.return = async () => {\n dispose();\n return { done: true, value: undefined };\n };\n return iterator;\n },\n async dispose() {\n disposed = true;\n if (connecting) {\n // if there is a connection, close it\n const [socket] = await connecting;\n socket.close(1000, 'Normal Closure');\n }\n },\n terminate() {\n if (connecting) {\n // only if there is a connection\n emitter.emit('closed', new TerminatedCloseEvent());\n }\n },\n };\n}\n/**\n * A syntetic close event `4499: Terminated` is issued to the current to immediately\n * close the connection without waiting for the one coming from `WebSocket.onclose`.\n *\n * Terminating is not considered fatal and a connection retry will occur as expected.\n *\n * Useful in cases where the WebSocket is stuck and not emitting any events;\n * can happen on iOS Safari, see: https://github.com/enisdenjo/graphql-ws/discussions/290.\n */\nclass TerminatedCloseEvent extends Error {\n constructor() {\n super(...arguments);\n this.name = 'TerminatedCloseEvent';\n this.message = '4499: Terminated';\n this.code = 4499;\n this.reason = 'Terminated';\n this.wasClean = false;\n }\n}\nfunction isLikeCloseEvent(val) {\n return (0,_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.isObject)(val) && 'code' in val && 'reason' in val;\n}\nfunction isFatalInternalCloseCode(code) {\n if ([\n 1000,\n 1001,\n 1006,\n 1005,\n 1012,\n 1013,\n 1014, // Bad Gateway\n ].includes(code))\n return false;\n // all other internal errors are fatal\n return code >= 1000 && code <= 1999;\n}\nfunction isWebSocket(val) {\n return (typeof val === 'function' &&\n 'constructor' in val &&\n 'CLOSED' in val &&\n 'CLOSING' in val &&\n 'CONNECTING' in val &&\n 'OPEN' in val);\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9ub2RlX21vZHVsZXMvZ3JhcGhxbC13cy9saWIvY2xpZW50Lm1qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL0Bub2RlZm9ueS9tb25pdG9yaW5nLWJ1bmRsZS8uL25vZGVfbW9kdWxlcy9ncmFwaHFsLXdzL2xpYi9jbGllbnQubWpzPzc5NmUiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKlxuICogY2xpZW50XG4gKlxuICovXG52YXIgX19hd2FpdCA9ICh0aGlzICYmIHRoaXMuX19hd2FpdCkgfHwgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHRoaXMgaW5zdGFuY2VvZiBfX2F3YWl0ID8gKHRoaXMudiA9IHYsIHRoaXMpIDogbmV3IF9fYXdhaXQodik7IH1cbnZhciBfX2FzeW5jR2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2FzeW5jR2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XG4gICAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcbiAgICB2YXIgZyA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSwgaSwgcSA9IFtdO1xuICAgIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgaWYgKGdbbl0pIGlbbl0gPSBmdW5jdGlvbiAodikgeyByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKGEsIGIpIHsgcS5wdXNoKFtuLCB2LCBhLCBiXSkgPiAxIHx8IHJlc3VtZShuLCB2KTsgfSk7IH07IH1cbiAgICBmdW5jdGlvbiByZXN1bWUobiwgdikgeyB0cnkgeyBzdGVwKGdbbl0odikpOyB9IGNhdGNoIChlKSB7IHNldHRsZShxWzBdWzNdLCBlKTsgfSB9XG4gICAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XG4gICAgZnVuY3Rpb24gZnVsZmlsbCh2YWx1ZSkgeyByZXN1bWUoXCJuZXh0XCIsIHZhbHVlKTsgfVxuICAgIGZ1bmN0aW9uIHJlamVjdCh2YWx1ZSkgeyByZXN1bWUoXCJ0aHJvd1wiLCB2YWx1ZSk7IH1cbiAgICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XG59O1xuaW1wb3J0IHsgR1JBUEhRTF9UUkFOU1BPUlRfV1NfUFJPVE9DT0wsIENsb3NlQ29kZSwgTWVzc2FnZVR5cGUsIHBhcnNlTWVzc2FnZSwgc3RyaW5naWZ5TWVzc2FnZSwgfSBmcm9tICcuL2NvbW1vbi5tanMnO1xuaW1wb3J0IHsgaXNPYmplY3QsIGxpbWl0Q2xvc2VSZWFzb24gfSBmcm9tICcuL3V0aWxzLm1qcyc7XG4vKiogVGhpcyBmaWxlIGlzIHRoZSBlbnRyeSBwb2ludCBmb3IgYnJvd3NlcnMsIHJlLWV4cG9ydCBjb21tb24gZWxlbWVudHMuICovXG5leHBvcnQgKiBmcm9tICcuL2NvbW1vbi5tanMnO1xuLyoqXG4gKiBDcmVhdGVzIGEgZGlzcG9zYWJsZSBHcmFwaFFMIG92ZXIgV2ViU29ja2V0IGNsaWVudC5cbiAqXG4gKiBAY2F0ZWdvcnkgQ2xpZW50XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDbGllbnQob3B0aW9ucykge1xuICAgIGNvbnN0IHsgdXJsLCBjb25uZWN0aW9uUGFyYW1zLCBsYXp5ID0gdHJ1ZSwgb25Ob25MYXp5RXJyb3IgPSBjb25zb2xlLmVycm9yLCBsYXp5Q2xvc2VUaW1lb3V0OiBsYXp5Q2xvc2VUaW1lb3V0TXMgPSAwLCBrZWVwQWxpdmUgPSAwLCBkaXNhYmxlUG9uZywgY29ubmVjdGlvbkFja1dhaXRUaW1lb3V0ID0gMCwgcmV0cnlBdHRlbXB0cyA9IDUsIHJldHJ5V2FpdCA9IGFzeW5jIGZ1bmN0aW9uIHJhbmRvbWlzZWRFeHBvbmVudGlhbEJhY2tvZmYocmV0cmllcykge1xuICAgICAgICBsZXQgcmV0cnlEZWxheSA9IDEwMDA7IC8vIHN0YXJ0IHdpdGggMXMgZGVsYXlcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZXRyaWVzOyBpKyspIHtcbiAgICAgICAgICAgIHJldHJ5RGVsYXkgKj0gMjtcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCByZXRyeURlbGF5ICtcbiAgICAgICAgICAgIC8vIGFkZCByYW5kb20gdGltZW91dCBmcm9tIDMwMG1zIHRvIDNzXG4gICAgICAgICAgICBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAoMzAwMCAtIDMwMCkgKyAzMDApKSk7XG4gICAgfSwgc2hvdWxkUmV0cnkgPSBpc0xpa2VDbG9zZUV2ZW50LCBpc0ZhdGFsQ29ubmVjdGlvblByb2JsZW0sIG9uLCB3ZWJTb2NrZXRJbXBsLCBcbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZXMgYSB2NCBVVUlEIHRvIGJlIHVzZWQgYXMgdGhlIElEIHVzaW5nIGBNYXRoYFxuICAgICAqIGFzIHRoZSByYW5kb20gbnVtYmVyIGdlbmVyYXRvci4gU3VwcGx5IHlvdXIgb3duIGdlbmVyYXRvclxuICAgICAqIGluIGNhc2UgeW91IG5lZWQgbW9yZSB1bmlxdWVuZXNzLlxuICAgICAqXG4gICAgICogUmVmZXJlbmNlOiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9qZWQvOTgyODgzXG4gICAgICovXG4gICAgZ2VuZXJhdGVJRCA9IGZ1bmN0aW9uIGdlbmVyYXRlVVVJRCgpIHtcbiAgICAgICAgcmV0dXJuICd4eHh4eHh4eC14eHh4LTR4eHgteXh4eC14eHh4eHh4eHh4eHgnLnJlcGxhY2UoL1t4eV0vZywgKGMpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHIgPSAoTWF0aC5yYW5kb20oKSAqIDE2KSB8IDAsIHYgPSBjID09ICd4JyA/IHIgOiAociAmIDB4MykgfCAweDg7XG4gICAgICAgICAgICByZXR1cm4gdi50b1N0cmluZygxNik7XG4gICAgICAgIH0pO1xuICAgIH0sIGpzb25NZXNzYWdlUmVwbGFjZXI6IHJlcGxhY2VyLCBqc29uTWVzc2FnZVJldml2ZXI6IHJldml2ZXIsIH0gPSBvcHRpb25zO1xuICAgIGxldCB3cztcbiAgICBpZiAod2ViU29ja2V0SW1wbCkge1xuICAgICAgICBpZiAoIWlzV2ViU29ja2V0KHdlYlNvY2tldEltcGwpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgV2ViU29ja2V0IGltcGxlbWVudGF0aW9uIHByb3ZpZGVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgd3MgPSB3ZWJTb2NrZXRJbXBsO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlb2YgV2ViU29ja2V0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB3cyA9IFdlYlNvY2tldDtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgd3MgPVxuICAgICAgICAgICAgZ2xvYmFsLldlYlNvY2tldCB8fFxuICAgICAgICAgICAgICAgIC8vIEB0cy1leHBlY3QtZXJyb3I6IFN1cHBvcnQgbW9yZSBicm93c2Vyc1xuICAgICAgICAgICAgICAgIGdsb2JhbC5Nb3pXZWJTb2NrZXQ7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHdzID1cbiAgICAgICAgICAgIHdpbmRvdy5XZWJTb2NrZXQgfHxcbiAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yOiBTdXBwb3J0IG1vcmUgYnJvd3NlcnNcbiAgICAgICAgICAgICAgICB3aW5kb3cuTW96V2ViU29ja2V0O1xuICAgIH1cbiAgICBpZiAoIXdzKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJXZWJTb2NrZXQgaW1wbGVtZW50YXRpb24gbWlzc2luZzsgb24gTm9kZSB5b3UgY2FuIGBpbXBvcnQgV2ViU29ja2V0IGZyb20gJ3dzJztgIGFuZCBwYXNzIGB3ZWJTb2NrZXRJbXBsOiBXZWJTb2NrZXRgIHRvIGBjcmVhdGVDbGllbnRgXCIpO1xuICAgIGNvbnN0IFdlYlNvY2tldEltcGwgPSB3cztcbiAgICAvLyB3ZWJzb2NrZXQgc3RhdHVzIGVtaXR0ZXIsIHN1YnNjcmlwdGlvbnMgYXJlIGhhbmRsZWQgZGlmZmVyZW50bHlcbiAgICBjb25zdCBlbWl0dGVyID0gKCgpID0+IHtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9ICgoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lcnMgPSB7fTtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgb24oaWQsIGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpZF0gPSBsaXN0ZW5lcjtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBsaXN0ZW5lcnNbaWRdO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZW1pdChtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBfYTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCdpZCcgaW4gbWVzc2FnZSlcbiAgICAgICAgICAgICAgICAgICAgICAgIChfYSA9IGxpc3RlbmVyc1ttZXNzYWdlLmlkXSkgPT09IG51bGwgfHwgX2EgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9hLmNhbGwobGlzdGVuZXJzLCBtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSkoKTtcbiAgICAgICAgY29uc3QgbGlzdGVuZXJzID0ge1xuICAgICAgICAgICAgY29ubmVjdGluZzogKG9uID09PSBudWxsIHx8IG9uID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvbi5jb25uZWN0aW5nKSA/IFtvbi5jb25uZWN0aW5nXSA6IFtdLFxuICAgICAgICAgICAgb3BlbmVkOiAob24gPT09IG51bGwgfHwgb24gPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9uLm9wZW5lZCkgPyBbb24ub3BlbmVkXSA6IFtdLFxuICAgICAgICAgICAgY29ubmVjdGVkOiAob24gPT09IG51bGwgfHwgb24gPT09IHZvaWQgMCA/IHZvaWQgMCA6IG9uLmNvbm5lY3RlZCkgPyBbb24uY29ubmVjdGVkXSA6IFtdLFxuICAgICAgICAgICAgcGluZzogKG9uID09PSBudWxsIHx8IG9uID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvbi5waW5nKSA/IFtvbi5waW5nXSA6IFtdLFxuICAgICAgICAgICAgcG9uZzogKG9uID09PSBudWxsIHx8IG9uID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvbi5wb25nKSA/IFtvbi5wb25nXSA6IFtdLFxuICAgICAgICAgICAgbWVzc2FnZTogKG9uID09PSBudWxsIHx8IG9uID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvbi5tZXNzYWdlKSA/IFttZXNzYWdlLmVtaXQsIG9uLm1lc3NhZ2VdIDogW21lc3NhZ2UuZW1pdF0sXG4gICAgICAgICAgICBjbG9zZWQ6IChvbiA9PT0gbnVsbCB8fCBvbiA9PT0gdm9pZCAwID8gdm9pZCAwIDogb24uY2xvc2VkKSA/IFtvbi5jbG9zZWRdIDogW10sXG4gICAgICAgICAgICBlcnJvcjogKG9uID09PSBudWxsIHx8IG9uID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvbi5lcnJvcikgPyBbb24uZXJyb3JdIDogW10sXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBvbk1lc3NhZ2U6IG1lc3NhZ2Uub24sXG4gICAgICAgICAgICBvbihldmVudCwgbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBsID0gbGlzdGVuZXJzW2V2ZW50XTtcbiAgICAgICAgICAgICAgICBsLnB1c2gobGlzdGVuZXIpO1xuICAgICAgICAgICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGwuc3BsaWNlKGwuaW5kZXhPZihsaXN0ZW5lciksIDEpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW1pdChldmVudCwgLi4uYXJncykge1xuICAgICAgICAgICAgICAgIC8vIHdlIGNvcHkgdGhlIGxpc3RlbmVycyBzbyB0aGF0IHVubGlzdGVucyBkb250IFwicHVsbCB0aGUgcnVnIHVuZGVyIG91ciBmZWV0XCJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGxpc3RlbmVyIG9mIFsuLi5saXN0ZW5lcnNbZXZlbnRdXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yOiBUaGUgYXJncyBzaG91bGQgZml0XG4gICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyKC4uLmFyZ3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgfSkoKTtcbiAgICAvLyBpbnZva2VzIHRoZSBjYWxsYmFjayBlaXRoZXIgd2hlbiBhbiBlcnJvciBvciBjbG9zZWQgZXZlbnQgaXMgZW1pdHRlZCxcbiAgICAvLyBmaXJzdCBvbmUgdGhhdCBnZXRzIGNhbGxlZCBwcmV2YWlscywgb3RoZXIgZW1pc3Npb25zIGFyZSBpZ25vcmVkXG4gICAgZnVuY3Rpb24gZXJyb3JPckNsb3NlZChjYikge1xuICAgICAgICBjb25zdCBsaXN0ZW5pbmcgPSBbXG4gICAgICAgICAgICAvLyBlcnJvcnMgYXJlIGZhdGFsIGFuZCBtb3JlIGNyaXRpY2FsIHRoYW4gY2xvc2UgZXZlbnRzLCB0aHJvdyB0aGVtIGZpcnN0XG4gICAgICAgICAgICBlbWl0dGVyLm9uKCdlcnJvcicsIChlcnIpID0+IHtcbiAgICAgICAgICAgICAgICBsaXN0ZW5pbmcuZm9yRWFjaCgodW5saXN0ZW4pID0+IHVubGlzdGVuKCkpO1xuICAgICAgICAgICAgICAgIGNiKGVycik7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIC8vIGNsb3NlcyBjYW4gYmUgZ3JhY2VmdWwgYW5kIG5vdCBmYXRhbCwgdGhyb3cgdGhlbSBzZWNvbmQgKGlmIGVycm9yIGRpZG50IHRocm93KVxuICAgICAgICAgICAgZW1pdHRlci5vbignY2xvc2VkJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgbGlzdGVuaW5nLmZvckVhY2goKHVubGlzdGVuKSA9PiB1bmxpc3RlbigpKTtcbiAgICAgICAgICAgICAgICBjYihldmVudCk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgXTtcbiAgICB9XG4gICAgbGV0IGNvbm5lY3RpbmcsIGxvY2tzID0gMCwgbGF6eUNsb3NlVGltZW91dCwgcmV0cnlpbmcgPSBmYWxzZSwgcmV0cmllcyA9IDAsIGRpc3Bvc2VkID0gZmFsc2U7XG4gICAgYXN5bmMgZnVuY3Rpb24gY29ubmVjdCgpIHtcbiAgICAgICAgLy8gY2xlYXIgdGhlIGxhenkgY2xvc2UgdGltZW91dCBpbW1lZGlhdGVsbHkgc28gdGhhdCBjbG9zZSBnZXRzIGRlYm91bmNlZFxuICAgICAgICAvLyBzZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9lbmlzZGVuam8vZ3JhcGhxbC13cy9pc3N1ZXMvMzg4XG4gICAgICAgIGNsZWFyVGltZW91dChsYXp5Q2xvc2VUaW1lb3V0KTtcbiAgICAgICAgY29uc3QgW3NvY2tldCwgdGhyb3dPbkNsb3NlXSA9IGF3YWl0IChjb25uZWN0aW5nICE9PSBudWxsICYmIGNvbm5lY3RpbmcgIT09IHZvaWQgMCA/IGNvbm5lY3RpbmcgOiAoY29ubmVjdGluZyA9IG5ldyBQcm9taXNlKChjb25uZWN0ZWQsIGRlbmllZCkgPT4gKGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGlmIChyZXRyeWluZykge1xuICAgICAgICAgICAgICAgIGF3YWl0IHJldHJ5V2FpdChyZXRyaWVzKTtcbiAgICAgICAgICAgICAgICAvLyBzdWJzY3JpcHRpb25zIG1pZ2h0IGNvbXBsZXRlIHdoaWxlIHdhaXRpbmcgZm9yIHJldHJ5XG4gICAgICAgICAgICAgICAgaWYgKCFsb2Nrcykge1xuICAgICAgICAgICAgICAgICAgICBjb25uZWN0aW5nID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGVuaWVkKHsgY29kZTogMTAwMCwgcmVhc29uOiAnQWxsIFN1YnNjcmlwdGlvbnMgR29uZScgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHJpZXMrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVtaXR0ZXIuZW1pdCgnY29ubmVjdGluZycsIHJldHJ5aW5nKTtcbiAgICAgICAgICAgIGNvbnN0IHNvY2tldCA9IG5ldyBXZWJTb2NrZXRJbXBsKHR5cGVvZiB1cmwgPT09ICdmdW5jdGlvbicgPyBhd2FpdCB1cmwoKSA6IHVybCwgR1JBUEhRTF9UUkFOU1BPUlRfV1NfUFJPVE9DT0wpO1xuICAgICAgICAgICAgbGV0IGNvbm5lY3Rpb25BY2tUaW1lb3V0LCBxdWV1ZWRQaW5nO1xuICAgICAgICAgICAgZnVuY3Rpb24gZW5xdWV1ZVBpbmcoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzRmluaXRlKGtlZXBBbGl2ZSkgJiYga2VlcEFsaXZlID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQocXVldWVkUGluZyk7IC8vIGluIGNhc2Ugd2hlcmUgYSBwb25nIHdhcyByZWNlaXZlZCBiZWZvcmUgYSBwaW5nICh0aGlzIGlzIHZhbGlkIGJlaGF2aW91cilcbiAgICAgICAgICAgICAgICAgICAgcXVldWVkUGluZyA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNvY2tldC5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXRJbXBsLk9QRU4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb2NrZXQuc2VuZChzdHJpbmdpZnlNZXNzYWdlKHsgdHlwZTogTWVzc2FnZVR5cGUuUGluZyB9KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW1pdHRlci5lbWl0KCdwaW5nJywgZmFsc2UsIHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0sIGtlZXBBbGl2ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZXJyb3JPckNsb3NlZCgoZXJyT3JFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbm5lY3RpbmcgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KGNvbm5lY3Rpb25BY2tUaW1lb3V0KTtcbiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQocXVldWVkUGluZyk7XG4gICAgICAgICAgICAgICAgZGVuaWVkKGVyck9yRXZlbnQpO1xuICAgICAgICAgICAgICAgIGlmIChlcnJPckV2ZW50IGluc3RhbmNlb2YgVGVybWluYXRlZENsb3NlRXZlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgc29ja2V0LmNsb3NlKDQ0OTksICdUZXJtaW5hdGVkJyk7IC8vIGNsb3NlIGV2ZW50IGlzIGFydGlmaWNpYWwgYW5kIGVtaXR0ZWQgbWFudWFsbHksIHNlZSBgQ2xpZW50LnRlcm1pbmF0ZSgpYCBiZWxvd1xuICAgICAgICAgICAgICAgICAgICBzb2NrZXQub25lcnJvciA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHNvY2tldC5vbmNsb3NlID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHNvY2tldC5vbmVycm9yID0gKGVycikgPT4gZW1pdHRlci5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgICAgICAgICBzb2NrZXQub25jbG9zZSA9IChldmVudCkgPT4gZW1pdHRlci5lbWl0KCdjbG9zZWQnLCBldmVudCk7XG4gICAgICAgICAgICBzb2NrZXQub25vcGVuID0gYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGVtaXR0ZXIuZW1pdCgnb3BlbmVkJywgc29ja2V0KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGF5bG9hZCA9IHR5cGVvZiBjb25uZWN0aW9uUGFyYW1zID09PSAnZnVuY3Rpb24nXG4gICAgICAgICAgICAgICAgICAgICAgICA/IGF3YWl0IGNvbm5lY3Rpb25QYXJhbXMoKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBjb25uZWN0aW9uUGFyYW1zO1xuICAgICAgICAgICAgICAgICAgICAvLyBjb25uZWN0aW9uUGFyYW1zIG1pZ2h0IHRha2UgdG9vIGxvbmcgY2F1c2luZyB0aGUgc2VydmVyIHRvIGtpY2sgb2ZmIHRoZSBjbGllbnRcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhlIG5lY2Vzc2FyeSBlcnJvci9jbG9zZSBldmVudCBpcyBhbHJlYWR5IHJlcG9ydGVkIC0gc2ltcGx5IHN0b3AgZXhlY3V0aW9uXG4gICAgICAgICAgICAgICAgICAgIGlmIChzb2NrZXQucmVhZHlTdGF0ZSAhPT0gV2ViU29ja2V0SW1wbC5PUEVOKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICBzb2NrZXQuc2VuZChzdHJpbmdpZnlNZXNzYWdlKHBheWxvYWRcbiAgICAgICAgICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IE1lc3NhZ2VUeXBlLkNvbm5lY3Rpb25Jbml0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBheWxvYWQsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBNZXNzYWdlVHlwZS5Db25uZWN0aW9uSW5pdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBwYXlsb2FkIGlzIGNvbXBsZXRlbHkgYWJzZW50IGlmIG5vdCBwcm92aWRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgfSwgcmVwbGFjZXIpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzRmluaXRlKGNvbm5lY3Rpb25BY2tXYWl0VGltZW91dCkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25BY2tXYWl0VGltZW91dCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbm5lY3Rpb25BY2tUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc29ja2V0LmNsb3NlKENsb3NlQ29kZS5Db25uZWN0aW9uQWNrbm93bGVkZ2VtZW50VGltZW91dCwgJ0Nvbm5lY3Rpb24gYWNrbm93bGVkZ2VtZW50IHRpbWVvdXQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIGNvbm5lY3Rpb25BY2tXYWl0VGltZW91dCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZW5xdWV1ZVBpbmcoKTsgLy8gZW5xdWV1ZSBwaW5nIChub29wIGlmIGRpc2FibGVkKVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIGVtaXR0ZXIuZW1pdCgnZXJyb3InLCBlcnIpO1xuICAgICAgICAgICAgICAgICAgICBzb2NrZXQuY2xvc2UoQ2xvc2VDb2RlLkludGVybmFsQ2xpZW50RXJyb3IsIGxpbWl0Q2xvc2VSZWFzb24oZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IG5ldyBFcnJvcihlcnIpLm1lc3NhZ2UsICdJbnRlcm5hbCBjbGllbnQgZXJyb3InKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGxldCBhY2tub3dsZWRnZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHNvY2tldC5vbm1lc3NhZ2UgPSAoeyBkYXRhIH0pID0+IHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gcGFyc2VNZXNzYWdlKGRhdGEsIHJldml2ZXIpO1xuICAgICAgICAgICAgICAgICAgICBlbWl0dGVyLmVtaXQoJ21lc3NhZ2UnLCBtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UudHlwZSA9PT0gJ3BpbmcnIHx8IG1lc3NhZ2UudHlwZSA9PT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbWl0dGVyLmVtaXQobWVzc2FnZS50eXBlLCB0cnVlLCBtZXNzYWdlLnBheWxvYWQpOyAvLyByZWNlaXZlZFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UudHlwZSA9PT0gJ3BvbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZW5xdWV1ZVBpbmcoKTsgLy8gZW5xdWV1ZSBuZXh0IHBpbmcgKG5vb3AgaWYgZGlzYWJsZWQpXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICghZGlzYWJsZVBvbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZXNwb25kIHdpdGggcG9uZyBvbiBwaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc29ja2V0LnNlbmQoc3RyaW5naWZ5TWVzc2FnZShtZXNzYWdlLnBheWxvYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiBNZXNzYWdlVHlwZS5Qb25nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF5bG9hZDogbWVzc2FnZS5wYXlsb2FkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogTWVzc2FnZVR5cGUuUG9uZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHBheWxvYWQgaXMgY29tcGxldGVseSBhYnNlbnQgaWYgbm90IHByb3ZpZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbWl0dGVyLmVtaXQoJ3BvbmcnLCBmYWxzZSwgbWVzc2FnZS5wYXlsb2FkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsgLy8gcGluZyBhbmQgcG9uZ3M