UNPKG

@tai-kun/surrealdb

Version:

The SurrealDB SDK for JavaScript

462 lines (460 loc) 46.8 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/engines/websocket/engine.ts var engine_exports = {}; __export(engine_exports, { default: () => WebSocketEngine }); module.exports = __toCommonJS(engine_exports); var import_engine = require("../../engine/index.cjs"); var import_errors = require("../../errors/index.cjs"); var import_utils = require("../../utils/index.cjs"); var _WebSocketEngine = class _WebSocketEngine extends import_engine.EngineAbc { constructor(config) { super(config); this.name = "websocket"; this.ws = null; this.id = new import_utils.Serial(); const { pingInterval, createWebSocket } = config; this.newWs = createWebSocket; this.pingInterval = typeof pingInterval === "function" ? pingInterval : /* @__PURE__ */ ((ms) => () => ms)(Math.max(3e3, pingInterval ?? 3e4)); } async connect({ endpoint, signal }) { (0, import_utils.throwIfAborted)(signal); const conn = this.getConnectionInfo(); if (conn.state === "open") { return; } if (conn.state !== "closed") { (0, import_errors.unreachable)(conn); } await this.transition( { state: "connecting", endpoint }, () => "closed" ); const ws = await this.newWs(new URL(endpoint), this.fmt.wsProtocols); ws.addEventListener("error", (evt) => { if ( /* __TAI_KUN__SURREALDB__DIAGNOSTICS_CHANNEL__ */ false ) { channel.publish("websocket:ws:error", evt); } this.ee.emit( "error", new import_errors.WebSocketEngineError( 3150, // イベントに message プロパティが含まれているかどうかは分かりません。 // // - Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/error_event#event_type // - Node.js: // - undici: https://github.com/nodejs/undici/blob/v6.18.1/types/websocket.d.ts#L127-L133 // - ws: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/ws/index.d.ts#L289-L294 // - Deno: https://github.com/denoland/deno/blob/v1.43.6/ext/web/02_event.js#L1064-L1133 "message" in evt ? String(evt.message) : 'The "error" event was caught.', { ..."error" in evt ? { cause: evt.error } : {}, fatal: true } ) ); }); ws.addEventListener("close", async (evt) => { if ( /* __TAI_KUN__SURREALDB__DIAGNOSTICS_CHANNEL__ */ false ) { channel.publish("websocket:ws:close", evt); } this.ws = null; this.id.reset(); switch (evt.code) { // 正常系 case 1e3: // Normal Closure // 予約済み case 1004: // Reserved case 1005: // No Status case 1015: // TLS Handshake // 早期の切断に由来するエラーコードをエラーとして扱いません。 case 1001: // Going Away case 1006: break; case 1002: // Protocol Error case 1003: // Unsupported Data case 1007: // Invalid Frame Payload Data case 1008: // Policy Violation case 1009: // Message Too Big case 1010: // Mandatory Extension case 1011: // Internal Server Error case 1012: // Service Restart case 1013: // Try Again Later case 1014: this.ee.emit( "error", new import_errors.WebSocketEngineError(evt.code, evt.reason) ); } try { await this.transition("closed", () => "closed"); } catch (e) { this.ee.emit( "error", new import_errors.WebSocketEngineError( 3154, 'An error occurred within the handler for the "close" event.', { cause: e, fatal: false } ) ); } }); ws.addEventListener("open", async (evt) => { if ( /* __TAI_KUN__SURREALDB__DIAGNOSTICS_CHANNEL__ */ false ) { channel.publish("websocket:ws:open", evt); } try { this.ws = ws; await this.transition( { state: "open", endpoint }, () => { this.ws = null; return "closed"; } ); } catch (e) { this.ee.emit( "error", new import_errors.WebSocketEngineError( // open イベントハンドラー内で発生したエラーを、 // カスタムエラーコード 3151 として報告します。 3151, 'An error occurred within the handler for the "open" event.', { cause: e, fatal: true } ) ); } }); ws.addEventListener("message", async (evt) => { if ( /* __TAI_KUN__SURREALDB__DIAGNOSTICS_CHANNEL__ */ false ) { channel.publish("websocket:ws:message", evt); } try { const data = evt.data instanceof Blob ? await evt.data.arrayBuffer() : evt.data; const rpcResp = this.fmt.decodeSync(data); if (!(0, import_utils.isRpcResponse)(rpcResp)) { throw new import_errors.ServerResponseError("Missing rpc response.", { // cause: (evt.data as Buffer).map(v => v).join(), cause: { endpoint: endpoint.href, response: rpcResp // TODO(tai-kun): 情報を追加 // ...cause, } }); } if ("id" in rpcResp) { this.ee.emit(`rpc_${rpcResp.id}`, rpcResp); } else if ("result" in rpcResp) { if (!(0, import_utils.isLiveResult)(rpcResp.result)) { throw new import_errors.ServerResponseError("Missing live result", { cause: { endpoint: endpoint.href, liveResult: rpcResp.result // TODO(tai-kun): 情報を追加 // ...cause, } }); } const { id, ...payload } = rpcResp.result; this.ee.emit(`live_${String(id)}`, payload); } else { throw new import_errors.RpcResponseError(rpcResp, { cause: { endpoint: endpoint.href } }); } } catch (e) { this.ee.emit( "error", new import_errors.WebSocketEngineError( // message イベントハンドラー内で発生したエラーを、 // カスタムエラーコード 3152 として報告します。 3152, 'An error occurred within the handler for the "message" event.', { cause: e, fatal: false } ) ); } }); const openPromise = this.ee.once("open", { signal }); const errorPromise = this.ee.once("error", { signal }); try { const [result] = await Promise.race([ openPromise, errorPromise ]); if (result instanceof Error) { throw result; } if ("error" in result) { throw result.error; } } finally { await Promise.all([ openPromise.cancel(), errorPromise.cancel() ]); } const createPromise = /* @__PURE__ */ __name(() => { let i, int, res, pro = new import_utils.StatefulPromise((r) => { i = setTimeout(res = r, int = this.pingInterval(), false); }); return Object.assign(pro, { interval: int, // 現在未使用 cancel() { if (pro.state === "pending") { clearTimeout(i); res(true); } } }); }, "createPromise"); let promise = createPromise(); const pinger = (async () => { while (true) { const canceled = await promise; if (canceled) { break; } try { if ( /* __TAI_KUN__SURREALDB__DIAGNOSTICS_CHANNEL__ */ false ) { channel.publish("websocket:ping", { type: "ping" }); } const timeout = 5e3; const rpcResp = await this.rpc({ signal: (0, import_utils.getTimeoutSignal)(timeout), request: { method: "ping" } }); if (rpcResp.error) { throw new import_errors.RpcResponseError(rpcResp, { cause: { endpoint: endpoint.href } }); } if ( /* __TAI_KUN__SURREALDB__DIAGNOSTICS_CHANNEL__ */ false ) { channel.publish("websocket:pong", { type: "pong" }); } } catch (e) { this.ee.emit( "error", new import_errors.WebSocketEngineError( // ping メッセージの送信に失敗したエラーを、 // カスタムエラーコード 3153 として報告します。 3153, "Failed to send a ping message.", { cause: e, fatal: false } ) ); } finally { promise = createPromise(); } } })(); this.ee.on( "closing", /* @__PURE__ */ __name(async function stop() { this.off("closing", stop); promise.cancel(); await pinger; }, "stop") ); } async close({ signal }) { (0, import_utils.throwIfAborted)(signal); const conn = this.getConnectionInfo(); if (conn.state === "closed") { return; } if (conn.state !== "open") { (0, import_errors.unreachable)(conn); } await this.transition( { state: "closing", endpoint: conn.endpoint }, () => ({ state: "closing", endpoint: conn.endpoint }) ); const promiseClosed = this.ee.once("closed", { signal }); if (this.ws && this.ws.readyState !== 3 && this.ws.readyState !== 2) { this.ws.close(); } else { this.ee.emit("closed", { state: "closed" }); } const [result] = await promiseClosed; if ("error" in result) { throw result.error; } } async rpc({ request, signal }) { const conn = this.getConnectionInfo(); if (!this.ws || conn.state !== "open") { throw new import_errors.ConnectionUnavailableError({ cause: "The connection is not established via the .connect() method." }); } switch (request.method) { case "use": { let { namespace, database } = conn; const [ns, db] = request.params; if (ns !== void 0) { namespace = ns; } if (db !== void 0) { database = db; } if (namespace === null && database !== null) { throw new import_errors.MissingNamespaceError(database); } { if (ns === void 0 && conn.namespace !== null) { request = { method: request.method, params: [conn.namespace, request.params[1]] }; } if (db === void 0 && conn.database !== null) { request = { method: request.method, params: [request.params[0], conn.database] }; } } break; } case "query": { request = (0, import_engine.processQueryRequest)(request); break; } } const id = `${request.method}_${this.id.next()}`; const body = this.fmt.encodeSync({ id, method: request.method, params: request.params || [] }); if (typeof body !== "string" && !(body instanceof Uint8Array)) { throw new import_errors.SurrealTypeError(["String", "Uint8Array"], body); } const resp = this.ee.once(`rpc_${id}`, { signal }); this.ws.send(body); const [rawResp] = await resp; const rpcResp = rawResp; if ("result" in rpcResp) { const rpc = { method: request.method, params: request.params, result: rpcResp.result }; switch (rpc.method) { case "use": { const [ns, db] = rpc.params; if (ns !== void 0) { this.namespace = ns; } if (db !== void 0) { this.database = db; } break; } case "signin": case "signup": this.token = rpc.result; break; case "authenticate": [this.token] = rpc.params; break; case "invalidate": this.token = null; break; } } return rpcResp; } }; __name(_WebSocketEngine, "WebSocketEngine"); var WebSocketEngine = _WebSocketEngine; //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2VuZ2luZXMvd2Vic29ja2V0L2VuZ2luZS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHtcbiAgdHlwZSBDbG9zZUFyZ3MsXG4gIHR5cGUgQ29ubmVjdEFyZ3MsXG4gIEVuZ2luZUFiYyxcbiAgdHlwZSBFbmdpbmVBYmNDb25maWcsXG4gIHR5cGUgRW5naW5lRXZlbnRNYXAsXG4gIHByb2Nlc3NRdWVyeVJlcXVlc3QsXG4gIHR5cGUgUnBjQXJncyxcbn0gZnJvbSBcIkB0YWkta3VuL3N1cnJlYWxkYi9lbmdpbmVcIjtcbmltcG9ydCB7XG4gIENvbm5lY3Rpb25VbmF2YWlsYWJsZUVycm9yLFxuICBNaXNzaW5nTmFtZXNwYWNlRXJyb3IsXG4gIFJwY1Jlc3BvbnNlRXJyb3IsXG4gIFNlcnZlclJlc3BvbnNlRXJyb3IsXG4gIFN1cnJlYWxUeXBlRXJyb3IsXG4gIHVucmVhY2hhYmxlLFxuICBXZWJTb2NrZXRFbmdpbmVFcnJvcixcbn0gZnJvbSBcIkB0YWkta3VuL3N1cnJlYWxkYi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHtcbiAgQmlkaXJlY3Rpb25hbFJwY1Jlc3BvbnNlLFxuICBScGNQYXJhbXMsXG4gIFJwY1F1ZXJ5UmVxdWVzdCxcbiAgUnBjUmVzdWx0LFxufSBmcm9tIFwiQHRhaS1rdW4vc3VycmVhbGRiL3R5cGVzXCI7XG5pbXBvcnQge1xuICBjaGFubmVsLFxuICBnZXRUaW1lb3V0U2lnbmFsLFxuICBpc0xpdmVSZXN1bHQsXG4gIGlzUnBjUmVzcG9uc2UsXG4gIFNlcmlhbCxcbiAgU3RhdGVmdWxQcm9taXNlLFxuICB0eXBlIFRhc2tFbWl0dGVyLFxuICB0aHJvd0lmQWJvcnRlZCxcbn0gZnJvbSBcIkB0YWkta3VuL3N1cnJlYWxkYi91dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBQcm9taXNhYmxlIH0gZnJvbSBcInR5cGUtZmVzdFwiO1xuaW1wb3J0IHR5cGUgeyBXZWJTb2NrZXQgYXMgV3NXZWJTb2NrZXQgfSBmcm9tIFwid3NcIjtcblxudHlwZSBJbmZlcldlYlNvY2tldDxUPiA9IFQgZXh0ZW5kc1xuICB7IHJlYWRvbmx5IFdlYlNvY2tldDogbmV3KC4uLmFyZ3M6IGFueSkgPT4gaW5mZXIgVyB9ID8gVyA6IG5ldmVyO1xuXG50eXBlIE5hdGl2ZVdlYlNvY2tldCA9IEluZmVyV2ViU29ja2V0PFxuICB8IHR5cGVvZiBnbG9iYWxcbiAgfCB0eXBlb2Ygd2luZG93XG4gIHwgdHlwZW9mIHNlbGZcbj47XG5cbnR5cGUgV2ViU29ja2V0ID0gV3NXZWJTb2NrZXQgfCBOYXRpdmVXZWJTb2NrZXQ7IC8vIGlzb3dzIFx1MzA2RVx1NTc4Qlx1NUI5QVx1N0ZBOVx1MzA2Rlx1MzA1M1x1MzA4Q1x1MzA4OFx1MzA4QVx1NzJFRFx1MzA0NFx1MzAwMlxuXG5leHBvcnQgdHlwZSBDcmVhdGVXZWJTb2NrZXQgPSAoXG4gIGFkZHJlc3M6IFVSTCxcbiAgcHJvdG9jb2xzOiBzdHJpbmdbXSxcbikgPT4gUHJvbWlzYWJsZTxXZWJTb2NrZXQ+O1xuXG5leHBvcnQgaW50ZXJmYWNlIFdlYlNvY2tldEVuZ2luZUNvbmZpZyBleHRlbmRzIEVuZ2luZUFiY0NvbmZpZyB7XG4gIHJlYWRvbmx5IGNyZWF0ZVdlYlNvY2tldDogQ3JlYXRlV2ViU29ja2V0O1xuICByZWFkb25seSBwaW5nSW50ZXJ2YWw/OiBudW1iZXIgfCAoKCkgPT4gbnVtYmVyKSB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2ViU29ja2V0RW5naW5lIGV4dGVuZHMgRW5naW5lQWJjIHtcbiAgcmVhZG9ubHkgbmFtZSA9IFwid2Vic29ja2V0XCI7XG5cbiAgcHJvdGVjdGVkIHdzOiBXZWJTb2NrZXQgfCBudWxsID0gbnVsbDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkID0gbmV3IFNlcmlhbCgpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgbmV3V3M6IENyZWF0ZVdlYlNvY2tldDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHBpbmdJbnRlcnZhbDogKCkgPT4gbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogV2ViU29ja2V0RW5naW5lQ29uZmlnKSB7XG4gICAgc3VwZXIoY29uZmlnKTtcbiAgICBjb25zdCB7XG4gICAgICBwaW5nSW50ZXJ2YWwsXG4gICAgICBjcmVhdGVXZWJTb2NrZXQsXG4gICAgfSA9IGNvbmZpZztcbiAgICB0aGlzLm5ld1dzID0gY3JlYXRlV2ViU29ja2V0O1xuICAgIHRoaXMucGluZ0ludGVydmFsID0gdHlwZW9mIHBpbmdJbnRlcnZhbCA9PT0gXCJmdW5jdGlvblwiXG4gICAgICA/IHBpbmdJbnRlcnZhbFxuICAgICAgOiAobXMgPT4gKCkgPT4gbXMpKE1hdGgubWF4KDNfMDAwLCBwaW5nSW50ZXJ2YWwgPz8gMzBfMDAwKSk7XG4gIH1cblxuICBhc3luYyBjb25uZWN0KHsgZW5kcG9pbnQsIHNpZ25hbCB9OiBDb25uZWN0QXJncyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRocm93SWZBYm9ydGVkKHNpZ25hbCk7XG4gICAgY29uc3QgY29ubiA9IHRoaXMuZ2V0Q29ubmVjdGlvbkluZm8oKTtcblxuICAgIGlmIChjb25uLnN0YXRlID09PSBcIm9wZW5cIikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjb25uLnN0YXRlICE9PSBcImNsb3NlZFwiKSB7XG4gICAgICB1bnJlYWNoYWJsZShjb25uIGFzIG5ldmVyKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnRyYW5zaXRpb24oXG4gICAgICB7XG4gICAgICAgIHN0YXRlOiBcImNvbm5lY3RpbmdcIixcbiAgICAgICAgZW5kcG9pbnQsXG4gICAgICB9LFxuICAgICAgKCkgPT4gXCJjbG9zZWRcIixcbiAgICApO1xuICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5uZXdXcyhuZXcgVVJMKGVuZHBvaW50KSwgdGhpcy5mbXQud3NQcm90b2NvbHMpO1xuICAgIHdzLmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCBldnQgPT4ge1xuICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgY2hhbm5lbC5wdWJsaXNoKFwid2Vic29ja2V0OndzOmVycm9yXCIsIGV2dCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZWUuZW1pdChcbiAgICAgICAgXCJlcnJvclwiLFxuICAgICAgICBuZXcgV2ViU29ja2V0RW5naW5lRXJyb3IoXG4gICAgICAgICAgMzE1MCxcbiAgICAgICAgICAvLyBcdTMwQTRcdTMwRDlcdTMwRjNcdTMwQzhcdTMwNkIgbWVzc2FnZSBcdTMwRDdcdTMwRURcdTMwRDFcdTMwQzZcdTMwQTNcdTMwNENcdTU0MkJcdTMwN0VcdTMwOENcdTMwNjZcdTMwNDRcdTMwOEJcdTMwNEJcdTMwNjlcdTMwNDZcdTMwNEJcdTMwNkZcdTUyMDZcdTMwNEJcdTMwOEFcdTMwN0VcdTMwNUJcdTMwOTNcdTMwMDJcbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIC0gTW96aWxsYTogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dlYlNvY2tldC9lcnJvcl9ldmVudCNldmVudF90eXBlXG4gICAgICAgICAgLy8gLSBOb2RlLmpzOlxuICAgICAgICAgIC8vICAgICAtIHVuZGljaTogaHR0cHM6Ly9naXRodWIuY29tL25vZGVqcy91bmRpY2kvYmxvYi92Ni4xOC4xL3R5cGVzL3dlYnNvY2tldC5kLnRzI0wxMjctTDEzM1xuICAgICAgICAgIC8vICAgICAtIHdzOiBodHRwczovL2dpdGh1Yi5jb20vRGVmaW5pdGVseVR5cGVkL0RlZmluaXRlbHlUeXBlZC9ibG9iL21hc3Rlci90eXBlcy93cy9pbmRleC5kLnRzI0wyODktTDI5NFxuICAgICAgICAgIC8vIC0gRGVubzogaHR0cHM6Ly9naXRodWIuY29tL2Rlbm9sYW5kL2Rlbm8vYmxvYi92MS40My42L2V4dC93ZWIvMDJfZXZlbnQuanMjTDEwNjQtTDExMzNcbiAgICAgICAgICBcIm1lc3NhZ2VcIiBpbiBldnRcbiAgICAgICAgICAgID8gU3RyaW5nKGV2dC5tZXNzYWdlKVxuICAgICAgICAgICAgOiBcIlRoZSBcXFwiZXJyb3JcXFwiIGV2ZW50IHdhcyBjYXVnaHQuXCIsXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4uKFwiZXJyb3JcIiBpbiBldnQgPyB7IGNhdXNlOiBldnQuZXJyb3IgfSA6IHt9KSxcbiAgICAgICAgICAgIGZhdGFsOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH0pO1xuICAgIHdzLmFkZEV2ZW50TGlzdGVuZXIoXCJjbG9zZVwiLCBhc3luYyBldnQgPT4ge1xuICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgY2hhbm5lbC5wdWJsaXNoKFwid2Vic29ja2V0OndzOmNsb3NlXCIsIGV2dCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMud3MgPSBudWxsO1xuICAgICAgdGhpcy5pZC5yZXNldCgpO1xuXG4gICAgICBzd2l0Y2ggKGV2dC5jb2RlKSB7XG4gICAgICAgIC8vIFx1NkI2M1x1NUUzOFx1N0NGQlxuICAgICAgICBjYXNlIDEwMDA6IC8vIE5vcm1hbCBDbG9zdXJlXG4gICAgICAgIC8vIFx1NEU4OFx1N0QwNFx1NkUwOFx1MzA3RlxuICAgICAgICBjYXNlIDEwMDQ6IC8vIFJlc2VydmVkXG4gICAgICAgIGNhc2UgMTAwNTogLy8gTm8gU3RhdHVzXG4gICAgICAgIGNhc2UgMTAxNTogLy8gVExTIEhhbmRzaGFrZVxuICAgICAgICAvLyBcdTY1RTlcdTY3MUZcdTMwNkVcdTUyMDdcdTY1QURcdTMwNkJcdTc1MzFcdTY3NjVcdTMwNTlcdTMwOEJcdTMwQThcdTMwRTlcdTMwRkNcdTMwQjNcdTMwRkNcdTMwQzlcdTMwOTJcdTMwQThcdTMwRTlcdTMwRkNcdTMwNjhcdTMwNTdcdTMwNjZcdTYyNzFcdTMwNDRcdTMwN0VcdTMwNUJcdTMwOTNcdTMwMDJcbiAgICAgICAgY2FzZSAxMDAxOiAvLyBHb2luZyBBd2F5XG4gICAgICAgIGNhc2UgMTAwNjogLy8gQWJub3JtYWwgQ2xvc3VyZSAoXHUzMDRCXHUzMDY0XHUzMDAxXHU0RTg4XHU3RDA0XHU2RTA4XHUzMDdGKVxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgMTAwMjogLy8gUHJvdG9jb2wgRXJyb3JcbiAgICAgICAgY2FzZSAxMDAzOiAvLyBVbnN1cHBvcnRlZCBEYXRhXG4gICAgICAgIGNhc2UgMTAwNzogLy8gSW52YWxpZCBGcmFtZSBQYXlsb2FkIERhdGFcbiAgICAgICAgY2FzZSAxMDA4OiAvLyBQb2xpY3kgVmlvbGF0aW9uXG4gICAgICAgIGNhc2UgMTAwOTogLy8gTWVzc2FnZSBUb28gQmlnXG4gICAgICAgIGNhc2UgMTAxMDogLy8gTWFuZGF0b3J5IEV4dGVuc2lvblxuICAgICAgICBjYXNlIDEwMTE6IC8vIEludGVybmFsIFNlcnZlciBFcnJvclxuICAgICAgICBjYXNlIDEwMTI6IC8vIFNlcnZpY2UgUmVzdGFydFxuICAgICAgICBjYXNlIDEwMTM6IC8vIFRyeSBBZ2FpbiBMYXRlclxuICAgICAgICBjYXNlIDEwMTQ6IC8vIEJhZCBHYXRld2F5XG4gICAgICAgICAgdGhpcy5lZS5lbWl0KFxuICAgICAgICAgICAgXCJlcnJvclwiLFxuICAgICAgICAgICAgbmV3IFdlYlNvY2tldEVuZ2luZUVycm9yKGV2dC5jb2RlLCBldnQucmVhc29uKSxcbiAgICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zaXRpb24oXCJjbG9zZWRcIiwgKCkgPT4gXCJjbG9zZWRcIik7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdChcbiAgICAgICAgICBcImVycm9yXCIsXG4gICAgICAgICAgbmV3IFdlYlNvY2tldEVuZ2luZUVycm9yKFxuICAgICAgICAgICAgMzE1NCxcbiAgICAgICAgICAgIFwiQW4gZXJyb3Igb2NjdXJyZWQgd2l0aGluIHRoZSBoYW5kbGVyIGZvciB0aGUgXFxcImNsb3NlXFxcIiBldmVudC5cIixcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgY2F1c2U6IGUsXG4gICAgICAgICAgICAgIGZhdGFsOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB3cy5hZGRFdmVudExpc3RlbmVyKFwib3BlblwiLCBhc3luYyBldnQgPT4ge1xuICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgY2hhbm5lbC5wdWJsaXNoKFwid2Vic29ja2V0OndzOm9wZW5cIiwgZXZ0KTtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy53cyA9IHdzO1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zaXRpb24oXG4gICAgICAgICAge1xuICAgICAgICAgICAgc3RhdGU6IFwib3BlblwiLFxuICAgICAgICAgICAgZW5kcG9pbnQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLndzID0gbnVsbDtcblxuICAgICAgICAgICAgcmV0dXJuIFwiY2xvc2VkXCI7XG4gICAgICAgICAgfSxcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0KFxuICAgICAgICAgIFwiZXJyb3JcIixcbiAgICAgICAgICBuZXcgV2ViU29ja2V0RW5naW5lRXJyb3IoXG4gICAgICAgICAgICAvLyBvcGVuIFx1MzBBNFx1MzBEOVx1MzBGM1x1MzBDOFx1MzBDRlx1MzBGM1x1MzBDOVx1MzBFOVx1MzBGQ1x1NTE4NVx1MzA2N1x1NzY3QVx1NzUxRlx1MzA1N1x1MzA1Rlx1MzBBOFx1MzBFOVx1MzBGQ1x1MzA5Mlx1MzAwMVxuICAgICAgICAgICAgLy8gXHUzMEFCXHUzMEI5XHUzMEJGXHUzMEUwXHUzMEE4XHUzMEU5XHUzMEZDXHUzMEIzXHUzMEZDXHUzMEM5IDMxNTEgXHUzMDY4XHUzMDU3XHUzMDY2XHU1ODMxXHU1NDRBXHUzMDU3XHUzMDdFXHUzMDU5XHUzMDAyXG4gICAgICAgICAgICAzMTUxLFxuICAgICAgICAgICAgXCJBbiBlcnJvciBvY2N1cnJlZCB3aXRoaW4gdGhlIGhhbmRsZXIgZm9yIHRoZSBcXFwib3BlblxcXCIgZXZlbnQuXCIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNhdXNlOiBlLFxuICAgICAgICAgICAgICBmYXRhbDogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB3cy5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCBhc3luYyBldnQgPT4ge1xuICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgY2hhbm5lbC5wdWJsaXNoKFwid2Vic29ja2V0OndzOm1lc3NhZ2VcIiwgZXZ0KTtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gVE9ETyh0YWkta3VuKTogQmxvYiBcdTMwNkUgLnN0cmVhbSBcdTMwOTJcdTZEM0JcdTc1MjhcdTMwNjdcdTMwNERcdTMwOEJcdTMwODhcdTMwNDZcdTMwNkJcdTMwMDJDQk9SIFx1MzA2RVx1OTc1RVx1NTQwQ1x1NjcxRlx1MzBDN1x1MzBCM1x1MzBGQ1x1MzBDOVx1MzA5Mlx1NUI5Rlx1ODhDNVxuICAgICAgICAvLyBcdTMwNTdcdTMwNUZcdTMwNTFcdTMwNjlcdTMwMDFcdTMwRENcdTMwQzdcdTMwQTNcdTMwQjVcdTMwQTRcdTMwQkFcdTMwNkJcdTMwODhcdTMwNjNcdTMwNjZcdTMwNkZcdTU0MENcdTY3MUZcdTMwQzdcdTMwQjNcdTMwRkNcdTMwQzlcdTMwNkVcdTY1QjlcdTMwNENcdTlBRDhcdTkwMUZcdTMwNjBcdTMwNjhcdTYwMURcdTMwNDZcdTMwNkVcdTMwNjdcdTMwMDFcdTMwNURcdTMwNkVcdTMwNzhcdTMwOTNcdTMwNjlcdTMwNDZcdTMwNTlcdTMwOEJcdTMwNEJcdTY5MUNcdThBMEVcblxuICAgICAgICAvLyBOb2RlLmpzIHYyMiBcdTMwNjggd3MgdjguMTguMCBcdTRFRTVcdTk2NERcdTMwNkYgQmxvYiBcdTMwODJcdTY3NjVcdTMwOEJcdTMwMDJcbiAgICAgICAgY29uc3QgZGF0YSA9IGV2dC5kYXRhIGluc3RhbmNlb2YgQmxvYlxuICAgICAgICAgID8gYXdhaXQgKGV2dC5kYXRhIGFzIEJsb2IpLmFycmF5QnVmZmVyKClcbiAgICAgICAgICA6IGV2dC5kYXRhO1xuICAgICAgICBjb25zdCBycGNSZXNwID0gdGhpcy5mbXQuZGVjb2RlU3luYyhkYXRhKTtcblxuICAgICAgICBpZiAoIWlzUnBjUmVzcG9uc2UocnBjUmVzcCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgU2VydmVyUmVzcG9uc2VFcnJvcihcIk1pc3NpbmcgcnBjIHJlc3BvbnNlLlwiLCB7XG4gICAgICAgICAgICAvLyBjYXVzZTogKGV2dC5kYXRhIGFzIEJ1ZmZlcikubWFwKHYgPT4gdikuam9pbigpLFxuICAgICAgICAgICAgY2F1c2U6IHtcbiAgICAgICAgICAgICAgZW5kcG9pbnQ6IGVuZHBvaW50LmhyZWYsXG4gICAgICAgICAgICAgIHJlc3BvbnNlOiBycGNSZXNwLFxuICAgICAgICAgICAgICAvLyBUT0RPKHRhaS1rdW4pOiBcdTYwQzVcdTU4MzFcdTMwOTJcdThGRkRcdTUyQTBcbiAgICAgICAgICAgICAgLy8gLi4uY2F1c2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFwiaWRcIiBpbiBycGNSZXNwKSB7XG4gICAgICAgICAgdGhpcy5lZS5lbWl0KGBycGNfJHtycGNSZXNwLmlkfWAsIHJwY1Jlc3ApO1xuICAgICAgICB9IGVsc2UgaWYgKFwicmVzdWx0XCIgaW4gcnBjUmVzcCkge1xuICAgICAgICAgIGlmICghaXNMaXZlUmVzdWx0KHJwY1Jlc3AucmVzdWx0KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFNlcnZlclJlc3BvbnNlRXJyb3IoXCJNaXNzaW5nIGxpdmUgcmVzdWx0XCIsIHtcbiAgICAgICAgICAgICAgY2F1c2U6IHtcbiAgICAgICAgICAgICAgICBlbmRwb2ludDogZW5kcG9pbnQuaHJlZixcbiAgICAgICAgICAgICAgICBsaXZlUmVzdWx0OiBycGNSZXNwLnJlc3VsdCxcbiAgICAgICAgICAgICAgICAvLyBUT0RPKHRhaS1rdW4pOiBcdTYwQzVcdTU4MzFcdTMwOTJcdThGRkRcdTUyQTBcbiAgICAgICAgICAgICAgICAvLyAuLi5jYXVzZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHsgaWQsIC4uLnBheWxvYWQgfSA9IHJwY1Jlc3AucmVzdWx0O1xuXG4gICAgICAgICAgdGhpcy5lZS5lbWl0KGBsaXZlXyR7U3RyaW5nKGlkKX1gLCBwYXlsb2FkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUnBjUmVzcG9uc2VFcnJvcihycGNSZXNwLCB7XG4gICAgICAgICAgICBjYXVzZToge1xuICAgICAgICAgICAgICBlbmRwb2ludDogZW5kcG9pbnQuaHJlZixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0KFxuICAgICAgICAgIFwiZXJyb3JcIixcbiAgICAgICAgICBuZXcgV2ViU29ja2V0RW5naW5lRXJyb3IoXG4gICAgICAgICAgICAvLyBtZXNzYWdlIFx1MzBBNFx1MzBEOVx1MzBGM1x1MzBDOFx1MzBDRlx1MzBGM1x1MzBDOVx1MzBFOVx1MzBGQ1x1NTE4NVx1MzA2N1x1NzY3QVx1NzUxRlx1MzA1N1x1MzA1Rlx1MzBBOFx1MzBFOVx1MzBGQ1x1MzA5Mlx1MzAwMVxuICAgICAgICAgICAgLy8gXHUzMEFCXHUzMEI5XHUzMEJGXHUzMEUwXHUzMEE4XHUzMEU5XHUzMEZDXHUzMEIzXHUzMEZDXHUzMEM5IDMxNTIgXHUzMDY4XHUzMDU3XHUzMDY2XHU1ODMxXHU1NDRBXHUzMDU3XHUzMDdFXHUzMDU5XHUzMDAyXG4gICAgICAgICAgICAzMTUyLFxuICAgICAgICAgICAgXCJBbiBlcnJvciBvY2N1cnJlZCB3aXRoaW4gdGhlIGhhbmRsZXIgZm9yIHRoZSBcXFwibWVzc2FnZVxcXCIgZXZlbnQuXCIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNhdXNlOiBlLFxuICAgICAgICAgICAgICBmYXRhbDogZmFsc2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBvcGVuUHJvbWlzZSA9IHRoaXMuZWUub25jZShcIm9wZW5cIiwgeyBzaWduYWwgfSk7XG4gICAgY29uc3QgZXJyb3JQcm9taXNlID0gdGhpcy5lZS5vbmNlKFwiZXJyb3JcIiwgeyBzaWduYWwgfSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgW3Jlc3VsdF0gPSBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICBvcGVuUHJvbWlzZSxcbiAgICAgICAgZXJyb3JQcm9taXNlLFxuICAgICAgXSk7XG5cbiAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChcImVycm9yXCIgaW4gcmVzdWx0KSB7XG4gICAgICAgIHRocm93IHJlc3VsdC5lcnJvcjtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICBvcGVuUHJvbWlzZS5jYW5jZWwoKSxcbiAgICAgICAgZXJyb3JQcm9taXNlLmNhbmNlbCgpLFxuICAgICAgXSk7XG4gICAgfVxuXG4gICAgY29uc3QgY3JlYXRlUHJvbWlzZSA9ICgpID0+IHtcbiAgICAgIGxldCBpOiBhbnksXG4gICAgICAgIGludDogbnVtYmVyLFxuICAgICAgICByZXM6ICh2OiBib29sZWFuKSA9PiB2b2lkLFxuICAgICAgICBwcm8gPSBuZXcgU3RhdGVmdWxQcm9taXNlPGJvb2xlYW4+KHIgPT4ge1xuICAgICAgICAgIGkgPSBzZXRUaW1lb3V0KHJlcyA9IHIsIGludCA9IHRoaXMucGluZ0ludGVydmFsKCksIGZhbHNlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHBybywge1xuICAgICAgICBpbnRlcnZhbDogaW50ISwgLy8gXHU3M0ZFXHU1NzI4XHU2NzJBXHU0RjdGXHU3NTI4XG4gICAgICAgIGNhbmNlbCgpIHtcbiAgICAgICAgICBpZiAocHJvLnN0YXRlID09PSBcInBlbmRpbmdcIikge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KGkpO1xuICAgICAgICAgICAgcmVzKHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH07XG4gICAgbGV0IHByb21pc2UgPSBjcmVhdGVQcm9taXNlKCk7XG4gICAgY29uc3QgcGluZ2VyID0gKGFzeW5jICgpID0+IHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGNvbnN0IGNhbmNlbGVkID0gYXdhaXQgcHJvbWlzZTtcblxuICAgICAgICBpZiAoY2FuY2VsZWQpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgICAgIGNoYW5uZWwucHVibGlzaChcIndlYnNvY2tldDpwaW5nXCIsIHsgdHlwZTogXCJwaW5nXCIgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgdGltZW91dCA9IDVfMDAwO1xuICAgICAgICAgIGNvbnN0IHJwY1Jlc3AgPSBhd2FpdCB0aGlzLnJwYyh7XG4gICAgICAgICAgICBzaWduYWw6IGdldFRpbWVvdXRTaWduYWwodGltZW91dCksXG4gICAgICAgICAgICByZXF1ZXN0OiB7XG4gICAgICAgICAgICAgIG1ldGhvZDogXCJwaW5nXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKHJwY1Jlc3AuZXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBScGNSZXNwb25zZUVycm9yKHJwY1Jlc3AsIHtcbiAgICAgICAgICAgICAgY2F1c2U6IHtcbiAgICAgICAgICAgICAgICBlbmRwb2ludDogZW5kcG9pbnQuaHJlZixcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICgvKiBfX1RBSV9LVU5fX1NVUlJFQUxEQl9fRElBR05PU1RJQ1NfQ0hBTk5FTF9fICovIGZhbHNlKSB7XG4gICAgICAgICAgICBjaGFubmVsLnB1Ymxpc2goXCJ3ZWJzb2NrZXQ6cG9uZ1wiLCB7IHR5cGU6IFwicG9uZ1wiIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHRoaXMuZWUuZW1pdChcbiAgICAgICAgICAgIFwiZXJyb3JcIixcbiAgICAgICAgICAgIG5ldyBXZWJTb2NrZXRFbmdpbmVFcnJvcihcbiAgICAgICAgICAgICAgLy8gcGluZyBcdTMwRTFcdTMwQzNcdTMwQkJcdTMwRkNcdTMwQjhcdTMwNkVcdTkwMDFcdTRGRTFcdTMwNkJcdTU5MzFcdTY1NTdcdTMwNTdcdTMwNUZcdTMwQThcdTMwRTlcdTMwRkNcdTMwOTJcdTMwMDFcbiAgICAgICAgICAgICAgLy8gXHUzMEFCXHUzMEI5XHUzMEJGXHUzMEUwXHUzMEE4XHUzMEU5XHUzMEZDXHUzMEIzXHUzMEZDXHUzMEM5IDMxNTMgXHUzMDY4XHUzMDU3XHUzMDY2XHU1ODMxXHU1NDRBXHUzMDU3XHUzMDdFXHUzMDU5XHUzMDAyXG4gICAgICAgICAgICAgIDMxNTMsXG4gICAgICAgICAgICAgIFwiRmFpbGVkIHRvIHNlbmQgYSBwaW5nIG1lc3NhZ2UuXCIsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjYXVzZTogZSxcbiAgICAgICAgICAgICAgICBmYXRhbDogZmFsc2UsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApLFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgcHJvbWlzZSA9IGNyZWF0ZVByb21pc2UoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICB0aGlzLmVlLm9uKFxuICAgICAgXCJjbG9zaW5nXCIsXG4gICAgICBhc3luYyBmdW5jdGlvbiBzdG9wKHRoaXM6IFRhc2tFbWl0dGVyPEVuZ2luZUV2ZW50TWFwPikge1xuICAgICAgICB0aGlzLm9mZihcImNsb3NpbmdcIiwgc3RvcCk7XG4gICAgICAgIHByb21pc2UuY2FuY2VsKCk7XG4gICAgICAgIGF3YWl0IHBpbmdlcjtcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGNsb3NlKHsgc2lnbmFsIH06IENsb3NlQXJncyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRocm93SWZBYm9ydGVkKHNpZ25hbCk7XG4gICAgY29uc3QgY29ubiA9IHRoaXMuZ2V0Q29ubmVjdGlvbkluZm8oKTtcblxuICAgIGlmIChjb25uLnN0YXRlID09PSBcImNsb3NlZFwiKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNvbm4uc3RhdGUgIT09IFwib3BlblwiKSB7XG4gICAgICB1bnJlYWNoYWJsZShjb25uIGFzIG5ldmVyKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnRyYW5zaXRpb24oXG4gICAgICB7XG4gICAgICAgIHN0YXRlOiBcImNsb3NpbmdcIixcbiAgICAgICAgZW5kcG9pbnQ6IGNvbm4uZW5kcG9pbnQsXG4gICAgICB9LFxuICAgICAgKCkgPT4gKHtcbiAgICAgICAgc3RhdGU6IFwiY2xvc2luZ1wiLFxuICAgICAgICBlbmRwb2ludDogY29ubi5lbmRwb2ludCxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgY29uc3QgcHJvbWlzZUNsb3NlZCA9IHRoaXMuZWUub25jZShcImNsb3NlZFwiLCB7IHNpZ25hbCB9KTtcblxuICAgIGlmIChcbiAgICAgIHRoaXMud3NcbiAgICAgICYmIHRoaXMud3MucmVhZHlTdGF0ZSAhPT0gMyAvLyBXZWJTb2NrZXQuQ0xPU0VEXG4gICAgICAmJiB0aGlzLndzLnJlYWR5U3RhdGUgIT09IDIgLy8gV2ViU29ja2V0LkNMT1NJTkdcbiAgICApIHtcbiAgICAgIHRoaXMud3MuY2xvc2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5lZS5lbWl0KFwiY2xvc2VkXCIsIHtcbiAgICAgICAgc3RhdGU6IFwiY2xvc2VkXCIsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBbcmVzdWx0XSA9IGF3YWl0IHByb21pc2VDbG9zZWQ7XG5cbiAgICBpZiAoXCJlcnJvclwiIGluIHJlc3VsdCkge1xuICAgICAgdGhyb3cgcmVzdWx0LmVycm9yO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJwYyh7IHJlcXVlc3QsIHNpZ25hbCB9OiBScGNBcmdzKTogUHJvbWlzZTxCaWRpcmVjdGlvbmFsUnBjUmVzcG9uc2U+IHtcbiAgICAvLyBcdTYzQTVcdTdEOUFcdTYwQzVcdTU4MzFcdTMwNkVcdTMwQjlcdTMwQ0FcdTMwQzNcdTMwRDdcdTMwQjdcdTMwRTdcdTMwQzNcdTMwQzhcdTMwOTJcdTUzRDZcdTVGOTdcdTMwNTdcdTMwN0VcdTMwNTlcdTMwMDJcbiAgICAvLyBcdTRFRTVcdTk2NERcdTMwMDFcdTYzQTVcdTdEOUFcdTYwQzVcdTU4MzFcdTMwOTJcdTUzQzJcdTcxNjdcdTMwNTlcdTMwOEJcdTk2OUJcdTMwNkZcdTMwNTNcdTMwOENcdTMwOTJcdTRGN0ZcdTc1MjhcdTMwNTdcdTMwN0VcdTMwNTlcdTMwMDJcbiAgICBjb25zdCBjb25uID0gdGhpcy5nZXRDb25uZWN0aW9uSW5mbygpO1xuXG4gICAgaWYgKCF0aGlzLndzIHx8IGNvbm4uc3RhdGUgIT09IFwib3BlblwiKSB7XG4gICAgICB0aHJvdyBuZXcgQ29ubmVjdGlvblVuYXZhaWxhYmxlRXJyb3Ioe1xuICAgICAgICBjYXVzZTogXCJUaGUgY29ubmVjdGlvbiBpcyBub3QgZXN0YWJsaXNoZWQgdmlhIHRoZSAuY29ubmVjdCgpIG1ldGhvZC5cIixcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHN3aXRjaCAocmVxdWVzdC5tZXRob2QpIHtcbiAgICAgIGNhc2UgXCJ1c2VcIjoge1xuICAgICAgICBsZXQgeyBuYW1lc3BhY2UsIGRhdGFiYXNlIH0gPSBjb25uO1xuICAgICAgICBjb25zdCBbbnMsIGRiXSA9IHJlcXVlc3QucGFyYW1zO1xuXG4gICAgICAgIGlmIChucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbmFtZXNwYWNlID0gbnM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZGIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGRhdGFiYXNlID0gZGI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmFtZXNwYWNlID09PSBudWxsICYmIGRhdGFiYXNlICE9PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IE1pc3NpbmdOYW1lc3BhY2VFcnJvcihkYXRhYmFzZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAtIEpTT04gXHUzMDY3XHUzMDZGIG51bGwgXHUzMDY4IHVuZGVmaW5lZCBcdTMwOTJcdTUzM0FcdTUyMjVcdTMwNTdcdTMwNkFcdTMwNDRcdTMwNTFcdTMwNjlcdTMwMDFTdXJlYWxEQiBcdTMwNkZcdTUzM0FcdTUyMjVcdTMwNTlcdTMwOEJcdTMwMDJcbiAgICAgICAgLy8gLSBudWxsIFx1MzA2Rlx1OTA3OFx1NjI5RVx1NEUyRFx1MzA2RVx1NTQwRFx1NTI0RFx1N0E3QVx1OTU5M1x1MzA3RVx1MzA1Rlx1MzA2Rlx1MzBDN1x1MzBGQ1x1MzBCRlx1MzBEOVx1MzBGQ1x1MzBCOVx1MzA5Mlx1NjcyQVx1OTA3OFx1NjI5RVx1MzA2Qlx1MzA1OVx1MzA4Qlx1MzA2RVx1MzA2N1x1MzAwMXVuZGVmaW5lZCBcdTMwOTJcdTRGN0ZcdTMwNDhcdTMwOEJcbiAgICAgICAgLy8gICBDQk9SIFx1MzBENVx1MzBBOVx1MzBGQ1x1MzBERVx1MzBDM1x1MzBCRlx1MzBGQ1x1MzA2OFx1NTQwQ1x1MzA1OFx1MzA4OFx1MzA0Nlx1MzA2QVx1NEY3Rlx1MzA0NFx1NjVCOVx1MzA5MiBKU09OIFx1MzBENVx1MzBBOVx1MzBGQ1x1MzBERVx1MzBDM1x1MzBCRlx1MzBGQ1x1MzA2N1x1MzA1OVx1MzA4Qlx1MzA2OFx1NEU4Qlx1NjU0NVx1MzA4Qlx1NTNFRlx1ODBGRFx1NjAyN1x1MzA0Q1x1OUFEOFx1MzA0NFx1MzAwMlxuICAgICAgICAvLyBcdTMwNjhcdTMwNDRcdTMwNDZcdTUyRDVcdTZBNUZcdTMwNENcdTMwNDJcdTMwNjNcdTMwNjZcdTMwMDF1bmRlZmluZWQgXHUzMDkyXHU2NTg3XHU1QjU3XHU1MjE3XHUzMDZCXHU3RjZFXHUzMDREXHU2M0RCXHUzMDQ4XHUzMDhCXHUzMDg4XHUzMDQ2XHUzMDZCXHU1MkFBXHU1MjlCXHUzMDU5XHUzMDhCXHUzMDAyXG4gICAgICAgIHtcbiAgICAgICAgICBpZiAobnMgPT09IHVuZGVmaW5lZCAmJiBjb25uLm5hbWVzcGFjZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmVxdWVzdCA9IHtcbiAgICAgICAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBbY29ubi5uYW1lc3BhY2UsIHJlcXVlc3QucGFyYW1zWzFdXSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGRiID09PSB1bmRlZmluZWQgJiYgY29ubi5kYXRhYmFzZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmVxdWVzdCA9IHtcbiAgICAgICAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBbcmVxdWVzdC5wYXJhbXNbMF0sIGNvbm4uZGF0YWJhc2VdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgY2FzZSBcInF1ZXJ5XCI6IHtcbiAgICAgICAgcmVxdWVzdCA9IHByb2Nlc3NRdWVyeVJlcXVlc3QocmVxdWVzdCkgYXMgUnBjUXVlcnlSZXF1ZXN0O1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBpZDogQmlkaXJlY3Rpb25hbFJwY1Jlc3BvbnNlW1wiaWRcIl0gPVxuICAgICAgYCR7cmVxdWVzdC5tZXRob2R9XyR7dGhpcy5pZC5uZXh0KCl9YDtcbiAgICBjb25zdCBib2R5OiB1bmtub3duID0gdGhpcy5mbXQuZW5jb2RlU3luYyh7XG4gICAgICBpZCxcbiAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICBwYXJhbXM6IHJlcXVlc3QucGFyYW1zIHx8IFtdLFxuICAgIH0pO1xuXG4gICAgaWYgKHR5cGVvZiBib2R5ICE9PSBcInN0cmluZ1wiICYmICEoYm9keSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgICB0aHJvdyBuZXcgU3VycmVhbFR5cGVFcnJvcihbXCJTdHJpbmdcIiwgXCJVaW50OEFycmF5XCJdLCBib2R5KTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNwID0gdGhpcy5lZS5vbmNlKGBycGNfJHtpZH1gLCB7IHNpZ25hbCB9KTtcbiAgICB0aGlzLndzLnNlbmQoYm9keSk7XG4gICAgY29uc3QgW3Jhd1Jlc3BdID0gYXdhaXQgcmVzcDtcbiAgICAvLyBgcmF3UmVzcGAgXHUzMDZGIG1lc3NhZ2UgXHUzMEE0XHUzMEQ5XHUzMEYzXHUzMEM4XHUzMENGXHUzMEYzXHUzMEM5XHUzMEU5XHUzMEZDXHU1MTg1XHUzMDY3XHU2OTFDXHU4QTNDXHU2RTA4XHUzMDdGXHUzMDZBXHUzMDZFXHUzMDY3XHUzMDAxXHUzMDUzXHUzMDUzXHUzMDY3XHUzMDZGXHUzMEFEXHUzMEUzXHUzMEI5XHUzMEM4XHUzMDU5XHUzMDhCXHUzMDYwXHUzMDUxXHUzMDAyXG4gICAgY29uc3QgcnBjUmVzcCA9IHJhd1Jlc3AgYXMgQmlkaXJlY3Rpb25hbFJwY1Jlc3BvbnNlO1xuXG4gICAgaWYgKFwicmVzdWx0XCIgaW4gcnBjUmVzcCkge1xuICAgICAgY29uc3QgcnBjID0ge1xuICAgICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgICBwYXJhbXM6IHJlcXVlc3QucGFyYW1zLFxuICAgICAgICByZXN1bHQ6IHJwY1Jlc3AucmVzdWx0LFxuICAgICAgfSBhcyB7XG4gICAgICAgIFtNIGluICh0eXBlb2YgcmVxdWVzdClbXCJtZXRob2RcIl1dOiB7XG4gICAgICAgICAgbWV0aG9kOiBNO1xuICAgICAgICAgIHBhcmFtczogUnBjUGFyYW1zPE0+O1xuICAgICAgICAgIHJlc3VsdDogUnBjUmVzdWx0PE0+O1xuICAgICAgICB9O1xuICAgICAgfVsodHlwZW9mIHJlcXVlc3QpW1wibWV0aG9kXCJdXTtcblxuICAgICAgc3dpdGNoIChycGMubWV0aG9kKSB7XG4gICAgICAgIGNhc2UgXCJ1c2VcIjoge1xuICAgICAgICAgIGNvbnN0IFtucywgZGJdID0gcnBjLnBhcmFtcztcblxuICAgICAgICAgIGlmIChucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IG5zO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChkYiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFiYXNlID0gZGI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjYXNlIFwic2lnbmluXCI6XG4gICAgICAgIGNhc2UgXCJzaWdudXBcIjpcbiAgICAgICAgICB0aGlzLnRva2VuID0gcnBjLnJlc3VsdDtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIFwiYXV0aGVudGljYXRlXCI6XG4gICAgICAgICAgW3RoaXMudG9rZW5dID0gcnBjLnBhcmFtcztcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIFwiaW52YWxpZGF0ZVwiOlxuICAgICAgICAgIHRoaXMudG9rZW4gPSBudWxsO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBycGNSZXNwO1xuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsb0JBUU87QUFDUCxvQkFRTztBQU9QLG1CQVNPO0FBeUJQLElBQXFCLG1CQUFyQixNQUFxQix5QkFBd0Isd0JBQVU7QUFBQSxFQVFyRCxZQUFZLFFBQStCO0FBQ3pDLFVBQU0sTUFBTTtBQVJkLFNBQVMsT0FBTztBQUVoQixTQUFVLEtBQXVCO0FBQ2pDLFNBQW1CLEtBQUssSUFBSSxvQkFBTztBQU1qQyxVQUFNO0FBQUEsTUFDSjtBQUFBLE1BQ0E7QUFBQSxJQUNGLElBQUk7QUFDSixTQUFLLFFBQVE7QUFDYixTQUFLLGVBQWUsT0FBTyxpQkFBaUIsYUFDeEMsZUFDQyx5QkFBTSxNQUFNLElBQUksS0FBSyxJQUFJLEtBQU8sZ0JBQWdCLEdBQU0sQ0FBQztBQUFBLEVBQzlEO0FBQUEsRUFFQSxNQUFNLFFBQVEsRUFBRSxVQUFVLE9BQU8sR0FBK0I7QUFDOUQscUNBQWUsTUFBTTtBQUNyQixVQUFNLE9BQU8sS0FBSyxrQkFBa0I7QUFFcEMsUUFBSSxLQUFLLFVBQVUsUUFBUTtBQUN6QjtBQUFBLElBQ0Y7QUFFQSxRQUFJLEtBQUssVUFBVSxVQUFVO0FBQzNCLHFDQUFZLElBQWE7QUFBQSxJQUMzQjtBQUVBLFVBQU0sS0FBSztBQUFBLE1BQ1Q7QUFBQSxRQUNF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