UNPKG

125 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || Object.assign || function(t) {
3 for (var s, i = 1, n = arguments.length; i < n; i++) {
4 s = arguments[i];
5 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6 t[p] = s[p];
7 }
8 return t;
9};
10var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
11 return new (P || (P = Promise))(function (resolve, reject) {
12 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
13 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
14 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
15 step((generator = generator.apply(thisArg, _arguments || [])).next());
16 });
17};
18var __generator = (this && this.__generator) || function (thisArg, body) {
19 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
20 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
21 function verb(n) { return function (v) { return step([n, v]); }; }
22 function step(op) {
23 if (f) throw new TypeError("Generator is already executing.");
24 while (_) try {
25 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;
26 if (y = 0, t) op = [op[0] & 2, t.value];
27 switch (op[0]) {
28 case 0: case 1: t = op; break;
29 case 4: _.label++; return { value: op[1], done: false };
30 case 5: _.label++; y = op[1]; op = [0]; continue;
31 case 7: op = _.ops.pop(); _.trys.pop(); continue;
32 default:
33 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
34 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
35 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
36 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
37 if (t[2]) _.ops.pop();
38 _.trys.pop(); continue;
39 }
40 op = body.call(thisArg, _);
41 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
42 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
43 }
44};
45var _this = this;
46Object.defineProperty(exports, "__esModule", { value: true });
47process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
48require("reflect-metadata");
49var inversify_1 = require("inversify");
50var typeorm_1 = require("@bxjs/typeorm");
51var session_1 = require("./session");
52var $$ = require("./plugins");
53var path = require('path');
54var ErrorStackParser = require('error-stack-parser');
55var cookie = require('cookie');
56var MobileDetect = require('mobile-detect');
57var fetch = require('node-fetch');
58var _ = require('lodash');
59var moment = require('moment');
60var extend = require('extend');
61var querystring = require('querystring');
62// const parameter = require('parameter')
63// const parameterCheckInstance = new parameter({
64// // translate: function () {
65// // var args = Array.prototype.slice.call(arguments);
66// // // Assume there have I18n.t method for convert language.
67// // return I18n.t.apply(I18n, args);
68// // }
69// })
70var circular_json = require("circular-json");
71var mockjs = require('mockjs');
72var shortid = require('shortid');
73var validatorjs = require('validatorjs');
74var cross_spawn = require('cross-spawn');
75var ACMClient = require('acm-client');
76var co = require('co');
77// FIXME HACK原生方法JSON转换不可逆的BUG(JAVA端传来的富文本字段内容含有\n\t字符串中的字符生成JSON字符串无法正常解析报错)
78var raw_stringify = JSON.stringify;
79function new_stringify(value, replacer, space) {
80 var out = raw_stringify(value, replacer, space);
81 if (_.isString(out)) {
82 out = out.replace(/\\n/g, '\\\\n')
83 .replace(/\\t/g, '\\\\t')
84 .replace(/\\u/g, '\\\\u'); //JAVA端返回的unicode字符转义处理
85 }
86 return out;
87}
88JSON.stringify = new_stringify;
89// ts-node本地调试需要加载对应的源代码后缀名称
90function get_suffix_ts_or_js() {
91 if (global['__env__'] == 'local' && !/^\/code\/node_modules/.test(__dirname)) {
92 return 'ts';
93 }
94 else {
95 return 'js';
96 }
97}
98exports.get_suffix_ts_or_js = get_suffix_ts_or_js;
99// 准确定位错误码位置,间接得到函数调用位置地址信息,结合符号报表的正确解析处理完美得到错误定位信息,准确代码调试。
100function __get_base_func_caller_source_position(position) {
101 if (position === void 0) { position = 3; }
102 try {
103 throw new Error();
104 }
105 catch (err) {
106 var out = ErrorStackParser.parse(err);
107 var idx = 0;
108 // 找到第二个TS文件的执行位置
109 var find_ts_sufix_file_count = 0;
110 for (; idx < out.length; idx++) {
111 if (/\.ts$/.test(out[idx].fileName)) {
112 find_ts_sufix_file_count += 1;
113 }
114 if (find_ts_sufix_file_count == position) {
115 break;
116 }
117 }
118 if (find_ts_sufix_file_count == position) {
119 return '[' + out[idx]['fileName'] + ':' + out[idx]['lineNumber'] + ']';
120 }
121 else {
122 // TODO 需要定位为什么调用栈无法找到对应的位置出现越界??
123 // console.error(err)
124 console.error(circular_json.stringify(out, null, 4)
125 .replace(/\r/g, '').replace(/\n/g, ''));
126 return '#';
127 }
128 }
129}
130// 获取异常调用栈用于辅助错误提示定位
131function xstack(err, compact) {
132 if (compact === void 0) { compact = true; }
133 try {
134 // TODO 优化裁剪一些无用信息减少日志尺寸更加便于人工分析处理
135 var stack = ErrorStackParser.parse(err);
136 if (compact) {
137 var sources = [];
138 for (var _i = 0, stack_1 = stack; _i < stack_1.length; _i++) {
139 var v = stack_1[_i];
140 sources.push(v['fileName'] + ":" + v['lineNumber']);
141 }
142 return sources;
143 }
144 return stack;
145 }
146 catch (err1) {
147 var source = __get_base_func_caller_source_position();
148 return "invalid error input param (" + source + ")";
149 }
150}
151exports.xstack = xstack;
152// // 错误栈的递归嵌套格式显示数据结构定义(param嵌套找到最后一个msg的JSON解析语法错误就是错误链的原始错误发生位置)
153// let x = {
154// "code": "UNKNOWN",
155// "msg": "未知错误",
156// "param": {
157// "msg": "您输入的用户名或密码错误,请重新登录 (ErrorCode: 1005, url: https://login.alibaba-inc.com/authorize/login.do)"
158// },
159// "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\"]",
160// }
161// 对于异常内容的格式化参数解析处理成为四元组code/msg/param/stack
162function xerror(err, __param) {
163 xassert(err instanceof Error);
164 try {
165 // 标准错误的统一转换处理
166 var data_1 = JSON.parse(err.message);
167 if (data_1.code && data_1.msg && ERRORS[data_1.code]) {
168 return data_1;
169 }
170 }
171 catch (err) {
172 // ignore parse error
173 }
174 // 非标准错误的统一格式转换处理
175 var msg = ERRORS[ERR$UNKNOWN]['zh']; // TODO 错误码多语言回传到客户端问题
176 var code = ERR$UNKNOWN;
177 var param = { msg: err.message, param: __param }; // 用户自定义的错误参数信息 msg为非错误码JSON四元组就是嵌套的终止条件。
178 var stack = xstack(err);
179 var data = { msg: msg, code: code, param: param, stack: stack };
180 return data;
181}
182exports.xerror = xerror;
183// 用于获取错误栈的root cause根本原因(第一个被拦截的错误发生位置)
184function xroot(err) {
185 xassert(err instanceof Error);
186 var _a = xerror(err), msg = _a.msg, param = _a.param, code = _a.code, stack = _a.stack;
187 // 递归遍历找到错误链的root cause
188 for (; param && param.msg;) {
189 try {
190 var json = JSON.parse(param.msg);
191 param = json.param;
192 }
193 catch (err) {
194 msg = param.msg;
195 code = param.code;
196 stack = param.stack;
197 param = param.param;
198 break;
199 }
200 }
201 return { msg: msg, code: code, param: param, stack: stack };
202}
203exports.xroot = xroot;
204// TODO 报错处理(显示问题反馈联系人信息)
205// 将未处理的错误上抛的异常链记录下来用于精准追踪代码的执行过程(以及准确获取到根节点的错误码)
206// 对于promise异步回调的统一出错处理写法实例
207// export function login(username: string, password: string) {
208// return new Promise((resolve, reject) => {
209// co(function* () {
210// let user = yield buc.oauthclient.login(username, password)
211// resolve(user)
212// }).catch(async function (err) {
213// xthrow(err, reject)
214// })
215// })
216// }
217function xthrow(code, param, reject_param) {
218 if (code === void 0) { code = ERR$UNKNOWN; }
219 if (param === void 0) { param = undefined; }
220 if (reject_param === void 0) { reject_param = undefined; }
221 // promise中进行reject异常处理的抛出错误方法的形参逻辑预处理转换。
222 var reject = _.isFunction(param) ? param : undefined;
223 if (reject)
224 param = reject_param;
225 var data = {};
226 var source = __get_base_func_caller_source_position();
227 if (code instanceof Error) {
228 try {
229 data = JSON.parse(code.message);
230 // 将透传上抛的错误的路径信息和附加参数也记录下来方便提供完整应用堆栈信息辅助调试业务逻辑
231 if (!_.isArray(data.stack)) {
232 data.stack = [];
233 }
234 data.stack.push(source);
235 }
236 catch (err) {
237 // ignore
238 }
239 // 标准错误直接上抛处理
240 if (data.code && data.msg && ERRORS[data.code]) {
241 // 测试严重BUG reject函数类型表达式为假必须要用lodash判定是否为函数
242 if (_.isFunction(reject)) {
243 // promise回调中进行抛错误处理
244 var err = new Error(JSON.stringify(data));
245 reject(err);
246 return;
247 }
248 else {
249 throw new Error(JSON.stringify(data));
250 }
251 }
252 // 将非标准错误转换为标准错误后再上抛处理
253 data = xerror(code, param);
254 data.code = ERR$UNKNOWN;
255 data.msg = ERRORS[ERR$UNKNOWN]['zh']; // FIXME TODO 错误码的多语言处理转换!!
256 data.param = { msg: code.message, param: param, stack: [source] };
257 }
258 else {
259 // 对于常量定义错误的统一格式化处理
260 data = { code: code, msg: global['ERRORS'][code]['zh'], param: param, stack: [source] };
261 }
262 // 对于是否promise场景下的错误上抛进行正确的转换处理
263 if (_.isFunction(reject)) {
264 // promise回调中进行抛错误处理
265 reject(new Error(JSON.stringify(data)));
266 }
267 else {
268 // 非promise回调中异常传递
269 throw new Error(JSON.stringify(data));
270 }
271}
272exports.xthrow = xthrow;
273function xassert(expr, code, param) {
274 if (code === void 0) { code = ERR$ASSERT; }
275 var source = __get_base_func_caller_source_position();
276 var stack = [source];
277 if (!expr)
278 throw new Error(JSON.stringify({ code: code, msg: global['ERRORS'][code]['zh'], param: param, stack: stack }));
279 return expr;
280}
281exports.xassert = xassert;
282// // https://github.com/node-modules/parameter 参数验证规则详见此文档(egg团队开发的组件)
283// // 注意事项:GET通过URL传递的参数都是字符串类型应该尽量避免GET传递参数,需要多用POST的JSON格式传递参数并且POSTMAN上进行辅助测试正确数据类型映射。
284// export function xcheck(param: { [propName: string]: any }, rules: { [propName: string]: any }) {
285// let errors = parameterCheckInstance.validate(rules, param)
286// if (_.isEmpty(errors)) {
287// return true
288// } else {
289// xthrow(ERR$PARAM, errors)
290// }
291// }
292function xlog() {
293 var args = [];
294 for (var _i = 0; _i < arguments.length; _i++) {
295 args[_i] = arguments[_i];
296 }
297 // 兼容云端以及本地日志调试(解决任意对象的JSON字符串内容的完整输出)
298 var source = __get_base_func_caller_source_position() + '[' + xnow('YYYY-MM-DD HH:mm:ss.SSS') + ']';
299 var output = circular_json.stringify(args.slice(), null, 4);
300 if (global['__env__'] != 'prod' && !/^\/code\/node_modules/.test(__dirname)) {
301 // 打印到控制台一份日志(在阿里云非线上FC环境中)
302 console.log.apply(undefined, [source + output]);
303 // 写日志文件到/tmp下临时处理一下 TODO 需要改为类似log4j的本地日志库仅在非线上环境使用方便开发单机日常机器上调试。
304 var fs = require('fs');
305 var logFilePath = process.env['NODE_LOGFILE'] ? process.env['NODE_LOGFILE'] : '/tmp/bxjs.log';
306 fs.appendFileSync(logFilePath, source + output + "\r\n");
307 }
308 else {
309 // 生产环境下只打印到控制台绑定的SLS日志服务器上,并且需要去除掉换行信息否则打印会不正常。
310 // 去除掉换行方便方便SLS上的日志输出排版显示
311 output = output.replace(/\r/g, '').replace(/\n/g, '');
312 console.log.apply(undefined, [source + output]);
313 }
314}
315exports.xlog = xlog;
316// // 将详细错误信息及时发送到钉钉群上实时反馈给维护者
317// await xwarn({
318// code,
319// // TODO 如何认证通过了获取到用户信息也需要发送过去,方便联系对接人员进行立刻问题处理反馈。
320// message,
321// stack,
322// param,
323// })
324// 将详细错误信息及时发送到钉钉群上实时反馈给维护者
325// 钉钉IM群机器人报警通知
326function xwarn() {
327 var args = [];
328 for (var _i = 0; _i < arguments.length; _i++) {
329 args[_i] = arguments[_i];
330 }
331 return __awaiter(this, void 0, void 0, function () {
332 var source, out, access_token, mobiles;
333 return __generator(this, function (_a) {
334 switch (_a.label) {
335 case 0:
336 source = __get_base_func_caller_source_position();
337 // 对于异常参数警告信息进行错误内容标准解析
338 if (args.length > 0 && args[0] instanceof Error) {
339 args[0] = xerror(args[0]);
340 }
341 out = [source, xnow('YYYY-MM-DD HH:mm:ss.SSS'), __assign({}, args)];
342 access_token = xconfig('framework.warn.dingding.access_token');
343 mobiles = xconfig('framework.warn.dingding.mobiles');
344 if (!access_token || !mobiles) {
345 access_token = '020a09eac5f2fa320ae851442d5e19e23693c64ad2255c85354b4a49a5a48d35';
346 mobiles = ['15381151346'];
347 }
348 return [4 /*yield*/, xpost("https://oapi.dingtalk.com/robot/send?access_token=" + access_token, {
349 msgtype: 'text',
350 text: {
351 content: out
352 },
353 at: {
354 atMobiles: mobiles,
355 isAtAll: false
356 }
357 })
358 // 线上SLS日志上也保存一份
359 // console.warn(out)
360 ];
361 case 1:
362 _a.sent();
363 // 线上SLS日志上也保存一份
364 // console.warn(out)
365 xlog(out);
366 return [2 /*return*/];
367 }
368 });
369 });
370}
371// 捕获未监听到的异常记录后直接退出(运行堆栈已经破坏直接记录日志后异常退出即可,由外部监控自动重启)
372process.on('uncaughtException', function (err) {
373 return __awaiter(this, void 0, void 0, function () {
374 return __generator(this, function (_a) {
375 switch (_a.label) {
376 case 0:
377 xlog(xerror(err));
378 return [4 /*yield*/, xwarn(err)];
379 case 1:
380 _a.sent();
381 process.exit(-1);
382 return [2 /*return*/];
383 }
384 });
385 });
386});
387// 记录await/async中出现未捕获的异常错误
388process.on('unhandledRejection', function (reason, p) { return __awaiter(_this, void 0, void 0, function () {
389 return __generator(this, function (_a) {
390 switch (_a.label) {
391 case 0:
392 xlog('Unhandled Rejection at: Promise', p, 'reason:', reason);
393 // application specific logging, throwing an error, or other logic here
394 return [4 /*yield*/, xwarn(reason, p)];
395 case 1:
396 // application specific logging, throwing an error, or other logic here
397 _a.sent();
398 process.exit(-1);
399 return [2 /*return*/];
400 }
401 });
402}); });
403// async/await的非阻塞异步延迟方法,用于调试阻塞程序的执行进行单步调试的效果。
404var sleep = require('sleep-async')();
405function xsleep(ms) {
406 if (ms === void 0) { ms = -1; }
407 if (ms <= 0) {
408 ms = 50 * 365 * 24 * 3600 * 1000; // 50年最大数视为永久阻塞方便断点单步调试问题
409 }
410 return new Promise(function (resolve, reject) {
411 try {
412 sleep.sleep(ms, function () {
413 resolve();
414 });
415 }
416 catch (err) {
417 xlog(xerror(err));
418 resolve();
419 // xthrow(err,reject)
420 }
421 });
422}
423exports.xsleep = xsleep;
424function xpost(url, param, headers, timeout) {
425 if (timeout === void 0) { timeout = 3000; }
426 return __awaiter(this, void 0, void 0, function () {
427 var res, json, text, err_1;
428 return __generator(this, function (_a) {
429 switch (_a.label) {
430 case 0:
431 // TODO 线上测试不稳定超时暂时忽略掉通过进程最大运行时间去控制超时失败
432 timeout = 5000; // -1 不行线上会被阻塞住僵死
433 res = null;
434 json = null;
435 text = null;
436 _a.label = 1;
437 case 1:
438 _a.trys.push([1, 4, , 5]);
439 return [4 /*yield*/, fetch(url, {
440 method: 'POST',
441 body: JSON.stringify(param),
442 headers: __assign({ 'Content-Type': 'application/json' }, headers),
443 timeout: timeout <= 0 ? 0 : timeout,
444 })];
445 case 2:
446 res = _a.sent();
447 return [4 /*yield*/, res.text()]; // 解析出完整的返回内容避免HTML以及非法格式信息便于正确报错定位后端接口错误
448 case 3:
449 text = _a.sent(); // 解析出完整的返回内容避免HTML以及非法格式信息便于正确报错定位后端接口错误
450 json = JSON.parse(text);
451 return [2 /*return*/, json];
452 case 4:
453 err_1 = _a.sent();
454 xthrow(err_1, { url: url, param: param, headers: headers, text: text });
455 return [3 /*break*/, 5];
456 case 5: return [2 /*return*/];
457 }
458 });
459 });
460}
461exports.xpost = xpost;
462// 默认超时3000毫秒
463function xget(url, param, headers, timeout) {
464 if (timeout === void 0) { timeout = 3000; }
465 return __awaiter(this, void 0, void 0, function () {
466 var res, json, text, err_2;
467 return __generator(this, function (_a) {
468 switch (_a.label) {
469 case 0:
470 // TODO 线上测试不稳定超时暂时忽略掉通过进程最大运行时间去控制超时失败
471 timeout = 5000; // -1 不行线上会被阻塞住僵死
472 res = null;
473 json = null;
474 text = null;
475 _a.label = 1;
476 case 1:
477 _a.trys.push([1, 4, , 5]);
478 url = url + (param ? '?' : '') + querystring.stringify(param);
479 return [4 /*yield*/, fetch(url, {
480 method: 'GET',
481 headers: __assign({ 'Content-Type': 'application/json' }, headers),
482 timeout: timeout <= 0 ? 0 : timeout,
483 })];
484 case 2:
485 res = _a.sent();
486 return [4 /*yield*/, res.text()]; // 解析出完整的返回内容避免HTML以及非法格式信息便于正确报错定位后端接口错误
487 case 3:
488 text = _a.sent(); // 解析出完整的返回内容避免HTML以及非法格式信息便于正确报错定位后端接口错误
489 json = JSON.parse(text);
490 return [2 /*return*/, json];
491 case 4:
492 err_2 = _a.sent();
493 xthrow(err_2, { url: url, param: param, headers: headers, text: text });
494 return [3 /*break*/, 5];
495 case 5: return [2 /*return*/];
496 }
497 });
498 });
499}
500exports.xget = xget;
501// 302临时重定向跳转实现
502function xredirect(url, param) {
503 if (param === void 0) { param = {}; }
504 // TODO 多个程序实例并发处理的时候存在时序问题不能保证全局变量被准确清空。
505 // 检查应用重复设置重定向地址未及时return返回控制器问题
506 xassert(global['__redirect_url__'] === undefined);
507 if (param) {
508 xassert(_.isPlainObject(param));
509 // 删除param中两个框架预定义参数__url__和__api__不允许进行参数传递(禁止业务逻辑使用避免框架后续升级以及与短网址功能冲突)
510 delete param.__api__;
511 delete param.__url__;
512 // 补额外的附加参数
513 if (/\?/.test(url)) {
514 url += '&';
515 }
516 else {
517 url += '?';
518 }
519 url += querystring.stringify(param);
520 }
521 global['__redirect_url__'] = url;
522}
523exports.xredirect = xredirect;
524// 如果只有key参数表示读取属性(缺省值为undefined),如果key为空表示读取所有的请求cookies属性,否则表示响应设置cookies
525function xcookie(key, value, option) {
526 if (!arguments.length) {
527 // 读取所有的请求cookies属性object
528 return global['__request_cookies__'] ? global['__request_cookies__'] : {};
529 }
530 else if (arguments.length == 1) {
531 return key ? xcookie()[key] : undefined;
532 }
533 else {
534 if (global['__respond_cookies__'] === undefined) {
535 global['__respond_cookies__'] = {};
536 }
537 if (key) {
538 // COOKIES缺省属性设置(有效时间24小时并且统一关联到根页面上获取COOKIES值)
539 option = xassign({ path: '/', maxAge: 24 * 3600 }, option);
540 global['__respond_cookies__'][key] = cookie.serialize(key, value, option);
541 }
542 return;
543 }
544}
545exports.xcookie = xcookie;
546// 判断user-agent请求是否为移动端
547function xismobile() {
548 var md = new MobileDetect(global['__user_agent__']);
549 return !!md.mobile();
550}
551function xassign(target, source) {
552 var args = [];
553 for (var _i = 2; _i < arguments.length; _i++) {
554 args[_i - 2] = arguments[_i];
555 }
556 var param = [true, target, source].concat(args);
557 return extend.apply(null, param);
558}
559// 查询app/config目录下的应用配置数据
560function xconfig(path, defaultValue) {
561 if (defaultValue === void 0) { defaultValue = undefined; }
562 if (global['__config__']) {
563 return _.get(global['__config__'], path, defaultValue);
564 }
565 var fp = require('path');
566 var fs = require('fs');
567 // 自动获取app/config的相对路径目录位置得到根路径的位置
568 var config_path = '';
569 if (__dirname.includes('/node_modules/@bxjs/base/')) {
570 // 在应用目录下
571 config_path = fp.join(__dirname, '../../../../app/config');
572 }
573 else {
574 // 在axjs库开发目录下
575 config_path = fp.join(__dirname, '../app/config');
576 }
577 // 自动识别判断运行环境global['__env__']并且加载对应的base数据和env数据
578 var config_base_path = config_path + '/config.base.' + get_suffix_ts_or_js();
579 var config_env_path = config_path + ("/config." + global['__env__'] + ".") + get_suffix_ts_or_js();
580 if (!fs.existsSync(config_base_path)) {
581 return defaultValue;
582 }
583 var config_base = require(config_base_path).default;
584 var config_env = {};
585 if (fs.existsSync(config_env_path)) {
586 config_env = require(config_env_path).default;
587 }
588 // bugfix Object.assign不支持深度拷贝问题
589 // global['__config__'] = Object.assign({}, config_base, config_env)
590 // global['__config__'] = _.assign({}, config_env, config_base)
591 global['__config__'] = xassign({}, config_base, config_env);
592 return _.get(global['__config__'], path, defaultValue);
593}
594function xconnect(callback, config) {
595 if (config === void 0) { config = 'default'; }
596 return __awaiter(this, void 0, void 0, function () {
597 var _this = this;
598 return __generator(this, function (_a) {
599 return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
600 var cfg, mng, name, db_1, err_3;
601 var _this = this;
602 return __generator(this, function (_a) {
603 switch (_a.label) {
604 case 0:
605 cfg = {};
606 _a.label = 1;
607 case 1:
608 _a.trys.push([1, 3, , 4]);
609 cfg = xassign({}, xconfig('plugins.database.default', {}));
610 xassert(!_.isEmpty(cfg), ERR$PARAM, { config: config });
611 // 强制补上约定的实体存放路径定义位置(不允许配置是约定规范)
612 if (__dirname.includes('/node_modules/@bxjs/base/')) {
613 // 在应用目录下
614 cfg['entities'] = [
615 path.join(__dirname, '../../../../app/plugins/database/entity/*.' + get_suffix_ts_or_js())
616 ];
617 }
618 else {
619 // 在axjs库开发目录下
620 cfg['entities'] = [
621 path.join(__dirname, '../app/plugins/database/entity/*.' + get_suffix_ts_or_js())
622 ];
623 }
624 mng = typeorm_1.getConnectionManager();
625 name = cfg.name ? cfg.name : 'default';
626 if (!mng.has(name)) {
627 mng.create(cfg);
628 }
629 db_1 = mng.get(name);
630 if (global['g_connection'] === undefined) {
631 global['g_connection'] = {};
632 }
633 if (!db_1.isConnected) { // TODO 需要进行连接池的管理
634 global['g_connection'][name] = db_1.connect();
635 }
636 return [4 /*yield*/, global['g_connection'][name].then(function (connection) { return __awaiter(_this, void 0, void 0, function () {
637 var out;
638 return __generator(this, function (_a) {
639 switch (_a.label) {
640 case 0:
641 xassert(db_1.isConnected);
642 return [4 /*yield*/, callback(connection)
643 // await db.close() // typeorm没有进行连接池的管理不能进行销毁
644 ];
645 case 1:
646 out = _a.sent();
647 // await db.close() // typeorm没有进行连接池的管理不能进行销毁
648 resolve(out);
649 return [2 /*return*/];
650 }
651 });
652 }); }).catch(function (err) { return __awaiter(_this, void 0, void 0, function () {
653 return __generator(this, function (_a) {
654 // await db.close()
655 xthrow(err, reject, { cfg: cfg });
656 return [2 /*return*/];
657 });
658 }); })];
659 case 2:
660 _a.sent();
661 return [3 /*break*/, 4];
662 case 3:
663 err_3 = _a.sent();
664 xthrow(err_3, reject, { cfg: cfg });
665 return [3 /*break*/, 4];
666 case 4: return [2 /*return*/];
667 }
668 });
669 }); })];
670 });
671 });
672}
673// 创建XBaseEntity对象并且自动赋值前端请求的赋值数据
674function xnew(TYPE, param) {
675 var args = [];
676 for (var _i = 2; _i < arguments.length; _i++) {
677 args[_i - 2] = arguments[_i];
678 }
679 // 泛型实现类似这个功能
680 // asset = new AlilangAsset()
681 // getRepository(AlilangAsset).merge(asset, param as any)
682 // AlilangAsset.merge(asset, param as any)
683 // return asset
684 var obj = new TYPE();
685 if (_.isEmpty(param)) {
686 return obj;
687 }
688 var repo = typeorm_1.getRepository(TYPE);
689 repo.merge.apply(repo, [obj, param].concat(args));
690 return obj;
691}
692// 查询构造器易用性封装
693function xquery(connect, TYPE, alias) {
694 return connect.getRepository(TYPE).createQueryBuilder(alias);
695}
696// 分页查询获取总数以及原始记录数据
697function xcount(sql, page, size) {
698 return __awaiter(this, void 0, void 0, function () {
699 var _a, count, rows;
700 return __generator(this, function (_b) {
701 switch (_b.label) {
702 case 0:
703 xassert(page >= 1);
704 return [4 /*yield*/, Promise.all([
705 sql.getCount(),
706 sql.offset((page - 1) * size).limit(size).getRawMany()
707 ])];
708 case 1:
709 _a = _b.sent(), count = _a[0], rows = _a[1];
710 return [2 /*return*/, [rows, count]];
711 }
712 });
713 });
714}
715// 路由参数的修饰符配置
716// TODO 更多接口相关参数的配置扩展,例如:是否支持JSONP
717function xroute(param) {
718 // 缺省值处理
719 param = xassign({ name: '', desc: '', path: '', auth: true }, param);
720 return function (target, propertyKey, descriptor) {
721 var _this = this;
722 // TODO 注入到类实例定义中进行全局引用动态类的特性添加(trait功能的动态实现)
723 // 动态绑定路由类实例的上下文属性
724 target.prototype.context = function () {
725 return {
726 param: param,
727 // 是否登录的鉴权方法统一框架层面上的处理实现,此处仅仅是通用接口的约束的定义。
728 auth: function () { return __awaiter(_this, void 0, void 0, function () {
729 var auth, _a;
730 return __generator(this, function (_b) {
731 switch (_b.label) {
732 case 0:
733 if (!(param && param.auth)) return [3 /*break*/, 2];
734 auth = xgot(YAuth);
735 _a = xassert;
736 return [4 /*yield*/, auth.getLoginStatus()];
737 case 1:
738 _a.apply(void 0, [_b.sent(), ERR$UNAUTHORIZED]);
739 _b.label = 2;
740 case 2: return [2 /*return*/];
741 }
742 });
743 }); }
744 };
745 };
746 };
747}
748// 完全没有必要的多余定义,需要通过MOCK定义进行细节数据类型的显性定义处理逻辑验证。
749// // 基本数据类型的规范扩展定义,方便API接口的定义以及形参自动验证合法性,并且与数据库数据类型保持一致。
750// type INT = number // 有符号整数
751// type UINT = number // 无符号整数
752// type DECIMAL = number // 精确小数
753// type FLOAT = number // 单精度浮点数(不精确小数)
754// type DOUBLE = number// 双精度浮点数(不精确小数)
755// type BOOL = boolean
756// type STR = string
757// type DATE = string // 年月日 '2017-06-25'
758// type TIME = string // 时分秒 '00:00:00'
759// type DATETIME = string // 年月日时分秒 '2017-06-25 00:00:00'
760// 模拟数据模板定义使用教程 http://mockjs.com/0.1/#%E6%95%B0%E6%8D%AE%E5%8D%A0%E4%BD%8D%E7%AC%A6%E5%AE%9A%E4%B9%89%20DPD
761function xmock(rules) {
762 return mockjs.mock(rules);
763}
764function xrandom(name, data) {
765 var _a;
766 mockjs.Random.extend((_a = {},
767 _a[name] = function () {
768 var args = [];
769 for (var _i = 0; _i < arguments.length; _i++) {
770 args[_i] = arguments[_i];
771 }
772 xassert(data.length > 0);
773 if (data.length == 1)
774 return data[0];
775 var max = data.length - 1;
776 var idx = xmock("@int(0," + max + ")");
777 return data[idx];
778 },
779 _a));
780}
781// 扩展一些预定义bxjs的基础随机方法或者覆盖一些mockjs中的方法
782mockjs.Random.extend({
783 // bxjs表定义的主键统一定义(约定系统中为字符串7-14字节长度算法)
784 id: function () {
785 var args = [];
786 for (var _i = 0; _i < arguments.length; _i++) {
787 args[_i] = arguments[_i];
788 }
789 return shortid.generate();
790 },
791 // 中国手机号随机生成算法(约定系统中的手机号为字符串数据类型)
792 mobile: function () {
793 var args = [];
794 for (var _i = 0; _i < arguments.length; _i++) {
795 args[_i] = arguments[_i];
796 }
797 var isps = [
798 134, 135, 136, 137, 138, 139, 147, 150, 151, 152, 157, 158, 159, 182, 183, 184, 187, 188, 178,
799 130, 131, 132, 145, 155, 156, 185, 186, 176,
800 133, 134, 153, 180, 181, 189, 177, 173,
801 176, 173, 177, 178, 170,
802 140, 141, 142, 143, 144, 146, 148, 149, 154
803 ];
804 var max = isps.length - 1;
805 var idx = xmock("@int(0," + max + ")");
806 var num = xmock("@int(100000000,199999999)");
807 return (isps[idx] * 100000000 + num % 100000000) + '';
808 },
809 // 转换为缺省中文内容提示
810 paragraph: function () {
811 var args = [];
812 for (var _i = 0; _i < arguments.length; _i++) {
813 args[_i] = arguments[_i];
814 }
815 switch (args.length) {
816 case 0:
817 return xmock('@cparagraph');
818 case 1:
819 return xmock("@cparagraph(" + args[0] + ")");
820 case 2:
821 return xmock("@cparagraph(" + args[0] + "," + args[1] + ")");
822 default:
823 xassert(false);
824 }
825 },
826 sentence: function () {
827 var args = [];
828 for (var _i = 0; _i < arguments.length; _i++) {
829 args[_i] = arguments[_i];
830 }
831 switch (args.length) {
832 case 0:
833 return xmock('@csentence');
834 case 1:
835 return xmock("@csentence(" + args[0] + ")");
836 case 2:
837 return xmock("@csentence(" + args[0] + "," + args[1] + ")");
838 default:
839 xassert(false);
840 }
841 },
842 title: function () {
843 var args = [];
844 for (var _i = 0; _i < arguments.length; _i++) {
845 args[_i] = arguments[_i];
846 }
847 switch (args.length) {
848 case 0:
849 return xmock('@ctitle');
850 case 1:
851 return xmock("@ctitle(" + args[0] + ")");
852 case 2:
853 return xmock("@ctitle(" + args[0] + "," + args[1] + ")");
854 default:
855 xassert(false);
856 }
857 },
858});
859// laravel风格JSON对象验证器封装,详细文档见 https://github.com/skaterdav85/validatorjs
860function xcheck(param, rules, messages) {
861 var obj = new validatorjs(param, rules);
862 if (obj.fails()) {
863 xthrow(ERR$PARAM, obj.errors);
864 }
865}
866// 【IoC容器管理】应用层的插件实现类绑定到BXJS统一注册的标准插件的映射关系在全局容器实例中注册
867function xbind(TYPE) {
868 var o = new TYPE();
869 return xcontainer.bind(o.id).to(require("@app/plugins/" + o.id).default);
870}
871// 【IoC容器管理】框架或应用依赖标准规范接口插件的类实例获取方法
872function xgot(TYPE) {
873 var o = new TYPE();
874 return xcontainer.get(o.id);
875}
876// 同步系统命令调用执行
877function xcmd() {
878 var args = [];
879 for (var _i = 0; _i < arguments.length; _i++) {
880 args[_i] = arguments[_i];
881 }
882 return __awaiter(this, void 0, void 0, function () {
883 var options, cmd, ret, err_4;
884 return __generator(this, function (_a) {
885 switch (_a.label) {
886 case 0:
887 _a.trys.push([0, 1, , 3]);
888 options = {};
889 options.cwd = options.cwd || process.env.__ctxPath || process.cwd();
890 xassert(_.isArray(args) && args.length > 0);
891 cmd = args.shift();
892 ret = cross_spawn.sync(cmd, args, xassign({ stdio: 'inherit' }, options));
893 xassert(ret.status === 0, ERR$UNKNOWN, ret);
894 return [2 /*return*/, ret];
895 case 1:
896 err_4 = _a.sent();
897 return [4 /*yield*/, xwarn(err_4)];
898 case 2:
899 _a.sent();
900 xthrow(err_4);
901 return [3 /*break*/, 3];
902 case 3: return [2 /*return*/];
903 }
904 });
905 });
906}
907// 对于数组嵌套回调函数的nodejs异步处理方法的统一封装
908function xmap(values, callack) {
909 return __awaiter(this, void 0, void 0, function () {
910 return __generator(this, function (_a) {
911 xassert(_.isArray(values) && _.isFunction(callack));
912 return [2 /*return*/, Promise.all(values.map(callack))];
913 });
914 });
915}
916// Refer to document: https://help.aliyun.com/document_detail/62670.html
917// 获取ACM配置信息接口的统一封装
918function xacm(group, id) {
919 return __awaiter(this, void 0, void 0, function () {
920 var cfg, acm;
921 var _this = this;
922 return __generator(this, function (_a) {
923 cfg = xconfig("plugins.acm");
924 xassert(group && cfg && cfg[group], ERR$CONFIG, { cfg: cfg });
925 acm = new ACMClient(cfg[group]);
926 return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
927 return __generator(this, function (_a) {
928 try {
929 co(function () {
930 var content, err_5;
931 return __generator(this, function (_a) {
932 switch (_a.label) {
933 case 0:
934 _a.trys.push([0, 2, , 3]);
935 group = group + ':' + global['__env__']; // 补上环境后缀支持各种开发环境的个性化配置
936 return [4 /*yield*/, acm.getConfig(id, group)];
937 case 1:
938 content = _a.sent();
939 xassert(content, ERR$CONFIG, { id: id, group: group });
940 resolve(content);
941 return [3 /*break*/, 3];
942 case 2:
943 err_5 = _a.sent();
944 xthrow(err_5, reject, { id: id, group: group, cfg: cfg[group] });
945 return [3 /*break*/, 3];
946 case 3: return [2 /*return*/];
947 }
948 });
949 });
950 }
951 catch (err) {
952 xthrow(err, reject, { id: id, group: group, cfg: cfg[group] });
953 }
954 return [2 /*return*/];
955 });
956 }); })];
957 });
958 });
959}
960// 根据当前配置的时区正确获取当前时间值避免线上FC容器默认是格林尼治时间而非北京时间问题
961function xnow(format) {
962 if (format === void 0) { format = 'YYYY-MM-DD HH:mm:ss'; }
963 return moment().utcOffset(8).format(format);
964}
965// base64编码
966function xbase64encode(value) {
967 xassert(!_.isEmpty(value) && _.isString(value));
968 return new Buffer(value).toString('base64');
969}
970// base64解码
971function xbase64decode(value) {
972 xassert(!_.isEmpty(value) && _.isString(value));
973 return new Buffer(value, 'base64').toString();
974}
975// 请求上下文变量自动重置方法(以global变量中key为__下划线开始结束的属性自动清空为undefined,如需赋值其他缺省值需要在此函数中明确定义)
976function xreset() {
977 // 所有请求上下文属性的自动清空初始化处理(通过约定global的特殊属性__xxx__简化koa中的context设计机制,将这部分机制做到框架上对应用不可见)
978 for (var _i = 0, _a = Object.keys(global); _i < _a.length; _i++) {
979 var key = _a[_i];
980 if (key.startsWith('__') && key.endsWith('__')) {
981 global[key] = undefined;
982 }
983 }
984 // 明确定义的一些全局变量的初始值赋值
985 if (!global['__env__']) {
986 global['__env__'] = 'local'; // local,daily,pre,gray,prod 在统一入口处自动识别配置(目前暂不支持gray配置尚未开发无法自动识别)
987 }
988 global['__config__'] = undefined;
989 global['__session__'] = {};
990 global['__cache__'] = {};
991 global['__user__'] = {};
992 global['__user_agent__'] = undefined;
993 global['__client_ip__'] = undefined;
994 global['__redirect_url__'] = undefined;
995 global['__request_cookies__'] = {};
996 global['__respond_cookies__'] = {};
997}
998// 首次模块加载的时候执行一次,确保应用中不可以有__xxx__参数作为全局变量在模块初始化的时候
999xreset();
1000global['xreset'] = xreset;
1001global['xconnect'] = xconnect;
1002global['xnew'] = xnew;
1003global['xquery'] = xquery;
1004global['xcount'] = xcount;
1005global['xassign'] = xassign;
1006global['xconfig'] = xconfig;
1007global['xthrow'] = xthrow;
1008global['xassert'] = xassert;
1009global['xerror'] = xerror;
1010global['xroot'] = xroot;
1011global['xstack'] = xstack;
1012global['xwarn'] = xwarn;
1013global['xlog'] = xlog;
1014global['xpost'] = xpost;
1015global['xget'] = xget;
1016global['xsleep'] = xsleep;
1017global['xredirect'] = xredirect;
1018global['xcookie'] = xcookie;
1019global['xismobile'] = xismobile;
1020global['xsession'] = session_1.xsession;
1021global['xuser'] = session_1.xuser;
1022global['xcache'] = session_1.xcache;
1023global['xroute'] = xroute;
1024global['xmock'] = xmock;
1025global['xrandom'] = xrandom;
1026global['xcheck'] = xcheck;
1027global['xcontainer'] = new inversify_1.Container(); // 全局单实例容器初始化
1028global['xbind'] = xbind;
1029global['xgot'] = xgot;
1030global['YAuth'] = $$.YAuth; // 全局声明认证插件规范抽象类
1031global['xcmd'] = xcmd;
1032global['xmap'] = xmap;
1033global['xacm'] = xacm;
1034global['xbase64encode'] = xbase64encode;
1035global['xbase64decode'] = xbase64decode;
1036global['xnow'] = xnow;
1037//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxpQkE0eUJBOztBQTV5QkEsT0FBTyxDQUFDLEdBQUcsQ0FBQyw0QkFBNEIsR0FBRyxHQUFHLENBQUE7QUFDOUMsNEJBQXlCO0FBQ3pCLHVDQUFtQztBQUNuQyx5Q0FBNkc7QUFDN0cscUNBQWlEO0FBQ2pELDhCQUErQjtBQUUvQixJQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7QUFDNUIsSUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtBQUN0RCxJQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7QUFDaEMsSUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFBO0FBQzdDLElBQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQUNuQyxJQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7QUFDM0IsSUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQ2hDLElBQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUNoQyxJQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUE7QUFDMUMseUNBQXlDO0FBQ3pDLGlEQUFpRDtBQUNqRCxrQ0FBa0M7QUFDbEMsK0RBQStEO0FBQy9ELHNFQUFzRTtBQUN0RSw4Q0FBOEM7QUFDOUMsV0FBVztBQUNYLEtBQUs7QUFDTCxJQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUE7QUFDOUMsSUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQ2hDLElBQU0sT0FBTyxHQUFHLE9BQU8sQ0FB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QU0sQ0FBQyxHQUFHLElBQUksQ0FBQTtBQUNyQixNQUFNLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQSxDQUFDLGdCQUFnQjtBQUMzQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFBO0FBQ3JCLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUE7QUFDckIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQTtBQUNyQixNQUFNLENBQUMsZUFBZSxDQUFDLEdBQUcsYUFBYSxDQUFBO0FBQ3ZDLE1BQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxhQUFhLENBQUE7QUFDdkMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbInByb2Nlc3MuZW52Lk5PREVfVExTX1JFSkVDVF9VTkFVVEhPUklaRUQgPSAnMCdcbmltcG9ydCAncmVmbGVjdC1tZXRhZGF0YSdcbmltcG9ydCB7Q29udGFpbmVyfSBmcm9tICdpbnZlcnNpZnknXG5pbXBvcnQge2dldENvbm5lY3Rpb25NYW5hZ2VyLCBDb25uZWN0aW9uLCBCYXNlRW50aXR5LCBnZXRSZXBvc2l0b3J5LCBTZWxlY3RRdWVyeUJ1aWxkZXJ9IGZyb20gJ0BieGpzL3R5cGVvcm0nXG5pbXBvcnQge3hzZXNzaW9uLCB4dXNlciwgeGNhY2hlfSBmcm9tICcuL3Nlc3Npb24nXG5pbXBvcnQgKiBhcyAkJCBmcm9tICcuL3BsdWdpbnMnXG5cbmNvbnN0IHBhdGggPSByZXF1aXJlKCdwYXRoJylcbmNvbnN0IEVycm9yU3RhY2tQYXJzZXIgPSByZXF1aXJlKCdlcnJvci1zdGFjay1wYXJzZXInKVxuY29uc3QgY29va2llID0gcmVxdWlyZSgnY29va2llJylcbmNvbnN0IE1vYmlsZURldGVjdCA9IHJlcXVpcmUoJ21vYmlsZS1kZXRlY3QnKVxuY29uc3QgZmV0Y2ggPSByZXF1aXJlKCdub2RlLWZldGNoJylcbmNvbnN0IF8gPSByZXF1aXJlKCdsb2Rhc2gnKVxuY29uc3QgbW9tZW50ID0gcmVxdWlyZSgnbW9tZW50JylcbmNvbnN0IGV4dGVuZCA9IHJlcXVpcmUoJ2V4dGVuZCcpXG5jb25zdCBxdWVyeXN0cmluZyA9IHJlcXVpcmUoJ3F1ZXJ5c3RyaW5nJylcbi8vIGNvbnN0IHBhcmFtZXRlciA9IHJlcXVpcmUoJ3BhcmFtZXRlcicpXG4vLyBjb25zdCBwYXJhbWV0ZXJDaGVja0luc3RhbmNlID0gbmV3IHBhcmFtZXRlcih7XG4vLyAgICAgLy8gdHJhbnNsYXRlOiBmdW5jdGlvbiAoKSB7XG4vLyAgICAgLy8gICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbi8vICAgICAvLyAgICAgLy8gQXNzdW1lIHRoZXJlIGhhdmUgSTE4bi50IG1ldGhvZCBmb3IgY29udmVydCBsYW5ndWFnZS5cbi8vICAgICAvLyAgICAgcmV0dXJuIEkxOG4udC5hcHBseShJMThuLCBhcmdzKTtcbi8vICAgICAvLyB9XG4vLyB9KVxuY29uc3QgY2lyY3VsYXJfanNvbiA9IHJlcXVpcmUoXCJjaXJjdWxhci1qc29uXCIpXG5jb25zdCBtb2NranMgPSByZXF1aXJlKCdtb2NranMnKVxuY29uc3Qgc2hvcnRpZCA9IHJlcXVpcmUoJ3Nob3J0aWQnKVxuY29uc3QgdmFsaWRhdG9yanMgPSByZXF1aXJlKCd2YWxpZGF0b3JqcycpXG5jb25zdCBjcm9zc19zcGF3biA9IHJlcXVpcmUoJ2Nyb3NzLXNwYXduJylcbmNvbnN0IEFDTUNsaWVudCA9IHJlcXVpcmUoJ2FjbS1jbGllbnQnKVxuY29uc3QgY28gPSByZXF1aXJlKCdjbycpXG5cbi8vIEZJWE1FIEhBQ0vljp/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+S4reW8guW4uOS8oOmAklxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoSlNPTi5zdHJpbmdpZnkoZGF0YSkpXG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24geGFzc2VydChleHByOiBhbnksIGNvZGU6IHN0cmluZyA9IEVSUiRBU1NFUlQsIHBhcmFtPzogYW55KSB7XG4gICAgbGV0IHNvdXJjZSA9IF9fZ2V0X2Jhc2VfZnVuY19jYWxsZXJfc291cmNlX3Bvc2l0aW9uKClcbiAgICBsZXQgc3RhY2sgPSBbc291cmNlXVxuICAgIGlmICghZXhwcikgdGhyb3cgbmV3IEVycm9yKEpTT04uc3RyaW5naWZ5KHtjb2RlLCBtc2c6IGdsb2JhbFsnRVJST1JTJ11bY29kZV1bJ3poJ10sIHBhcmFtLCBzdGFja30pKVxuICAgIHJldHVybiBleHByXG59XG5cbi8vIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9ub2RlLW1vZHVsZXMvcGFyYW1ldGVyIOWPguaVsOmqjOivgeinhOWImeivpuingeatpOaWh+aho++8iGVnZ+WboumYn+W8gOWPkeeahOe7hOS7tu+8iVxuLy8gLy8g5rOo5oSP5LqL6aG577yaR0VU6YCa6L+HVVJM5Lyg6YCS55qE5Y+C5pWw6YO95piv5a2X56ym5Liy57G75Z6L5bqU6K+l5bC96YeP6YG/5YWNR0VU5Lyg6YCS5Y+C5pWw77yM6ZyA6KaB5aSa55SoUE9TVOeahEpTT07moLzlvI/kvKDpgJLlj4LmlbDlubbkuJRQT1NUTUFO5LiK6L+b6KGM6L6F5Yqp5rWL6K+V5q2j56Gu5pWw5o2u57G75Z6L5pig5bCE44CCXG4vLyBleHBvcnQgZnVuY3Rpb24geGNoZWNrKHBhcmFtOiB7IFtwcm9wTmFtZTogc3RyaW5nXTogYW55IH0sIHJ1bGVzOiB7IFtwcm9wTmFtZTogc3RyaW5nXTogYW55IH0pIHtcbi8vICAgICBsZXQgZXJyb3JzID0gcGFyYW1ldGVyQ2hlY2tJbnN0YW5jZS52YWxpZGF0ZShydWxlcywgcGFyYW0pXG4vLyAgICAgaWYgKF8uaXNFbXB0eShlcnJvcnMpKSB7XG4vLyAgICAgICAgIHJldHVybiB0cnVlXG4vLyAgICAgfSBlbHNlIHtcbi8vICAgICAgICAgeHRocm93KEVSUiRQQVJBTSwgZXJyb3JzKVxuLy8gICAgIH1cbi8vIH1cblxuZXhwb3J0IGZ1bmN0aW9uIHhsb2coLi4uYXJncykge1xuICAgIC8vIOWFvOWuueS6keerr+S7peWPiuacrOWcsOaXpeW/l+iwg+ivle+8iOino+WGs+S7u+aEj+WvueixoeeahEpTT07lrZfnrKbkuLLlhoXlrrnnmoTlrozmlbTovpPlh7rvvIlcbiAgICBsZXQgc291cmNlID0gX19nZXRfYmFzZV9mdW5jX2NhbGxlcl9zb3VyY2VfcG9zaXRpb24oKSArICdbJyArIHhub3coJ1lZWVktTU0tREQgSEg6bW06c3MuU1NTJykgKyAnXSdcbiAgICBsZXQgb3V0cHV0ID0gY2lyY3VsYXJfanNvbi5zdHJpbmdpZnkoWy4uLmFyZ3NdLCBudWxsLCA0KVxuICAgIGlmIChnbG9iYWxbJ19fZW52X18nXSAhPSAncHJvZCcgJiYgIS9eXFwvY29kZVxcL25vZGVfbW9kdWxlcy8udGVzdChfX2Rpcm5hbWUpKSB7XG4gICAgICAgIC8vIOaJk+WNsOWIsOaOp+WItuWPsOS4gOS7veaXpeW/lyjlnKjpmL/ph4zkupHpnZ7nur/kuIpGQ+eOr+Wig+S4rSlcbiAgICAgICAgY29uc29sZS5sb2cuYXBwbHkodW5kZWZpbmVkLCBbc291cmNlICsgb3V0cHV0XSlcbiAgICAgICAgLy8g5YaZ5pel5b+X5paH5Lu25YiwL3RtcOS4i+S4tOaXtuWkhOeQhuS4gOS4iyBUT0RPIOmcgOimgeaUueS4uuexu+S8vGxvZzRq55qE5pys5Zyw5pel5b+X5bqT5LuF5Zyo6Z2e57q/5LiK546v5aKD5L2/55So5pa55L6/5byA5Y+R5Y2V5py65pel5bi45py65Zmo5LiK6LCD6K+V44CCXG4gICAgICAgIGNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKVxuICAgICAgICBjb25zdCBsb2dGaWxlUGF0aCA9IHByb2Nlc3MuZW52WydOT0RFX0xPR0ZJTEUnXSA/IHByb2Nlc3MuZW52WydOT0RFX0xPR0ZJTEUnXSA6ICcvdG1wL2J4anMubG9nJ1xuICAgICAgICBmcy5hcHBlbmRGaWxlU3luYyhsb2dGaWxlUGF0aCwgc291cmNlICsgb3V0cHV0ICsgXCJcXHJcXG5cIilcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyDnlJ/kuqfnjq/looPkuIvlj6rmiZPljbDliLDmjqfliLblj7Dnu5HlrprnmoRTTFPml6Xlv5fmnI3liqHlmajkuIrvvIzlubbkuJTpnIDopoHljrvpmaTmjonmjaLooYzkv6Hmga/lkKbliJnmiZPljbDkvJrkuI3mraPluLjjgIJcbiAgICAgICAgLy8g5Y676Zmk5o6J5o2i6KGM5pa55L6/5pa55L6/U0xT5LiK55qE5pel5b+X6L6T5Ye65o6S54mI5pi+56S6XG4gICAgICAgIG91dHB1dCA9IG91dHB1dC5yZXBsYWNlKC9cXHIvZywgJycpLnJlcGxhY2UoL1xcbi9nLCAnJylcbiAgICAgICAgY29uc29sZS5sb2cuYXBwbHkodW5kZWZpbmVkLCBbc291cmNlICsgb3V0cHV0XSlcbiAgICB9XG59XG5cbi8vIC8vIOWwhuivpue7humUmeivr+S/oeaBr+WPiuaXtuWPkemAgeWIsOmSiemSiee+pOS4iuWunuaXtuWPjemmiOe7mee7tOaKpOiAhVxuLy8gYXdhaXQgeHdhcm4oe1xuLy8gICAgIGNvZGUsXG4vLyAgICAgLy8gVE9ETyDlpoLkvZXorqTor4HpgJrov4fkuobojrflj5bliLDnlKjmiLfkv6Hmga/kuZ/pnIDopoHlj5HpgIHov4fljrvvvIzmlrnkvr/ogZTns7vlr7nmjqXkurrlkZjov5vooYznq4vliLvpl67popjlpITnkIblj43ppojjgIJcbi8vICAgICBtZXNzYWdlLFxuLy8gICAgIHN0YWNrLFxuLy8gICAgIHBhcmFtLFxuLy8gfSlcbi8vIOWwhuivpue7humUmeivr+S/oeaBr+WPiuaXtuWPkemAgeWIsOmSiemSiee+pOS4iuWunuaXtuWPjemmiOe7mee7tOaKpOiAhVxuLy8g6ZKJ6ZKJSU3nvqTmnLrlmajkurrmiqXorabpgJrnn6VcbmFzeW5jIGZ1bmN0aW9uIHh3YXJuKC4uLmFyZ3MpIHtcbiAgICAvLyDlvpfliLB4d2FybuaWueazleiiq+iwg+eUqOeahOS9jee9rlxuICAgIGxldCBzb3VyY2UgPSBfX2dldF9iYXNlX2Z1bmNfY2FsbGVyX3NvdXJjZV9wb3NpdGlvbigpXG5cbiAgICAvLyDlr7nkuo7lvILluLjlj4LmlbDorablkYrkv6Hmga/ov5vooYzplJnor6/lhoXlrrnmoIflh4bop6PmnpBcbiAgICBpZiAoYXJncy5sZW5ndGggPiAwICYmIGFyZ3NbMF0gaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgICBhcmdzWzBdID0geGVycm9yKGFyZ3NbMF0pXG4gICAgfVxuXG4gICAgbGV0IG91dCA9IFtzb3VyY2UsIHhub3coJ1lZWVktTU0tREQgSEg6bW06c3MuU1NTJyksIHsuLi5hcmdzfV1cblxuICAgIC8vIOS7jumFjee9ruS/oeaBr+S4reivu+WPluaKpeitpumAmuefpeS6uuaJi+acuuWIl+ihqOWSjOWvueW6lOeahOe+pOacuuWZqOS6uueahHdlYmhvb2vnmoRhY2Nlc3NfdG9rZW7kv6Hmga9cbiAgICBsZXQgYWNjZXNzX3Rva2VuID0geGNvbmZpZygnZnJhbWV3b3JrLndhcm4uZGluZ2RpbmcuYWNjZXNzX3Rva2VuJylcbiAgICBsZXQgbW9iaWxlcyA9IHhjb25maWcoJ2ZyYW1ld29yay53YXJuLmRpbmdkaW5nLm1vYmlsZXMnKVxuICAgIGlmICghYWNjZXNzX3Rva2VuIHx8ICFtb2JpbGVzKSB7XG4gICAgICAgIGFjY2Vzc190b2tlbiA9ICcwMjBhMDllYWM1ZjJmYTMyMGFlODUxNDQyZDVlMTllMjM2OTNjNjRhZDIyNTVjODUzNTRiNGE0OWE1YTQ4ZDM1J1xuICAgICAgICBtb2JpbGVzID0gWycxNTM4MTE1MTM0NiddXG4gICAgfVxuXG4gICAgYXdhaXQgeHBvc3QoYGh0dHBzOi8vb2FwaS5kaW5ndGFsay5jb20vcm9ib3Qvc2VuZD9hY2Nlc3NfdG9rZW49JHthY2Nlc3NfdG9rZW59YCwge1xuICAgICAgICBtc2d0eXBlOiAndGV4dCcsXG4gICAgICAgIHRleHQ6IHtcbiAgICAgICAgICAgIGNvbnRlbnQ6IG91dFxuICAgICAgICB9LFxuICAgICAgICBhdDoge1xuICAgICAgICAgICAgYXRNb2JpbGVzOiBtb2JpbGVzLFxuICAgICAgICAgICAgaXNBdEFsbDogZmFsc2VcbiAgICAgICAgfVxuICAgIH0pXG5cbiAgICAvLyDnur/kuIpTTFPml6Xlv5fkuIrkuZ/kv53lrZjkuIDku71cbiAgICAvLyBjb25zb2xlLndhcm4ob3V0KVxuICAgIHhsb2cob3V0KVxufVxuXG4vLyDmjZXojrfmnKrnm5HlkKzliLDnmoTlvILluLjorrDlvZXlkI7nm7TmjqXpgIDlh7rvvIjov5DooYzloIbmoIjlt7Lnu4/noLTlnY/nm7TmjqXorrDlvZXml6Xlv5flkI7lvILluLjpgIDlh7rljbPlj6/vvIznlLHlpJbpg6jnm5Hmjqfoh6rliqjph43lkK/vvIlcbnByb2Nlc3Mub24oJ3VuY2F1Z2h0RXhjZXB0aW9uJywgYXN5bmMgZnVuY3Rpb24gKGVycikge1xuICAgIHhsb2coeGVycm9yKGVycikpXG4gICAgYXdhaXQgeHdhcm4oZXJyKVxuICAgIHByb2Nlc3MuZXhpdCgtMSlcbn0pXG5cbi8vIOiusOW9lWF3YWl0L2FzeW5j5Lit5Ye6546w5pyq5o2V6I6355qE5byC5bi46ZSZ6K+vXG5wcm9jZXNzLm9uKCd1bmhhbmRsZWRSZWplY3Rpb24nLCBhc3luYyAocmVhc29uLCBwKSA9PiB7XG4gICAgeGxvZygnVW5oYW5kbGVkIFJlamVjdGlvbiBhdDogUHJvbWlzZScsIHAsICdyZWFzb246JywgcmVhc29uKTtcbiAgICAvLyBhcHBsaWNhdGlvbiBzcGVjaWZpYyBsb2dnaW5nLCB0aHJvd2luZyBhbiBlcnJvciwgb3Igb3RoZXIgbG9naWMgaGVyZVxuICAgIGF3YWl0IHh3YXJuKHJlYXNvbiwgcClcbiAgICBwcm9jZXNzLmV4aXQoLTEpXG59KVxuXG4vLyBhc3luYy9hd2FpdOeahOmdnumYu+WhnuW8guatpeW7tui/n+aWueazle+8jOeUqOS6juiwg+ivlemYu+Whnueoi+W6j+eahOaJp+ihjOi/m+ihjOWNleatpeiwg+ivleeahOaViOaenOOAglxuY29uc3Qgc2xlZXAgPSByZXF1aXJlKCdzbGVlcC1hc3luYycpKClcblxuZXhwb3J0IGZ1bmN0aW9uIHhzbGVlcChtczogbnVtYmVyID0gLTEpIHtcbiAgICBpZiAobXMgPD0gMCkge1xuICAgICAgICBtcyA9IDUwICogMzY1ICogMjQgKiAzNjAwICogMTAwMCAvLyA1MOW5tOacgOWkp+aVsOinhuS4uuawuOS5hemYu+WhnuaWueS+v+aWreeCueWNleatpeiwg+ivlemXrumimFxuICAgIH1cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgc2xlZXAuc2xlZXAobXMsICgpID0+IHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKClcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgeGxvZyh4ZXJyb3IoZXJyKSlcbiAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICAgICAgLy8geHRocm93KGVycixyZWplY3QpXG4gICAgICAgIH1cbiAgICB9KVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24geHBvc3QodXJsOiBzdHJpbmcsIHBhcmFtPzogeyBbcHJvcE5hbWU6IHN0cmluZ106IGFueSB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlcnM/OiB7IFtwcm9wTmFtZTogc3RyaW5nXTogYW55IH0sIHRpbWVvdXQ6IG51bWJlciA9IDMwMDApIHtcbiAgICAvLyBUT0RPIOe6v+S4iua1i+ivleS4jeeos+Wumui2heaXtuaaguaXtuW/veeVpeaOiemAmui/h+i/m+eoi+acgOWkp+i/kOihjOaXtumXtOWOu+aOp+WItui2heaXtuWksei0pVxuICAgIHRpbWVvdXQgPSA1MDAwIC8vIC0xIOS4jeihjOe6v+S4iuS8muiiq+mYu+WhnuS9j+WDteatu1xuICAgIGxldCByZXM6IGFueSA9IG51bGxcbiAgICBsZXQganNvbjogYW55ID0gbnVsbFxuICAgIGxldCB0ZXh0OiBhbnkgPSBudWxsXG4gICAgdHJ5IHtcbiAgICAgICAgcmVzID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgICAgICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHBhcmFtKSxcbiAgICAgICAgICAgIGhlYWRlcnM6IHsnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLCAuLi5oZWFkZXJzfSxcbiAgICAgICAgICAgIHRpbWVvdXQ6IHRpbWVvdXQgPD0gMCA/IDAgOiB0aW1lb3V0LCAvLyDpu5jorqQz56eS6LaF5pe25o6l5Y+j6L+U5Zue6YG/5YWN5YO15q27XG4gICAgICAgIH0pXG4gICAgICAgIHRleHQgPSBhd2FpdCByZXMudGV4dCgpIC8vIOino+aekOWHuuWujOaVtOeahOi/lOWbnuWGheWuuemBv+WFjUhUTUzku6Xlj4rpnZ7ms5XmoLzlvI/kv6Hmga/kvr/kuo7mraPnoa7miqXplJnlrprkvY3lkI7nq6/mjqXlj6PplJnor69cbiAgICAgICAganNvbiA9IEpTT04ucGFyc2UodGV4dClcbiAgICAgICAgcmV0dXJuIGpzb25cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgeHRocm93KGVyciwge3VybCwgcGFyYW0sIGhlYWRlcnMsIHRleHR9KVxuICAgIH1cbn1cblxuLy8g6buY6K6k6LaF5pe2MzAwMOavq+enklxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHhnZXQodXJsOiBzdHJpbmcsIHBhcmFtPzogeyBbcHJvcE5hbWU6IHN0cmluZ106IGFueSB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVycz86IHsgW3Byb3BOYW1lOiBzdHJpbmddOiBhbnkgfSwgdGltZW91dDogbnVtYmVyID0gMzAwMCkge1xuICAgIC8vIFRPRE8g57q/5LiK5rWL6K+V5LiN56iz5a6a6LaF5pe25pqC5pe25b+955Wl5o6J6YCa6L+H6L+b56iL5pyA5aSn6L+Q6KGM5pe26Ze05Y675o6n5Yi26LaF5pe25aSx6LSlXG4gICAgdGltZW91dCA9IDUwMDAgLy8gLTEg5LiN6KGM57q/5LiK5Lya6KKr6Zi75aGe5L2P5YO15q27XG4gICAgbGV0IHJlczogYW55ID0gbnVsbFxuICAgIGxldCBqc29uOiBhbnkgPSBudWxsXG4gICAgbGV0IHRleHQ6IGFueSA9IG51bGxcbiAgICB0cnkge1xuICAgICAgICB1cmwgPSB1cmwgKyAocGFyYW0gPyAnPycgOiAnJykgKyBxdWVyeXN0cmluZy5zdHJpbmdpZnkocGFyYW0pXG4gICAgICAgIHJlcyA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgICAgICAgICAgbWV0aG9kOiAnR0VUJyxcbiAgICAgICAgICAgIGhlYWRlcnM6IHsnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLCAuLi5oZWFkZXJzfSxcbiAgICAgICAgICAgIHRpbWVvdXQ6IHRpbWVvdXQgPD0gMCA/IDAgOiB0aW1lb3V0LCAvLyDpu5jorqQz56eS6LaF5pe25o6l5Y+j6L+U5Zue6YG/5YWN5YO15q27XG4gICAgICAgIH0pXG4gICAgICAgIHRleHQgPSBhd2FpdCByZXMudGV4dCgpIC8vIOino+aekOWHuuWujOaVtOeahOi/lOWbnuWGheWuuemBv+WFjUhUTUzku6Xlj4rpnZ7ms5XmoLzlvI/kv6Hmga/kvr/kuo7mraPnoa7miqXplJnlrprkvY3lkI7nq6/mjqXlj6PplJnor69cbiAgICAgICAganNvbiA9IEpTT04ucGFyc2UodGV4dClcbiAgICAgICAgcmV0dXJuIGpzb25cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgeHRocm93KGVyciwge3VybCwgcGFyYW0sIGhlYWRlcnMsIHRleHR9KVxuICAgIH1cbn1cblxuLy8gMzAy5Li05pe26YeN5a6a5ZCR6Lez6L2s5a6e546wXG5leHBvcnQgZnVuY3Rpb24geHJlZGlyZWN0KHVybDogc3RyaW5nLCBwYXJhbTogYW55ID0ge30pIHtcbiAgICAvLyBUT0RPIOWkmuS4queoi+W6j+WunuS+i+W5tuWPkeWkhOeQhueahOaXtuWAmeWtmOWcqOaXtuW6j+mXrumimOS4jeiDveS/neivgeWFqOWxgOWPmOmHj+iiq+WHhuehrua4heepuuOAglxuICAgIC8vIOajgOafpeW6lOeUqOmHjeWkjeiuvue9rumHjeWumuWQkeWcsOWdgOacquWPiuaXtnJldHVybui/lOWbnuaOp+WItuWZqOmXrumimFxuICAgIHhhc3NlcnQoZ2xvYmFsWydfX3JlZGlyZWN0X3VybF9fJ10gPT09IHVuZGVmaW5lZClcbiAgICBpZiAocGFyYW0pIHtcbiAgICAgICAgeGFzc2VydChfLmlzUGxhaW5PYmplY3QocGFyYW0pKVxuICAgICAgICAvLyDliKDpmaRwYXJhbeS4reS4pOS4quahhuaetumihOWumuS5ieWPguaVsF9fdXJsX1/lkoxfX2FwaV9f5LiN5YWB6K646L+b6KGM5Y+C5pWw5Lyg6YCS77yI56aB5q2i5Lia5Yqh6YC76L6R5L2/55So6YG/5YWN5qGG5p625ZCO57ut5Y2H57qn5Lul5Y+K5LiO55+t572R5Z2A5Yqf6IO95Yay56qB77yJXG4gICAgICAgIGRlbGV0ZSBwYXJhbS5fX2FwaV9fXG4gICAgICAgIGRlbGV0ZSBwYXJhbS5fX3VybF9fXG4gICAgICAgIC8vIOihpemineWklueahOmZhOWKoOWPguaVsFxuICAgICAgICBpZiAoL1xcPy8udGVzdCh1cmwpKSB7XG4gICAgICAgICAgICB1cmwgKz0gJyYnXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1cmwgKz0gJz8nXG4gICAgICAgIH1cbiAgICAgICAgdXJsICs9IHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeShwYXJhbSlcbiAgICB9XG4gICAgZ2xvYmFsWydfX3JlZGlyZWN0X3VybF9fJ10gPSB1cmxcbn1cblxuLy8g5aaC5p6c5Y+q5pyJa2V55Y+C5pWw6KGo56S66K+75Y+W5bGe5oCn77yI57y655yB5YC85Li6dW5kZWZpbmVk77yJ77yM5aaC5p6ca2V55Li656m66KGo56S66K+75Y+W5omA5pyJ55qE6K+35rGCY29va2llc+WxnuaAp++8jOWQpuWImeihqOekuuWTjeW6lOiuvue9rmNvb2tpZXNcbmV4cG9ydCBmdW5jdGlvbiB4Y29va2llKGtleT86IHN0cmluZywgdmFsdWU/OiBzdHJpbmcsIG9wdGlvbj86IHt9KTogYW55IHtcbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgLy8g6K+75Y+W5omA5pyJ55qE6K+35rGCY29va2llc+WxnuaAp29iamVjdFxuICAgICAgICByZXR1cm4gZ2xvYmFsWydfX3JlcXVlc3RfY29va2llc19fJ10gPyBnbG9iYWxbJ19fcmVxdWVzdF9jb29raWVzX18nXSA6IHt9XG4gICAgfSBlbHNlIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDEpIHtcbiAgICAgICAgcmV0dXJuIGtleSA/IHhjb29raWUoKVtrZXldIDogdW5kZWZpbmVkXG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGdsb2JhbFsnX19yZXNwb25kX2Nvb2tpZXNfXyddID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGdsb2JhbFsnX19yZXNwb25kX2Nvb2tpZXNfXyddID0ge31cbiAgICAgICAgfVxuICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICAvLyBDT09LSUVT57y655yB5bGe5oCn6K6+572u77yI5pyJ5pWI5pe26Ze0MjTlsI/ml7blubbkuJTnu5/kuIDlhbPogZTliLDmoLnpobXpnaLkuIrojrflj5ZDT09LSUVT5YC877yJXG4gICAgICAgICAgICBvcHRpb24gPSB4YXNzaWduKHtwYXRoOiAnLycsIG1heEFnZTogMjQgKiAzNjAwfSwgb3B0aW9uKVxuICAgICAgICAgICAgZ2xvYmFsWydfX3Jlc3BvbmRfY29va2llc19fJ11ba2V5XSA9IGNvb2tpZS5zZXJpYWxpemUoa2V5LCB2YWx1ZSwgb3B0aW9uKVxuICAgICAgICB9XG4gICAgICAgIHJldHVyblxuICAgIH1cbn1cblxuLy8g5Yik5patdXNlci1hZ2VudOivt+axguaYr+WQpuS4uuenu+WKqOerr1xuZnVuY3Rpb24geGlzbW9iaWxlKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG1kID0gbmV3IE1vYmlsZURldGVjdChnbG9iYWxbJ19fdXNlcl9hZ2VudF9fJ10pXG4gICAgcmV0dXJuICEhbWQubW9iaWxlKClcbn1cblxuZnVuY3Rpb24geGFzc2lnbih0YXJnZXQsIHNvdXJjZSwgLi4uYXJncykge1xuICAgIGNvbnN0IHBhcmFtID0gW3RydWUsIHRhcmdldCwgc291cmNlLCAuLi5hcmdzXVxuICAgIHJldHVybiBleHRlbmQuYXBwbHkobnVsbCwgcGFyYW0pXG59XG5cbi8vIOafpeivomFwcC9jb25maWfnm67lvZXkuIvnmoTlupTnlKjphY3nva7mlbDmja5cbmZ1bmN0aW9uIHhjb25maWcocGF0aDogc3RyaW5nLCBkZWZhdWx0VmFsdWU6IGFueSA9IHVuZGVmaW5lZCkge1xuICAgIGlmIChnbG9iYWxbJ19fY29uZmlnX18nXSkge1xuICAgICAgICByZXR1cm4gXy5nZXQoZ2xvYmFsWydfX2NvbmZpZ19fJ10sIHBhdGgsIGRlZmF1bHRWYWx1ZSlcbiAgICB9XG5cbiAgICBjb25zdCBmcCA9IHJlcXVpcmUoJ3BhdGgnKVxuICAgIGNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKVxuICAgIC8vIOiHquWKqOiOt+WPlmFwcC9jb25maWfnmoTnm7jlr7not6/lvoTnm67lvZXkvY3nva7lvpfliLDmoLnot6/lvoTnmoTkvY3nva5cbiAgICBsZXQgY29uZmlnX3BhdGggPSAnJ1xuICAgIGlmIChfX2Rpcm5hbWUuaW5jbHVkZXMoJy9ub2RlX21vZHVsZXMvQGJ4anMvYmFzZS8nKSkge1xuICAgICAgICAvLyDlnKjlupTnlKjnm67lvZXkuItcbiAgICAgICAgY29uZmlnX3BhdGggPSBmcC5qb2luKF9fZGlybmFtZSwgJy4uLy4uLy4uLy4uL2FwcC9jb25maWcnKVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIOWcqGF4anPlupPlvIDlj5Hnm67lvZXkuItcbiAgICAgICAgY29uZmlnX3BhdGggPSBmcC5qb2luKF9fZGlybmFtZSwgJy4uL2FwcC9jb25maWcnKVxuICAgIH1cblxuICAgIC8vIOiHquWKqOivhuWIq+WIpOaWrei/kOihjOeOr+Wig2dsb2JhbFsnX19lbnZfXydd5bm25LiU5Yqg6L295a+55bqU55qEYmFzZeaVsOaNruWSjGVuduaVsOaNrlxuICAgIGNvbnN0IGNvbmZpZ19iYXNlX3BhdGggPSBjb25maWdfcGF0aCArICcvY29uZmlnLmJhc2UuJyArIGdldF9zdWZmaXhfdHNfb3JfanMoKVxuICAgIGNvbnN0IGNvbmZpZ19lbnZfcGF0aCA9IGNvbmZpZ19wYXRoICsgYC9jb25maWcuJHtnbG9iYWxbJ19fZW52X18nXX0uYCArIGdldF9zdWZmaXhfdHNfb3JfanMoKVxuICAgIGlmICghZnMuZXhpc3RzU3luYyhjb25maWdfYmFzZV9wYXRoKSkge1xuICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlXG4gICAgfVxuICAgIGxldCBjb25maWdfYmFzZSA9IHJlcXVpcmUoY29uZmlnX2Jhc2VfcGF0aCkuZGVmYXVsdFxuICAgIGxldCBjb25maWdfZW52ID0ge31cbiAgICBpZiAoZnMuZXhpc3RzU3luYyhjb25maWdfZW52X3BhdGgpKSB7XG4gICAgICAgIGNvbmZpZ19lbnYgPSByZXF1aXJlKGNvbmZpZ19lbnZfcGF0aCkuZGVmYXVsdFxuICAgIH1cbiAgICAvLyBidWdmaXggT2JqZWN0LmFzc2lnbuS4jeaUr+aMgea3seW6puaLt+i0nemXrumimFxuICAgIC8vIGdsb2JhbFsnX19jb25maWdfXyddID0gT2JqZWN0LmFzc2lnbih7fSwgY29uZmlnX2Jhc2UsIGNvbmZpZ19lbnYpXG4gICAgLy8gZ2xvYmFsWydfX2NvbmZpZ19fJ10gPSBfLmFzc2lnbih7fSwgY29uZmlnX2VudiwgY29uZmlnX2Jhc2UpXG4gICAgZ2xvYmFsWydfX2NvbmZpZ19fJ10gPSB4YXNzaWduKHt9LCBjb25maWdfYmFzZSwgY29uZmlnX2VudilcbiAgICByZXR1cm4gXy5nZXQoZ2xvYmFsWydfX2NvbmZpZ19fJ10sIHBhdGgsIGRlZmF1bHRWYWx1ZSlcbn1cblxuYXN5bmMgZnVuY3Rpb24geGNvbm5lY3QoY2FsbGJhY2s6IChjb25uZWN0OiBDb25uZWN0aW9uKSA9PiBQcm9taXNlPGFueT4sIGNvbmZpZyA9ICdkZWZhdWx0Jykge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGxldCBjZmcgPSB7fSBhcyBhbnlcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNmZyA9IHhhc3NpZ24oe30sIHhjb25maWcoJ3BsdWdpbnMuZGF0YWJhc2UuZGVmYXVsdCcsIHt9KSlcbiAgICAgICAgICAgIHhhc3NlcnQoIV8uaXNFbXB0eShjZmcpLCBFUlIkUEFSQU0sIHtjb25maWd9KVxuICAgICAgICAgICAgLy8g5by65Yi26KGl5LiK57qm5a6a55qE5a6e5L2T5a2Y5pS+6Lev5b6E5a6a5LmJ5L2N572u77yI5LiN5YWB6K646YWN572u5piv57qm5a6a6KeE6IyD77yJXG4gICAgICAgICAgICBpZiAoX19kaXJuYW1lLmluY2x1ZGVzKCcvbm9kZV9tb2R1bGVzL0BieGpzL2Jhc2UvJykpIHtcbiAgICAgICAgICAgICAgICAvLyDlnKjlupTnlKjnm67lvZXkuItcbiAgICAgICAgICAgICAgICBjZmdbJ2VudGl0aWVzJ10gPSBbXG4gICAgICAgICAgICAgICAgICAgIHBhdGguam9pbihfX2Rpcm5hbWUsICcuLi8uLi8uLi8uLi9hcHAvcGx1Z2lucy9kYXRhYmFzZS9lbnRpdHkvKi4nICsgZ2V0X3N1ZmZpeF90c19vcl9qcygpKVxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8g5ZyoYXhqc+W6k+W8gOWPkeebruW9leS4i1xuICAgICAgICAgICAgICAgIGNmZ1snZW50aXRpZXMnXSA9IFtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uL2FwcC9wbHVnaW5zL2RhdGFiYXNlL2VudGl0eS8qLicgKyBnZXRfc3VmZml4X3RzX29yX2pzKCkpXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8g6I635Y+W6L+e5o6l5rGg5Lit55qE6ZO+5o6lKOWFqOWxgOWPmOmHj+aooeWdl+WunuS+i+eahOS9v+eUqClcbiAgICAgICAgICAgIGNvbnN0IG1uZyA9IGdldENvbm5lY3Rpb25NYW5hZ2VyKClcbiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBjZmcubmFtZSA/IGNmZy5uYW1lIDogJ2RlZmF1bHQnXG4gICAgICAgICAgICBpZiAoIW1uZy5oYXMobmFtZSkpIHtcbiAgICAgICAgICAgICAgICBtbmcuY3JlYXRlKGNmZylcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGRiID0gbW5nLmdldChuYW1lKVxuICAgICAgICAgICAgaWYgKGdsb2JhbFsnZ19jb25uZWN0aW9uJ10gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGdsb2JhbFsnZ19jb25uZWN0aW9uJ10gPSB7fVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFkYi5pc0Nvbm5lY3RlZCkgeyAvLyBUT0RPIOmcgOimgei/m+ihjOi/nuaOpeaxoOeahOeuoeeQhlxuICAgICAgICAgICAgICAgIGdsb2JhbFsnZ19jb25uZWN0aW9uJ11bbmFtZV0gPSBkYi5jb25uZWN0KClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IGdsb2JhbFsnZ19jb25uZWN0aW9uJ11bbmFtZV0udGhlbihhc3luYyBjb25uZWN0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB4YXNzZXJ0KGRiLmlzQ29ubmVjdGVkKVxuICAgICAgICAgICAgICAgIGNvbnN0IG91dCA9IGF3YWl0IGNhbGxiYWNrKGNvbm5lY3Rpb24pXG4gICAgICAgICAgICAgICAgLy8gYXdhaXQgZGIuY2xvc2UoKSAvLyB0eXBlb3Jt5rKh5pyJ6L+b6KGM6L+e5o6l5rGg55qE566h55CG5LiN6IO96L+b6KGM6ZSA5q+BXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShvdXQpXG4gICAgICAgICAgICB9KS5jYXRjaChhc3luYyBlcnIgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGF3YWl0IGRiLmNsb3NlKClcbiAgICAgICAgICAgICAgICB4dGhyb3coZXJyLCByZWplY3QsIHtjZmd9KVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB4dGhyb3coZXJyLCByZWplY3QsIHtjZmd9KVxuICAgICAgICB9XG4gICAgfSlcbn1cblxuLy8g5Yib5bu6WEJhc2VFbnRpdHnlr7nosaHlubbkuJToh6rliqjotYvlgLzliY3nq6/or7fmsYLnmoTotYvlgLzmlbDmja5cbmZ1bmN0aW9uIHhuZXc8VCBleHRlbmRzIEJhc2VFbnRpdHk+KFRZUEU6IG5ldyAoKSA9PiBULCBwYXJhbT86IGFueSwgLi4uYXJncyk6IFQge1xuICAgIC8vIOazm+Wei+WunueOsOexu+S8vOi/meS4quWKn+iDvVxuICAgIC8vIGFzc2V0ID0gbmV3IEFsaWxhbmdBc3NldCgpXG4gICAgLy8gZ2V0UmVwb3NpdG9yeShBbGlsYW5nQXNzZXQpLm1lcmdlKGFzc2V0LCBwYXJhbSBhcyBhbnkpXG4gICAgLy8gQWxpbGFuZ0Fzc2V0Lm1lcmdlKGFzc2V0LCBwYXJhbSBhcyBhbnkpXG4gICAgLy8gcmV0dXJuIGFzc2V0XG4gICAgbGV0IG9iaiA9IG5ldyBUWVBFKClcbiAgICBpZiAoXy5pc0VtcHR5KHBhcmFtKSkge1xuICAgICAgICByZXR1cm4gb2JqXG4gICAgfVxuICAgIGxldCByZXBvID0gZ2V0UmVwb3NpdG9yeTxUPihUWVBFKVxuICAgIHJlcG8ubWVyZ2UuYXBwbHkocmVwbywgW29iaiwgcGFyYW0sIC4uLmFyZ3NdKVxuICAgIHJldHVybiBvYmpcbn1cblxuLy8g5p+l6K+i5p6E6YCg5Zmo5piT55So5oCn5bCB6KOFXG5mdW5jdGlvbiB4cXVlcnk8VD4oY29ubmVjdDogQ29ubmVjdGlvbiwgVFlQRTogbmV3ICgpID0+IFQsIGFsaWFzPzogc3RyaW5nKTogU2VsZWN0UXVlcnlCdWlsZGVyPFQ+IHtcbiAgICByZXR1cm4gY29ubmVjdC5nZXRSZXBvc2l0b3J5KFRZUEUpLmNyZWF0ZVF1ZXJ5QnVpbGRlcihhbGlhcylcbn1cblxuLy8g5YiG6aG15p+l6K+i6I635Y+W5oC75pWw5Lul5Y+K5Y6f5aeL6K6w5b2V5pWw5o2uXG5hc3luYyBmdW5jdGlvbiB4Y291bnQ8VD4oc3FsOiBTZWxlY3RRdWVyeUJ1aWxkZXI8VD4sIHBhZ2U6IG51bWJlciwgc2l6ZTogbnVtYmVyKTogUHJvbWlzZTxbYW55W10gfCBudWxsLCBudW1iZXJdPiB7XG4gICAgeGFzc2VydChwYWdlID49IDEpXG4gICAgY29uc3QgW2NvdW50LCByb3dzXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgICAgc3FsLmdldENvdW50KCksXG4gICAgICAgIHNxbC5vZmZzZXQoKHBhZ2UgLSAxKSAqIHNpemUpLmxpbWl0KHNpemUpLmdldFJhd01hbnkoKVxuICAgIF0pXG4gICAgcmV0dXJuIFtyb3dzLCBjb3VudF1cbn1cblxuXG4vLyDot6/nlLHlj4LmlbDnmoTkv67ppbDnrKbphY3nva5cbi8vIFRPRE8g5pu05aSa5o6l5Y+j55u45YWz5Y+C5pWw55qE6YWN572u5omp5bGV77yM5L6L5aaC77ya5piv5ZCm5pSv5oyBSlNPTlBcbmZ1bmN0aW9uIHhyb3V0ZShwYXJhbTogeyBuYW1lPzogc3RyaW5nLCBkZXNjPzogc3RyaW5nLCBwYXRoPzogc3RyaW5nLCBhdXRoPzogYm9vbGVhbiB9KSB7XG4gICAgLy8g57y655yB5YC85aSE55CGXG4gICAgcGFyYW0gPSB4YXNzaWduKHtuYW1lOiAnJywgZGVzYzogJycsIHBhdGg6ICcnLCBhdXRoOiB0cnVlfSwgcGFyYW0pXG4gICAgcmV0dXJuIGZ1bmN0aW9uICh0YXJnZXQ6IEZ1bmN0aW9uLCBwcm9wZXJ0eUtleTogc3RyaW5nLCBkZXNjcmlwdG9yOiBQcm9wZXJ0eURlc2NyaXB0b3IpIHtcbiAgICAgICAgLy8gVE9ETyDms6jlhaXliLDnsbvlrp7kvovlrprkuYnkuK3ov5vooYzlhajlsYDlvJXnlKjliqjmgIHnsbvnmoTnibnmgKfmt7vliqDvvIh0cmFpdOWKn+iDveeahOWKqOaAgeWunueOsO+8iVxuICAgICAgICAvLyDliqjmgIHnu5Hlrprot6/nlLHnsbvlrp7kvovnmoTkuIrkuIvmloflsZ7mgKdcbiAgICAgICAgdGFyZ2V0LnByb3RvdHlwZS5jb250ZXh0ID0gKCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBwYXJhbTogcGFyYW0sIC8vIOS/neWtmOW9k+WJjeaOp+WItuWZqOeUqOaIt+WumuS5ieWPguaVsOS/oeaBr1xuICAgICAgICAgICAgICAgIC8vIOaYr+WQpueZu+W9leeahOmJtOadg+aWueazlee7n+S4gOahhuaetuWxgumdouS4iueahOWkhOeQhuWunueOsO+8jOatpOWkhOS7heS7heaYr+mAmueUqOaOpeWPo+eahOe6puadn+eahOWumuS5ieOAglxuICAgICAgICAgICAgICAgIGF1dGg6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy8g6LCD55So55m75b2V5Yqf6IO955qE5YmN56uv5o6l5Y+j5a6e546w77yM5Y+W5Yiw5a+55bqU55qE5a6e546w5pa55rOV44CCXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbSAmJiBwYXJhbS5hdXRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyDpnIDopoHpibTmnYPov5vooYzkvJror53mnInmlYjmgKfov5vooYzlkIjms5XmgKfmoKHpqozlpITnkIbvvIHvvIFcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIOacquiupOivgemUmeivr+aKm+WHuuWkhOeQhu+8jOWJjeerr+WNlemhteW6lOeUqOaOpeWPo+aKpemUmemAu+i+keWkhOeQhuato+ehrumUmeivr+aPkOekuui3s+i9rOOAglxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV0aCA9IHhnb3QoWUF1dGgpXG4gICAgICAgICAgICAgICAgICAgICAgICB4YXNzZXJ0KGF3YWl0IGF1dGguZ2V0TG9naW5TdGF0dXMoKSwgRVJSJFVOQVVUSE9SSVpFRClcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbn1cblxuLy8g5a6M5YWo5rKh5pyJ5b+F6KaB55qE5aSa5L2Z5a6a5LmJ77yM6ZyA6KaB6YCa6L+HTU9DS+WumuS5iei/m+ihjOe7huiKguaVsOaNruexu+Wei+eahOaYvuaAp+WumuS5ieWkhOeQhumAu+i+kemqjOivgeOAglxuLy8gLy8g5Z+65pys5pWw5o2u57G75Z6L55qE6KeE6IyD5omp5bGV5a6a5LmJ77yM5pa55L6/QVBJ5o6l5Y+j55qE5a6a5LmJ5Lul5Y+K5b2i5Y+C6Ieq5Yqo6aqM6K+B5ZCI5rOV5oCn77yM5bm25LiU5LiO5pWw5o2u5bqT5pWw5o2u57G75Z6L5L+d5oyB5LiA6Ie044CCXG4vLyB0eXBlIElOVCA9IG51bWJlciAgIC8vIOacieespuWPt+aVtOaVsFxuLy8gdHlwZSBVSU5UID0gbnVtYmVyICAvLyDml6DnrKblj7fmlbTmlbBcbi8vIHR5cGUgREVDSU1BTCA9IG51bWJlciAvLyDnsr7noa7lsI/mlbBcbi8vIHR5cGUgRkxPQVQgPSBudW1iZXIgLy8g5Y2V57K+5bqm5rWu54K55pWw77yI5LiN57K+56Gu5bCP5pWw77yJXG4vLyB0eXBlIERPVUJMRSA9IG51bWJlci8vIOWPjOeyvuW6pua1rueCueaVsO+8iOS4jeeyvuehruWwj+aVsO+8iVxuLy8gdHlwZSBCT09MID0gYm9vbGVhblxuLy8gdHlwZSBTVFIgPSBzdHJpbmdcbi8vIHR5cGUgREFURSA9IHN0cmluZyAvLyDlubTmnIjml6UgJzIwMTctMDYtMjUnXG4vLyB0eXBlIFRJTUUgPSBzdHJpbmcgLy8g5pe25YiG56eSICcwMDowMDowMCdcbi8vIHR5cGUgREFURVRJTUUgPSBzdHJpbmcgLy8g5bm05pyI5pel5pe25YiG56eSICcyMDE3LTA2LTI1IDAwOjAwOjAwJ1xuXG4vLyDmqKHmi5/mlbDmja7mqKHmnb/lrprkuYnkvb/nlKjmlZnnqIsgaHR0cDovL21vY2tqcy5jb20vMC4xLyMlRTYlOTUlQjAlRTYlOEQlQUUlRTUlOEQlQTAlRTQlQkQlOEQlRTclQUMlQTYlRTUlQUUlOUElRTQlQjklODklMjBEUERcbmZ1bmN0aW9uIHhtb2NrPFQ+KHJ1bGVzOiBUKTogYW55IHtcbiAgICByZXR1cm4gbW9ja2pzLm1vY2socnVsZXMpXG59XG5cbmZ1bmN0aW9uIHhyYW5kb20obmFtZTogc3RyaW5nLCBkYXRhOiBhbnlbXSkge1xuICAgIG1vY2tqcy5SYW5kb20uZXh0ZW5kKHtcbiAgICAgICAgW25hbWVdOiAoLi4uYXJncykgPT4ge1xuICAgICAgICAgICAgeGFzc2VydChkYXRhLmxlbmd0aCA+IDApXG4gICAgICAgICAgICBpZiAoZGF0YS5sZW5ndGggPT0gMSkgcmV0dXJuIGRhdGFbMF1cbiAgICAgICAgICAgIGxldCBtYXggPSBkYXRhLmxlbmd0aCAtIDFcbiAgICAgICAgICAgIGxldCBpZHggPSB4bW9jayhgQGludCgwLCR7bWF4fSlgKVxuICAgICAgICAgICAgcmV0dXJuIGRhdGFbaWR4XVxuICAgICAgICB9XG4gICAgfSlcbn1cblxuLy8g5omp5bGV5LiA5Lqb6aKE5a6a5LmJYnhqc+eahOWfuuehgOmaj+acuuaWueazleaIluiAheimhuebluS4gOS6m21vY2tqc+S4reeahOaWueazlVxubW9ja2pzLlJhbmRvbS5leHRlbmQoe1xuICAgIC8vIGJ4anPooajlrprkuYnnmoTkuLvplK7nu5/kuIDlrprkuYnvvIjnuqblrprns7vnu5/kuK3kuLrlrZfnrKbkuLI3LTE05a2X6IqC6ZW/5bqm566X5rOV77yJXG4gICAgaWQ6ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIHJldHVybiBzaG9ydGlkLmdlbmVyYXRlKClcbiAgICB9LFxuICAgIC8vIOS4reWbveaJi+acuuWPt+maj+acuueUn+aIkOeul+azlSjnuqblrprns7vnu5/kuK3nmoTmiYvmnLrlj7fkuLrlrZfnrKbkuLLmlbDmja7nsbvlnospXG4gICAgbW9iaWxlOiAoLi4uYXJncykgPT4ge1xuICAgICAgICBjb25zdCBpc3BzID0gW1xuICAgICAgICAgICAgMTM0LCAxMzUsIDEzNiwgMTM3LCAxMzgsIDEzOSwgMTQ3LCAxNTAsIDE1MSwgMTUyLCAxNTcsIDE1OCwgMTU5LCAxODIsIDE4MywgMTg0LCAxODcsIDE4OCwgMTc4LFxuICAgICAgICAgICAgMTMwLCAxMzEsIDEzMiwgMTQ1LCAxNTUsIDE1NiwgMTg1LCAxODYsIDE3NixcbiAgICAgICAgICAgIDEzMywgMTM0LCAxNTMsIDE4MCwgMTgxLCAxODksIDE3NywgMTczLFxuICAgICAgICAgICAgMTc2LCAxNzMsIDE3NywgMTc4LCAxNzAsXG4gICAgICAgICAgICAxNDAsIDE0MSwgMTQyLCAxNDMsIDE0NCwgMTQ2LCAxNDgsIDE0OSwgMTU0XVxuICAgICAgICBsZXQgbWF4ID0gaXNwcy5sZW5ndGggLSAxXG4gICAgICAgIGxldCBpZHggPSB4bW9jayhgQGludCgwLCR7bWF4fSlgKVxuICAgICAgICBsZXQgbnVtID0geG1vY2soYEBpbnQoMTAwMDAwMDAwLDE5OTk5OTk5OSlgKVxuICAgICAgICByZXR1cm4gKGlzcHNbaWR4XSAqIDEwMDAwMDAwMCArIG51bSAlIDEwMDAwMDAwMCkgKyAnJ1xuICAgIH0sXG4gICAgLy8g6L2s5o2i5Li657y655yB5Lit5paH5YaF5a655o+Q56S6XG4gICAgcGFyYWdyYXBoOiAoLi4uYXJncykgPT4ge1xuICAgICAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHhtb2NrKCdAY3BhcmFncmFwaCcpXG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHhtb2NrKGBAY3BhcmFncmFwaCgke2FyZ3NbMF19KWApXG4gICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHhtb2NrKGBAY3BhcmFncmFwaCgke2FyZ3NbMF19LCR7YXJnc1sxXX0pYClcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgeGFzc2VydChmYWxzZSlcbiAgICAgICAgfVxuXG4gICAgfSxcbiAgICBzZW50ZW5jZTogKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIHJldHVybiB4bW9jaygnQGNzZW50ZW5jZScpXG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHhtb2NrKGBAY3NlbnRlbmNlKCR7YXJnc1swXX0pYClcbiAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICByZXR1cm4geG1vY2soYEBjc2VudGVuY2UoJHthcmdzWzBdfSwke2FyZ3NbMV19KWApXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHhhc3NlcnQoZmFsc2UpXG4gICAgICAgIH1cblxuICAgIH0sXG4gICAgdGl0bGU6ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICByZXR1cm4geG1vY2soJ0BjdGl0bGUnKVxuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIHJldHVybiB4bW9jayhgQGN0aXRsZSgke2FyZ3NbMF19KWApXG4gICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHhtb2NrKGBAY3RpdGxlKCR7YXJnc1swXX0sJHthcmdzWzFdfSlgKVxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB4YXNzZXJ0KGZhbHNlKVxuICAgICAgICB9XG5cbiAgICB9LFxufSlcblxuLy8gbGFyYXZlbOmjjuagvEpTT07lr7nosaHpqozor4HlmajlsIHoo4XvvIzor6bnu4bmlofmoaPop4EgaHR0cHM6Ly9naXRodWIuY29tL3NrYXRlcmRhdjg1L3ZhbGlkYXRvcmpzXG5mdW5jdGlvbiB4Y2hlY2s8VD4ocGFyYW06IFQsIHJ1bGVzOiBULCBtZXNzYWdlcz86IE9iamVjdCkge1xuICAgIGxldCBvYmogPSBuZXcgdmFsaWRhdG9yanMocGFyYW0sIHJ1bGVzKVxuICAgIGlmIChvYmouZmFpbHMoKSkge1xuICAgICAgICB4dGhyb3coRVJSJFBBUkFNLCBvYmouZXJyb3JzKVxuICAgIH1cbn1cblxuLy8g44CQSW9D5a655Zmo566h55CG44CR5bqU55So5bGC55qE5o+S5Lu25a6e546w57G757uR5a6a5YiwQlhKU+e7n+S4gOazqOWGjOeahOagh+WHhuaPkuS7tueahOaYoOWwhOWFs+ezu+WcqOWFqOWxgOWuueWZqOWunuS+i+S4reazqOWGjFxuZnVuY3Rpb24geGJpbmQ8VD4oVFlQRTogbmV3ICgpID0+IFQpIHtcbiAgICBjb25zdCBvOiBhbnkgPSBuZXcgVFlQRSgpXG4gICAgcmV0dXJuIHhjb250YWluZXIuYmluZDxUPihvLmlkKS50byhyZXF1aXJlKGBAYXBwL3BsdWdpbnMvJHtvLmlkfWApLmRlZmF1bHQpXG59XG5cbi8vIOOAkElvQ+WuueWZqOeuoeeQhuOAkeahhuaetuaIluW6lOeUqOS+nei1luagh+WHhuinhOiMg+aOpeWPo+aPkuS7tueahOexu+WunuS+i+iOt+WPluaWueazlVxuZnVuY3Rpb24geGdvdDxUPihUWVBFOiBuZXcgKCkgPT4gVCkge1xuICAgIGNvbnN0IG86IGFueSA9IG5ldyBUWVBFKClcbiAgICByZXR1cm4geGNvbnRhaW5lci5nZXQ8VD4oby5pZClcbn1cblxuLy8g5ZCM5q2l57O757uf5ZG95Luk6LCD55So5omn6KGMXG5hc3luYyBmdW5jdGlvbiB4Y21kKC4uLmFyZ3M6IHN0cmluZ1tdKTogUHJvbWlzZTxhbnk+IHtcbiAgICB0cnkge1xuICAgICAgICBjb25zdCBvcHRpb25zOiBhbnkgPSB7fVxuICAgICAgICBvcHRpb25zLmN3ZCA9IG9wdGlvbnMuY3dkIHx8IHByb2Nlc3MuZW52Ll9fY3R4UGF0aCB8fCBwcm9jZXNzLmN3ZCgpO1xuICAgICAgICB4YXNzZXJ0KF8uaXNBcnJheShhcmdzKSAmJiBhcmdzLmxlbmd0aCA+IDApXG4gICAgICAgIGNvbnN0IGNtZCA9IGFyZ3Muc2hpZnQoKVxuICAgICAgICBjb25zdCByZXQgPSBjcm9zc19zcGF3bi5zeW5jKGNtZCwgYXJncywgeGFzc2lnbih7c3RkaW86ICdpbmhlcml0J30sIG9wdGlvbnMpKVxuICAgICAgICB4YXNzZXJ0KHJldC5zdGF0dXMgPT09IDAsIEVSUiRVTktOT1dOLCByZXQpXG4gICAgICAgIHJldHVybiByZXRcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgYXdhaXQgeHdhcm4oZXJyKVxuICAgICAgICB4dGhyb3coZXJyKVxuICAgIH1cbn1cblxuLy8g5a+55LqO5pWw57uE5bWM5aWX5Zue6LCD5Ye95pWw55qEbm9kZWpz5byC5q2l5aSE55CG5pa55rOV55qE57uf5LiA5bCB6KOFXG5hc3luYyBmdW5jdGlvbiB4bWFwPFQ+KHZhbHVlczogVFtdLCBjYWxsYWNrOiAodjogVCkgPT4gUHJvbWlzZTxhbnk+KTogUHJvbWlzZTxhbnlbXT4ge1xuICAgIHhhc3NlcnQoXy5pc0FycmF5KHZhbHVlcykgJiYgXy5pc0Z1bmN0aW9uKGNhbGxhY2spKVxuICAgIHJldHVybiBQcm9taXNlLmFsbCh2YWx1ZXMubWFwKGNhbGxhY2spKVxufVxuXG4vLyBSZWZlciB0byBkb2N1bWVudDogIGh0dHBzOi8vaGVscC5hbGl5dW4uY29tL2RvY3VtZW50X2RldGFpbC82MjY3MC5odG1sXG4vLyDojrflj5ZBQ03phY3nva7kv6Hmga/mjqXlj6PnmoTnu5/kuIDlsIHoo4VcbmFzeW5jIGZ1bmN0aW9uIHhhY20oZ3JvdXA6IHN0cmluZywgaWQ6IHN0cmluZykge1xuICAgIGNvbnN0IGNmZyA9IHhjb25maWcoYHBsdWdpbnMuYWNtYClcbiAgICB4YXNzZXJ0KGdyb3VwICYmIGNmZyAmJiBjZmdbZ3JvdXBdLCBFUlIkQ09ORklHLCB7Y2ZnfSlcbiAgICBjb25zdCBhY20gPSBuZXcgQUNNQ2xpZW50KGNmZ1tncm91cF0pXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvKGZ1bmN0aW9uKiAoKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSBncm91cCArICc6JyArIGdsb2JhbFsnX19lbnZfXyddIC8vIOihpeS4iueOr+Wig+WQjue8gOaUr+aMgeWQhOenjeW8gOWPkeeOr+Wig+eahOS4quaAp+WMlumFjee9rlxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50ID0geWllbGQgYWNtLmdldENvbmZpZyhpZCwgZ3JvdXApXG4gICAgICAgICAgICAgICAgICAgIHhhc3NlcnQoY29udGVudCwgRVJSJENPTkZJRywge2lkLCBncm91cH0pXG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoY29udGVudClcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KGVyciwgcmVqZWN0LCB7aWQsIGdyb3VwLCBjZmc6IGNmZ1tncm91cF19KVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHh0aHJvdyhlcnIsIHJlamVjdCwge2lkLCBncm91cCwgY2ZnOiBjZmdbZ3JvdXBdfSlcbiAgICAgICAgfVxuICAgIH0pXG59XG5cbi8vIOagueaNruW9k+WJjemFjee9rueahOaXtuWMuuato+ehruiOt+WPluW9k+WJjeaXtumXtOWAvOmBv+WFjee6v+S4ikZD5a655Zmo6buY6K6k5piv5qC85p6X5bC85rK75pe26Ze06ICM6Z2e5YyX5Lqs5pe26Ze06Zeu6aKYXG5mdW5jdGlvbiB4bm93KGZvcm1hdCA9ICdZWVlZLU1NLUREIEhIOm1tOnNzJykge1xuICAgIHJldHVybiBtb21lbnQoKS51dGNPZmZzZXQoOCkuZm9ybWF0KGZvcm1hdClcbn1cblxuLy8gYmFzZTY057yW56CBXG5mdW5jdGlvbiB4YmFzZTY0ZW5jb2RlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB4YXNzZXJ0KCFfLmlzRW1wdHkodmFsdWUpICYmIF8uaXNTdHJpbmcodmFsdWUpKVxuICAgIHJldHVybiBuZXcgQnVmZmVyKHZhbHVlKS50b1N0cmluZygnYmFzZTY0Jylcbn1cblxuLy8gYmFzZTY06Kej56CBXG5mdW5jdGlvbiB4YmFzZTY0ZGVjb2RlKHZhbHVlOiBzdHJpbmcpIHtcbiAgICB4YXNzZXJ0KCFfLmlzRW1wdHkodmFsdWUpICYmIF8uaXNTdHJpbmcodmFsdWUpKVxuICAgIHJldHVybiBuZXcgQnVmZmVyKHZhbHVlLCAnYmFzZTY0JykudG9TdHJpbmcoKVxufVxuXG4vLyDor7fmsYLkuIrkuIvmloflj5jph4/oh6rliqjph43nva7mlrnms5XvvIjku6VnbG9iYWzlj5jph4/kuK1rZXnkuLpfX+S4i+WIkue6v+W8gOWni+e7k+adn+eahOWxnuaAp+iHquWKqOa4heepuuS4unVuZGVmaW5lZO+8jOWmgumcgOi1i+WAvOWFtuS7lue8uuecgeWAvOmcgOimgeWcqOatpOWHveaVsOS4reaYjuehruWumuS5ie+8iVxuZnVuY3Rpb24geHJlc2V0KCkge1xuICAgIC8vIOaJgOacieivt+axguS4iuS4i+aWh+WxnuaAp+eahOiHquWKqOa4heepuuWIneWni+WMluWkhOeQhu+8iOmAmui/h+e6puWummdsb2JhbOeahOeJueauiuWxnuaAp19feHh4X1/nroDljJZrb2HkuK3nmoRjb250ZXh06K6+6K6h5py65Yi277yM5bCG6L+Z6YOo5YiG5py65Yi25YGa5Yiw5qGG5p625LiK5a+55bqU55So5LiN5Y+v6KeB77yJXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKGdsb2JhbCkpIHtcbiAgICAgICAgaWYgKGtleS5zdGFydHNXaXRoKCdfXycpICYmIGtleS5lbmRzV2l0aCgnX18nKSkge1xuICAgICAgICAgICAgZ2xvYmFsW2tleV0gPSB1bmRlZmluZWRcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyDmmI7noa7lrprkuYnnmoTkuIDkupvlhajlsYDlj5jph4/nmoTliJ3lp4vlgLzotYvlgLxcbiAgICBpZiAoIWdsb2JhbFsnX19lbnZfXyddKSB7XG4gICAgICAgIGdsb2JhbFsnX19lbnZfXyddID0gJ2xvY2FsJyAvLyBsb2NhbCxkYWlseSxwcmUsZ3JheSxwcm9kIOWcqOe7n+S4gOWFpeWPo+WkhOiHquWKqOivhuWIq+mFjee9rijnm67liY3mmoLkuI3mlK/mjIFncmF56YWN572u5bCa5pyq5byA5Y+R5peg5rOV6Ieq5Yqo6K+G5YirKVxuICAgIH1cbiAgICBnbG9iYWxbJ19fY29uZmlnX18nXSA9IHVuZGVmaW5lZFxuICAgIGdsb2JhbFsnX19zZXNzaW9uX18nXSA9IHt9XG4gICAgZ2xvYmFsWydfX2NhY2hlX18nXSA9IHt9XG4gICAgZ2xvYmFsWydfX3VzZXJfXyddID0ge31cbiAgICBnbG9iYWxbJ19fdXNlcl9hZ2VudF9fJ10gPSB1bmRlZmluZWRcbiAgICBnbG9iYWxbJ19fY2xpZW50X2lwX18nXSA9IHVuZGVmaW5lZFxuICAgIGdsb2JhbFsnX19yZWRpcmVjdF91cmxfXyddID0gdW5kZWZpbmVkXG4gICAgZ2xvYmFsWydfX3JlcXVlc3RfY29va2llc19fJ10gPSB7fVxuICAgIGdsb2JhbFsnX19yZXNwb25kX2Nvb2tpZXNfXyddID0ge31cbn1cblxuLy8g6aaW5qyh5qih5Z2X5Yqg6L2955qE5pe25YCZ5omn6KGM5LiA5qyh77yM56Gu5L+d5bqU55So5Lit5LiN5Y+v5Lul5pyJX194eHhfX+WPguaVsOS9nOS4uuWFqOWxgOWPmOmHj+WcqOaooeWdl+WIneWni+WMlueahOaXtuWAmVxueHJlc2V0KClcblxuZ2xvYmFsWyd4cmVzZXQnXSA9IHhyZXNldFxuZ2xvYmFsWyd4Y29ubmVjdCddID0geGNvbm5lY3Rcbmdsb2JhbFsneG5ldyddID0geG5ld1xuZ2xvYmFsWyd4cXVlcnknXSA9IHhxdWVyeVxuZ2xvYmFsWyd4Y291bnQnXSA9IHhjb3VudFxuZ2xvYmFsWyd4YXNzaWduJ10gPSB4YXNzaWduXG5nbG9iYWxbJ3hjb25maWcnXSA9IHhjb25maWdcbmdsb2JhbFsneHRocm93J10gPSB4dGhyb3dcbmdsb2JhbFsneGFzc2VydCddID0geGFzc2VydFxuZ2xvYmFsWyd4ZXJyb3InXSA9IHhlcnJvclxuZ2xvYmFsWyd4cm9vdCddID0geHJvb3Rcbmdsb2JhbFsneHN0YWNrJ10gPSB4c3RhY2tcbmdsb2JhbFsneHdhcm4nXSA9IHh3YXJuXG5nbG9iYWxbJ3hsb2cnXSA9IHhsb2dcbmdsb2JhbFsneHBvc3QnXSA9IHhwb3N0XG5nbG9iYWxbJ3hnZXQnXSA9IHhnZXRcbmdsb2JhbFsneHNsZWVwJ10gPSB4c2xlZXBcbmdsb2JhbFsneHJlZGlyZWN0J10gPSB4cmVkaXJlY3Rcbmdsb2JhbFsneGNvb2tpZSddID0geGNvb2tpZVxuZ2xvYmFsWyd4aXNtb2JpbGUnXSA9IHhpc21vYmlsZVxuZ2xvYmFsWyd4c2Vzc2lvbiddID0geHNlc3Npb25cbmdsb2JhbFsneHVzZXInXSA9IHh1c2VyXG5nbG9iYWxbJ3hjYWNoZSddID0geGNhY2hlXG5nbG9iYWxbJ3hyb3V0ZSddID0geHJvdXRlXG5nbG9iYWxbJ3htb2NrJ10gPSB4bW9ja1xuZ2xvYmFsWyd4cmFuZG9tJ10gPSB4cmFuZG9tXG5nbG9iYWxbJ3hjaGVjayddID0geGNoZWNrXG5nbG9iYWxbJ3hjb250YWluZXInXSA9IG5ldyBDb250YWluZXIoKSAvLyDlhajlsYDljZXlrp7kvovlrrnlmajliJ3lp4vljJZcbmdsb2JhbFsneGJpbmQnXSA9IHhiaW5kXG5nbG9iYWxbJ3hnb3QnXSA9IHhnb3Rcbmdsb2JhbFsnWUF1dGgnXSA9ICQkLllBdXRoIC8vIOWFqOWxgOWjsOaYjuiupOivgeaPkuS7tuinhOiMg+aKveixoeexu1xuZ2xvYmFsWyd4Y21kJ10gPSB4Y21kXG5nbG9iYWxbJ3htYXAnXSA9IHhtYXBcbmdsb2JhbFsneGFjbSddID0geGFjbVxuZ2xvYmFsWyd4YmFzZTY0ZW5jb2RlJ10gPSB4YmFzZTY0ZW5jb2RlXG5nbG9iYWxbJ3hiYXNlNjRkZWNvZGUnXSA9IHhiYXNlNjRkZWNvZGVcbmdsb2JhbFsneG5vdyddID0geG5vd1xuIl19
\No newline at end of file