1 | ;
|
2 | var __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 | };
|
10 | var __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 | };
|
18 | var __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 | };
|
45 | var _this = this;
|
46 | Object.defineProperty(exports, "__esModule", { value: true });
|
47 | process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
48 | require("reflect-metadata");
|
49 | var inversify_1 = require("inversify");
|
50 | var typeorm_1 = require("@bxjs/typeorm");
|
51 | var session_1 = require("./session");
|
52 | var $$ = require("./plugins");
|
53 | var path = require('path');
|
54 | var ErrorStackParser = require('error-stack-parser');
|
55 | var cookie = require('cookie');
|
56 | var MobileDetect = require('mobile-detect');
|
57 | var fetch = require('node-fetch');
|
58 | var _ = require('lodash');
|
59 | var moment = require('moment');
|
60 | var extend = require('extend');
|
61 | var 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 | // })
|
70 | var circular_json = require("circular-json");
|
71 | var mockjs = require('mockjs');
|
72 | var shortid = require('shortid');
|
73 | var validatorjs = require('validatorjs');
|
74 | var cross_spawn = require('cross-spawn');
|
75 | var ACMClient = require('acm-client');
|
76 | var co = require('co');
|
77 | // FIXME HACK原生方法JSON转换不可逆的BUG(JAVA端传来的富文本字段内容含有\n\t字符串中的字符生成JSON字符串无法正常解析报错)
|
78 | var raw_stringify = JSON.stringify;
|
79 | function 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 | }
|
88 | JSON.stringify = new_stringify;
|
89 | // ts-node本地调试需要加载对应的源代码后缀名称
|
90 | function 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 | }
|
98 | exports.get_suffix_ts_or_js = get_suffix_ts_or_js;
|
99 | // 准确定位错误码位置,间接得到函数调用位置地址信息,结合符号报表的正确解析处理完美得到错误定位信息,准确代码调试。
|
100 | function __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 | // 获取异常调用栈用于辅助错误提示定位
|
131 | function 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 | }
|
151 | exports.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
|
162 | function 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 | }
|
182 | exports.xerror = xerror;
|
183 | // 用于获取错误栈的root cause根本原因(第一个被拦截的错误发生位置)
|
184 | function 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 | }
|
203 | exports.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 | // }
|
217 | function 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 | }
|
272 | exports.xthrow = xthrow;
|
273 | function 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 | }
|
281 | exports.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 | // }
|
292 | function 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 | }
|
315 | exports.xlog = xlog;
|
316 | // // 将详细错误信息及时发送到钉钉群上实时反馈给维护者
|
317 | // await xwarn({
|
318 | // code,
|
319 | // // TODO 如何认证通过了获取到用户信息也需要发送过去,方便联系对接人员进行立刻问题处理反馈。
|
320 | // message,
|
321 | // stack,
|
322 | // param,
|
323 | // })
|
324 | // 将详细错误信息及时发送到钉钉群上实时反馈给维护者
|
325 | // 钉钉IM群机器人报警通知
|
326 | function 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 | // 捕获未监听到的异常记录后直接退出(运行堆栈已经破坏直接记录日志后异常退出即可,由外部监控自动重启)
|
372 | process.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中出现未捕获的异常错误
|
388 | process.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的非阻塞异步延迟方法,用于调试阻塞程序的执行进行单步调试的效果。
|
404 | var sleep = require('sleep-async')();
|
405 | function 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 | }
|
423 | exports.xsleep = xsleep;
|
424 | function 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 | }
|
461 | exports.xpost = xpost;
|
462 | // 默认超时3000毫秒
|
463 | function 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 | }
|
500 | exports.xget = xget;
|
501 | // 302临时重定向跳转实现
|
502 | function 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 | }
|
523 | exports.xredirect = xredirect;
|
524 | // 如果只有key参数表示读取属性(缺省值为undefined),如果key为空表示读取所有的请求cookies属性,否则表示响应设置cookies
|
525 | function 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 | }
|
545 | exports.xcookie = xcookie;
|
546 | // 判断user-agent请求是否为移动端
|
547 | function xismobile() {
|
548 | var md = new MobileDetect(global['__user_agent__']);
|
549 | return !!md.mobile();
|
550 | }
|
551 | function 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目录下的应用配置数据
|
560 | function 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 | }
|
594 | function 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对象并且自动赋值前端请求的赋值数据
|
674 | function 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 | // 查询构造器易用性封装
|
693 | function xquery(connect, TYPE, alias) {
|
694 | return connect.getRepository(TYPE).createQueryBuilder(alias);
|
695 | }
|
696 | // 分页查询获取总数以及原始记录数据
|
697 | function 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
|
717 | function 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
|
761 | function xmock(rules) {
|
762 | return mockjs.mock(rules);
|
763 | }
|
764 | function 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中的方法
|
782 | mockjs.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
|
860 | function 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统一注册的标准插件的映射关系在全局容器实例中注册
|
867 | function xbind(TYPE) {
|
868 | var o = new TYPE();
|
869 | return xcontainer.bind(o.id).to(require("@app/plugins/" + o.id).default);
|
870 | }
|
871 | // 【IoC容器管理】框架或应用依赖标准规范接口插件的类实例获取方法
|
872 | function xgot(TYPE) {
|
873 | var o = new TYPE();
|
874 | return xcontainer.get(o.id);
|
875 | }
|
876 | // 同步系统命令调用执行
|
877 | function 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异步处理方法的统一封装
|
908 | function 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配置信息接口的统一封装
|
918 | function 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容器默认是格林尼治时间而非北京时间问题
|
961 | function xnow(format) {
|
962 | if (format === void 0) { format = 'YYYY-MM-DD HH:mm:ss'; }
|
963 | return moment().utcOffset(8).format(format);
|
964 | }
|
965 | // base64编码
|
966 | function xbase64encode(value) {
|
967 | xassert(!_.isEmpty(value) && _.isString(value));
|
968 | return new Buffer(value).toString('base64');
|
969 | }
|
970 | // base64解码
|
971 | function xbase64decode(value) {
|
972 | xassert(!_.isEmpty(value) && _.isString(value));
|
973 | return new Buffer(value, 'base64').toString();
|
974 | }
|
975 | // 请求上下文变量自动重置方法(以global变量中key为__下划线开始结束的属性自动清空为undefined,如需赋值其他缺省值需要在此函数中明确定义)
|
976 | function 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__参数作为全局变量在模块初始化的时候
|
999 | xreset();
|
1000 | global['xreset'] = xreset;
|
1001 | global['xconnect'] = xconnect;
|
1002 | global['xnew'] = xnew;
|
1003 | global['xquery'] = xquery;
|
1004 | global['xcount'] = xcount;
|
1005 | global['xassign'] = xassign;
|
1006 | global['xconfig'] = xconfig;
|
1007 | global['xthrow'] = xthrow;
|
1008 | global['xassert'] = xassert;
|
1009 | global['xerror'] = xerror;
|
1010 | global['xroot'] = xroot;
|
1011 | global['xstack'] = xstack;
|
1012 | global['xwarn'] = xwarn;
|
1013 | global['xlog'] = xlog;
|
1014 | global['xpost'] = xpost;
|
1015 | global['xget'] = xget;
|
1016 | global['xsleep'] = xsleep;
|
1017 | global['xredirect'] = xredirect;
|
1018 | global['xcookie'] = xcookie;
|
1019 | global['xismobile'] = xismobile;
|
1020 | global['xsession'] = session_1.xsession;
|
1021 | global['xuser'] = session_1.xuser;
|
1022 | global['xcache'] = session_1.xcache;
|
1023 | global['xroute'] = xroute;
|
1024 | global['xmock'] = xmock;
|
1025 | global['xrandom'] = xrandom;
|
1026 | global['xcheck'] = xcheck;
|
1027 | global['xcontainer'] = new inversify_1.Container(); // 全局单实例容器初始化
|
1028 | global['xbind'] = xbind;
|
1029 | global['xgot'] = xgot;
|
1030 | global['YAuth'] = $$.YAuth; // 全局声明认证插件规范抽象类
|
1031 | global['xcmd'] = xcmd;
|
1032 | global['xmap'] = xmap;
|
1033 | global['xacm'] = xacm;
|
1034 | global['xbase64encode'] = xbase64encode;
|
1035 | global['xbase64decode'] = xbase64decode;
|
1036 | global['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 |