@bxjs/base
Version:
bxjs base framework & api
348 lines • 42.9 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
require('source-map-support').install();
require('tsconfig-paths').register();
process.env.TZ = 'Asia/Shanghai';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
var path = require('path');
var ErrorStackParser = require('error-stack-parser');
var cookie = require('cookie');
var MobileDetect = require('mobile-detect');
var fetch = require('node-fetch');
var _ = require('lodash');
var moment = require('moment');
var extend = require('extend');
var querystring = require('querystring');
// const parameter = require('parameter')
// const parameterCheckInstance = new parameter({
// // translate: function () {
// // var args = Array.prototype.slice.call(arguments);
// // // Assume there have I18n.t method for convert language.
// // return I18n.t.apply(I18n, args);
// // }
// })
var circular_json = require("circular-json");
var mockjs = require('mockjs');
var shortid = require('shortid');
var validatorjs = require('validatorjs');
var cross_spawn = require('cross-spawn');
var ACMClient = require('amber_utf-8');
var co = require('co');
require('./error');
// FIXME HACK原生方法JSON转换不可逆的BUG(JAVA端传来的富文本字段内容含有\n\t字符串中的字符生成JSON字符串无法正常解析报错)
var raw_stringify = JSON.stringify;
function new_stringify(value, replacer, space) {
var out = raw_stringify(value, replacer, space);
if (_.isString(out)) {
out = out.replace(/\\n/g, '\\\\n')
.replace(/\\t/g, '\\\\t')
.replace(/\\u/g, '\\\\u'); //JAVA端返回的unicode字符转义处理
}
return out;
}
JSON.stringify = new_stringify;
// ts-node本地调试需要加载对应的源代码后缀名称
function get_suffix_ts_or_js() {
if (global['__env__'] == 'local' && !/^\/code\/node_modules/.test(__dirname)) {
return 'ts';
}
else {
return 'js';
}
}
exports.get_suffix_ts_or_js = get_suffix_ts_or_js;
// 准确定位错误码位置,间接得到函数调用位置地址信息,结合符号报表的正确解析处理完美得到错误定位信息,准确代码调试。
function __get_base_func_caller_source_position(position) {
if (position === void 0) { position = 3; }
try {
throw new Error();
}
catch (err) {
var out = ErrorStackParser.parse(err);
var idx = 0;
// 找到第二个TS文件的执行位置
var find_ts_sufix_file_count = 0;
for (; idx < out.length; idx++) {
if (/\.ts$/.test(out[idx].fileName)) {
find_ts_sufix_file_count += 1;
}
if (find_ts_sufix_file_count == position) {
break;
}
}
if (find_ts_sufix_file_count == position) {
return '[' + out[idx]['fileName'] + ':' + out[idx]['lineNumber'] + ']';
}
else {
// TODO 需要定位为什么调用栈无法找到对应的位置出现越界??
// console.error(err)
console.error(circular_json.stringify(out, null, 4)
.replace(/\r/g, '').replace(/\n/g, ''));
return '#';
}
}
}
// 获取异常调用栈用于辅助错误提示定位
function xstack(err, compact) {
if (compact === void 0) { compact = true; }
try {
// TODO 优化裁剪一些无用信息减少日志尺寸更加便于人工分析处理
var stack = ErrorStackParser.parse(err);
if (compact) {
var sources = [];
for (var _i = 0, stack_1 = stack; _i < stack_1.length; _i++) {
var v = stack_1[_i];
sources.push(v['fileName'] + ":" + v['lineNumber']);
}
return sources;
}
return stack;
}
catch (err1) {
var source = __get_base_func_caller_source_position();
return "invalid error input param (" + source + ")";
}
}
exports.xstack = xstack;
// // 错误栈的递归嵌套格式显示数据结构定义(param嵌套找到最后一个msg的JSON解析语法错误就是错误链的原始错误发生位置)
// let x = {
// "code": "UNKNOWN",
// "msg": "未知错误",
// "param": {
// "msg": "您输入的用户名或密码错误,请重新登录 (ErrorCode: 1005, url: https://login.alibaba-inc.com/authorize/login.do)"
// },
// "stack": "[\"/Users/chujinghui/Desktop/work/xjs/bxjs/framework/base.ts:110\",\"/Users/chujinghui/Desktop/work/xjs/bxjs/app/entries/web/mobile/meeting-room-visit.ts:161\",\"/Users/chujinghui/Desktop/work/xjs/bxjs/app/entries/web/mobile/meeting-room-visit.js:40\",\"/Users/chujinghui/Desktop/work/xjs/bxjs/app/entries/web/mobile/meeting-room-visit.js:21\",\"/Users/chujinghui/Desktop/work/xjs/bxjs/app/entries/web/mobile/meeting-room-visit.js:13\",\"internal/process/next_tick.js:188\"]",
// }
// 对于异常内容的格式化参数解析处理成为四元组code/msg/param/stack
function xerror(err, __param) {
xassert(err instanceof Error);
try {
// 标准错误的统一转换处理
var data_1 = JSON.parse(err.message);
if (data_1.code && data_1.msg && ERRORS[data_1.code]) {
return data_1;
}
}
catch (err) {
// ignore parse error
}
// 非标准错误的统一格式转换处理
var msg = ERRORS[ERR$UNKNOWN]['zh']; // TODO 错误码多语言回传到客户端问题
var code = ERR$UNKNOWN;
var param = { msg: err.message, param: __param }; // 用户自定义的错误参数信息 msg为非错误码JSON四元组就是嵌套的终止条件。
var stack = xstack(err);
var data = { msg: msg, code: code, param: param, stack: stack };
return data;
}
exports.xerror = xerror;
// 用于获取错误栈的root cause根本原因(第一个被拦截的错误发生位置)
function xroot(err) {
xassert(err instanceof Error);
var _a = xerror(err), msg = _a.msg, param = _a.param, code = _a.code, stack = _a.stack;
// 递归遍历找到错误链的root cause
for (; param && param.msg;) {
try {
var json = JSON.parse(param.msg);
param = json.param;
}
catch (err) {
msg = param.msg;
code = param.code;
stack = param.stack;
param = param.param;
break;
}
}
return { msg: msg, code: code, param: param, stack: stack };
}
exports.xroot = xroot;
// TODO 报错处理(显示问题反馈联系人信息)
// 将未处理的错误上抛的异常链记录下来用于精准追踪代码的执行过程(以及准确获取到根节点的错误码)
// 对于promise异步回调的统一出错处理写法实例
// export function login(username: string, password: string) {
// return new Promise((resolve, reject) => {
// co(function* () {
// let user = yield buc.oauthclient.login(username, password)
// resolve(user)
// }).catch(async function (err) {
// xthrow(err, reject)
// })
// })
// }
function xthrow(code, param, reject_param) {
if (code === void 0) { code = ERR$UNKNOWN; }
if (param === void 0) { param = undefined; }
if (reject_param === void 0) { reject_param = undefined; }
// promise中进行reject异常处理的抛出错误方法的形参逻辑预处理转换。
var reject = _.isFunction(param) ? param : undefined;
if (reject)
param = reject_param;
var data = {};
var source = __get_base_func_caller_source_position();
if (code instanceof Error) {
try {
data = JSON.parse(code.message);
// 将透传上抛的错误的路径信息和附加参数也记录下来方便提供完整应用堆栈信息辅助调试业务逻辑
if (!_.isArray(data.stack)) {
data.stack = [];
}
data.stack.push(source);
}
catch (err) {
// ignore
}
// 标准错误直接上抛处理
if (data.code && data.msg && ERRORS[data.code]) {
// 测试严重BUG reject函数类型表达式为假必须要用lodash判定是否为函数
if (_.isFunction(reject)) {
// promise回调中进行抛错误处理
var err = new Error(JSON.stringify(data));
reject(err);
return;
}
else {
throw new Error(JSON.stringify(data));
}
}
// 将非标准错误转换为标准错误后再上抛处理
data = xerror(code, param);
data.code = ERR$UNKNOWN;
data.msg = ERRORS[ERR$UNKNOWN]['zh']; // FIXME TODO 错误码的多语言处理转换!!
data.param = { msg: code.message, param: param, stack: [source] };
}
else {
// 对于常量定义错误的统一格式化处理
data = { code: code, msg: global['ERRORS'][code]['zh'], param: param, stack: [source] };
}
// 对于是否promise场景下的错误上抛进行正确的转换处理
if (_.isFunction(reject)) {
// promise回调中进行抛错误处理
reject(new Error(JSON.stringify(data)));
}
else {
// 非promise回调中异常传递
throw new Error(JSON.stringify(data));
}
}
exports.xthrow = xthrow;
function xassert(expr, code, param) {
if (code === void 0) { code = ERR$ASSERT; }
var source = __get_base_func_caller_source_position();
var stack = [source];
if (!expr)
throw new Error(JSON.stringify({ code: code, msg: global['ERRORS'][code]['zh'], param: param, stack: stack }));
return expr;
}
exports.xassert = xassert;
// uuid冲突可能性存在1S平均到1000毫秒1000次并发,每1ms并发冲突可能性(8个字节随机数+10000随机数)
function xuuid() {
return __awaiter(this, void 0, void 0, function () {
var options, uuid;
return __generator(this, function (_a) {
options = {};
uuid = require('uuid/v1')(options = {
// msecs: new Date().getTime(),
nsecs: Math.floor(Math.random() * 10000) // 优化算法中的随机数使用缺陷(1毫秒中N个并发8字节密码随机数和1万随机整数,1秒1000并发)
// node: buf,//mac地址(一台机器上多个VM也可能冲突问题,机器标识随机6个字节更友好些)
// msecs: new Date().getTime(),//unix元年距离的毫秒时间
// msecs: time[0] * 1000 + Math.floor(time[1] / 1000000),//毫秒时间
// nsecs: Math.floor((time[1] % 1000000) / 100),//将纳秒时间951ms851969ns转换为100纳秒为单位
// clockseq: (bytes[0] << 8 | bytes[1]) & 0x3fff,//时间序列使用随机数替代1024个随机数
});
console.log(options);
return [2 /*return*/, uuid];
});
});
}
// 获取mac地址
function __xgetmac__() {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if (global['g_bxjs_sMacAddress']) {
return [2 /*return*/, new Promise(function (resolve, reject) {
try {
xassert(require('getmac').isMac(global['g_bxjs_sMacAddress']));
resolve(global['g_bxjs_sMacAddress']);
}
catch (err) {
xthrow(err, reject);
}
})];
}
return [2 /*return*/, new Promise(function (resolve, reject) {
require('getmac').getMac(function (err, macAddress) {
if (err)
xthrow(err, reject);
resolve(macAddress);
});
})];
});
});
}
function test() {
return __awaiter(this, void 0, void 0, function () {
var _a, _b, _c, _d;
return __generator(this, function (_e) {
switch (_e.label) {
case 0:
// var machine = require('machine-uuid')
// console.log(machine('mynamespace'));
// 2c433a07-140a-5bb9-949a-4997b566c397
// console.log(machine('mynamespace'));
_b = (_a = console).log;
return [4 /*yield*/, __xgetmac__()];
case 1:
// var machine = require('machine-uuid')
// console.log(machine('mynamespace'));
// 2c433a07-140a-5bb9-949a-4997b566c397
// console.log(machine('mynamespace'));
_b.apply(_a, [_e.sent()]);
_d = (_c = console).log;
return [4 /*yield*/, xuuid()];
case 2:
_d.apply(_c, [_e.sent()]);
return [2 /*return*/];
}
});
});
}
test().then(function (data) {
}).catch(function (err) {
console.log(err);
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVidWcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJkZWJ1Zy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUMsT0FBTyxFQUFFLENBQUE7QUFDdkMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsUUFBUSxFQUFFLENBQUE7QUFDcEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEdBQUcsZUFBZSxDQUFBO0FBQ2hDLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLEdBQUcsR0FBRyxDQUFBO0FBQzlDLElBQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQTtBQUM1QixJQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFBO0FBQ3RELElBQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUNoQyxJQUFNLFlBQVksR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUE7QUFDN0MsSUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFBO0FBQ25DLElBQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUMzQixJQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7QUFDaEMsSUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQ2hDLElBQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQTtBQUMxQyx5Q0FBeUM7QUFDekMsaURBQWlEO0FBQ2pELGtDQUFrQztBQUNsQywrREFBK0Q7QUFDL0Qsc0VBQXNFO0FBQ3RFLDhDQUE4QztBQUM5QyxXQUFXO0FBQ1gsS0FBSztBQUNMLElBQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQTtBQUM5QyxJQUFNLE1BQU0sR0FB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b0JBQUMscUJBQU0sS0FBSyxFQUFFLEVBQUE7O29CQUF6QixjQUFZLFNBQWEsRUFBQyxDQUFBOzs7OztDQUM3QjtBQUVELElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFBLElBQUk7QUFFaEIsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFVBQUEsR0FBRztJQUNSLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7QUFDcEIsQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJyZXF1aXJlKCdzb3VyY2UtbWFwLXN1cHBvcnQnKS5pbnN0YWxsKClcbnJlcXVpcmUoJ3RzY29uZmlnLXBhdGhzJykucmVnaXN0ZXIoKVxucHJvY2Vzcy5lbnYuVFogPSAnQXNpYS9TaGFuZ2hhaSdcbnByb2Nlc3MuZW52Lk5PREVfVExTX1JFSkVDVF9VTkFVVEhPUklaRUQgPSAnMCdcbmNvbnN0IHBhdGggPSByZXF1aXJlKCdwYXRoJylcbmNvbnN0IEVycm9yU3RhY2tQYXJzZXIgPSByZXF1aXJlKCdlcnJvci1zdGFjay1wYXJzZXInKVxuY29uc3QgY29va2llID0gcmVxdWlyZSgnY29va2llJylcbmNvbnN0IE1vYmlsZURldGVjdCA9IHJlcXVpcmUoJ21vYmlsZS1kZXRlY3QnKVxuY29uc3QgZmV0Y2ggPSByZXF1aXJlKCdub2RlLWZldGNoJylcbmNvbnN0IF8gPSByZXF1aXJlKCdsb2Rhc2gnKVxuY29uc3QgbW9tZW50ID0gcmVxdWlyZSgnbW9tZW50JylcbmNvbnN0IGV4dGVuZCA9IHJlcXVpcmUoJ2V4dGVuZCcpXG5jb25zdCBxdWVyeXN0cmluZyA9IHJlcXVpcmUoJ3F1ZXJ5c3RyaW5nJylcbi8vIGNvbnN0IHBhcmFtZXRlciA9IHJlcXVpcmUoJ3BhcmFtZXRlcicpXG4vLyBjb25zdCBwYXJhbWV0ZXJDaGVja0luc3RhbmNlID0gbmV3IHBhcmFtZXRlcih7XG4vLyAgICAgLy8gdHJhbnNsYXRlOiBmdW5jdGlvbiAoKSB7XG4vLyAgICAgLy8gICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbi8vICAgICAvLyAgICAgLy8gQXNzdW1lIHRoZXJlIGhhdmUgSTE4bi50IG1ldGhvZCBmb3IgY29udmVydCBsYW5ndWFnZS5cbi8vICAgICAvLyAgICAgcmV0dXJuIEkxOG4udC5hcHBseShJMThuLCBhcmdzKTtcbi8vICAgICAvLyB9XG4vLyB9KVxuY29uc3QgY2lyY3VsYXJfanNvbiA9IHJlcXVpcmUoXCJjaXJjdWxhci1qc29uXCIpXG5jb25zdCBtb2NranMgPSByZXF1aXJlKCdtb2NranMnKVxuY29uc3Qgc2hvcnRpZCA9IHJlcXVpcmUoJ3Nob3J0aWQnKVxuY29uc3QgdmFsaWRhdG9yanMgPSByZXF1aXJlKCd2YWxpZGF0b3JqcycpXG5jb25zdCBjcm9zc19zcGF3biA9IHJlcXVpcmUoJ2Nyb3NzLXNwYXduJylcbmNvbnN0IEFDTUNsaWVudCA9IHJlcXVpcmUoJ2FtYmVyX3V0Zi04JylcbmNvbnN0IGNvID0gcmVxdWlyZSgnY28nKVxucmVxdWlyZSgnLi9lcnJvcicpXG5cbi8vIEZJWE1FIEhBQ0vljp/nlJ/mlrnms5VKU09O6L2s5o2i5LiN5Y+v6YCG55qEQlVH77yISkFWQeerr+S8oOadpeeahOWvjOaWh+acrOWtl+auteWGheWuueWQq+aciVxcblxcdOWtl+espuS4suS4reeahOWtl+espueUn+aIkEpTT07lrZfnrKbkuLLml6Dms5XmraPluLjop6PmnpDmiqXplJnvvIlcbmNvbnN0IHJhd19zdHJpbmdpZnkgPSBKU09OLnN0cmluZ2lmeVxuXG5mdW5jdGlvbiBuZXdfc3RyaW5naWZ5KHZhbHVlOiBhbnksIHJlcGxhY2VyPzogKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSA9PiBhbnksXG4gICAgICAgICAgICAgICAgICAgICAgIHNwYWNlPzogc3RyaW5nIHwgbnVtYmVyKTogc3RyaW5nIHtcbiAgICBsZXQgb3V0ID0gcmF3X3N0cmluZ2lmeSh2YWx1ZSwgcmVwbGFjZXIsIHNwYWNlKVxuICAgIGlmIChfLmlzU3RyaW5nKG91dCkpIHtcbiAgICAgICAgb3V0ID0gb3V0LnJlcGxhY2UoL1xcXFxuL2csICdcXFxcXFxcXG4nKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFx0L2csICdcXFxcXFxcXHQnKVxuICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFx1L2csICdcXFxcXFxcXHUnKSAvL0pBVkHnq6/ov5Tlm57nmoR1bmljb2Rl5a2X56ym6L2s5LmJ5aSE55CGXG4gICAgfVxuICAgIHJldHVybiBvdXRcbn1cblxuSlNPTi5zdHJpbmdpZnkgPSBuZXdfc3RyaW5naWZ5IGFzIGFueVxuXG4vLyB0cy1ub2Rl5pys5Zyw6LCD6K+V6ZyA6KaB5Yqg6L295a+55bqU55qE5rqQ5Luj56CB5ZCO57yA5ZCN56ewXG5leHBvcnQgZnVuY3Rpb24gZ2V0X3N1ZmZpeF90c19vcl9qcygpIHtcbiAgICBpZiAoZ2xvYmFsWydfX2Vudl9fJ10gPT0gJ2xvY2FsJyAmJiAhL15cXC9jb2RlXFwvbm9kZV9tb2R1bGVzLy50ZXN0KF9fZGlybmFtZSkpIHtcbiAgICAgICAgcmV0dXJuICd0cydcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gJ2pzJ1xuICAgIH1cbn1cblxuLy8g5YeG56Gu5a6a5L2N6ZSZ6K+v56CB5L2N572u77yM6Ze05o6l5b6X5Yiw5Ye95pWw6LCD55So5L2N572u5Zyw5Z2A5L+h5oGv77yM57uT5ZCI56ym5Y+35oql6KGo55qE5q2j56Gu6Kej5p6Q5aSE55CG5a6M576O5b6X5Yiw6ZSZ6K+v5a6a5L2N5L+h5oGv77yM5YeG56Gu5Luj56CB6LCD6K+V44CCXG5mdW5jdGlvbiBfX2dldF9iYXNlX2Z1bmNfY2FsbGVyX3NvdXJjZV9wb3NpdGlvbihwb3NpdGlvbjogbnVtYmVyID0gMykge1xuICAgIHRyeSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxldCBvdXQgPSBFcnJvclN0YWNrUGFyc2VyLnBhcnNlKGVycilcbiAgICAgICAgbGV0IGlkeCA9IDBcbiAgICAgICAgLy8g5om+5Yiw56ys5LqM5LiqVFPmlofku7bnmoTmiafooYzkvY3nva5cbiAgICAgICAgbGV0IGZpbmRfdHNfc3VmaXhfZmlsZV9jb3VudCA9IDBcbiAgICAgICAgZm9yICg7IGlkeCA8IG91dC5sZW5ndGg7IGlkeCsrKSB7XG4gICAgICAgICAgICBpZiAoL1xcLnRzJC8udGVzdChvdXRbaWR4XS5maWxlTmFtZSkpIHtcbiAgICAgICAgICAgICAgICBmaW5kX3RzX3N1Zml4X2ZpbGVfY291bnQgKz0gMVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGZpbmRfdHNfc3VmaXhfZmlsZV9jb3VudCA9PSBwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZpbmRfdHNfc3VmaXhfZmlsZV9jb3VudCA9PSBwb3NpdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuICdbJyArIG91dFtpZHhdWydmaWxlTmFtZSddICsgJzonICsgb3V0W2lkeF1bJ2xpbmVOdW1iZXInXSArICddJ1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVE9ETyDpnIDopoHlrprkvY3kuLrku4DkuYjosIPnlKjmoIjml6Dms5Xmib7liLDlr7nlupTnmoTkvY3nva7lh7rnjrDotornlYzvvJ/vvJ9cbiAgICAgICAgICAgIC8vIGNvbnNvbGUuZXJyb3IoZXJyKVxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihjaXJjdWxhcl9qc29uLnN0cmluZ2lmeShvdXQsIG51bGwsIDQpXG4gICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcci9nLCAnJykucmVwbGFjZSgvXFxuL2csICcnKSlcbiAgICAgICAgICAgIHJldHVybiAnIydcbiAgICAgICAgfVxuXG4gICAgfVxufVxuXG4vLyDojrflj5blvILluLjosIPnlKjmoIjnlKjkuo7ovoXliqnplJnor6/mj5DnpLrlrprkvY1cbmV4cG9ydCBmdW5jdGlvbiB4c3RhY2soZXJyLCBjb21wYWN0ID0gdHJ1ZSkge1xuICAgIHRyeSB7XG4gICAgICAgIC8vIFRPRE8g5LyY5YyW6KOB5Ymq5LiA5Lqb5peg55So5L+h5oGv5YeP5bCR5pel5b+X5bC65a+45pu05Yqg5L6/5LqO5Lq65bel5YiG5p6Q5aSE55CGXG4gICAgICAgIGxldCBzdGFjayA9IEVycm9yU3RhY2tQYXJzZXIucGFyc2UoZXJyKVxuICAgICAgICBpZiAoY29tcGFjdCkge1xuICAgICAgICAgICAgbGV0IHNvdXJjZXM6IHN0cmluZ1tdID0gW11cbiAgICAgICAgICAgIGZvciAobGV0IHYgb2Ygc3RhY2spIHtcbiAgICAgICAgICAgICAgICBzb3VyY2VzLnB1c2goYCR7dlsnZmlsZU5hbWUnXX06JHt2WydsaW5lTnVtYmVyJ119YClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzb3VyY2VzXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0YWNrXG4gICAgfSBjYXRjaCAoZXJyMSkge1xuICAgICAgICBsZXQgc291cmNlID0gX19nZXRfYmFzZV9mdW5jX2NhbGxlcl9zb3VyY2VfcG9zaXRpb24oKVxuICAgICAgICByZXR1cm4gYGludmFsaWQgZXJyb3IgaW5wdXQgcGFyYW0gKCR7c291cmNlfSlgXG4gICAgfVxufVxuXG4vLyAvLyDplJnor6/moIjnmoTpgJLlvZLltYzlpZfmoLzlvI/mmL7npLrmlbDmja7nu5PmnoTlrprkuYnvvIhwYXJhbeW1jOWll+aJvuWIsOacgOWQjuS4gOS4qm1zZ+eahEpTT07op6PmnpDor63ms5XplJnor6/lsLHmmK/plJnor6/pk77nmoTljp/lp4vplJnor6/lj5HnlJ/kvY3nva7vvIlcbi8vIGxldCB4ID0ge1xuLy8gICAgIFwiY29kZVwiOiBcIlVOS05PV05cIixcbi8vICAgICBcIm1zZ1wiOiBcIuacquefpemUmeivr1wiLFxuLy8gICAgIFwicGFyYW1cIjoge1xuLy8gICAgICAgICBcIm1zZ1wiOiBcIuaCqOi+k+WFpeeahOeUqOaIt+WQjeaIluWvhueggemUmeivr++8jOivt+mHjeaWsOeZu+W9lSAoRXJyb3JDb2RlOiAxMDA1LCB1cmw6IGh0dHBzOi8vbG9naW4uYWxpYmFiYS1pbmMuY29tL2F1dGhvcml6ZS9sb2dpbi5kbylcIlxuLy8gICAgIH0sXG4vLyAgICAgXCJzdGFja1wiOiBcIltcXFwiL1VzZXJzL2NodWppbmdodWkvRGVza3RvcC93b3JrL3hqcy9ieGpzL2ZyYW1ld29yay9iYXNlLnRzOjExMFxcXCIsXFxcIi9Vc2Vycy9jaHVqaW5naHVpL0Rlc2t0b3Avd29yay94anMvYnhqcy9hcHAvZW50cmllcy93ZWIvbW9iaWxlL21lZXRpbmctcm9vbS12aXNpdC50czoxNjFcXFwiLFxcXCIvVXNlcnMvY2h1amluZ2h1aS9EZXNrdG9wL3dvcmsveGpzL2J4anMvYXBwL2VudHJpZXMvd2ViL21vYmlsZS9tZWV0aW5nLXJvb20tdmlzaXQuanM6NDBcXFwiLFxcXCIvVXNlcnMvY2h1amluZ2h1aS9EZXNrdG9wL3dvcmsveGpzL2J4anMvYXBwL2VudHJpZXMvd2ViL21vYmlsZS9tZWV0aW5nLXJvb20tdmlzaXQuanM6MjFcXFwiLFxcXCIvVXNlcnMvY2h1amluZ2h1aS9EZXNrdG9wL3dvcmsveGpzL2J4anMvYXBwL2VudHJpZXMvd2ViL21vYmlsZS9tZWV0aW5nLXJvb20tdmlzaXQuanM6MTNcXFwiLFxcXCJpbnRlcm5hbC9wcm9jZXNzL25leHRfdGljay5qczoxODhcXFwiXVwiLFxuLy8gfVxuXG4vLyDlr7nkuo7lvILluLjlhoXlrrnnmoTmoLzlvI/ljJblj4LmlbDop6PmnpDlpITnkIbmiJDkuLrlm5vlhYPnu4Rjb2RlL21zZy9wYXJhbS9zdGFja1xuZXhwb3J0IGZ1bmN0aW9uIHhlcnJvcihlcnIsIF9fcGFyYW0/OiBhbnkpIHtcbiAgICB4YXNzZXJ0KGVyciBpbnN0YW5jZW9mIEVycm9yKVxuICAgIHRyeSB7XG4gICAgICAgIC8vIOagh+WHhumUmeivr+eahOe7n+S4gOi9rOaNouWkhOeQhlxuICAgICAgICBsZXQgZGF0YTogYW55ID0gSlNPTi5wYXJzZShlcnIubWVzc2FnZSlcbiAgICAgICAgaWYgKGRhdGEuY29kZSAmJiBkYXRhLm1zZyAmJiBFUlJPUlNbZGF0YS5jb2RlXSkge1xuICAgICAgICAgICAgcmV0dXJuIGRhdGFcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBpZ25vcmUgcGFyc2UgZXJyb3JcbiAgICB9XG4gICAgLy8g6Z2e5qCH5YeG6ZSZ6K+v55qE57uf5LiA5qC85byP6L2s5o2i5aSE55CGXG4gICAgbGV0IG1zZyA9IEVSUk9SU1tFUlIkVU5LTk9XTl1bJ3poJ10gLy8gVE9ETyDplJnor6/noIHlpJror63oqIDlm57kvKDliLDlrqLmiLfnq6/pl67pophcbiAgICBsZXQgY29kZSA9IEVSUiRVTktOT1dOXG4gICAgbGV0IHBhcmFtOiBhbnkgPSB7bXNnOiBlcnIubWVzc2FnZSwgcGFyYW06IF9fcGFyYW19IC8vIOeUqOaIt+iHquWumuS5ieeahOmUmeivr+WPguaVsOS/oeaBryBtc2fkuLrpnZ7plJnor6/noIFKU09O5Zub5YWD57uE5bCx5piv5bWM5aWX55qE57uI5q2i5p2h5Lu244CCXG4gICAgbGV0IHN0YWNrID0geHN0YWNrKGVycilcbiAgICBsZXQgZGF0YSA9IHttc2csIGNvZGUsIHBhcmFtLCBzdGFja31cbiAgICByZXR1cm4gZGF0YVxufVxuXG4vLyDnlKjkuo7ojrflj5bplJnor6/moIjnmoRyb290IGNhdXNl5qC55pys5Y6f5Zug77yI56ys5LiA5Liq6KKr5oum5oiq55qE6ZSZ6K+v5Y+R55Sf5L2N572u77yJXG5leHBvcnQgZnVuY3Rpb24geHJvb3QoZXJyOiBFcnJvcikge1xuICAgIHhhc3NlcnQoZXJyIGluc3RhbmNlb2YgRXJyb3IpXG4gICAgbGV0IHttc2csIHBhcmFtLCBjb2RlLCBzdGFja30gPSB4ZXJyb3IoZXJyKVxuXG4gICAgLy8g6YCS5b2S6YGN5Y6G5om+5Yiw6ZSZ6K+v6ZO+55qEcm9vdCBjYXVzZVxuICAgIGZvciAoOyBwYXJhbSAmJiBwYXJhbS5tc2c7KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBsZXQganNvbjogYW55ID0gSlNPTi5wYXJzZShwYXJhbS5tc2cpXG4gICAgICAgICAgICBwYXJhbSA9IGpzb24ucGFyYW1cbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBtc2cgPSBwYXJhbS5tc2dcbiAgICAgICAgICAgIGNvZGUgPSBwYXJhbS5jb2RlXG4gICAgICAgICAgICBzdGFjayA9IHBhcmFtLnN0YWNrXG4gICAgICAgICAgICBwYXJhbSA9IHBhcmFtLnBhcmFtXG4gICAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7bXNnLCBjb2RlLCBwYXJhbSwgc3RhY2t9XG59XG5cbi8vIFRPRE8g5oql6ZSZ5aSE55CG77yI5pi+56S66Zeu6aKY5Y+N6aaI6IGU57O75Lq65L+h5oGv77yJXG4vLyDlsIbmnKrlpITnkIbnmoTplJnor6/kuIrmipvnmoTlvILluLjpk77orrDlvZXkuIvmnaXnlKjkuo7nsr7lh4bov73ouKrku6PnoIHnmoTmiafooYzov4fnqIvvvIjku6Xlj4rlh4bnoa7ojrflj5bliLDmoLnoioLngrnnmoTplJnor6/noIHvvIlcbi8vIOWvueS6jnByb21pc2XlvILmraXlm57osIPnmoTnu5/kuIDlh7rplJnlpITnkIblhpnms5Xlrp7kvotcbi8vIGV4cG9ydCBmdW5jdGlvbiBsb2dpbih1c2VybmFtZTogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKSB7XG4vLyAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbi8vICAgICAgICAgY28oZnVuY3Rpb24qICgpIHtcbi8vICAgICAgICAgICAgIGxldCB1c2VyID0geWllbGQgYnVjLm9hdXRoY2xpZW50LmxvZ2luKHVzZXJuYW1lLCBwYXNzd29yZClcbi8vICAgICAgICAgICAgIHJlc29sdmUodXNlcilcbi8vICAgICAgICAgfSkuY2F0Y2goYXN5bmMgZnVuY3Rpb24gKGVycikge1xuLy8gICAgICAgICAgICAgeHRocm93KGVyciwgcmVqZWN0KVxuLy8gICAgICAgICB9KVxuLy8gICAgIH0pXG4vLyB9XG5leHBvcnQgZnVuY3Rpb24geHRocm93KGNvZGU6IHN0cmluZyB8IEVycm9yID0gRVJSJFVOS05PV04sIHBhcmFtOiBhbnkgPSB1bmRlZmluZWQsIHJlamVjdF9wYXJhbTogYW55ID0gdW5kZWZpbmVkKSB7XG4gICAgLy8gcHJvbWlzZeS4rei/m+ihjHJlamVjdOW8guW4uOWkhOeQhueahOaKm+WHuumUmeivr+aWueazleeahOW9ouWPgumAu+i+kemihOWkhOeQhui9rOaNouOAglxuICAgIGxldCByZWplY3Q6IGFueSA9IF8uaXNGdW5jdGlvbihwYXJhbSkgPyBwYXJhbSA6IHVuZGVmaW5lZFxuICAgIGlmIChyZWplY3QpIHBhcmFtID0gcmVqZWN0X3BhcmFtXG4gICAgbGV0IGRhdGE6IGFueSA9IHt9XG4gICAgbGV0IHNvdXJjZSA9IF9fZ2V0X2Jhc2VfZnVuY19jYWxsZXJfc291cmNlX3Bvc2l0aW9uKClcblxuICAgIGlmIChjb2RlIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGNvZGUubWVzc2FnZSlcbiAgICAgICAgICAgIC8vIOWwhumAj+S8oOS4iuaKm+eahOmUmeivr+eahOi3r+W+hOS/oeaBr+WSjOmZhOWKoOWPguaVsOS5n+iusOW9leS4i+adpeaWueS+v+aPkOS+m+WujOaVtOW6lOeUqOWghuagiOS/oeaBr+i+heWKqeiwg+ivleS4muWKoemAu+i+kVxuICAgICAgICAgICAgaWYgKCFfLmlzQXJyYXkoZGF0YS5zdGFjaykpIHtcbiAgICAgICAgICAgICAgICBkYXRhLnN0YWNrID0gW11cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRhdGEuc3RhY2sucHVzaChzb3VyY2UpXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgLy8gaWdub3JlXG4gICAgICAgIH1cbiAgICAgICAgLy8g5qCH5YeG6ZSZ6K+v55u05o6l5LiK5oqb5aSE55CGXG4gICAgICAgIGlmIChkYXRhLmNvZGUgJiYgZGF0YS5tc2cgJiYgRVJST1JTW2RhdGEuY29kZV0pIHtcbiAgICAgICAgICAgIC8vIOa1i+ivleS4pemHjUJVRyByZWplY3Tlh73mlbDnsbvlnovooajovr7lvI/kuLrlgYflv4XpobvopoHnlKhsb2Rhc2jliKTlrprmmK/lkKbkuLrlh73mlbBcbiAgICAgICAgICAgIGlmIChfLmlzRnVuY3Rpb24ocmVqZWN0KSkge1xuICAgICAgICAgICAgICAgIC8vIHByb21pc2Xlm57osIPkuK3ov5vooYzmipvplJnor6/lpITnkIZcbiAgICAgICAgICAgICAgICBsZXQgZXJyID0gbmV3IEVycm9yKEpTT04uc3RyaW5naWZ5KGRhdGEpKVxuICAgICAgICAgICAgICAgIHJlamVjdChlcnIpXG4gICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihKU09OLnN0cmluZ2lmeShkYXRhKSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyDlsIbpnZ7moIflh4bplJnor6/ovazmjaLkuLrmoIflh4bplJnor6/lkI7lho3kuIrmipvlpITnkIZcbiAgICAgICAgZGF0YSA9IHhlcnJvcihjb2RlLCBwYXJhbSlcbiAgICAgICAgZGF0YS5jb2RlID0gRVJSJFVOS05PV05cbiAgICAgICAgZGF0YS5tc2cgPSBFUlJPUlNbRVJSJFVOS05PV05dWyd6aCddIC8vIEZJWE1FIFRPRE8g6ZSZ6K+v56CB55qE5aSa6K+t6KiA5aSE55CG6L2s5o2i77yB77yBXG4gICAgICAgIGRhdGEucGFyYW0gPSB7bXNnOiBjb2RlLm1lc3NhZ2UsIHBhcmFtLCBzdGFjazogW3NvdXJjZV19XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8g5a+55LqO5bi46YeP5a6a5LmJ6ZSZ6K+v55qE57uf5LiA5qC85byP5YyW5aSE55CGXG4gICAgICAgIGRhdGEgPSB7Y29kZSwgbXNnOiBnbG9iYWxbJ0VSUk9SUyddW2NvZGUgYXMgc3RyaW5nXVsnemgnXSwgcGFyYW0sIHN0YWNrOiBbc291cmNlXX1cbiAgICB9XG5cbiAgICAvLyDlr7nkuo7mmK/lkKZwcm9taXNl5Zy65pmv5LiL55qE6ZSZ6K+v5LiK5oqb6L+b6KGM5q2j56Gu55qE6L2s5o2i5aSE55CGXG4gICAgaWYgKF8uaXNGdW5jdGlvbihyZWplY3QpKSB7XG4gICAgICAgIC8vIHByb21pc2Xlm57osIPkuK3ov5vooYzmipvplJnor6/lpITnkIZcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihKU09OLnN0cmluZ2lmeShkYXRhKSkpXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8g6Z2ecHJvbWlzZeWbnuiwg+S4reW8guW4uOS8oOmAklxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoSlNPTi5zdHJpbmdpZnkoZGF0YSkpXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24geGFzc2VydChleHByOiBhbnksIGNvZGU6IHN0cmluZyA9IEVSUiRBU1NFUlQsIHBhcmFtPzogYW55KSB7XG4gICAgbGV0IHNvdXJjZSA9IF9fZ2V0X2Jhc2VfZnVuY19jYWxsZXJfc291cmNlX3Bvc2l0aW9uKClcbiAgICBsZXQgc3RhY2sgPSBbc291cmNlXVxuICAgIGlmICghZXhwcikgdGhyb3cgbmV3IEVycm9yKEpTT04uc3RyaW5naWZ5KHtjb2RlLCBtc2c6IGdsb2JhbFsnRVJST1JTJ11bY29kZV1bJ3poJ10sIHBhcmFtLCBzdGFja30pKVxuICAgIHJldHVybiBleHByXG59XG5cbi8vIHV1aWTlhrLnqoHlj6/og73mgKflrZjlnKgxU+W5s+Wdh+WIsDEwMDDmr6vnp5IxMDAw5qyh5bm25Y+R77yM5q+PMW1z5bm25Y+R5Yay56qB5Y+v6IO95oCn77yIOOS4quWtl+iKgumaj+acuuaVsCsxMDAwMOmaj+acuuaVsO+8iVxuYXN5bmMgZnVuY3Rpb24geHV1aWQoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAvLyAvLyDlsIHoo4XmraPnoa7nmoR1dWlk5a6e546w566X5rOV56Gu5L+d5ZSv5LiA5oCn77yI5L2/55SoNuS4quWtl+iKgueahOacuuWZqG1hY+WcsOWdgO+8jOehruS/neWIhuW4g+W8j+acuuWZqOeul+azleaJp+ihjOeahOWUr+S4gOaAp++8iVxuICAgIC8vIGNvbnN0IG1hYyA9IGF3YWl0IF9feGdldG1hY19fKClcbiAgICAvLyAvLyDlsIblrZfnrKbkuLLovazmjaLkuLpidWZmZXLkuozov5vliLblpITnkIZcbiAgICAvLyBsZXQgYnVmID0gW11cbiAgICAvLyAvLyBNQUPlnLDlnYDmoLzlvI8gIyM6IyM6IyM6IyM6IyM6IyNcbiAgICAvLyBjb25zdCB2YWx1ZXMgPSBtYWMuc3BsaXQoJzonKVxuICAgIC8vIHhhc3NlcnQodmFsdWVzICYmIHZhbHVlcy5sZW5ndGggPT0gNilcbiAgICAvLyBmb3IgKGxldCBpID0gMDsgaSA8IDY7ICsraSkge1xuICAgIC8vICAgICBjb25zdCB0bXBCeXRlID0gcGFyc2VJbnQodmFsdWVzW2ldLCAxNik7XG4gICAgLy8gICAgIGJ1Zi5wdXNoKHRtcEJ5dGUpXG4gICAgLy8gfVxuICAgIC8vIGNvbnN0IHRpbWUgPSByZXF1aXJlKCduYW5vLXNlY29uZHMnKS5ub3coKVxuICAgIC8vIGNvbnN0IGJ5dGVzID0gcmVxdWlyZSgnY3J5cHRvJykucmFuZG9tQnl0ZXMoOClcbiAgICBsZXQgb3B0aW9ucyA9IHt9XG4gICAgLy8g5LulbWFj5Zyw5Z2A5L2c5Li65py65Zmo5ZSv5LiA5qCH6K+G56Gu5L+d5q2j56Gu5oCnXG4gICAgY29uc3QgdXVpZCA9IHJlcXVpcmUoJ3V1aWQvdjEnKShvcHRpb25zID0ge1xuICAgICAgICAvLyBtc2VjczogbmV3IERhdGUoKS5nZXRUaW1lKCksXG4gICAgICAgIG5zZWNzOiBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAxMDAwMCkgLy8g5LyY5YyW566X5rOV5Lit55qE6ZqP5py65pWw5L2/55So57y66Zm377yIMeavq+enkuS4rU7kuKrlubblj5E45a2X6IqC5a+G56CB6ZqP5py65pWw5ZKMMeS4h+maj+acuuaVtOaVsO+8jDHnp5IxMDAw5bm25Y+R77yJXG4gICAgICAgIC8vIG5vZGU6IGJ1ZiwvL21hY+WcsOWdgCjkuIDlj7DmnLrlmajkuIrlpJrkuKpWTeS5n+WPr+iDveWGsueqgemXrumimO+8jOacuuWZqOagh+ivhumaj+acujbkuKrlrZfoioLmm7Tlj4vlpb3kupspXG4gICAgICAgIC8vIG1zZWNzOiBuZXcgRGF0ZSgpLmdldFRpbWUoKSwvL3VuaXjlhYPlubTot53nprvnmoTmr6vnp5Lml7bpl7RcbiAgICAgICAgLy8gbXNlY3M6IHRpbWVbMF0gKiAxMDAwICsgTWF0aC5mbG9vcih0aW1lWzFdIC8gMTAwMDAwMCksLy/mr6vnp5Lml7bpl7RcbiAgICAgICAgLy8gbnNlY3M6IE1hdGguZmxvb3IoKHRpbWVbMV0gJSAxMDAwMDAwKSAvIDEwMCksLy/lsIbnurPnp5Lml7bpl7Q5NTFtczg1MTk2OW5z6L2s5o2i5Li6MTAw57qz56eS5Li65Y2V5L2NXG4gICAgICAgIC8vIGNsb2Nrc2VxOiAoYnl0ZXNbMF0gPDwgOCB8IGJ5dGVzWzFdKSAmIDB4M2ZmZiwvL+aXtumXtOW6j+WIl+S9v+eUqOmaj+acuuaVsOabv+S7ozEwMjTkuKrpmo/mnLrmlbBcbiAgICB9KVxuICAgIGNvbnNvbGUubG9nKG9wdGlvbnMpXG4gICAgcmV0dXJuIHV1aWQ7XG59XG5cbi8vIOiOt+WPlm1hY+WcsOWdgFxuYXN5bmMgZnVuY3Rpb24gX194Z2V0bWFjX18oKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAoZ2xvYmFsWydnX2J4anNfc01hY0FkZHJlc3MnXSkge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHhhc3NlcnQocmVxdWlyZSgnZ2V0bWFjJykuaXNNYWMoZ2xvYmFsWydnX2J4anNfc01hY0FkZHJlc3MnXSkpXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShnbG9iYWxbJ2dfYnhqc19zTWFjQWRkcmVzcyddKVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgeHRocm93KGVyciwgcmVqZWN0KVxuICAgICAgICAgICAgfVxuICAgICAgICB9KVxuICAgIH1cbiAgICByZXR1cm4gbmV3IFByb21pc2U8c3RyaW5nPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHJlcXVpcmUoJ2dldG1hYycpLmdldE1hYyhmdW5jdGlvbiAoZXJyLCBtYWNBZGRyZXNzKSB7XG4gICAgICAgICAgICBpZiAoZXJyKSB4dGhyb3coZXJyLCByZWplY3QpXG4gICAgICAgICAgICByZXNvbHZlKG1hY0FkZHJlc3MpXG4gICAgICAgIH0pXG4gICAgfSlcbn1cblxuYXN5bmMgZnVuY3Rpb24gdGVzdCgpIHtcblxuICAgIC8vIHZhciBtYWNoaW5lID0gcmVxdWlyZSgnbWFjaGluZS11dWlkJylcblxuICAgIC8vIGNvbnNvbGUubG9nKG1hY2hpbmUoJ215bmFtZXNwYWNlJykpO1xuLy8gMmM0MzNhMDctMTQwYS01YmI5LTk0OWEtNDk5N2I1NjZjMzk3XG4gICAgLy8gY29uc29sZS5sb2cobWFjaGluZSgnbXluYW1lc3BhY2UnKSk7XG5cbiAgICBjb25zb2xlLmxvZyhhd2FpdCBfX3hnZXRtYWNfXygpKVxuICAgIGNvbnNvbGUubG9nKGF3YWl0IHh1dWlkKCkpXG59XG5cbnRlc3QoKS50aGVuKGRhdGEgPT4ge1xuXG59KS5jYXRjaChlcnIgPT4ge1xuICAgIGNvbnNvbGUubG9nKGVycilcbn0pXG4iXX0=
;