UNPKG

119 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();
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 output = output.replace(/\r/g, '').replace(/\n/g, '');
311 console.log.apply(undefined, [source + output]);
312 }
313}
314exports.xlog = xlog;
315// // 将详细错误信息及时发送到钉钉群上实时反馈给维护者
316// await xwarn({
317// code,
318// // TODO 如何认证通过了获取到用户信息也需要发送过去,方便联系对接人员进行立刻问题处理反馈。
319// message,
320// stack,
321// param,
322// })
323// 将详细错误信息及时发送到钉钉群上实时反馈给维护者
324// 钉钉IM群机器人报警通知
325function xwarn() {
326 var args = [];
327 for (var _i = 0; _i < arguments.length; _i++) {
328 args[_i] = arguments[_i];
329 }
330 return __awaiter(this, void 0, void 0, function () {
331 var source, out, access_token, mobiles;
332 return __generator(this, function (_a) {
333 switch (_a.label) {
334 case 0:
335 source = __get_base_func_caller_source_position();
336 // 对于异常参数警告信息进行错误内容标准解析
337 if (args.length > 0 && args[0] instanceof Error) {
338 args[0] = xerror(args[0]);
339 }
340 out = [source, moment().format('YYYY-MM-DD HH:mm:ss'), __assign({}, args)];
341 access_token = xconfig('framework.warn.dingding.access_token');
342 mobiles = xconfig('framework.warn.dingding.mobiles');
343 if (!access_token || !mobiles) {
344 access_token = '020a09eac5f2fa320ae851442d5e19e23693c64ad2255c85354b4a49a5a48d35';
345 mobiles = ['15381151346'];
346 }
347 return [4 /*yield*/, xpost("https://oapi.dingtalk.com/robot/send?access_token=" + access_token, {
348 msgtype: 'text',
349 text: {
350 content: out
351 },
352 at: {
353 atMobiles: mobiles,
354 isAtAll: false
355 }
356 })
357 // 线上SLS日志上也保存一份
358 // console.warn(out)
359 ];
360 case 1:
361 _a.sent();
362 // 线上SLS日志上也保存一份
363 // console.warn(out)
364 xlog(out);
365 return [2 /*return*/];
366 }
367 });
368 });
369}
370// 捕获未监听到的异常记录后直接退出(运行堆栈已经破坏直接记录日志后异常退出即可,由外部监控自动重启)
371process.on('uncaughtException', function (err) {
372 return __awaiter(this, void 0, void 0, function () {
373 return __generator(this, function (_a) {
374 switch (_a.label) {
375 case 0:
376 xlog(xerror(err));
377 return [4 /*yield*/, xwarn(err)];
378 case 1:
379 _a.sent();
380 process.exit(-1);
381 return [2 /*return*/];
382 }
383 });
384 });
385});
386// 记录await/async中出现未捕获的异常错误
387process.on('unhandledRejection', function (reason, p) { return __awaiter(_this, void 0, void 0, function () {
388 return __generator(this, function (_a) {
389 switch (_a.label) {
390 case 0:
391 xlog('Unhandled Rejection at: Promise', p, 'reason:', reason);
392 // application specific logging, throwing an error, or other logic here
393 return [4 /*yield*/, xwarn(reason, p)];
394 case 1:
395 // application specific logging, throwing an error, or other logic here
396 _a.sent();
397 process.exit(-1);
398 return [2 /*return*/];
399 }
400 });
401}); });
402// async/await的非阻塞异步延迟方法,用于调试阻塞程序的执行进行单步调试的效果。
403var sleep = require('sleep-async')();
404function xsleep(ms) {
405 if (ms === void 0) { ms = -1; }
406 if (ms <= 0) {
407 ms = 50 * 365 * 24 * 3600 * 1000; // 50年最大数视为永久阻塞方便断点单步调试问题
408 }
409 return new Promise(function (resolve, reject) {
410 try {
411 sleep.sleep(ms, function () {
412 resolve();
413 });
414 }
415 catch (err) {
416 xlog(xerror(err));
417 resolve();
418 // xthrow(err,reject)
419 }
420 });
421}
422exports.xsleep = xsleep;
423function xpost(url, param, headers, timeout) {
424 if (timeout === void 0) { timeout = 3000; }
425 return __awaiter(this, void 0, void 0, function () {
426 var res, json, text, err_1;
427 return __generator(this, function (_a) {
428 switch (_a.label) {
429 case 0:
430 // TODO 线上测试不稳定超时暂时忽略掉通过进程最大运行时间去控制超时失败
431 timeout = 5000; // -1 不行线上会被阻塞住僵死
432 res = null;
433 json = null;
434 text = null;
435 _a.label = 1;
436 case 1:
437 _a.trys.push([1, 4, , 5]);
438 return [4 /*yield*/, fetch(url, {
439 method: 'POST',
440 body: JSON.stringify(param),
441 headers: __assign({ 'Content-Type': 'application/json' }, headers),
442 timeout: timeout <= 0 ? 0 : timeout,
443 })];
444 case 2:
445 res = _a.sent();
446 return [4 /*yield*/, res.text()]; // 解析出完整的返回内容避免HTML以及非法格式信息便于正确报错定位后端接口错误
447 case 3:
448 text = _a.sent(); // 解析出完整的返回内容避免HTML以及非法格式信息便于正确报错定位后端接口错误
449 json = JSON.parse(text);
450 return [2 /*return*/, json];
451 case 4:
452 err_1 = _a.sent();
453 xthrow(err_1, { url: url, param: param, headers: headers, text: text });
454 return [3 /*break*/, 5];
455 case 5: return [2 /*return*/];
456 }
457 });
458 });
459}
460exports.xpost = xpost;
461// 默认超时3000毫秒
462function xget(url, param, headers, timeout) {
463 if (timeout === void 0) { timeout = 3000; }
464 return __awaiter(this, void 0, void 0, function () {
465 var res, json, text, err_2;
466 return __generator(this, function (_a) {
467 switch (_a.label) {
468 case 0:
469 // TODO 线上测试不稳定超时暂时忽略掉通过进程最大运行时间去控制超时失败
470 timeout = 5000; // -1 不行线上会被阻塞住僵死
471 res = null;
472 json = null;
473 text = null;
474 _a.label = 1;
475 case 1:
476 _a.trys.push([1, 4, , 5]);
477 url = url + (param ? '?' : '') + querystring.stringify(param);
478 return [4 /*yield*/, fetch(url, {
479 method: 'GET',
480 headers: __assign({ 'Content-Type': 'application/json' }, headers),
481 timeout: timeout <= 0 ? 0 : timeout,
482 })];
483 case 2:
484 res = _a.sent();
485 return [4 /*yield*/, res.text()]; // 解析出完整的返回内容避免HTML以及非法格式信息便于正确报错定位后端接口错误
486 case 3:
487 text = _a.sent(); // 解析出完整的返回内容避免HTML以及非法格式信息便于正确报错定位后端接口错误
488 json = JSON.parse(text);
489 return [2 /*return*/, json];
490 case 4:
491 err_2 = _a.sent();
492 xthrow(err_2, { url: url, param: param, headers: headers, text: text });
493 return [3 /*break*/, 5];
494 case 5: return [2 /*return*/];
495 }
496 });
497 });
498}
499exports.xget = xget;
500// 302临时重定向跳转实现
501function xredirect(url, param) {
502 if (param === void 0) { param = {}; }
503 // TODO 多个程序实例并发处理的时候存在时序问题不能保证全局变量被准确清空。
504 // 检查应用重复设置重定向地址未及时return返回控制器问题
505 xassert(global['__redirect_url__'] === undefined);
506 if (param) {
507 xassert(_.isPlainObject(param));
508 // 删除param中两个框架预定义参数__url__和__api__不允许进行参数传递(禁止业务逻辑使用避免框架后续升级以及与短网址功能冲突)
509 delete param.__api__;
510 delete param.__url__;
511 // 补额外的附加参数
512 if (/\?/.test(url)) {
513 url += '&';
514 }
515 else {
516 url += '?';
517 }
518 url += querystring.stringify(param);
519 }
520 global['__redirect_url__'] = url;
521}
522exports.xredirect = xredirect;
523// 如果只有key参数表示读取属性(缺省值为undefined),如果key为空表示读取所有的请求cookies属性,否则表示响应设置cookies
524function xcookie(key, value, option) {
525 if (!arguments.length) {
526 // 读取所有的请求cookies属性object
527 return global['__request_cookies__'] ? global['__request_cookies__'] : {};
528 }
529 else if (arguments.length == 1) {
530 return key ? xcookie()[key] : undefined;
531 }
532 else {
533 if (global['__respond_cookies__'] === undefined) {
534 global['__respond_cookies__'] = {};
535 }
536 if (key) {
537 // COOKIES缺省属性设置(有效时间24小时并且统一关联到根页面上获取COOKIES值)
538 option = xassign({ path: '/', maxAge: 24 * 3600 }, option);
539 global['__respond_cookies__'][key] = cookie.serialize(key, value, option);
540 }
541 return;
542 }
543}
544exports.xcookie = xcookie;
545// 判断user-agent请求是否为移动端
546function xismobile() {
547 var md = new MobileDetect(global['__user_agent__']);
548 return !!md.mobile();
549}
550function xassign(target, source) {
551 var args = [];
552 for (var _i = 2; _i < arguments.length; _i++) {
553 args[_i - 2] = arguments[_i];
554 }
555 var param = [true, target, source].concat(args);
556 return extend.apply(null, param);
557}
558// 查询app/config目录下的应用配置数据
559function xconfig(path, defaultValue) {
560 if (defaultValue === void 0) { defaultValue = undefined; }
561 if (global['__config__']) {
562 return _.get(global['__config__'], path, defaultValue);
563 }
564 var fp = require('path');
565 var fs = require('fs');
566 // 自动获取app/config的相对路径目录位置得到根路径的位置
567 var config_path = '';
568 if (__dirname.includes('/node_modules/@bxjs/base/')) {
569 // 在应用目录下
570 config_path = fp.join(__dirname, '../../../../app/config');
571 }
572 else {
573 // 在axjs库开发目录下
574 config_path = fp.join(__dirname, '../app/config');
575 }
576 // 自动识别判断运行环境global['__env__']并且加载对应的base数据和env数据
577 var config_base_path = config_path + '/config.base.' + get_suffix_ts_or_js();
578 var config_env_path = config_path + ("/config." + global['__env__'] + ".") + get_suffix_ts_or_js();
579 if (!fs.existsSync(config_base_path)) {
580 return defaultValue;
581 }
582 var config_base = require(config_base_path).default;
583 var config_env = {};
584 if (fs.existsSync(config_env_path)) {
585 config_env = require(config_env_path).default;
586 }
587 // bugfix Object.assign不支持深度拷贝问题
588 // global['__config__'] = Object.assign({}, config_base, config_env)
589 // global['__config__'] = _.assign({}, config_env, config_base)
590 global['__config__'] = xassign({}, config_base, config_env);
591 return _.get(global['__config__'], path, defaultValue);
592}
593function xconnect(callback, config) {
594 if (config === void 0) { config = 'default'; }
595 return __awaiter(this, void 0, void 0, function () {
596 var _this = this;
597 return __generator(this, function (_a) {
598 return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
599 var cfg, mng, name, db_1, err_3;
600 var _this = this;
601 return __generator(this, function (_a) {
602 switch (_a.label) {
603 case 0:
604 cfg = {};
605 _a.label = 1;
606 case 1:
607 _a.trys.push([1, 3, , 4]);
608 cfg = xassign({}, xconfig('plugins.database.default', {}));
609 xassert(!_.isEmpty(cfg), ERR$PARAM, { config: config });
610 // 强制补上约定的实体存放路径定义位置(不允许配置是约定规范)
611 if (__dirname.includes('/node_modules/@bxjs/base/')) {
612 // 在应用目录下
613 cfg['entities'] = [
614 path.join(__dirname, '../../../../app/plugins/database/entity/*.' + get_suffix_ts_or_js())
615 ];
616 }
617 else {
618 // 在axjs库开发目录下
619 cfg['entities'] = [
620 path.join(__dirname, '../app/plugins/database/entity/*.' + get_suffix_ts_or_js())
621 ];
622 }
623 mng = typeorm_1.getConnectionManager();
624 name = cfg.name ? cfg.name : 'default';
625 if (!mng.has(name)) {
626 mng.create(cfg);
627 }
628 db_1 = mng.get(name);
629 if (global['__connection__'] === undefined) {
630 global['__connection__'] = {};
631 }
632 if (!db_1.isConnected) { // TODO 需要进行连接池的管理
633 global['__connection__'][name] = db_1.connect();
634 }
635 return [4 /*yield*/, global['__connection__'][name].then(function (connection) { return __awaiter(_this, void 0, void 0, function () {
636 var out;
637 return __generator(this, function (_a) {
638 switch (_a.label) {
639 case 0:
640 xassert(db_1.isConnected);
641 return [4 /*yield*/, callback(connection)
642 // await db.close() // typeorm没有进行连接池的管理不能进行销毁
643 ];
644 case 1:
645 out = _a.sent();
646 // await db.close() // typeorm没有进行连接池的管理不能进行销毁
647 resolve(out);
648 return [2 /*return*/];
649 }
650 });
651 }); }).catch(function (err) { return __awaiter(_this, void 0, void 0, function () {
652 return __generator(this, function (_a) {
653 // await db.close()
654 xthrow(err, reject, { cfg: cfg });
655 return [2 /*return*/];
656 });
657 }); })];
658 case 2:
659 _a.sent();
660 return [3 /*break*/, 4];
661 case 3:
662 err_3 = _a.sent();
663 xthrow(err_3, reject, { cfg: cfg });
664 return [3 /*break*/, 4];
665 case 4: return [2 /*return*/];
666 }
667 });
668 }); })];
669 });
670 });
671}
672// 创建XBaseEntity对象并且自动赋值前端请求的赋值数据
673function xnew(TYPE, param) {
674 var args = [];
675 for (var _i = 2; _i < arguments.length; _i++) {
676 args[_i - 2] = arguments[_i];
677 }
678 // 泛型实现类似这个功能
679 // asset = new AlilangAsset()
680 // getRepository(AlilangAsset).merge(asset, param as any)
681 // AlilangAsset.merge(asset, param as any)
682 // return asset
683 var obj = new TYPE();
684 if (_.isEmpty(param)) {
685 return obj;
686 }
687 var repo = typeorm_1.getRepository(TYPE);
688 repo.merge.apply(repo, [obj, param].concat(args));
689 return obj;
690}
691// 查询构造器易用性封装
692function xquery(connect, TYPE, alias) {
693 return connect.getRepository(TYPE).createQueryBuilder(alias);
694}
695// 分页查询获取总数以及原始记录数据
696function xcount(sql, page, size) {
697 return __awaiter(this, void 0, void 0, function () {
698 var _a, count, rows;
699 return __generator(this, function (_b) {
700 switch (_b.label) {
701 case 0:
702 xassert(page >= 1);
703 return [4 /*yield*/, Promise.all([
704 sql.getCount(),
705 sql.offset((page - 1) * size).limit(size).getRawMany()
706 ])];
707 case 1:
708 _a = _b.sent(), count = _a[0], rows = _a[1];
709 return [2 /*return*/, [rows, count]];
710 }
711 });
712 });
713}
714// 路由参数的修饰符配置
715// TODO 更多接口相关参数的配置扩展,例如:是否支持JSONP
716function xroute(param) {
717 // 缺省值处理
718 param = xassign({ name: '', desc: '', path: '', auth: true }, param);
719 return function (target, propertyKey, descriptor) {
720 var _this = this;
721 // TODO 注入到类实例定义中进行全局引用动态类的特性添加(trait功能的动态实现)
722 // 动态绑定路由类实例的上下文属性
723 target.prototype.context = function () {
724 return {
725 param: param,
726 // 是否登录的鉴权方法统一框架层面上的处理实现,此处仅仅是通用接口的约束的定义。
727 auth: function () { return __awaiter(_this, void 0, void 0, function () {
728 var auth, _a;
729 return __generator(this, function (_b) {
730 switch (_b.label) {
731 case 0:
732 if (!(param && param.auth)) return [3 /*break*/, 2];
733 auth = xgot(YAuth);
734 _a = xassert;
735 return [4 /*yield*/, auth.getLoginStatus()];
736 case 1:
737 _a.apply(void 0, [_b.sent(), ERR$UNAUTHORIZED]);
738 _b.label = 2;
739 case 2: return [2 /*return*/];
740 }
741 });
742 }); }
743 };
744 };
745 };
746}
747// 完全没有必要的多余定义,需要通过MOCK定义进行细节数据类型的显性定义处理逻辑验证。
748// // 基本数据类型的规范扩展定义,方便API接口的定义以及形参自动验证合法性,并且与数据库数据类型保持一致。
749// type INT = number // 有符号整数
750// type UINT = number // 无符号整数
751// type DECIMAL = number // 精确小数
752// type FLOAT = number // 单精度浮点数(不精确小数)
753// type DOUBLE = number// 双精度浮点数(不精确小数)
754// type BOOL = boolean
755// type STR = string
756// type DATE = string // 年月日 '2017-06-25'
757// type TIME = string // 时分秒 '00:00:00'
758// type DATETIME = string // 年月日时分秒 '2017-06-25 00:00:00'
759// 模拟数据模板定义使用教程 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
760function xmock(rules) {
761 return mockjs.mock(rules);
762}
763function xrandom(name, data) {
764 var _a;
765 mockjs.Random.extend((_a = {},
766 _a[name] = function () {
767 var args = [];
768 for (var _i = 0; _i < arguments.length; _i++) {
769 args[_i] = arguments[_i];
770 }
771 xassert(data.length > 0);
772 if (data.length == 1)
773 return data[0];
774 var max = data.length - 1;
775 var idx = xmock("@int(0," + max + ")");
776 return data[idx];
777 },
778 _a));
779}
780// 扩展一些预定义bxjs的基础随机方法或者覆盖一些mockjs中的方法
781mockjs.Random.extend({
782 // bxjs表定义的主键统一定义(约定系统中为字符串7-14字节长度算法)
783 id: function () {
784 var args = [];
785 for (var _i = 0; _i < arguments.length; _i++) {
786 args[_i] = arguments[_i];
787 }
788 return shortid.generate();
789 },
790 // 中国手机号随机生成算法(约定系统中的手机号为字符串数据类型)
791 mobile: function () {
792 var args = [];
793 for (var _i = 0; _i < arguments.length; _i++) {
794 args[_i] = arguments[_i];
795 }
796 var isps = [
797 134, 135, 136, 137, 138, 139, 147, 150, 151, 152, 157, 158, 159, 182, 183, 184, 187, 188, 178,
798 130, 131, 132, 145, 155, 156, 185, 186, 176,
799 133, 134, 153, 180, 181, 189, 177, 173,
800 176, 173, 177, 178, 170,
801 140, 141, 142, 143, 144, 146, 148, 149, 154
802 ];
803 var max = isps.length - 1;
804 var idx = xmock("@int(0," + max + ")");
805 var num = xmock("@int(100000000,199999999)");
806 return (isps[idx] * 100000000 + num % 100000000) + '';
807 },
808 // 转换为缺省中文内容提示
809 paragraph: function () {
810 var args = [];
811 for (var _i = 0; _i < arguments.length; _i++) {
812 args[_i] = arguments[_i];
813 }
814 switch (args.length) {
815 case 0:
816 return xmock('@cparagraph');
817 case 1:
818 return xmock("@cparagraph(" + args[0] + ")");
819 case 2:
820 return xmock("@cparagraph(" + args[0] + "," + args[1] + ")");
821 default:
822 xassert(false);
823 }
824 },
825 sentence: function () {
826 var args = [];
827 for (var _i = 0; _i < arguments.length; _i++) {
828 args[_i] = arguments[_i];
829 }
830 switch (args.length) {
831 case 0:
832 return xmock('@csentence');
833 case 1:
834 return xmock("@csentence(" + args[0] + ")");
835 case 2:
836 return xmock("@csentence(" + args[0] + "," + args[1] + ")");
837 default:
838 xassert(false);
839 }
840 },
841 title: function () {
842 var args = [];
843 for (var _i = 0; _i < arguments.length; _i++) {
844 args[_i] = arguments[_i];
845 }
846 switch (args.length) {
847 case 0:
848 return xmock('@ctitle');
849 case 1:
850 return xmock("@ctitle(" + args[0] + ")");
851 case 2:
852 return xmock("@ctitle(" + args[0] + "," + args[1] + ")");
853 default:
854 xassert(false);
855 }
856 },
857});
858// laravel风格JSON对象验证器封装,详细文档见 https://github.com/skaterdav85/validatorjs
859function xcheck(param, rules, messages) {
860 var obj = new validatorjs(param, rules);
861 if (obj.fails()) {
862 xthrow(ERR$PARAM, obj.errors);
863 }
864}
865// 【IoC容器管理】应用层的插件实现类绑定到BXJS统一注册的标准插件的映射关系在全局容器实例中注册
866function xbind(TYPE) {
867 var o = new TYPE();
868 return xcontainer.bind(o.id).to(require("@app/plugins/" + o.id).default);
869}
870// 【IoC容器管理】框架或应用依赖标准规范接口插件的类实例获取方法
871function xgot(TYPE) {
872 var o = new TYPE();
873 return xcontainer.get(o.id);
874}
875// 同步系统命令调用执行
876function xcmd() {
877 var args = [];
878 for (var _i = 0; _i < arguments.length; _i++) {
879 args[_i] = arguments[_i];
880 }
881 return __awaiter(this, void 0, void 0, function () {
882 var options, cmd, ret, err_4;
883 return __generator(this, function (_a) {
884 switch (_a.label) {
885 case 0:
886 _a.trys.push([0, 1, , 3]);
887 options = {};
888 options.cwd = options.cwd || process.env.__ctxPath || process.cwd();
889 xassert(_.isArray(args) && args.length > 0);
890 cmd = args.shift();
891 ret = cross_spawn.sync(cmd, args, xassign({ stdio: 'inherit' }, options));
892 xassert(ret.status === 0, ERR$UNKNOWN, ret);
893 return [2 /*return*/, ret];
894 case 1:
895 err_4 = _a.sent();
896 return [4 /*yield*/, xwarn(err_4)];
897 case 2:
898 _a.sent();
899 xthrow(err_4);
900 return [3 /*break*/, 3];
901 case 3: return [2 /*return*/];
902 }
903 });
904 });
905}
906// 对于数组嵌套回调函数的nodejs异步处理方法的统一封装
907function xmap(values, callack) {
908 return __awaiter(this, void 0, void 0, function () {
909 return __generator(this, function (_a) {
910 xassert(_.isArray(values) && _.isFunction(callack));
911 return [2 /*return*/, Promise.all(values.map(callack))];
912 });
913 });
914}
915// Refer to document: https://help.aliyun.com/document_detail/62670.html
916// 获取ACM配置信息接口的统一封装
917function xacm(group, id) {
918 return __awaiter(this, void 0, void 0, function () {
919 var cfg, acm;
920 var _this = this;
921 return __generator(this, function (_a) {
922 cfg = xconfig("plugins.acm");
923 xassert(cfg && cfg[group], ERR$CONFIG, { cfg: cfg });
924 acm = new ACMClient(cfg[group]);
925 return [2 /*return*/, new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
926 return __generator(this, function (_a) {
927 try {
928 co(function () {
929 var content, err_5;
930 return __generator(this, function (_a) {
931 switch (_a.label) {
932 case 0:
933 _a.trys.push([0, 2, , 3]);
934 return [4 /*yield*/, acm.getConfig(id, group)];
935 case 1:
936 content = _a.sent();
937 xassert(content, ERR$CONFIG);
938 resolve(content);
939 return [3 /*break*/, 3];
940 case 2:
941 err_5 = _a.sent();
942 xthrow(err_5, reject, { id: id, group: group, cfg: cfg[group] });
943 return [3 /*break*/, 3];
944 case 3: return [2 /*return*/];
945 }
946 });
947 });
948 }
949 catch (err) {
950 xthrow(err, reject, { id: id, group: group, cfg: cfg[group] });
951 }
952 return [2 /*return*/];
953 });
954 }); })];
955 });
956 });
957}
958if (!global['__env__']) {
959 global['__env__'] = 'local'; // local,daily,pre,gray,prod 在统一入口处自动识别配置(目前暂不支持gray配置尚未开发无法自动识别)
960}
961global['__config__'] = undefined;
962global['__session__'] = {};
963global['__cache__'] = {};
964global['__user__'] = {};
965global['__user_agent__'] = undefined;
966global['__client_ip__'] = undefined;
967global['__redirect_url__'] = undefined;
968global['__request_cookies__'] = {};
969global['__respond_cookies__'] = {};
970global['xconnect'] = xconnect;
971global['xnew'] = xnew;
972global['xquery'] = xquery;
973global['xcount'] = xcount;
974global['xassign'] = xassign;
975global['xconfig'] = xconfig;
976global['xthrow'] = xthrow;
977global['xassert'] = xassert;
978global['xerror'] = xerror;
979global['xroot'] = xroot;
980global['xstack'] = xstack;
981global['xwarn'] = xwarn;
982global['xlog'] = xlog;
983global['xpost'] = xpost;
984global['xget'] = xget;
985global['xsleep'] = xsleep;
986global['xredirect'] = xredirect;
987global['xcookie'] = xcookie;
988global['xismobile'] = xismobile;
989global['xsession'] = session_1.xsession;
990global['xuser'] = session_1.xuser;
991global['xcache'] = session_1.xcache;
992global['xroute'] = xroute;
993global['xmock'] = xmock;
994global['xrandom'] = xrandom;
995global['xcheck'] = xcheck;
996global['xcontainer'] = new inversify_1.Container(); // 全局单实例容器初始化
997global['xbind'] = xbind;
998global['xgot'] = xgot;
999global['YAuth'] = $$.YAuth; // 全局声明认证插件规范抽象类
1000global['xcmd'] = xcmd;
1001global['xmap'] = xmap;
1002global['xacm'] = xacm;
1003//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxpQkF3d0JBOztBQXh3QkEsT0FBTyxDQUFDLEdBQUcsQ0FBQyw0QkFBNEIsR0FBRyxHQUFHLENBQUE7QUFDOUMsNEJBQXlCO0FBQ3pCLHVDQUFtQztBQUNuQyx5Q0FBNkc7QUFDN0cscUNBQWlEO0FBQ2pELDhCQUErQjtBQUUvQixJQUFNLElBQUksR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7QUFDNUIsSUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtBQUN0RCxJQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7QUFDaEMsSUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFBO0FBQzdDLElBQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQUNuQyxJQUFNLENBQUMsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7QUFDM0IsSUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQ2hDLElBQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUNoQyxJQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUE7QUFDMUMseUNBQXlDO0FBQ3pDLGlEQUFpRDtBQUNqRCxrQ0FBa0M7QUFDbEMsK0RBQStEO0FBQy9ELHNFQUFzRTtBQUN0RSw4Q0FBOEM7QUFDOUMsV0FBVztBQUNYLEtBQUs7QUFDTCxJQUFNLGFBQWEsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUE7QUFDOUMsSUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQ2hDLElBQU0sT0FBTyxHQUFHLE9BQU8sQ0FB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QUFDckIsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbInByb2Nlc3MuZW52Lk5PREVfVExTX1JFSkVDVF9VTkFVVEhPUklaRUQgPSAnMCdcbmltcG9ydCAncmVmbGVjdC1tZXRhZGF0YSdcbmltcG9ydCB7Q29udGFpbmVyfSBmcm9tICdpbnZlcnNpZnknXG5pbXBvcnQge2dldENvbm5lY3Rpb25NYW5hZ2VyLCBDb25uZWN0aW9uLCBCYXNlRW50aXR5LCBnZXRSZXBvc2l0b3J5LCBTZWxlY3RRdWVyeUJ1aWxkZXJ9IGZyb20gJ0BieGpzL3R5cGVvcm0nXG5pbXBvcnQge3hzZXNzaW9uLCB4dXNlciwgeGNhY2hlfSBmcm9tICcuL3Nlc3Npb24nXG5pbXBvcnQgKiBhcyAkJCBmcm9tICcuL3BsdWdpbnMnXG5cbmNvbnN0IHBhdGggPSByZXF1aXJlKCdwYXRoJylcbmNvbnN0IEVycm9yU3RhY2tQYXJzZXIgPSByZXF1aXJlKCdlcnJvci1zdGFjay1wYXJzZXInKVxuY29uc3QgY29va2llID0gcmVxdWlyZSgnY29va2llJylcbmNvbnN0IE1vYmlsZURldGVjdCA9IHJlcXVpcmUoJ21vYmlsZS1kZXRlY3QnKVxuY29uc3QgZmV0Y2ggPSByZXF1aXJlKCdub2RlLWZldGNoJylcbmNvbnN0IF8gPSByZXF1aXJlKCdsb2Rhc2gnKVxuY29uc3QgbW9tZW50ID0gcmVxdWlyZSgnbW9tZW50JylcbmNvbnN0IGV4dGVuZCA9IHJlcXVpcmUoJ2V4dGVuZCcpXG5jb25zdCBxdWVyeXN0cmluZyA9IHJlcXVpcmUoJ3F1ZXJ5c3RyaW5nJylcbi8vIGNvbnN0IHBhcmFtZXRlciA9IHJlcXVpcmUoJ3BhcmFtZXRlcicpXG4vLyBjb25zdCBwYXJhbWV0ZXJDaGVja0luc3RhbmNlID0gbmV3IHBhcmFtZXRlcih7XG4vLyAgICAgLy8gdHJhbnNsYXRlOiBmdW5jdGlvbiAoKSB7XG4vLyAgICAgLy8gICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbi8vICAgICAvLyAgICAgLy8gQXNzdW1lIHRoZXJlIGhhdmUgSTE4bi50IG1ldGhvZCBmb3IgY29udmVydCBsYW5ndWFnZS5cbi8vICAgICAvLyAgICAgcmV0dXJuIEkxOG4udC5hcHBseShJMThuLCBhcmdzKTtcbi8vICAgICAvLyB9XG4vLyB9KVxuY29uc3QgY2lyY3VsYXJfanNvbiA9IHJlcXVpcmUoXCJjaXJjdWxhci1qc29uXCIpXG5jb25zdCBtb2NranMgPSByZXF1aXJlKCdtb2NranMnKVxuY29uc3Qgc2hvcnRpZCA9IHJlcXVpcmUoJ3Nob3J0aWQnKVxuY29uc3QgdmFsaWRhdG9yanMgPSByZXF1aXJlKCd2YWxpZGF0b3JqcycpXG5jb25zdCBjcm9zc19zcGF3biA9IHJlcXVpcmUoJ2Nyb3NzLXNwYXduJylcbmNvbnN0IEFDTUNsaWVudCA9IHJlcXVpcmUoJ2FjbS1jbGllbnQnKVxuY29uc3QgY28gPSByZXF1aXJlKCdjbycpXG5cbi8vIEZJWE1FIEhBQ0vljp/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+WvueixoeeahEpTT07lrZfnrKbkuLLlhoXlrrnnmoTlrozmlbTovpPlh7rvvIlcbiAgICBsZXQgc291cmNlID0gX19nZXRfYmFzZV9mdW5jX2NhbGxlcl9zb3VyY2VfcG9zaXRpb24oKVxuICAgIGxldCBvdXRwdXQgPSBjaXJjdWxhcl9qc29uLnN0cmluZ2lmeShbLi4uYXJnc10sIG51bGwsIDQpXG4gICAgaWYgKGdsb2JhbFsnX19lbnZfXyddICE9ICdwcm9kJyAmJiAhL15cXC9jb2RlXFwvbm9kZV9tb2R1bGVzLy50ZXN0KF9fZGlybmFtZSkpIHtcbiAgICAgICAgLy8g5omT5Y2w5Yiw5o6n5Yi25Y+w5LiA5Lu95pel5b+XKOWcqOmYv+mHjOS6kemdnue6v+S4ikZD546v5aKD5LitKVxuICAgICAgICBjb25zb2xlLmxvZy5hcHBseSh1bmRlZmluZWQsIFtzb3VyY2UgKyBvdXRwdXRdKVxuICAgICAgICAvLyDlhpnml6Xlv5fmlofku7bliLAvdG1w5LiL5Li05pe25aSE55CG5LiA5LiLIFRPRE8g6ZyA6KaB5pS55Li657G75Ly8bG9nNGrnmoTmnKzlnLDml6Xlv5flupPku4XlnKjpnZ7nur/kuIrnjq/looPkvb/nlKjmlrnkvr/lvIDlj5HljZXmnLrml6XluLjmnLrlmajkuIrosIPor5XjgIJcbiAgICAgICAgY29uc3QgZnMgPSByZXF1aXJlKCdmcycpXG4gICAgICAgIGNvbnN0IGxvZ0ZpbGVQYXRoID0gcHJvY2Vzcy5lbnZbJ05PREVfTE9HRklMRSddID8gcHJvY2Vzcy5lbnZbJ05PREVfTE9HRklMRSddIDogJy90bXAvYnhqcy5sb2cnXG4gICAgICAgIGZzLmFwcGVuZEZpbGVTeW5jKGxvZ0ZpbGVQYXRoLCBzb3VyY2UgKyBvdXRwdXQgKyBcIlxcclxcblwiKVxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIOeUn+S6p+eOr+Wig+S4i+WPquaJk+WNsOWIsOaOp+WItuWPsOe7keWumueahFNMU+aXpeW/l+acjeWKoeWZqOS4iu+8jOW5tuS4lOmcgOimgeWOu+mZpOaOieaNouihjOS/oeaBr+WQpuWImeaJk+WNsOS8muS4jeato+W4uOOAglxuICAgICAgICBvdXRwdXQgPSBvdXRwdXQucmVwbGFjZSgvXFxyL2csICcnKS5yZXBsYWNlKC9cXG4vZywgJycpXG4gICAgICAgIGNvbnNvbGUubG9nLmFwcGx5KHVuZGVmaW5lZCwgW3NvdXJjZSArIG91dHB1dF0pXG4gICAgfVxufVxuXG4vLyAvLyDlsIbor6bnu4bplJnor6/kv6Hmga/lj4rml7blj5HpgIHliLDpkonpkonnvqTkuIrlrp7ml7blj43ppojnu5nnu7TmiqTogIVcbi8vIGF3YWl0IHh3YXJuKHtcbi8vICAgICBjb2RlLFxuLy8gICAgIC8vIFRPRE8g5aaC5L2V6K6k6K+B6YCa6L+H5LqG6I635Y+W5Yiw55So5oi35L+h5oGv5Lmf6ZyA6KaB5Y+R6YCB6L+H5Y6777yM5pa55L6/6IGU57O75a+55o6l5Lq65ZGY6L+b6KGM56uL5Yi76Zeu6aKY5aSE55CG5Y+N6aaI44CCXG4vLyAgICAgbWVzc2FnZSxcbi8vICAgICBzdGFjayxcbi8vICAgICBwYXJhbSxcbi8vIH0pXG4vLyDlsIbor6bnu4bplJnor6/kv6Hmga/lj4rml7blj5HpgIHliLDpkonpkonnvqTkuIrlrp7ml7blj43ppojnu5nnu7TmiqTogIVcbi8vIOmSiemSiUlN576k5py65Zmo5Lq65oql6K2m6YCa55+lXG5hc3luYyBmdW5jdGlvbiB4d2FybiguLi5hcmdzKSB7XG4gICAgLy8g5b6X5YiweHdhcm7mlrnms5XooqvosIPnlKjnmoTkvY3nva5cbiAgICBsZXQgc291cmNlID0gX19nZXRfYmFzZV9mdW5jX2NhbGxlcl9zb3VyY2VfcG9zaXRpb24oKVxuXG4gICAgLy8g5a+55LqO5byC5bi45Y+C5pWw6K2m5ZGK5L+h5oGv6L+b6KGM6ZSZ6K+v5YaF5a655qCH5YeG6Kej5p6QXG4gICAgaWYgKGFyZ3MubGVuZ3RoID4gMCAmJiBhcmdzWzBdIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgYXJnc1swXSA9IHhlcnJvcihhcmdzWzBdKVxuICAgIH1cblxuICAgIGxldCBvdXQgPSBbc291cmNlLCBtb21lbnQoKS5mb3JtYXQoJ1lZWVktTU0tREQgSEg6bW06c3MnKSwgey4uLmFyZ3N9XVxuXG4gICAgLy8g5LuO6YWN572u5L+h5oGv5Lit6K+75Y+W5oql6K2m6YCa55+l5Lq65omL5py65YiX6KGo5ZKM5a+55bqU55qE576k5py65Zmo5Lq655qEd2ViaG9va+eahGFjY2Vzc190b2tlbuS/oeaBr1xuICAgIGxldCBhY2Nlc3NfdG9rZW4gPSB4Y29uZmlnKCdmcmFtZXdvcmsud2Fybi5kaW5nZGluZy5hY2Nlc3NfdG9rZW4nKVxuICAgIGxldCBtb2JpbGVzID0geGNvbmZpZygnZnJhbWV3b3JrLndhcm4uZGluZ2RpbmcubW9iaWxlcycpXG4gICAgaWYgKCFhY2Nlc3NfdG9rZW4gfHwgIW1vYmlsZXMpIHtcbiAgICAgICAgYWNjZXNzX3Rva2VuID0gJzAyMGEwOWVhYzVmMmZhMzIwYWU4NTE0NDJkNWUxOWUyMzY5M2M2NGFkMjI1NWM4NTM1NGI0YTQ5YTVhNDhkMzUnXG4gICAgICAgIG1vYmlsZXMgPSBbJzE1MzgxMTUxMzQ2J11cbiAgICB9XG5cbiAgICBhd2FpdCB4cG9zdChgaHR0cHM6Ly9vYXBpLmRpbmd0YWxrLmNvbS9yb2JvdC9zZW5kP2FjY2Vzc190b2tlbj0ke2FjY2Vzc190b2tlbn1gLCB7XG4gICAgICAgIG1zZ3R5cGU6ICd0ZXh0JyxcbiAgICAgICAgdGV4dDoge1xuICAgICAgICAgICAgY29udGVudDogb3V0XG4gICAgICAgIH0sXG4gICAgICAgIGF0OiB7XG4gICAgICAgICAgICBhdE1vYmlsZXM6IG1vYmlsZXMsXG4gICAgICAgICAgICBpc0F0QWxsOiBmYWxzZVxuICAgICAgICB9XG4gICAgfSlcblxuICAgIC8vIOe6v+S4ilNMU+aXpeW/l+S4iuS5n+S/neWtmOS4gOS7vVxuICAgIC8vIGNvbnNvbGUud2FybihvdXQpXG4gICAgeGxvZyhvdXQpXG59XG5cbi8vIOaNleiOt+acquebkeWQrOWIsOeahOW8guW4uOiusOW9leWQjuebtOaOpemAgOWHuu+8iOi/kOihjOWghuagiOW3sue7j+egtOWdj+ebtOaOpeiusOW9leaXpeW/l+WQjuW8guW4uOmAgOWHuuWNs+WPr++8jOeUseWklumDqOebkeaOp+iHquWKqOmHjeWQr++8iVxucHJvY2Vzcy5vbigndW5jYXVnaHRFeGNlcHRpb24nLCBhc3luYyBmdW5jdGlvbiAoZXJyKSB7XG4gICAgeGxvZyh4ZXJyb3IoZXJyKSlcbiAgICBhd2FpdCB4d2FybihlcnIpXG4gICAgcHJvY2Vzcy5leGl0KC0xKVxufSlcblxuLy8g6K6w5b2VYXdhaXQvYXN5bmPkuK3lh7rnjrDmnKrmjZXojrfnmoTlvILluLjplJnor69cbnByb2Nlc3Mub24oJ3VuaGFuZGxlZFJlamVjdGlvbicsIGFzeW5jIChyZWFzb24sIHApID0+IHtcbiAgICB4bG9nKCdVbmhhbmRsZWQgUmVqZWN0aW9uIGF0OiBQcm9taXNlJywgcCwgJ3JlYXNvbjonLCByZWFzb24pO1xuICAgIC8vIGFwcGxpY2F0aW9uIHNwZWNpZmljIGxvZ2dpbmcsIHRocm93aW5nIGFuIGVycm9yLCBvciBvdGhlciBsb2dpYyBoZXJlXG4gICAgYXdhaXQgeHdhcm4ocmVhc29uLCBwKVxuICAgIHByb2Nlc3MuZXhpdCgtMSlcbn0pXG5cbi8vIGFzeW5jL2F3YWl055qE6Z2e6Zi75aGe5byC5q2l5bu26L+f5pa55rOV77yM55So5LqO6LCD6K+V6Zi75aGe56iL5bqP55qE5omn6KGM6L+b6KGM5Y2V5q2l6LCD6K+V55qE5pWI5p6c44CCXG5jb25zdCBzbGVlcCA9IHJlcXVpcmUoJ3NsZWVwLWFzeW5jJykoKVxuXG5leHBvcnQgZnVuY3Rpb24geHNsZWVwKG1zOiBudW1iZXIgPSAtMSkge1xuICAgIGlmIChtcyA8PSAwKSB7XG4gICAgICAgIG1zID0gNTAgKiAzNjUgKiAyNCAqIDM2MDAgKiAxMDAwIC8vIDUw5bm05pyA5aSn5pWw6KeG5Li65rC45LmF6Zi75aGe5pa55L6/5pat54K55Y2V5q2l6LCD6K+V6Zeu6aKYXG4gICAgfVxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzbGVlcC5zbGVlcChtcywgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICB4bG9nKHhlcnJvcihlcnIpKVxuICAgICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgICAgICAvLyB4dGhyb3coZXJyLHJlamVjdClcbiAgICAgICAgfVxuICAgIH0pXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB4cG9zdCh1cmw6IHN0cmluZywgcGFyYW0/OiB7IFtwcm9wTmFtZTogc3RyaW5nXTogYW55IH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVycz86IHsgW3Byb3BOYW1lOiBzdHJpbmddOiBhbnkgfSwgdGltZW91dDogbnVtYmVyID0gMzAwMCkge1xuICAgIC8vIFRPRE8g57q/5LiK5rWL6K+V5LiN56iz5a6a6LaF5pe25pqC5pe25b+955Wl5o6J6YCa6L+H6L+b56iL5pyA5aSn6L+Q6KGM5pe26Ze05Y675o6n5Yi26LaF5pe25aSx6LSlXG4gICAgdGltZW91dCA9IDUwMDAgLy8gLTEg5LiN6KGM57q/5LiK5Lya6KKr6Zi75aGe5L2P5YO15q27XG4gICAgbGV0IHJlczogYW55ID0gbnVsbFxuICAgIGxldCBqc29uOiBhbnkgPSBudWxsXG4gICAgbGV0IHRleHQ6IGFueSA9IG51bGxcbiAgICB0cnkge1xuICAgICAgICByZXMgPSBhd2FpdCBmZXRjaCh1cmwsIHtcbiAgICAgICAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkocGFyYW0pLFxuICAgICAgICAgICAgaGVhZGVyczogeydDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsIC4uLmhlYWRlcnN9LFxuICAgICAgICAgICAgdGltZW91dDogdGltZW91dCA8PSAwID8gMCA6IHRpbWVvdXQsIC8vIOm7mOiupDPnp5LotoXml7bmjqXlj6Pov5Tlm57pgb/lhY3lg7XmrbtcbiAgICAgICAgfSlcbiAgICAgICAgdGV4dCA9IGF3YWl0IHJlcy50ZXh0KCkgLy8g6Kej5p6Q5Ye65a6M5pW055qE6L+U5Zue5YaF5a656YG/5YWNSFRNTOS7peWPiumdnuazleagvOW8j+S/oeaBr+S+v+S6juato+ehruaKpemUmeWumuS9jeWQjuerr+aOpeWPo+mUmeivr1xuICAgICAgICBqc29uID0gSlNPTi5wYXJzZSh0ZXh0KVxuICAgICAgICByZXR1cm4ganNvblxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICB4dGhyb3coZXJyLCB7dXJsLCBwYXJhbSwgaGVhZGVycywgdGV4dH0pXG4gICAgfVxufVxuXG4vLyDpu5jorqTotoXml7YzMDAw5q+r56eSXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24geGdldCh1cmw6IHN0cmluZywgcGFyYW0/OiB7IFtwcm9wTmFtZTogc3RyaW5nXTogYW55IH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJzPzogeyBbcHJvcE5hbWU6IHN0cmluZ106IGFueSB9LCB0aW1lb3V0OiBudW1iZXIgPSAzMDAwKSB7XG4gICAgLy8gVE9ETyDnur/kuIrmtYvor5XkuI3nqLPlrprotoXml7bmmoLml7blv73nlaXmjonpgJrov4fov5vnqIvmnIDlpKfov5DooYzml7bpl7TljrvmjqfliLbotoXml7blpLHotKVcbiAgICB0aW1lb3V0ID0gNTAwMCAvLyAtMSDkuI3ooYznur/kuIrkvJrooqvpmLvloZ7kvY/lg7XmrbtcbiAgICBsZXQgcmVzOiBhbnkgPSBudWxsXG4gICAgbGV0IGpzb246IGFueSA9IG51bGxcbiAgICBsZXQgdGV4dDogYW55ID0gbnVsbFxuICAgIHRyeSB7XG4gICAgICAgIHVybCA9IHVybCArIChwYXJhbSA/ICc/JyA6ICcnKSArIHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeShwYXJhbSlcbiAgICAgICAgcmVzID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgICAgICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgICAgICAgaGVhZGVyczogeydDb250ZW50LVR5cGUnOiAnYXBwbGljYXRpb24vanNvbicsIC4uLmhlYWRlcnN9LFxuICAgICAgICAgICAgdGltZW91dDogdGltZW91dCA8PSAwID8gMCA6IHRpbWVvdXQsIC8vIOm7mOiupDPnp5LotoXml7bmjqXlj6Pov5Tlm57pgb/lhY3lg7XmrbtcbiAgICAgICAgfSlcbiAgICAgICAgdGV4dCA9IGF3YWl0IHJlcy50ZXh0KCkgLy8g6Kej5p6Q5Ye65a6M5pW055qE6L+U5Zue5YaF5a656YG/5YWNSFRNTOS7peWPiumdnuazleagvOW8j+S/oeaBr+S+v+S6juato+ehruaKpemUmeWumuS9jeWQjuerr+aOpeWPo+mUmeivr1xuICAgICAgICBqc29uID0gSlNPTi5wYXJzZSh0ZXh0KVxuICAgICAgICByZXR1cm4ganNvblxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICB4dGhyb3coZXJyLCB7dXJsLCBwYXJhbSwgaGVhZGVycywgdGV4dH0pXG4gICAgfVxufVxuXG4vLyAzMDLkuLTml7bph43lrprlkJHot7Povazlrp7njrBcbmV4cG9ydCBmdW5jdGlvbiB4cmVkaXJlY3QodXJsOiBzdHJpbmcsIHBhcmFtOiBhbnkgPSB7fSkge1xuICAgIC8vIFRPRE8g5aSa5Liq56iL5bqP5a6e5L6L5bm25Y+R5aSE55CG55qE5pe25YCZ5a2Y5Zyo5pe25bqP6Zeu6aKY5LiN6IO95L+d6K+B5YWo5bGA5Y+Y6YeP6KKr5YeG56Gu5riF56m644CCXG4gICAgLy8g5qOA5p+l5bqU55So6YeN5aSN6K6+572u6YeN5a6a5ZCR5Zyw5Z2A5pyq5Y+K5pe2cmV0dXJu6L+U5Zue5o6n5Yi25Zmo6Zeu6aKYXG4gICAgeGFzc2VydChnbG9iYWxbJ19fcmVkaXJlY3RfdXJsX18nXSA9PT0gdW5kZWZpbmVkKVxuICAgIGlmIChwYXJhbSkge1xuICAgICAgICB4YXNzZXJ0KF8uaXNQbGFpbk9iamVjdChwYXJhbSkpXG4gICAgICAgIC8vIOWIoOmZpHBhcmFt5Lit5Lik5Liq5qGG5p626aKE5a6a5LmJ5Y+C5pWwX191cmxfX+WSjF9fYXBpX1/kuI3lhYHorrjov5vooYzlj4LmlbDkvKDpgJLvvIjnpoHmraLkuJrliqHpgLvovpHkvb/nlKjpgb/lhY3moYbmnrblkI7nu63ljYfnuqfku6Xlj4rkuI7nn63nvZHlnYDlip/og73lhrLnqoHvvIlcbiAgICAgICAgZGVsZXRlIHBhcmFtLl9fYXBpX19cbiAgICAgICAgZGVsZXRlIHBhcmFtLl9fdXJsX19cbiAgICAgICAgLy8g6KGl6aKd5aSW55qE6ZmE5Yqg5Y+C5pWwXG4gICAgICAgIGlmICgvXFw/Ly50ZXN0KHVybCkpIHtcbiAgICAgICAgICAgIHVybCArPSAnJidcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHVybCArPSAnPydcbiAgICAgICAgfVxuICAgICAgICB1cmwgKz0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHBhcmFtKVxuICAgIH1cbiAgICBnbG9iYWxbJ19fcmVkaXJlY3RfdXJsX18nXSA9IHVybFxufVxuXG4vLyDlpoLmnpzlj6rmnIlrZXnlj4LmlbDooajnpLror7vlj5blsZ7mgKfvvIjnvLrnnIHlgLzkuLp1bmRlZmluZWTvvInvvIzlpoLmnpxrZXnkuLrnqbrooajnpLror7vlj5bmiYDmnInnmoTor7fmsYJjb29raWVz5bGe5oCn77yM5ZCm5YiZ6KGo56S65ZON5bqU6K6+572uY29va2llc1xuZXhwb3J0IGZ1bmN0aW9uIHhjb29raWUoa2V5Pzogc3RyaW5nLCB2YWx1ZT86IHN0cmluZywgb3B0aW9uPzoge30pOiBhbnkge1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAvLyDor7vlj5bmiYDmnInnmoTor7fmsYJjb29raWVz5bGe5oCnb2JqZWN0XG4gICAgICAgIHJldHVybiBnbG9iYWxbJ19fcmVxdWVzdF9jb29raWVzX18nXSA/IGdsb2JhbFsnX19yZXF1ZXN0X2Nvb2tpZXNfXyddIDoge31cbiAgICB9IGVsc2UgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT0gMSkge1xuICAgICAgICByZXR1cm4ga2V5ID8geGNvb2tpZSgpW2tleV0gOiB1bmRlZmluZWRcbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZ2xvYmFsWydfX3Jlc3BvbmRfY29va2llc19fJ10gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgZ2xvYmFsWydfX3Jlc3BvbmRfY29va2llc19fJ10gPSB7fVxuICAgICAgICB9XG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgIC8vIENPT0tJRVPnvLrnnIHlsZ7mgKforr7nva7vvIjmnInmlYjml7bpl7QyNOWwj+aXtuW5tuS4lOe7n+S4gOWFs+iBlOWIsOaguemhtemdouS4iuiOt+WPlkNPT0tJRVPlgLzvvIlcbiAgICAgICAgICAgIG9wdGlvbiA9IHhhc3NpZ24oe3BhdGg6ICcvJywgbWF4QWdlOiAyNCAqIDM2MDB9LCBvcHRpb24pXG4gICAgICAgICAgICBnbG9iYWxbJ19fcmVzcG9uZF9jb29raWVzX18nXVtrZXldID0gY29va2llLnNlcmlhbGl6ZShrZXksIHZhbHVlLCBvcHRpb24pXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuXG4gICAgfVxufVxuXG4vLyDliKTmlq11c2VyLWFnZW506K+35rGC5piv5ZCm5Li656e75Yqo56uvXG5mdW5jdGlvbiB4aXNtb2JpbGUoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgbWQgPSBuZXcgTW9iaWxlRGV0ZWN0KGdsb2JhbFsnX191c2VyX2FnZW50X18nXSlcbiAgICByZXR1cm4gISFtZC5tb2JpbGUoKVxufVxuXG5mdW5jdGlvbiB4YXNzaWduKHRhcmdldCwgc291cmNlLCAuLi5hcmdzKSB7XG4gICAgY29uc3QgcGFyYW0gPSBbdHJ1ZSwgdGFyZ2V0LCBzb3VyY2UsIC4uLmFyZ3NdXG4gICAgcmV0dXJuIGV4dGVuZC5hcHBseShudWxsLCBwYXJhbSlcbn1cblxuLy8g5p+l6K+iYXBwL2NvbmZpZ+ebruW9leS4i+eahOW6lOeUqOmFjee9ruaVsOaNrlxuZnVuY3Rpb24geGNvbmZpZyhwYXRoOiBzdHJpbmcsIGRlZmF1bHRWYWx1ZTogYW55ID0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKGdsb2JhbFsnX19jb25maWdfXyddKSB7XG4gICAgICAgIHJldHVybiBfLmdldChnbG9iYWxbJ19fY29uZmlnX18nXSwgcGF0aCwgZGVmYXVsdFZhbHVlKVxuICAgIH1cblxuICAgIGNvbnN0IGZwID0gcmVxdWlyZSgncGF0aCcpXG4gICAgY29uc3QgZnMgPSByZXF1aXJlKCdmcycpXG4gICAgLy8g6Ieq5Yqo6I635Y+WYXBwL2NvbmZpZ+eahOebuOWvuei3r+W+hOebruW9leS9jee9ruW+l+WIsOaguei3r+W+hOeahOS9jee9rlxuICAgIGxldCBjb25maWdfcGF0aCA9ICcnXG4gICAgaWYgKF9fZGlybmFtZS5pbmNsdWRlcygnL25vZGVfbW9kdWxlcy9AYnhqcy9iYXNlLycpKSB7XG4gICAgICAgIC8vIOWcqOW6lOeUqOebruW9leS4i1xuICAgICAgICBjb25maWdfcGF0aCA9IGZwLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vLi4vLi4vYXBwL2NvbmZpZycpXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8g5ZyoYXhqc+W6k+W8gOWPkeebruW9leS4i1xuICAgICAgICBjb25maWdfcGF0aCA9IGZwLmpvaW4oX19kaXJuYW1lLCAnLi4vYXBwL2NvbmZpZycpXG4gICAgfVxuXG4gICAgLy8g6Ieq5Yqo6K+G5Yir5Yik5pat6L+Q6KGM546v5aKDZ2xvYmFsWydfX2Vudl9fJ13lubbkuJTliqDovb3lr7nlupTnmoRiYXNl5pWw5o2u5ZKMZW525pWw5o2uXG4gICAgY29uc3QgY29uZmlnX2Jhc2VfcGF0aCA9IGNvbmZpZ19wYXRoICsgJy9jb25maWcuYmFzZS4nICsgZ2V0X3N1ZmZpeF90c19vcl9qcygpXG4gICAgY29uc3QgY29uZmlnX2Vudl9wYXRoID0gY29uZmlnX3BhdGggKyBgL2NvbmZpZy4ke2dsb2JhbFsnX19lbnZfXyddfS5gICsgZ2V0X3N1ZmZpeF90c19vcl9qcygpXG4gICAgaWYgKCFmcy5leGlzdHNTeW5jKGNvbmZpZ19iYXNlX3BhdGgpKSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0VmFsdWVcbiAgICB9XG4gICAgbGV0IGNvbmZpZ19iYXNlID0gcmVxdWlyZShjb25maWdfYmFzZV9wYXRoKS5kZWZhdWx0XG4gICAgbGV0IGNvbmZpZ19lbnYgPSB7fVxuICAgIGlmIChmcy5leGlzdHNTeW5jKGNvbmZpZ19lbnZfcGF0aCkpIHtcbiAgICAgICAgY29uZmlnX2VudiA9IHJlcXVpcmUoY29uZmlnX2Vudl9wYXRoKS5kZWZhdWx0XG4gICAgfVxuICAgIC8vIGJ1Z2ZpeCBPYmplY3QuYXNzaWdu5LiN5pSv5oyB5rex5bqm5ou36LSd6Zeu6aKYXG4gICAgLy8gZ2xvYmFsWydfX2NvbmZpZ19fJ10gPSBPYmplY3QuYXNzaWduKHt9LCBjb25maWdfYmFzZSwgY29uZmlnX2VudilcbiAgICAvLyBnbG9iYWxbJ19fY29uZmlnX18nXSA9IF8uYXNzaWduKHt9LCBjb25maWdfZW52LCBjb25maWdfYmFzZSlcbiAgICBnbG9iYWxbJ19fY29uZmlnX18nXSA9IHhhc3NpZ24oe30sIGNvbmZpZ19iYXNlLCBjb25maWdfZW52KVxuICAgIHJldHVybiBfLmdldChnbG9iYWxbJ19fY29uZmlnX18nXSwgcGF0aCwgZGVmYXVsdFZhbHVlKVxufVxuXG5hc3luYyBmdW5jdGlvbiB4Y29ubmVjdChjYWxsYmFjazogKGNvbm5lY3Q6IENvbm5lY3Rpb24pID0+IFByb21pc2U8YW55PiwgY29uZmlnID0gJ2RlZmF1bHQnKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgbGV0IGNmZyA9IHt9IGFzIGFueVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY2ZnID0geGFzc2lnbih7fSwgeGNvbmZpZygncGx1Z2lucy5kYXRhYmFzZS5kZWZhdWx0Jywge30pKVxuICAgICAgICAgICAgeGFzc2VydCghXy5pc0VtcHR5KGNmZyksIEVSUiRQQVJBTSwge2NvbmZpZ30pXG4gICAgICAgICAgICAvLyDlvLrliLbooaXkuIrnuqblrprnmoTlrp7kvZPlrZjmlL7ot6/lvoTlrprkuYnkvY3nva7vvIjkuI3lhYHorrjphY3nva7mmK/nuqblrprop4TojIPvvIlcbiAgICAgICAgICAgIGlmIChfX2Rpcm5hbWUuaW5jbHVkZXMoJy9ub2RlX21vZHVsZXMvQGJ4anMvYmFzZS8nKSkge1xuICAgICAgICAgICAgICAgIC8vIOWcqOW6lOeUqOebruW9leS4i1xuICAgICAgICAgICAgICAgIGNmZ1snZW50aXRpZXMnXSA9IFtcbiAgICAgICAgICAgICAgICAgICAgcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uLy4uLy4uLy4uL2FwcC9wbHVnaW5zL2RhdGFiYXNlL2VudGl0eS8qLicgKyBnZXRfc3VmZml4X3RzX29yX2pzKCkpXG4gICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyDlnKhheGpz5bqT5byA5Y+R55uu5b2V5LiLXG4gICAgICAgICAgICAgICAgY2ZnWydlbnRpdGllcyddID0gW1xuICAgICAgICAgICAgICAgICAgICBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vYXBwL3BsdWdpbnMvZGF0YWJhc2UvZW50aXR5LyouJyArIGdldF9zdWZmaXhfdHNfb3JfanMoKSlcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyDojrflj5bov57mjqXmsaDkuK3nmoTpk77mjqVcbiAgICAgICAgICAgIGNvbnN0IG1uZyA9IGdldENvbm5lY3Rpb25NYW5hZ2VyKClcbiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBjZmcubmFtZSA/IGNmZy5uYW1lIDogJ2RlZmF1bHQnXG4gICAgICAgICAgICBpZiAoIW1uZy5oYXMobmFtZSkpIHtcbiAgICAgICAgICAgICAgICBtbmcuY3JlYXRlKGNmZylcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGRiID0gbW5nLmdldChuYW1lKVxuICAgICAgICAgICAgaWYgKGdsb2JhbFsnX19jb25uZWN0aW9uX18nXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgZ2xvYmFsWydfX2Nvbm5lY3Rpb25fXyddID0ge31cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghZGIuaXNDb25uZWN0ZWQpIHsgLy8gVE9ETyDpnIDopoHov5vooYzov57mjqXmsaDnmoTnrqHnkIZcbiAgICAgICAgICAgICAgICBnbG9iYWxbJ19fY29ubmVjdGlvbl9fJ11bbmFtZV0gPSBkYi5jb25uZWN0KClcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IGdsb2JhbFsnX19jb25uZWN0aW9uX18nXVtuYW1lXS50aGVuKGFzeW5jIGNvbm5lY3Rpb24gPT4ge1xuICAgICAgICAgICAgICAgIHhhc3NlcnQoZGIuaXNDb25uZWN0ZWQpXG4gICAgICAgICAgICAgICAgY29uc3Qgb3V0ID0gYXdhaXQgY2FsbGJhY2soY29ubmVjdGlvbilcbiAgICAgICAgICAgICAgICAvLyBhd2FpdCBkYi5jbG9zZSgpIC8vIHR5cGVvcm3msqHmnInov5vooYzov57mjqXmsaDnmoTnrqHnkIbkuI3og73ov5vooYzplIDmr4FcbiAgICAgICAgICAgICAgICByZXNvbHZlKG91dClcbiAgICAgICAgICAgIH0pLmNhdGNoKGFzeW5jIGVyciA9PiB7XG4gICAgICAgICAgICAgICAgLy8gYXdhaXQgZGIuY2xvc2UoKVxuICAgICAgICAgICAgICAgIHh0aHJvdyhlcnIsIHJlamVjdCwge2NmZ30pXG4gICAgICAgICAgICB9KVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIHh0aHJvdyhlcnIsIHJlamVjdCwge2NmZ30pXG4gICAgICAgIH1cbiAgICB9KVxufVxuXG4vLyDliJvlu7pYQmFzZUVudGl0eeWvueixoeW5tuS4lOiHquWKqOi1i+WAvOWJjeerr+ivt+axgueahOi1i+WAvOaVsOaNrlxuZnVuY3Rpb24geG5ldzxUIGV4dGVuZHMgQmFzZUVudGl0eT4oVFlQRTogbmV3ICgpID0+IFQsIHBhcmFtPzogYW55LCAuLi5hcmdzKTogVCB7XG4gICAgLy8g5rOb5Z6L5a6e546w57G75Ly86L+Z5Liq5Yqf6IO9XG4gICAgLy8gYXNzZXQgPSBuZXcgQWxpbGFuZ0Fzc2V0KClcbiAgICAvLyBnZXRSZXBvc2l0b3J5KEFsaWxhbmdBc3NldCkubWVyZ2UoYXNzZXQsIHBhcmFtIGFzIGFueSlcbiAgICAvLyBBbGlsYW5nQXNzZXQubWVyZ2UoYXNzZXQsIHBhcmFtIGFzIGFueSlcbiAgICAvLyByZXR1cm4gYXNzZXRcbiAgICBsZXQgb2JqID0gbmV3IFRZUEUoKVxuICAgIGlmIChfLmlzRW1wdHkocGFyYW0pKSB7XG4gICAgICAgIHJldHVybiBvYmpcbiAgICB9XG4gICAgbGV0IHJlcG8gPSBnZXRSZXBvc2l0b3J5PFQ+KFRZUEUpXG4gICAgcmVwby5tZXJnZS5hcHBseShyZXBvLCBbb2JqLCBwYXJhbSwgLi4uYXJnc10pXG4gICAgcmV0dXJuIG9ialxufVxuXG4vLyDmn6Xor6LmnoTpgKDlmajmmJPnlKjmgKflsIHoo4VcbmZ1bmN0aW9uIHhxdWVyeTxUPihjb25uZWN0OiBDb25uZWN0aW9uLCBUWVBFOiBuZXcgKCkgPT4gVCwgYWxpYXM/OiBzdHJpbmcpOiBTZWxlY3RRdWVyeUJ1aWxkZXI8VD4ge1xuICAgIHJldHVybiBjb25uZWN0LmdldFJlcG9zaXRvcnkoVFlQRSkuY3JlYXRlUXVlcnlCdWlsZGVyKGFsaWFzKVxufVxuXG4vLyDliIbpobXmn6Xor6Lojrflj5bmgLvmlbDku6Xlj4rljp/lp4vorrDlvZXmlbDmja5cbmFzeW5jIGZ1bmN0aW9uIHhjb3VudDxUPihzcWw6IFNlbGVjdFF1ZXJ5QnVpbGRlcjxUPiwgcGFnZTogbnVtYmVyLCBzaXplOiBudW1iZXIpOiBQcm9taXNlPFthbnlbXSB8IG51bGwsIG51bWJlcl0+IHtcbiAgICB4YXNzZXJ0KHBhZ2UgPj0gMSlcbiAgICBjb25zdCBbY291bnQsIHJvd3NdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICBzcWwuZ2V0Q291bnQoKSxcbiAgICAgICAgc3FsLm9mZnNldCgocGFnZSAtIDEpICogc2l6ZSkubGltaXQoc2l6ZSkuZ2V0UmF3TWFueSgpXG4gICAgXSlcbiAgICByZXR1cm4gW3Jvd3MsIGNvdW50XVxufVxuXG5cbi8vIOi3r+eUseWPguaVsOeahOS/rumlsOespumFjee9rlxuLy8gVE9ETyDmm7TlpJrmjqXlj6Pnm7jlhbPlj4LmlbDnmoTphY3nva7mianlsZXvvIzkvovlpoLvvJrmmK/lkKbmlK/mjIFKU09OUFxuZnVuY3Rpb24geHJvdXRlKHBhcmFtOiB7IG5hbWU/OiBzdHJpbmcsIGRlc2M/OiBzdHJpbmcsIHBhdGg/OiBzdHJpbmcsIGF1dGg/OiBib29sZWFuIH0pIHtcbiAgICAvLyDnvLrnnIHlgLzlpITnkIZcbiAgICBwYXJhbSA9IHhhc3NpZ24oe25hbWU6ICcnLCBkZXNjOiAnJywgcGF0aDogJycsIGF1dGg6IHRydWV9LCBwYXJhbSlcbiAgICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldDogRnVuY3Rpb24sIHByb3BlcnR5S2V5OiBzdHJpbmcsIGRlc2NyaXB0b3I6IFByb3BlcnR5RGVzY3JpcHRvcikge1xuICAgICAgICAvLyBUT0RPIOazqOWFpeWIsOexu+WunuS+i+WumuS5ieS4rei/m+ihjOWFqOWxgOW8leeUqOWKqOaAgeexu+eahOeJueaAp+a3u+WKoO+8iHRyYWl05Yqf6IO955qE5Yqo5oCB5a6e546w77yJXG4gICAgICAgIC8vIOWKqOaAgee7keWumui3r+eUseexu+WunuS+i+eahOS4iuS4i+aWh+WxnuaAp1xuICAgICAgICB0YXJnZXQucHJvdG90eXBlLmNvbnRleHQgPSAoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHBhcmFtOiBwYXJhbSwgLy8g5L+d5a2Y5b2T5YmN5o6n5Yi25Zmo55So5oi35a6a5LmJ5Y+C5pWw5L+h5oGvXG4gICAgICAgICAgICAgICAgLy8g5piv5ZCm55m75b2V55qE6Ym05p2D5pa55rOV57uf5LiA5qGG5p625bGC6Z2i5LiK55qE5aSE55CG5a6e546w77yM5q2k5aSE5LuF5LuF5piv6YCa55So5o6l5Y+j55qE57qm5p2f55qE5a6a5LmJ44CCXG4gICAgICAgICAgICAgICAgYXV0aDogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyDosIPnlKjnmbvlvZXlip/og73nmoTliY3nq6/mjqXlj6Plrp7njrDvvIzlj5bliLDlr7nlupTnmoTlrp7njrDmlrnms5XjgIJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtICYmIHBhcmFtLmF1dGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIOmcgOimgemJtOadg+i/m+ihjOS8muivneacieaViOaAp+i/m+ihjOWQiOazleaAp+agoemqjOWkhOeQhu+8ge+8gVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8g5pyq6K6k6K+B6ZSZ6K+v5oqb5Ye65aSE55CG77yM5YmN56uv5Y2V6aG15bqU55So5o6l5Y+j5oql6ZSZ6YC76L6R5aSE55CG5q2j56Gu6ZSZ6K+v5o+Q56S66Lez6L2s44CCXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhdXRoID0geGdvdChZQXV0aClcbiAgICAgICAgICAgICAgICAgICAgICAgIHhhc3NlcnQoYXdhaXQgYXV0aC5nZXRMb2dpblN0YXR1cygpLCBFUlIkVU5BVVRIT1JJWkVEKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyDlrozlhajmsqHmnInlv4XopoHnmoTlpJrkvZnlrprkuYnvvIzpnIDopoHpgJrov4dNT0NL5a6a5LmJ6L+b6KGM57uG6IqC5pWw5o2u57G75Z6L55qE5pi+5oCn5a6a5LmJ5aSE55CG6YC76L6R6aqM6K+B44CCXG4vLyAvLyDln7rmnKzmlbDmja7nsbvlnovnmoTop4TojIPmianlsZXlrprkuYnvvIzmlrnkvr9BUEnmjqXlj6PnmoTlrprkuYnku6Xlj4rlvaLlj4Loh6rliqjpqozor4HlkIjms5XmgKfvvIzlubbkuJTkuI7mlbDmja7lupPmlbDmja7nsbvlnovkv53mjIHkuIDoh7TjgIJcbi8vIHR5cGUgSU5UID0gbnVtYmVyICAgLy8g5pyJ56ym5Y+35pW05pWwXG4vLyB0eXBlIFVJTlQgPSBudW1iZXIgIC8vIOaXoOespuWPt+aVtOaVsFxuLy8gdHlwZSBERUNJTUFMID0gbnVtYmVyIC8vIOeyvuehruWwj+aVsFxuLy8gdHlwZSBGTE9BVCA9IG51bWJlciAvLyDljZXnsr7luqbmta7ngrnmlbDvvIjkuI3nsr7noa7lsI/mlbDvvIlcbi8vIHR5cGUgRE9VQkxFID0gbnVtYmVyLy8g5Y+M57K+5bqm5rWu54K55pWw77yI5LiN57K+56Gu5bCP5pWw77yJXG4vLyB0eXBlIEJPT0wgPSBib29sZWFuXG4vLyB0eXBlIFNUUiA9IHN0cmluZ1xuLy8gdHlwZSBEQVRFID0gc3RyaW5nIC8vIOW5tOaciOaXpSAnMjAxNy0wNi0yNSdcbi8vIHR5cGUgVElNRSA9IHN0cmluZyAvLyDml7bliIbnp5IgJzAwOjAwOjAwJ1xuLy8gdHlwZSBEQVRFVElNRSA9IHN0cmluZyAvLyDlubTmnIjml6Xml7bliIbnp5IgJzIwMTctMDYtMjUgMDA6MDA6MDAnXG5cbi8vIOaooeaLn+aVsOaNruaooeadv+WumuS5ieS9v+eUqOaVmeeoiyBodHRwOi8vbW9ja2pzLmNvbS8wLjEvIyVFNiU5NSVCMCVFNiU4RCVBRSVFNSU4RCVBMCVFNCVCRCU4RCVFNyVBQyVBNiVFNSVBRSU5QSVFNCVCOSU4OSUyMERQRFxuZnVuY3Rpb24geG1vY2s8VD4ocnVsZXM6IFQpOiBhbnkge1xuICAgIHJldHVybiBtb2NranMubW9jayhydWxlcylcbn1cblxuZnVuY3Rpb24geHJhbmRvbShuYW1lOiBzdHJpbmcsIGRhdGE6IGFueVtdKSB7XG4gICAgbW9ja2pzLlJhbmRvbS5leHRlbmQoe1xuICAgICAgICBbbmFtZV06ICguLi5hcmdzKSA9PiB7XG4gICAgICAgICAgICB4YXNzZXJ0KGRhdGEubGVuZ3RoID4gMClcbiAgICAgICAgICAgIGlmIChkYXRhLmxlbmd0aCA9PSAxKSByZXR1cm4gZGF0YVswXVxuICAgICAgICAgICAgbGV0IG1heCA9IGRhdGEubGVuZ3RoIC0gMVxuICAgICAgICAgICAgbGV0IGlkeCA9IHhtb2NrKGBAaW50KDAsJHttYXh9KWApXG4gICAgICAgICAgICByZXR1cm4gZGF0YVtpZHhdXG4gICAgICAgIH1cbiAgICB9KVxufVxuXG4vLyDmianlsZXkuIDkupvpooTlrprkuYlieGpz55qE5Z+656GA6ZqP5py65pa55rOV5oiW6ICF6KaG55uW5LiA5LqbbW9ja2pz5Lit55qE5pa55rOVXG5tb2NranMuUmFuZG9tLmV4dGVuZCh7XG4gICAgLy8gYnhqc+ihqOWumuS5ieeahOS4u+mUrue7n+S4gOWumuS5ie+8iOe6puWumuezu+e7n+S4reS4uuWtl+espuS4sjctMTTlrZfoioLplb/luqbnrpfms5XvvIlcbiAgICBpZDogKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgcmV0dXJuIHNob3J0aWQuZ2VuZXJhdGUoKVxuICAgIH0sXG4gICAgLy8g5Lit5Zu95omL5py65Y+36ZqP5py655Sf5oiQ566X5rOVKOe6puWumuezu+e7n+S4reeahOaJi+acuuWPt+S4uuWtl+espuS4suaVsOaNruexu+WeiylcbiAgICBtb2JpbGU6ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIGNvbnN0IGlzcHMgPSBbXG4gICAgICAgICAgICAxMzQsIDEzNSwgMTM2LCAxMzcsIDEzOCwgMTM5LCAxNDcsIDE1MCwgMTUxLCAxNTIsIDE1NywgMTU4LCAxNTksIDE4MiwgMTgzLCAxODQsIDE4NywgMTg4LCAxNzgsXG4gICAgICAgICAgICAxMzAsIDEzMSwgMTMyLCAxNDUsIDE1NSwgMTU2LCAxODUsIDE4NiwgMTc2LFxuICAgICAgICAgICAgMTMzLCAxMzQsIDE1MywgMTgwLCAxODEsIDE4OSwgMTc3LCAxNzMsXG4gICAgICAgICAgICAxNzYsIDE3MywgMTc3LCAxNzgsIDE3MCxcbiAgICAgICAgICAgIDE0MCwgMTQxLCAxNDIsIDE0MywgMTQ0LCAxNDYsIDE0OCwgMTQ5LCAxNTRdXG4gICAgICAgIGxldCBtYXggPSBpc3BzLmxlbmd0aCAtIDFcbiAgICAgICAgbGV0IGlkeCA9IHhtb2NrKGBAaW50KDAsJHttYXh9KWApXG4gICAgICAgIGxldCBudW0gPSB4bW9jayhgQGludCgxMDAwMDAwMDAsMTk5OTk5OTk5KWApXG4gICAgICAgIHJldHVybiAoaXNwc1tpZHhdICogMTAwMDAwMDAwICsgbnVtICUgMTAwMDAwMDAwKSArICcnXG4gICAgfSxcbiAgICAvLyDovazmjaLkuLrnvLrnnIHkuK3mloflhoXlrrnmj5DnpLpcbiAgICBwYXJhZ3JhcGg6ICguLi5hcmdzKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICByZXR1cm4geG1vY2soJ0BjcGFyYWdyYXBoJylcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICByZXR1cm4geG1vY2soYEBjcGFyYWdyYXBoKCR7YXJnc1swXX0pYClcbiAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICByZXR1cm4geG1vY2soYEBjcGFyYWdyYXBoKCR7YXJnc1swXX0sJHthcmdzWzFdfSlgKVxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICB4YXNzZXJ0KGZhbHNlKVxuICAgICAgICB9XG5cbiAgICB9LFxuICAgIHNlbnRlbmNlOiAoLi4uYXJncykgPT4ge1xuICAgICAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHhtb2NrKCdAY3NlbnRlbmNlJylcbiAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICByZXR1cm4geG1vY2soYEBjc2VudGVuY2UoJHthcmdzWzBdfSlgKVxuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIHJldHVybiB4bW9jayhgQGNzZW50ZW5jZSgke2FyZ3NbMF19LCR7YXJnc1sxXX0pYClcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgeGFzc2VydChmYWxzZSlcbiAgICAgICAgfVxuXG4gICAgfSxcbiAgICB0aXRsZTogKC4uLmFyZ3MpID0+IHtcbiAgICAgICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIHJldHVybiB4bW9jaygnQGN0aXRsZScpXG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHhtb2NrKGBAY3RpdGxlKCR7YXJnc1swXX0pYClcbiAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICByZXR1cm4geG1vY2soYEBjdGl0bGUoJHthcmdzWzBdfSwke2FyZ3NbMV19KWApXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHhhc3NlcnQoZmFsc2UpXG4gICAgICAgIH1cblxuICAgIH0sXG59KVxuXG4vLyBsYXJhdmVs6aOO5qC8SlNPTuWvueixoemqjOivgeWZqOWwgeijhe+8jOivpue7huaWh+aho+ingSBodHRwczovL2dpdGh1Yi5jb20vc2thdGVyZGF2ODUvdmFsaWRhdG9yanNcbmZ1bmN0aW9uIHhjaGVjazxUPihwYXJhbTogVCwgcnVsZXM6IFQsIG1lc3NhZ2VzPzogT2JqZWN0KSB7XG4gICAgbGV0IG9iaiA9IG5ldyB2YWxpZGF0b3JqcyhwYXJhbSwgcnVsZXMpXG4gICAgaWYgKG9iai5mYWlscygpKSB7XG4gICAgICAgIHh0aHJvdyhFUlIkUEFSQU0sIG9iai5lcnJvcnMpXG4gICAgfVxufVxuXG4vLyDjgJBJb0PlrrnlmajnrqHnkIbjgJHlupTnlKjlsYLnmoTmj5Lku7blrp7njrDnsbvnu5HlrprliLBCWEpT57uf5LiA5rOo5YaM55qE5qCH5YeG5o+S5Lu255qE5pig5bCE5YWz57O75Zyo5YWo5bGA5a655Zmo5a6e5L6L5Lit5rOo5YaMXG5mdW5jdGlvbiB4YmluZDxUPihUWVBFOiBuZXcgKCkgPT4gVCkge1xuICAgIGNvbnN0IG86IGFueSA9IG5ldyBUWVBFKClcbiAgICByZXR1cm4geGNvbnRhaW5lci5iaW5kPFQ+KG8uaWQpLnRvKHJlcXVpcmUoYEBhcHAvcGx1Z2lucy8ke28uaWR9YCkuZGVmYXVsdClcbn1cblxuLy8g44CQSW9D5a655Zmo566h55CG44CR5qGG5p625oiW5bqU55So5L6d6LWW5qCH5YeG6KeE6IyD5o6l5Y+j5o+S5Lu255qE57G75a6e5L6L6I635Y+W5pa55rOVXG5mdW5jdGlvbiB4Z290PFQ+KFRZUEU6IG5ldyAoKSA9PiBUKSB7XG4gICAgY29uc3QgbzogYW55ID0gbmV3IFRZUEUoKVxuICAgIHJldHVybiB4Y29udGFpbmVyLmdldDxUPihvLmlkKVxufVxuXG4vLyDlkIzmraXns7vnu5/lkb3ku6TosIPnlKjmiafooYxcbmFzeW5jIGZ1bmN0aW9uIHhjbWQoLi4uYXJnczogc3RyaW5nW10pOiBQcm9taXNlPGFueT4ge1xuICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG9wdGlvbnM6IGFueSA9IHt9XG4gICAgICAgIG9wdGlvbnMuY3dkID0gb3B0aW9ucy5jd2QgfHwgcHJvY2Vzcy5lbnYuX19jdHhQYXRoIHx8IHByb2Nlc3MuY3dkKCk7XG4gICAgICAgIHhhc3NlcnQoXy5pc0FycmF5KGFyZ3MpICYmIGFyZ3MubGVuZ3RoID4gMClcbiAgICAgICAgY29uc3QgY21kID0gYXJncy5zaGlmdCgpXG4gICAgICAgIGNvbnN0IHJldCA9IGNyb3NzX3NwYXduLnN5bmMoY21kLCBhcmdzLCB4YXNzaWduKHtzdGRpbzogJ2luaGVyaXQnfSwgb3B0aW9ucykpXG4gICAgICAgIHhhc3NlcnQocmV0LnN0YXR1cyA9PT0gMCwgRVJSJFVOS05PV04sIHJldClcbiAgICAgICAgcmV0dXJuIHJldFxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBhd2FpdCB4d2FybihlcnIpXG4gICAgICAgIHh0aHJvdyhlcnIpXG4gICAgfVxufVxuXG4vLyDlr7nkuo7mlbDnu4TltYzlpZflm57osIPlh73mlbDnmoRub2RlanPlvILmraXlpITnkIbmlrnms5XnmoTnu5/kuIDlsIHoo4VcbmFzeW5jIGZ1bmN0aW9uIHhtYXA8VD4odmFsdWVzOiBUW10sIGNhbGxhY2s6ICh2OiBUKSA9PiBQcm9taXNlPGFueT4pOiBQcm9taXNlPGFueVtdPiB7XG4gICAgeGFzc2VydChfLmlzQXJyYXkodmFsdWVzKSAmJiBfLmlzRnVuY3Rpb24oY2FsbGFjaykpXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHZhbHVlcy5tYXAoY2FsbGFjaykpXG59XG5cbi8vIFJlZmVyIHRvIGRvY3VtZW50OiAgaHR0cHM6Ly9oZWxwLmFsaXl1bi5jb20vZG9jdW1lbnRfZGV0YWlsLzYyNjcwLmh0bWxcbi8vIOiOt+WPlkFDTemFjee9ruS/oeaBr+aOpeWPo+eahOe7n+S4gOWwgeijhVxuYXN5bmMgZnVuY3Rpb24geGFjbShncm91cDogc3RyaW5nLCBpZDogc3RyaW5nKSB7XG4gICAgY29uc3QgY2ZnID0geGNvbmZpZyhgcGx1Z2lucy5hY21gKVxuICAgIHhhc3NlcnQoY2ZnICYmIGNmZ1tncm91cF0sIEVSUiRDT05GSUcsIHtjZmd9KVxuICAgIGNvbnN0IGFjbSA9IG5ldyBBQ01DbGllbnQoY2ZnW2dyb3VwXSlcbiAgICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY28oZnVuY3Rpb24qICgpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb250ZW50ID0geWllbGQgYWNtLmdldENvbmZpZyhpZCwgZ3JvdXApXG4gICAgICAgICAgICAgICAgICAgIHhhc3NlcnQoY29udGVudCwgRVJSJENPTkZJRylcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShjb250ZW50KVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICB4dGhyb3coZXJyLCByZWplY3QsIHtpZCwgZ3JvdXAsIGNmZzogY2ZnW2dyb3VwXX0pXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgeHRocm93KGVyciwgcmVqZWN0LCB7aWQsIGdyb3VwLCBjZmc6IGNmZ1tncm91cF19KVxuICAgICAgICB9XG4gICAgfSlcbn1cblxuaWYgKCFnbG9iYWxbJ19fZW52X18nXSkge1xuICAgIGdsb2JhbFsnX19lbnZfXyddID0gJ2xvY2FsJyAvLyBsb2NhbCxkYWlseSxwcmUsZ3JheSxwcm9kIOWcqOe7n+S4gOWFpeWPo+WkhOiHquWKqOivhuWIq+mFjee9rijnm67liY3mmoLkuI3mlK/mjIFncmF56YWN572u5bCa5pyq5byA5Y+R5peg5rOV6Ieq5Yqo6K+G5YirKVxufVxuZ2xvYmFsWydfX2NvbmZpZ19fJ10gPSB1bmRlZmluZWRcbmdsb2JhbFsnX19zZXNzaW9uX18nXSA9IHt9XG5nbG9iYWxbJ19fY2FjaGVfXyddID0ge31cbmdsb2JhbFsnX191c2VyX18nXSA9IHt9XG5nbG9iYWxbJ19fdXNlcl9hZ2VudF9fJ10gPSB1bmRlZmluZWRcbmdsb2JhbFsnX19jbGllbnRfaXBfXyddID0gdW5kZWZpbmVkXG5nbG9iYWxbJ19fcmVkaXJlY3RfdXJsX18nXSA9IHVuZGVmaW5lZFxuZ2xvYmFsWydfX3JlcXVlc3RfY29va2llc19fJ10gPSB7fVxuZ2xvYmFsWydfX3Jlc3BvbmRfY29va2llc19fJ10gPSB7fVxuXG5nbG9iYWxbJ3hjb25uZWN0J10gPSB4Y29ubmVjdFxuZ2xvYmFsWyd4bmV3J10gPSB4bmV3XG5nbG9iYWxbJ3hxdWVyeSddID0geHF1ZXJ5XG5nbG9iYWxbJ3hjb3VudCddID0geGNvdW50XG5nbG9iYWxbJ3hhc3NpZ24nXSA9IHhhc3NpZ25cbmdsb2JhbFsneGNvbmZpZyddID0geGNvbmZpZ1xuZ2xvYmFsWyd4dGhyb3cnXSA9IHh0aHJvd1xuZ2xvYmFsWyd4YXNzZXJ0J10gPSB4YXNzZXJ0XG5nbG9iYWxbJ3hlcnJvciddID0geGVycm9yXG5nbG9iYWxbJ3hyb290J10gPSB4cm9vdFxuZ2xvYmFsWyd4c3RhY2snXSA9IHhzdGFja1xuZ2xvYmFsWyd4d2FybiddID0geHdhcm5cbmdsb2JhbFsneGxvZyddID0geGxvZ1xuZ2xvYmFsWyd4cG9zdCddID0geHBvc3Rcbmdsb2JhbFsneGdldCddID0geGdldFxuZ2xvYmFsWyd4c2xlZXAnXSA9IHhzbGVlcFxuZ2xvYmFsWyd4cmVkaXJlY3QnXSA9IHhyZWRpcmVjdFxuZ2xvYmFsWyd4Y29va2llJ10gPSB4Y29va2llXG5nbG9iYWxbJ3hpc21vYmlsZSddID0geGlzbW9iaWxlXG5nbG9iYWxbJ3hzZXNzaW9uJ10gPSB4c2Vzc2lvblxuZ2xvYmFsWyd4dXNlciddID0geHVzZXJcbmdsb2JhbFsneGNhY2hlJ10gPSB4Y2FjaGVcbmdsb2JhbFsneHJvdXRlJ10gPSB4cm91dGVcbmdsb2JhbFsneG1vY2snXSA9IHhtb2NrXG5nbG9iYWxbJ3hyYW5kb20nXSA9IHhyYW5kb21cbmdsb2JhbFsneGNoZWNrJ10gPSB4Y2hlY2tcbmdsb2JhbFsneGNvbnRhaW5lciddID0gbmV3IENvbnRhaW5lcigpIC8vIOWFqOWxgOWNleWunuS+i+WuueWZqOWIneWni+WMllxuZ2xvYmFsWyd4YmluZCddID0geGJpbmRcbmdsb2JhbFsneGdvdCddID0geGdvdFxuZ2xvYmFsWydZQXV0aCddID0gJCQuWUF1dGggLy8g5YWo5bGA5aOw5piO6K6k6K+B5o+S5Lu26KeE6IyD5oq96LGh57G7XG5nbG9iYWxbJ3hjbWQnXSA9IHhjbWRcbmdsb2JhbFsneG1hcCddID0geG1hcFxuZ2xvYmFsWyd4YWNtJ10gPSB4YWNtXG4iXX0=
\No newline at end of file