@tai-kun/surrealdb
Version:
The SurrealDB SDK for JavaScript
461 lines (459 loc) • 46 kB
JavaScript
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
// src/engines/websocket/engine.ts
import {
EngineAbc,
processQueryRequest
} from "../../engine/index.mjs";
import {
ConnectionUnavailableError,
MissingNamespaceError,
RpcResponseError,
ServerResponseError,
SurrealTypeError,
unreachable,
WebSocketEngineError
} from "../../errors/index.mjs";
import {
getTimeoutSignal,
isLiveResult,
isRpcResponse,
Serial,
StatefulPromise,
throwIfAborted
} from "../../utils/index.mjs";
var _WebSocketEngine = class _WebSocketEngine extends EngineAbc {
constructor(config) {
super(config);
this.name = "websocket";
this.ws = null;
this.id = new 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 }) {
throwIfAborted(signal);
const conn = this.getConnectionInfo();
if (conn.state === "open") {
return;
}
if (conn.state !== "closed") {
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 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 WebSocketEngineError(evt.code, evt.reason)
);
}
try {
await this.transition("closed", () => "closed");
} catch (e) {
this.ee.emit(
"error",
new 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 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 (!isRpcResponse(rpcResp)) {
throw new 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 (!isLiveResult(rpcResp.result)) {
throw new 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 RpcResponseError(rpcResp, {
cause: {
endpoint: endpoint.href
}
});
}
} catch (e) {
this.ee.emit(
"error",
new 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 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: getTimeoutSignal(timeout),
request: {
method: "ping"
}
});
if (rpcResp.error) {
throw new 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 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 }) {
throwIfAborted(signal);
const conn = this.getConnectionInfo();
if (conn.state === "closed") {
return;
}
if (conn.state !== "open") {
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 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 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 = 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 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;
export {
WebSocketEngine as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2VuZ2luZXMvd2Vic29ja2V0L2VuZ2luZS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiaW1wb3J0IHtcbiAgdHlwZSBDbG9zZUFyZ3MsXG4gIHR5cGUgQ29ubmVjdEFyZ3MsXG4gIEVuZ2luZUFiYyxcbiAgdHlwZSBFbmdpbmVBYmNDb25maWcsXG4gIHR5cGUgRW5naW5lRXZlbnRNYXAsXG4gIHByb2Nlc3NRdWVyeVJlcXVlc3QsXG4gIHR5cGUgUnBjQXJncyxcbn0gZnJvbSBcIkB0YWkta3VuL3N1cnJlYWxkYi9lbmdpbmVcIjtcbmltcG9ydCB7XG4gIENvbm5lY3Rpb25VbmF2YWlsYWJsZUVycm9yLFxuICBNaXNzaW5nTmFtZXNwYWNlRXJyb3IsXG4gIFJwY1Jlc3BvbnNlRXJyb3IsXG4gIFNlcnZlclJlc3BvbnNlRXJyb3IsXG4gIFN1cnJlYWxUeXBlRXJyb3IsXG4gIHVucmVhY2hhYmxlLFxuICBXZWJTb2NrZXRFbmdpbmVFcnJvcixcbn0gZnJvbSBcIkB0YWkta3VuL3N1cnJlYWxkYi9lcnJvcnNcIjtcbmltcG9ydCB0eXBlIHtcbiAgQmlkaXJlY3Rpb25hbFJwY1Jlc3BvbnNlLFxuICBScGNQYXJhbXMsXG4gIFJwY1F1ZXJ5UmVxdWVzdCxcbiAgUnBjUmVzdWx0LFxufSBmcm9tIFwiQHRhaS1rdW4vc3VycmVhbGRiL3R5cGVzXCI7XG5pbXBvcnQge1xuICBjaGFubmVsLFxuICBnZXRUaW1lb3V0U2lnbmFsLFxuICBpc0xpdmVSZXN1bHQsXG4gIGlzUnBjUmVzcG9uc2UsXG4gIFNlcmlhbCxcbiAgU3RhdGVmdWxQcm9taXNlLFxuICB0eXBlIFRhc2tFbWl0dGVyLFxuICB0aHJvd0lmQWJvcnRlZCxcbn0gZnJvbSBcIkB0YWkta3VuL3N1cnJlYWxkYi91dGlsc1wiO1xuaW1wb3J0IHR5cGUgeyBQcm9taXNhYmxlIH0gZnJvbSBcInR5cGUtZmVzdFwiO1xuaW1wb3J0IHR5cGUgeyBXZWJTb2NrZXQgYXMgV3NXZWJTb2NrZXQgfSBmcm9tIFwid3NcIjtcblxudHlwZSBJbmZlcldlYlNvY2tldDxUPiA9IFQgZXh0ZW5kc1xuICB7IHJlYWRvbmx5IFdlYlNvY2tldDogbmV3KC4uLmFyZ3M6IGFueSkgPT4gaW5mZXIgVyB9ID8gVyA6IG5ldmVyO1xuXG50eXBlIE5hdGl2ZVdlYlNvY2tldCA9IEluZmVyV2ViU29ja2V0PFxuICB8IHR5cGVvZiBnbG9iYWxcbiAgfCB0eXBlb2Ygd2luZG93XG4gIHwgdHlwZW9mIHNlbGZcbj47XG5cbnR5cGUgV2ViU29ja2V0ID0gV3NXZWJTb2NrZXQgfCBOYXRpdmVXZWJTb2NrZXQ7IC8vIGlzb3dzIFx1MzA2RVx1NTc4Qlx1NUI5QVx1N0ZBOVx1MzA2Rlx1MzA1M1x1MzA4Q1x1MzA4OFx1MzA4QVx1NzJFRFx1MzA0NFx1MzAwMlxuXG5leHBvcnQgdHlwZSBDcmVhdGVXZWJTb2NrZXQgPSAoXG4gIGFkZHJlc3M6IFVSTCxcbiAgcHJvdG9jb2xzOiBzdHJpbmdbXSxcbikgPT4gUHJvbWlzYWJsZTxXZWJTb2NrZXQ+O1xuXG5leHBvcnQgaW50ZXJmYWNlIFdlYlNvY2tldEVuZ2luZUNvbmZpZyBleHRlbmRzIEVuZ2luZUFiY0NvbmZpZyB7XG4gIHJlYWRvbmx5IGNyZWF0ZVdlYlNvY2tldDogQ3JlYXRlV2ViU29ja2V0O1xuICByZWFkb25seSBwaW5nSW50ZXJ2YWw/OiBudW1iZXIgfCAoKCkgPT4gbnVtYmVyKSB8IHVuZGVmaW5lZDtcbn1cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgV2ViU29ja2V0RW5naW5lIGV4dGVuZHMgRW5naW5lQWJjIHtcbiAgcmVhZG9ubHkgbmFtZSA9IFwid2Vic29ja2V0XCI7XG5cbiAgcHJvdGVjdGVkIHdzOiBXZWJTb2NrZXQgfCBudWxsID0gbnVsbDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGlkID0gbmV3IFNlcmlhbCgpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgbmV3V3M6IENyZWF0ZVdlYlNvY2tldDtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHBpbmdJbnRlcnZhbDogKCkgPT4gbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogV2ViU29ja2V0RW5naW5lQ29uZmlnKSB7XG4gICAgc3VwZXIoY29uZmlnKTtcbiAgICBjb25zdCB7XG4gICAgICBwaW5nSW50ZXJ2YWwsXG4gICAgICBjcmVhdGVXZWJTb2NrZXQsXG4gICAgfSA9IGNvbmZpZztcbiAgICB0aGlzLm5ld1dzID0gY3JlYXRlV2ViU29ja2V0O1xuICAgIHRoaXMucGluZ0ludGVydmFsID0gdHlwZW9mIHBpbmdJbnRlcnZhbCA9PT0gXCJmdW5jdGlvblwiXG4gICAgICA/IHBpbmdJbnRlcnZhbFxuICAgICAgOiAobXMgPT4gKCkgPT4gbXMpKE1hdGgubWF4KDNfMDAwLCBwaW5nSW50ZXJ2YWwgPz8gMzBfMDAwKSk7XG4gIH1cblxuICBhc3luYyBjb25uZWN0KHsgZW5kcG9pbnQsIHNpZ25hbCB9OiBDb25uZWN0QXJncyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRocm93SWZBYm9ydGVkKHNpZ25hbCk7XG4gICAgY29uc3QgY29ubiA9IHRoaXMuZ2V0Q29ubmVjdGlvbkluZm8oKTtcblxuICAgIGlmIChjb25uLnN0YXRlID09PSBcIm9wZW5cIikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjb25uLnN0YXRlICE9PSBcImNsb3NlZFwiKSB7XG4gICAgICB1bnJlYWNoYWJsZShjb25uIGFzIG5ldmVyKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnRyYW5zaXRpb24oXG4gICAgICB7XG4gICAgICAgIHN0YXRlOiBcImNvbm5lY3RpbmdcIixcbiAgICAgICAgZW5kcG9pbnQsXG4gICAgICB9LFxuICAgICAgKCkgPT4gXCJjbG9zZWRcIixcbiAgICApO1xuICAgIGNvbnN0IHdzID0gYXdhaXQgdGhpcy5uZXdXcyhuZXcgVVJMKGVuZHBvaW50KSwgdGhpcy5mbXQud3NQcm90b2NvbHMpO1xuICAgIHdzLmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCBldnQgPT4ge1xuICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgY2hhbm5lbC5wdWJsaXNoKFwid2Vic29ja2V0OndzOmVycm9yXCIsIGV2dCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZWUuZW1pdChcbiAgICAgICAgXCJlcnJvclwiLFxuICAgICAgICBuZXcgV2ViU29ja2V0RW5naW5lRXJyb3IoXG4gICAgICAgICAgMzE1MCxcbiAgICAgICAgICAvLyBcdTMwQTRcdTMwRDlcdTMwRjNcdTMwQzhcdTMwNkIgbWVzc2FnZSBcdTMwRDdcdTMwRURcdTMwRDFcdTMwQzZcdTMwQTNcdTMwNENcdTU0MkJcdTMwN0VcdTMwOENcdTMwNjZcdTMwNDRcdTMwOEJcdTMwNEJcdTMwNjlcdTMwNDZcdTMwNEJcdTMwNkZcdTUyMDZcdTMwNEJcdTMwOEFcdTMwN0VcdTMwNUJcdTMwOTNcdTMwMDJcbiAgICAgICAgICAvL1xuICAgICAgICAgIC8vIC0gTW96aWxsYTogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dlYlNvY2tldC9lcnJvcl9ldmVudCNldmVudF90eXBlXG4gICAgICAgICAgLy8gLSBOb2RlLmpzOlxuICAgICAgICAgIC8vICAgICAtIHVuZGljaTogaHR0cHM6Ly9naXRodWIuY29tL25vZGVqcy91bmRpY2kvYmxvYi92Ni4xOC4xL3R5cGVzL3dlYnNvY2tldC5kLnRzI0wxMjctTDEzM1xuICAgICAgICAgIC8vICAgICAtIHdzOiBodHRwczovL2dpdGh1Yi5jb20vRGVmaW5pdGVseVR5cGVkL0RlZmluaXRlbHlUeXBlZC9ibG9iL21hc3Rlci90eXBlcy93cy9pbmRleC5kLnRzI0wyODktTDI5NFxuICAgICAgICAgIC8vIC0gRGVubzogaHR0cHM6Ly9naXRodWIuY29tL2Rlbm9sYW5kL2Rlbm8vYmxvYi92MS40My42L2V4dC93ZWIvMDJfZXZlbnQuanMjTDEwNjQtTDExMzNcbiAgICAgICAgICBcIm1lc3NhZ2VcIiBpbiBldnRcbiAgICAgICAgICAgID8gU3RyaW5nKGV2dC5tZXNzYWdlKVxuICAgICAgICAgICAgOiBcIlRoZSBcXFwiZXJyb3JcXFwiIGV2ZW50IHdhcyBjYXVnaHQuXCIsXG4gICAgICAgICAge1xuICAgICAgICAgICAgLi4uKFwiZXJyb3JcIiBpbiBldnQgPyB7IGNhdXNlOiBldnQuZXJyb3IgfSA6IHt9KSxcbiAgICAgICAgICAgIGZhdGFsOiB0cnVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH0pO1xuICAgIHdzLmFkZEV2ZW50TGlzdGVuZXIoXCJjbG9zZVwiLCBhc3luYyBldnQgPT4ge1xuICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgY2hhbm5lbC5wdWJsaXNoKFwid2Vic29ja2V0OndzOmNsb3NlXCIsIGV2dCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMud3MgPSBudWxsO1xuICAgICAgdGhpcy5pZC5yZXNldCgpO1xuXG4gICAgICBzd2l0Y2ggKGV2dC5jb2RlKSB7XG4gICAgICAgIC8vIFx1NkI2M1x1NUUzOFx1N0NGQlxuICAgICAgICBjYXNlIDEwMDA6IC8vIE5vcm1hbCBDbG9zdXJlXG4gICAgICAgIC8vIFx1NEU4OFx1N0QwNFx1NkUwOFx1MzA3RlxuICAgICAgICBjYXNlIDEwMDQ6IC8vIFJlc2VydmVkXG4gICAgICAgIGNhc2UgMTAwNTogLy8gTm8gU3RhdHVzXG4gICAgICAgIGNhc2UgMTAxNTogLy8gVExTIEhhbmRzaGFrZVxuICAgICAgICAvLyBcdTY1RTlcdTY3MUZcdTMwNkVcdTUyMDdcdTY1QURcdTMwNkJcdTc1MzFcdTY3NjVcdTMwNTlcdTMwOEJcdTMwQThcdTMwRTlcdTMwRkNcdTMwQjNcdTMwRkNcdTMwQzlcdTMwOTJcdTMwQThcdTMwRTlcdTMwRkNcdTMwNjhcdTMwNTdcdTMwNjZcdTYyNzFcdTMwNDRcdTMwN0VcdTMwNUJcdTMwOTNcdTMwMDJcbiAgICAgICAgY2FzZSAxMDAxOiAvLyBHb2luZyBBd2F5XG4gICAgICAgIGNhc2UgMTAwNjogLy8gQWJub3JtYWwgQ2xvc3VyZSAoXHUzMDRCXHUzMDY0XHUzMDAxXHU0RTg4XHU3RDA0XHU2RTA4XHUzMDdGKVxuICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIGNhc2UgMTAwMjogLy8gUHJvdG9jb2wgRXJyb3JcbiAgICAgICAgY2FzZSAxMDAzOiAvLyBVbnN1cHBvcnRlZCBEYXRhXG4gICAgICAgIGNhc2UgMTAwNzogLy8gSW52YWxpZCBGcmFtZSBQYXlsb2FkIERhdGFcbiAgICAgICAgY2FzZSAxMDA4OiAvLyBQb2xpY3kgVmlvbGF0aW9uXG4gICAgICAgIGNhc2UgMTAwOTogLy8gTWVzc2FnZSBUb28gQmlnXG4gICAgICAgIGNhc2UgMTAxMDogLy8gTWFuZGF0b3J5IEV4dGVuc2lvblxuICAgICAgICBjYXNlIDEwMTE6IC8vIEludGVybmFsIFNlcnZlciBFcnJvclxuICAgICAgICBjYXNlIDEwMTI6IC8vIFNlcnZpY2UgUmVzdGFydFxuICAgICAgICBjYXNlIDEwMTM6IC8vIFRyeSBBZ2FpbiBMYXRlclxuICAgICAgICBjYXNlIDEwMTQ6IC8vIEJhZCBHYXRld2F5XG4gICAgICAgICAgdGhpcy5lZS5lbWl0KFxuICAgICAgICAgICAgXCJlcnJvclwiLFxuICAgICAgICAgICAgbmV3IFdlYlNvY2tldEVuZ2luZUVycm9yKGV2dC5jb2RlLCBldnQucmVhc29uKSxcbiAgICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zaXRpb24oXCJjbG9zZWRcIiwgKCkgPT4gXCJjbG9zZWRcIik7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRoaXMuZWUuZW1pdChcbiAgICAgICAgICBcImVycm9yXCIsXG4gICAgICAgICAgbmV3IFdlYlNvY2tldEVuZ2luZUVycm9yKFxuICAgICAgICAgICAgMzE1NCxcbiAgICAgICAgICAgIFwiQW4gZXJyb3Igb2NjdXJyZWQgd2l0aGluIHRoZSBoYW5kbGVyIGZvciB0aGUgXFxcImNsb3NlXFxcIiBldmVudC5cIixcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgY2F1c2U6IGUsXG4gICAgICAgICAgICAgIGZhdGFsOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB3cy5hZGRFdmVudExpc3RlbmVyKFwib3BlblwiLCBhc3luYyBldnQgPT4ge1xuICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgY2hhbm5lbC5wdWJsaXNoKFwid2Vic29ja2V0OndzOm9wZW5cIiwgZXZ0KTtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy53cyA9IHdzO1xuICAgICAgICBhd2FpdCB0aGlzLnRyYW5zaXRpb24oXG4gICAgICAgICAge1xuICAgICAgICAgICAgc3RhdGU6IFwib3BlblwiLFxuICAgICAgICAgICAgZW5kcG9pbnQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLndzID0gbnVsbDtcblxuICAgICAgICAgICAgcmV0dXJuIFwiY2xvc2VkXCI7XG4gICAgICAgICAgfSxcbiAgICAgICAgKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0KFxuICAgICAgICAgIFwiZXJyb3JcIixcbiAgICAgICAgICBuZXcgV2ViU29ja2V0RW5naW5lRXJyb3IoXG4gICAgICAgICAgICAvLyBvcGVuIFx1MzBBNFx1MzBEOVx1MzBGM1x1MzBDOFx1MzBDRlx1MzBGM1x1MzBDOVx1MzBFOVx1MzBGQ1x1NTE4NVx1MzA2N1x1NzY3QVx1NzUxRlx1MzA1N1x1MzA1Rlx1MzBBOFx1MzBFOVx1MzBGQ1x1MzA5Mlx1MzAwMVxuICAgICAgICAgICAgLy8gXHUzMEFCXHUzMEI5XHUzMEJGXHUzMEUwXHUzMEE4XHUzMEU5XHUzMEZDXHUzMEIzXHUzMEZDXHUzMEM5IDMxNTEgXHUzMDY4XHUzMDU3XHUzMDY2XHU1ODMxXHU1NDRBXHUzMDU3XHUzMDdFXHUzMDU5XHUzMDAyXG4gICAgICAgICAgICAzMTUxLFxuICAgICAgICAgICAgXCJBbiBlcnJvciBvY2N1cnJlZCB3aXRoaW4gdGhlIGhhbmRsZXIgZm9yIHRoZSBcXFwib3BlblxcXCIgZXZlbnQuXCIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNhdXNlOiBlLFxuICAgICAgICAgICAgICBmYXRhbDogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKSxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB3cy5hZGRFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCBhc3luYyBldnQgPT4ge1xuICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgY2hhbm5lbC5wdWJsaXNoKFwid2Vic29ja2V0OndzOm1lc3NhZ2VcIiwgZXZ0KTtcbiAgICAgIH1cblxuICAgICAgdHJ5IHtcbiAgICAgICAgLy8gVE9ETyh0YWkta3VuKTogQmxvYiBcdTMwNkUgLnN0cmVhbSBcdTMwOTJcdTZEM0JcdTc1MjhcdTMwNjdcdTMwNERcdTMwOEJcdTMwODhcdTMwNDZcdTMwNkJcdTMwMDJDQk9SIFx1MzA2RVx1OTc1RVx1NTQwQ1x1NjcxRlx1MzBDN1x1MzBCM1x1MzBGQ1x1MzBDOVx1MzA5Mlx1NUI5Rlx1ODhDNVxuICAgICAgICAvLyBcdTMwNTdcdTMwNUZcdTMwNTFcdTMwNjlcdTMwMDFcdTMwRENcdTMwQzdcdTMwQTNcdTMwQjVcdTMwQTRcdTMwQkFcdTMwNkJcdTMwODhcdTMwNjNcdTMwNjZcdTMwNkZcdTU0MENcdTY3MUZcdTMwQzdcdTMwQjNcdTMwRkNcdTMwQzlcdTMwNkVcdTY1QjlcdTMwNENcdTlBRDhcdTkwMUZcdTMwNjBcdTMwNjhcdTYwMURcdTMwNDZcdTMwNkVcdTMwNjdcdTMwMDFcdTMwNURcdTMwNkVcdTMwNzhcdTMwOTNcdTMwNjlcdTMwNDZcdTMwNTlcdTMwOEJcdTMwNEJcdTY5MUNcdThBMEVcblxuICAgICAgICAvLyBOb2RlLmpzIHYyMiBcdTMwNjggd3MgdjguMTguMCBcdTRFRTVcdTk2NERcdTMwNkYgQmxvYiBcdTMwODJcdTY3NjVcdTMwOEJcdTMwMDJcbiAgICAgICAgY29uc3QgZGF0YSA9IGV2dC5kYXRhIGluc3RhbmNlb2YgQmxvYlxuICAgICAgICAgID8gYXdhaXQgKGV2dC5kYXRhIGFzIEJsb2IpLmFycmF5QnVmZmVyKClcbiAgICAgICAgICA6IGV2dC5kYXRhO1xuICAgICAgICBjb25zdCBycGNSZXNwID0gdGhpcy5mbXQuZGVjb2RlU3luYyhkYXRhKTtcblxuICAgICAgICBpZiAoIWlzUnBjUmVzcG9uc2UocnBjUmVzcCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgU2VydmVyUmVzcG9uc2VFcnJvcihcIk1pc3NpbmcgcnBjIHJlc3BvbnNlLlwiLCB7XG4gICAgICAgICAgICAvLyBjYXVzZTogKGV2dC5kYXRhIGFzIEJ1ZmZlcikubWFwKHYgPT4gdikuam9pbigpLFxuICAgICAgICAgICAgY2F1c2U6IHtcbiAgICAgICAgICAgICAgZW5kcG9pbnQ6IGVuZHBvaW50LmhyZWYsXG4gICAgICAgICAgICAgIHJlc3BvbnNlOiBycGNSZXNwLFxuICAgICAgICAgICAgICAvLyBUT0RPKHRhaS1rdW4pOiBcdTYwQzVcdTU4MzFcdTMwOTJcdThGRkRcdTUyQTBcbiAgICAgICAgICAgICAgLy8gLi4uY2F1c2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFwiaWRcIiBpbiBycGNSZXNwKSB7XG4gICAgICAgICAgdGhpcy5lZS5lbWl0KGBycGNfJHtycGNSZXNwLmlkfWAsIHJwY1Jlc3ApO1xuICAgICAgICB9IGVsc2UgaWYgKFwicmVzdWx0XCIgaW4gcnBjUmVzcCkge1xuICAgICAgICAgIGlmICghaXNMaXZlUmVzdWx0KHJwY1Jlc3AucmVzdWx0KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFNlcnZlclJlc3BvbnNlRXJyb3IoXCJNaXNzaW5nIGxpdmUgcmVzdWx0XCIsIHtcbiAgICAgICAgICAgICAgY2F1c2U6IHtcbiAgICAgICAgICAgICAgICBlbmRwb2ludDogZW5kcG9pbnQuaHJlZixcbiAgICAgICAgICAgICAgICBsaXZlUmVzdWx0OiBycGNSZXNwLnJlc3VsdCxcbiAgICAgICAgICAgICAgICAvLyBUT0RPKHRhaS1rdW4pOiBcdTYwQzVcdTU4MzFcdTMwOTJcdThGRkRcdTUyQTBcbiAgICAgICAgICAgICAgICAvLyAuLi5jYXVzZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IHsgaWQsIC4uLnBheWxvYWQgfSA9IHJwY1Jlc3AucmVzdWx0O1xuXG4gICAgICAgICAgdGhpcy5lZS5lbWl0KGBsaXZlXyR7U3RyaW5nKGlkKX1gLCBwYXlsb2FkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUnBjUmVzcG9uc2VFcnJvcihycGNSZXNwLCB7XG4gICAgICAgICAgICBjYXVzZToge1xuICAgICAgICAgICAgICBlbmRwb2ludDogZW5kcG9pbnQuaHJlZixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdGhpcy5lZS5lbWl0KFxuICAgICAgICAgIFwiZXJyb3JcIixcbiAgICAgICAgICBuZXcgV2ViU29ja2V0RW5naW5lRXJyb3IoXG4gICAgICAgICAgICAvLyBtZXNzYWdlIFx1MzBBNFx1MzBEOVx1MzBGM1x1MzBDOFx1MzBDRlx1MzBGM1x1MzBDOVx1MzBFOVx1MzBGQ1x1NTE4NVx1MzA2N1x1NzY3QVx1NzUxRlx1MzA1N1x1MzA1Rlx1MzBBOFx1MzBFOVx1MzBGQ1x1MzA5Mlx1MzAwMVxuICAgICAgICAgICAgLy8gXHUzMEFCXHUzMEI5XHUzMEJGXHUzMEUwXHUzMEE4XHUzMEU5XHUzMEZDXHUzMEIzXHUzMEZDXHUzMEM5IDMxNTIgXHUzMDY4XHUzMDU3XHUzMDY2XHU1ODMxXHU1NDRBXHUzMDU3XHUzMDdFXHUzMDU5XHUzMDAyXG4gICAgICAgICAgICAzMTUyLFxuICAgICAgICAgICAgXCJBbiBlcnJvciBvY2N1cnJlZCB3aXRoaW4gdGhlIGhhbmRsZXIgZm9yIHRoZSBcXFwibWVzc2FnZVxcXCIgZXZlbnQuXCIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNhdXNlOiBlLFxuICAgICAgICAgICAgICBmYXRhbDogZmFsc2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBvcGVuUHJvbWlzZSA9IHRoaXMuZWUub25jZShcIm9wZW5cIiwgeyBzaWduYWwgfSk7XG4gICAgY29uc3QgZXJyb3JQcm9taXNlID0gdGhpcy5lZS5vbmNlKFwiZXJyb3JcIiwgeyBzaWduYWwgfSk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgW3Jlc3VsdF0gPSBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICBvcGVuUHJvbWlzZSxcbiAgICAgICAgZXJyb3JQcm9taXNlLFxuICAgICAgXSk7XG5cbiAgICAgIGlmIChyZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICB0aHJvdyByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChcImVycm9yXCIgaW4gcmVzdWx0KSB7XG4gICAgICAgIHRocm93IHJlc3VsdC5lcnJvcjtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICBvcGVuUHJvbWlzZS5jYW5jZWwoKSxcbiAgICAgICAgZXJyb3JQcm9taXNlLmNhbmNlbCgpLFxuICAgICAgXSk7XG4gICAgfVxuXG4gICAgY29uc3QgY3JlYXRlUHJvbWlzZSA9ICgpID0+IHtcbiAgICAgIGxldCBpOiBhbnksXG4gICAgICAgIGludDogbnVtYmVyLFxuICAgICAgICByZXM6ICh2OiBib29sZWFuKSA9PiB2b2lkLFxuICAgICAgICBwcm8gPSBuZXcgU3RhdGVmdWxQcm9taXNlPGJvb2xlYW4+KHIgPT4ge1xuICAgICAgICAgIGkgPSBzZXRUaW1lb3V0KHJlcyA9IHIsIGludCA9IHRoaXMucGluZ0ludGVydmFsKCksIGZhbHNlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHBybywge1xuICAgICAgICBpbnRlcnZhbDogaW50ISwgLy8gXHU3M0ZFXHU1NzI4XHU2NzJBXHU0RjdGXHU3NTI4XG4gICAgICAgIGNhbmNlbCgpIHtcbiAgICAgICAgICBpZiAocHJvLnN0YXRlID09PSBcInBlbmRpbmdcIikge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KGkpO1xuICAgICAgICAgICAgcmVzKHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH07XG4gICAgbGV0IHByb21pc2UgPSBjcmVhdGVQcm9taXNlKCk7XG4gICAgY29uc3QgcGluZ2VyID0gKGFzeW5jICgpID0+IHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGNvbnN0IGNhbmNlbGVkID0gYXdhaXQgcHJvbWlzZTtcblxuICAgICAgICBpZiAoY2FuY2VsZWQpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgaWYgKC8qIF9fVEFJX0tVTl9fU1VSUkVBTERCX19ESUFHTk9TVElDU19DSEFOTkVMX18gKi8gZmFsc2UpIHtcbiAgICAgICAgICAgIGNoYW5uZWwucHVibGlzaChcIndlYnNvY2tldDpwaW5nXCIsIHsgdHlwZTogXCJwaW5nXCIgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgdGltZW91dCA9IDVfMDAwO1xuICAgICAgICAgIGNvbnN0IHJwY1Jlc3AgPSBhd2FpdCB0aGlzLnJwYyh7XG4gICAgICAgICAgICBzaWduYWw6IGdldFRpbWVvdXRTaWduYWwodGltZW91dCksXG4gICAgICAgICAgICByZXF1ZXN0OiB7XG4gICAgICAgICAgICAgIG1ldGhvZDogXCJwaW5nXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgaWYgKHJwY1Jlc3AuZXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBScGNSZXNwb25zZUVycm9yKHJwY1Jlc3AsIHtcbiAgICAgICAgICAgICAgY2F1c2U6IHtcbiAgICAgICAgICAgICAgICBlbmRwb2ludDogZW5kcG9pbnQuaHJlZixcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICgvKiBfX1RBSV9LVU5fX1NVUlJFQUxEQl9fRElBR05PU1RJQ1NfQ0hBTk5FTF9fICovIGZhbHNlKSB7XG4gICAgICAgICAgICBjaGFubmVsLnB1Ymxpc2goXCJ3ZWJzb2NrZXQ6cG9uZ1wiLCB7IHR5cGU6IFwicG9uZ1wiIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHRoaXMuZWUuZW1pdChcbiAgICAgICAgICAgIFwiZXJyb3JcIixcbiAgICAgICAgICAgIG5ldyBXZWJTb2NrZXRFbmdpbmVFcnJvcihcbiAgICAgICAgICAgICAgLy8gcGluZyBcdTMwRTFcdTMwQzNcdTMwQkJcdTMwRkNcdTMwQjhcdTMwNkVcdTkwMDFcdTRGRTFcdTMwNkJcdTU5MzFcdTY1NTdcdTMwNTdcdTMwNUZcdTMwQThcdTMwRTlcdTMwRkNcdTMwOTJcdTMwMDFcbiAgICAgICAgICAgICAgLy8gXHUzMEFCXHUzMEI5XHUzMEJGXHUzMEUwXHUzMEE4XHUzMEU5XHUzMEZDXHUzMEIzXHUzMEZDXHUzMEM5IDMxNTMgXHUzMDY4XHUzMDU3XHUzMDY2XHU1ODMxXHU1NDRBXHUzMDU3XHUzMDdFXHUzMDU5XHUzMDAyXG4gICAgICAgICAgICAgIDMxNTMsXG4gICAgICAgICAgICAgIFwiRmFpbGVkIHRvIHNlbmQgYSBwaW5nIG1lc3NhZ2UuXCIsXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBjYXVzZTogZSxcbiAgICAgICAgICAgICAgICBmYXRhbDogZmFsc2UsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApLFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgcHJvbWlzZSA9IGNyZWF0ZVByb21pc2UoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICB0aGlzLmVlLm9uKFxuICAgICAgXCJjbG9zaW5nXCIsXG4gICAgICBhc3luYyBmdW5jdGlvbiBzdG9wKHRoaXM6IFRhc2tFbWl0dGVyPEVuZ2luZUV2ZW50TWFwPikge1xuICAgICAgICB0aGlzLm9mZihcImNsb3NpbmdcIiwgc3RvcCk7XG4gICAgICAgIHByb21pc2UuY2FuY2VsKCk7XG4gICAgICAgIGF3YWl0IHBpbmdlcjtcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGNsb3NlKHsgc2lnbmFsIH06IENsb3NlQXJncyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRocm93SWZBYm9ydGVkKHNpZ25hbCk7XG4gICAgY29uc3QgY29ubiA9IHRoaXMuZ2V0Q29ubmVjdGlvbkluZm8oKTtcblxuICAgIGlmIChjb25uLnN0YXRlID09PSBcImNsb3NlZFwiKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNvbm4uc3RhdGUgIT09IFwib3BlblwiKSB7XG4gICAgICB1bnJlYWNoYWJsZShjb25uIGFzIG5ldmVyKTtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnRyYW5zaXRpb24oXG4gICAgICB7XG4gICAgICAgIHN0YXRlOiBcImNsb3NpbmdcIixcbiAgICAgICAgZW5kcG9pbnQ6IGNvbm4uZW5kcG9pbnQsXG4gICAgICB9LFxuICAgICAgKCkgPT4gKHtcbiAgICAgICAgc3RhdGU6IFwiY2xvc2luZ1wiLFxuICAgICAgICBlbmRwb2ludDogY29ubi5lbmRwb2ludCxcbiAgICAgIH0pLFxuICAgICk7XG4gICAgY29uc3QgcHJvbWlzZUNsb3NlZCA9IHRoaXMuZWUub25jZShcImNsb3NlZFwiLCB7IHNpZ25hbCB9KTtcblxuICAgIGlmIChcbiAgICAgIHRoaXMud3NcbiAgICAgICYmIHRoaXMud3MucmVhZHlTdGF0ZSAhPT0gMyAvLyBXZWJTb2NrZXQuQ0xPU0VEXG4gICAgICAmJiB0aGlzLndzLnJlYWR5U3RhdGUgIT09IDIgLy8gV2ViU29ja2V0LkNMT1NJTkdcbiAgICApIHtcbiAgICAgIHRoaXMud3MuY2xvc2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5lZS5lbWl0KFwiY2xvc2VkXCIsIHtcbiAgICAgICAgc3RhdGU6IFwiY2xvc2VkXCIsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBbcmVzdWx0XSA9IGF3YWl0IHByb21pc2VDbG9zZWQ7XG5cbiAgICBpZiAoXCJlcnJvclwiIGluIHJlc3VsdCkge1xuICAgICAgdGhyb3cgcmVzdWx0LmVycm9yO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJwYyh7IHJlcXVlc3QsIHNpZ25hbCB9OiBScGNBcmdzKTogUHJvbWlzZTxCaWRpcmVjdGlvbmFsUnBjUmVzcG9uc2U+IHtcbiAgICAvLyBcdTYzQTVcdTdEOUFcdTYwQzVcdTU4MzFcdTMwNkVcdTMwQjlcdTMwQ0FcdTMwQzNcdTMwRDdcdTMwQjdcdTMwRTdcdTMwQzNcdTMwQzhcdTMwOTJcdTUzRDZcdTVGOTdcdTMwNTdcdTMwN0VcdTMwNTlcdTMwMDJcbiAgICAvLyBcdTRFRTVcdTk2NERcdTMwMDFcdTYzQTVcdTdEOUFcdTYwQzVcdTU4MzFcdTMwOTJcdTUzQzJcdTcxNjdcdTMwNTlcdTMwOEJcdTk2OUJcdTMwNkZcdTMwNTNcdTMwOENcdTMwOTJcdTRGN0ZcdTc1MjhcdTMwNTdcdTMwN0VcdTMwNTlcdTMwMDJcbiAgICBjb25zdCBjb25uID0gdGhpcy5nZXRDb25uZWN0aW9uSW5mbygpO1xuXG4gICAgaWYgKCF0aGlzLndzIHx8IGNvbm4uc3RhdGUgIT09IFwib3BlblwiKSB7XG4gICAgICB0aHJvdyBuZXcgQ29ubmVjdGlvblVuYXZhaWxhYmxlRXJyb3Ioe1xuICAgICAgICBjYXVzZTogXCJUaGUgY29ubmVjdGlvbiBpcyBub3QgZXN0YWJsaXNoZWQgdmlhIHRoZSAuY29ubmVjdCgpIG1ldGhvZC5cIixcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHN3aXRjaCAocmVxdWVzdC5tZXRob2QpIHtcbiAgICAgIGNhc2UgXCJ1c2VcIjoge1xuICAgICAgICBsZXQgeyBuYW1lc3BhY2UsIGRhdGFiYXNlIH0gPSBjb25uO1xuICAgICAgICBjb25zdCBbbnMsIGRiXSA9IHJlcXVlc3QucGFyYW1zO1xuXG4gICAgICAgIGlmIChucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgbmFtZXNwYWNlID0gbnM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZGIgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGRhdGFiYXNlID0gZGI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmFtZXNwYWNlID09PSBudWxsICYmIGRhdGFiYXNlICE9PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IE1pc3NpbmdOYW1lc3BhY2VFcnJvcihkYXRhYmFzZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAtIEpTT04gXHUzMDY3XHUzMDZGIG51bGwgXHUzMDY4IHVuZGVmaW5lZCBcdTMwOTJcdTUzM0FcdTUyMjVcdTMwNTdcdTMwNkFcdTMwNDRcdTMwNTFcdTMwNjlcdTMwMDFTdXJlYWxEQiBcdTMwNkZcdTUzM0FcdTUyMjVcdTMwNTlcdTMwOEJcdTMwMDJcbiAgICAgICAgLy8gLSBudWxsIFx1MzA2Rlx1OTA3OFx1NjI5RVx1NEUyRFx1MzA2RVx1NTQwRFx1NTI0RFx1N0E3QVx1OTU5M1x1MzA3RVx1MzA1Rlx1MzA2Rlx1MzBDN1x1MzBGQ1x1MzBCRlx1MzBEOVx1MzBGQ1x1MzBCOVx1MzA5Mlx1NjcyQVx1OTA3OFx1NjI5RVx1MzA2Qlx1MzA1OVx1MzA4Qlx1MzA2RVx1MzA2N1x1MzAwMXVuZGVmaW5lZCBcdTMwOTJcdTRGN0ZcdTMwNDhcdTMwOEJcbiAgICAgICAgLy8gICBDQk9SIFx1MzBENVx1MzBBOVx1MzBGQ1x1MzBERVx1MzBDM1x1MzBCRlx1MzBGQ1x1MzA2OFx1NTQwQ1x1MzA1OFx1MzA4OFx1MzA0Nlx1MzA2QVx1NEY3Rlx1MzA0NFx1NjVCOVx1MzA5MiBKU09OIFx1MzBENVx1MzBBOVx1MzBGQ1x1MzBERVx1MzBDM1x1MzBCRlx1MzBGQ1x1MzA2N1x1MzA1OVx1MzA4Qlx1MzA2OFx1NEU4Qlx1NjU0NVx1MzA4Qlx1NTNFRlx1ODBGRFx1NjAyN1x1MzA0Q1x1OUFEOFx1MzA0NFx1MzAwMlxuICAgICAgICAvLyBcdTMwNjhcdTMwNDRcdTMwNDZcdTUyRDVcdTZBNUZcdTMwNENcdTMwNDJcdTMwNjNcdTMwNjZcdTMwMDF1bmRlZmluZWQgXHUzMDkyXHU2NTg3XHU1QjU3XHU1MjE3XHUzMDZCXHU3RjZFXHUzMDREXHU2M0RCXHUzMDQ4XHUzMDhCXHUzMDg4XHUzMDQ2XHUzMDZCXHU1MkFBXHU1MjlCXHUzMDU5XHUzMDhCXHUzMDAyXG4gICAgICAgIHtcbiAgICAgICAgICBpZiAobnMgPT09IHVuZGVmaW5lZCAmJiBjb25uLm5hbWVzcGFjZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmVxdWVzdCA9IHtcbiAgICAgICAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBbY29ubi5uYW1lc3BhY2UsIHJlcXVlc3QucGFyYW1zWzFdXSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGRiID09PSB1bmRlZmluZWQgJiYgY29ubi5kYXRhYmFzZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgcmVxdWVzdCA9IHtcbiAgICAgICAgICAgICAgbWV0aG9kOiByZXF1ZXN0Lm1ldGhvZCxcbiAgICAgICAgICAgICAgcGFyYW1zOiBbcmVxdWVzdC5wYXJhbXNbMF0sIGNvbm4uZGF0YWJhc2VdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgY2FzZSBcInF1ZXJ5XCI6IHtcbiAgICAgICAgcmVxdWVzdCA9IHByb2Nlc3NRdWVyeVJlcXVlc3QocmVxdWVzdCkgYXMgUnBjUXVlcnlSZXF1ZXN0O1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBpZDogQmlkaXJlY3Rpb25hbFJwY1Jlc3BvbnNlW1wiaWRcIl0gPVxuICAgICAgYCR7cmVxdWVzdC5tZXRob2R9XyR7dGhpcy5pZC5uZXh0KCl9YDtcbiAgICBjb25zdCBib2R5OiB1bmtub3duID0gdGhpcy5mbXQuZW5jb2RlU3luYyh7XG4gICAgICBpZCxcbiAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICBwYXJhbXM6IHJlcXVlc3QucGFyYW1zIHx8IFtdLFxuICAgIH0pO1xuXG4gICAgaWYgKHR5cGVvZiBib2R5ICE9PSBcInN0cmluZ1wiICYmICEoYm9keSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKSB7XG4gICAgICB0aHJvdyBuZXcgU3VycmVhbFR5cGVFcnJvcihbXCJTdHJpbmdcIiwgXCJVaW50OEFycmF5XCJdLCBib2R5KTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNwID0gdGhpcy5lZS5vbmNlKGBycGNfJHtpZH1gLCB7IHNpZ25hbCB9KTtcbiAgICB0aGlzLndzLnNlbmQoYm9keSk7XG4gICAgY29uc3QgW3Jhd1Jlc3BdID0gYXdhaXQgcmVzcDtcbiAgICAvLyBgcmF3UmVzcGAgXHUzMDZGIG1lc3NhZ2UgXHUzMEE0XHUzMEQ5XHUzMEYzXHUzMEM4XHUzMENGXHUzMEYzXHUzMEM5XHUzMEU5XHUzMEZDXHU1MTg1XHUzMDY3XHU2OTFDXHU4QTNDXHU2RTA4XHUzMDdGXHUzMDZBXHUzMDZFXHUzMDY3XHUzMDAxXHUzMDUzXHUzMDUzXHUzMDY3XHUzMDZGXHUzMEFEXHUzMEUzXHUzMEI5XHUzMEM4XHUzMDU5XHUzMDhCXHUzMDYwXHUzMDUxXHUzMDAyXG4gICAgY29uc3QgcnBjUmVzcCA9IHJhd1Jlc3AgYXMgQmlkaXJlY3Rpb25hbFJwY1Jlc3BvbnNlO1xuXG4gICAgaWYgKFwicmVzdWx0XCIgaW4gcnBjUmVzcCkge1xuICAgICAgY29uc3QgcnBjID0ge1xuICAgICAgICBtZXRob2Q6IHJlcXVlc3QubWV0aG9kLFxuICAgICAgICBwYXJhbXM6IHJlcXVlc3QucGFyYW1zLFxuICAgICAgICByZXN1bHQ6IHJwY1Jlc3AucmVzdWx0LFxuICAgICAgfSBhcyB7XG4gICAgICAgIFtNIGluICh0eXBlb2YgcmVxdWVzdClbXCJtZXRob2RcIl1dOiB7XG4gICAgICAgICAgbWV0aG9kOiBNO1xuICAgICAgICAgIHBhcmFtczogUnBjUGFyYW1zPE0+O1xuICAgICAgICAgIHJlc3VsdDogUnBjUmVzdWx0PE0+O1xuICAgICAgICB9O1xuICAgICAgfVsodHlwZW9mIHJlcXVlc3QpW1wibWV0aG9kXCJdXTtcblxuICAgICAgc3dpdGNoIChycGMubWV0aG9kKSB7XG4gICAgICAgIGNhc2UgXCJ1c2VcIjoge1xuICAgICAgICAgIGNvbnN0IFtucywgZGJdID0gcnBjLnBhcmFtcztcblxuICAgICAgICAgIGlmIChucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IG5zO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChkYiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFiYXNlID0gZGI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICBjYXNlIFwic2lnbmluXCI6XG4gICAgICAgIGNhc2UgXCJzaWdudXBcIjpcbiAgICAgICAgICB0aGlzLnRva2VuID0gcnBjLnJlc3VsdDtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIFwiYXV0aGVudGljYXRlXCI6XG4gICAgICAgICAgW3RoaXMudG9rZW5dID0gcnBjLnBhcmFtcztcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIFwiaW52YWxpZGF0ZVwiOlxuICAgICAgICAgIHRoaXMudG9rZW4gPSBudWxsO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBycGNSZXNwO1xuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7O0FBQUE7QUFBQSxFQUdFO0FBQUEsRUFHQTtBQUFBLE9BRUs7QUFDUDtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxPQUNLO0FBT1A7QUFBQSxFQUVFO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBRUE7QUFBQSxPQUNLO0FBeUJQLElBQXFCLG1CQUFyQixNQUFxQix5QkFBd0IsVUFBVTtBQUFBLEVBUXJELFlBQVksUUFBK0I7QUFDekMsVUFBTSxNQUFNO0FBUmQsU0FBUyxPQUFPO0FBRWhCLFNBQVUsS0FBdUI7QUFDakMsU0FBbUIsS0FBSyxJQUFJLE9BQU87QUFNakMsVUFBTTtBQUFBLE1BQ0o7QUFBQSxNQUNBO0FBQUEsSUFDRixJQUFJO0FBQ0osU0FBSyxRQUFRO0FBQ2IsU0FBSyxlQUFlLE9BQU8saUJBQWlCLGFBQ3hDLGVBQ0MseUJBQU0sTUFBTSxJQUFJLEtBQUssSUFBSSxLQUFPLGdCQUFnQixHQUFNLENBQUM7QUFBQSxFQUM5RDtBQUFBLEVBRUEsTUFBTSxRQUFRLEVBQUUsVUFBVSxPQUFPLEdBQStCO0FBQzlELG1CQUFlLE1BQU07QUFDckIsVUFBTSxPQUFPLEtBQUssa0JBQWtCO0FBRXBDLFFBQUks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