UNPKG

74.6 kBJavaScriptView Raw
1"use strict";
2var __extends = (this && this.__extends) || (function () {
3 var extendStatics = Object.setPrototypeOf ||
4 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
6 return function (d, b) {
7 extendStatics(d, b);
8 function __() { this.constructor = d; }
9 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
10 };
11})();
12var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13 return new (P || (P = Promise))(function (resolve, reject) {
14 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
15 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
16 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
17 step((generator = generator.apply(thisArg, _arguments || [])).next());
18 });
19};
20var __generator = (this && this.__generator) || function (thisArg, body) {
21 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
22 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
23 function verb(n) { return function (v) { return step([n, v]); }; }
24 function step(op) {
25 if (f) throw new TypeError("Generator is already executing.");
26 while (_) try {
27 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;
28 if (y = 0, t) op = [op[0] & 2, t.value];
29 switch (op[0]) {
30 case 0: case 1: t = op; break;
31 case 4: _.label++; return { value: op[1], done: false };
32 case 5: _.label++; y = op[1]; op = [0]; continue;
33 case 7: op = _.ops.pop(); _.trys.pop(); continue;
34 default:
35 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
36 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
37 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
38 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
39 if (t[2]) _.ops.pop();
40 _.trys.pop(); continue;
41 }
42 op = body.call(thisArg, _);
43 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
44 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
45 }
46};
47Object.defineProperty(exports, "__esModule", { value: true });
48/**
49 * 研究阿里云的OTS表格设计将session、cache、user三种缓存信息算法构建在此之上。
50 */
51var TableStore = require('tablestore');
52var Long = TableStore.Long;
53var _ = require('lodash');
54var NoSqlInterface = /** @class */ (function () {
55 function NoSqlInterface(table, config) {
56 if (config === void 0) { config = 'default'; }
57 }
58 return NoSqlInterface;
59}());
60// export async function test() {
61// const ots = new NoSqlAliyunTablestore('session_test3')
62// // let out = await ots.create(60)
63// // FIXME 首次创建表需要有一定的系统延迟时间,需要放到install过程中进行维护。
64// // let out = await ots.insert('x', {a: 'aaa', b: {value: 'bbbb', timestamp: Date.now()}})
65// // let out = await ots.update('x', {a: 'aaa2', b: 'bbb2'})
66// // let out = await ots.update('x', {a: null, b: 1529666053100})
67// // let out = await ots.delete('x')
68//
69// let out
70// // out = await ots.insert('x', {a: 'aaa', b: {value: 'bbbb', timestamp: Date.now()}})
71// // out = await ots.query('x') // 取全部的字段
72// // out = await ots.query('x', ['a']) // 取部分字段
73// // out = await ots.query('y') // 取不存在的主键
74//
75// // out = await ots.create(24*60*60,2)
76// // out = await ots.insert('z', {a: 'aaa'+Date(), b: {value: 'bbbb'+Date(), timestamp: Date.now()}})
77// // out = await ots.update('z', {a: 'aaa'+Date(), b: 'bbbb'+Date()})
78// // out = await ots.query('z', null, 2)
79// out = await ots.query('z', null, 1)
80// // 用最佳方案去实现字段
81// return out
82// }
83// 对于阿里云tablestore的单表功能简单封装处理(一个主键并作为分区唯一区分一个记录,仅用于缓存功能实现。
84// 封装特点:每个记录一条主键并作为分区,每个记录有无数个kv值可供配置,每个kv值都有一个时间戳超时时间在表上单独配置。)
85var NoSqlAliyunTablestore = /** @class */ (function (_super) {
86 __extends(NoSqlAliyunTablestore, _super);
87 function NoSqlAliyunTablestore(table, config) {
88 if (config === void 0) { config = 'default'; }
89 var _this = _super.call(this, table, config) || this;
90 var instances = xconfig('plugins.nosql');
91 xassert(instances && _.isPlainObject(instances) && config in instances, ERR$CONFIG, { instances: instances });
92 _this._table = table;
93 _this._schema = {
94 KEYS: {
95 id: 'string' // 表的唯一记录主键值同时也是分区
96 }
97 };
98 _this._client = new TableStore.Client({
99 accessKeyId: instances[config].OTS_ACCESS_KEY_ID,
100 secretAccessKey: instances[config].OTS_SECRETE_ACCESS_KEY,
101 endpoint: instances[config].OTS_ENDPOINT,
102 instancename: instances[config].OTS_INSTANCENAME
103 });
104 return _this;
105 }
106 Object.defineProperty(NoSqlAliyunTablestore.prototype, "table", {
107 set: function (value) {
108 this._table = value;
109 },
110 enumerable: true,
111 configurable: true
112 });
113 // 约定所有表都需要有自增主键id作为内部唯一标识码,其余三个主键必须全部为字符串。(后端需要扩展int和date基本数据类型以及操作符重载实现优化开发)
114 // 属性字段可以根据业务演变任意的扩展增加由业务代码对于老数据不存在新增字段值的情况做兼容处理
115 NoSqlAliyunTablestore.prototype.insert = function (id, kvt) {
116 return __awaiter(this, void 0, void 0, function () {
117 var _a, _b, __this__, params, k;
118 return __generator(this, function (_c) {
119 xassert(Object.keys(kvt).length <= 128); // 规避跨行限制总计属性128个
120 __this__ = this;
121 params = {
122 tableName: this._table,
123 // 插入的时候需要确保不存在对应的数据以防止出错
124 condition: new TableStore.Condition(TableStore.RowExistenceExpectation.EXPECT_NOT_EXIST, null),
125 primaryKey: [],
126 attributeColumns: [],
127 // 按照下面数据格式进行schema定义的验证以及数据类型转换
128 // primaryKey: [{'gid': Long.fromNumber(20013)}, {'uid': Long.fromNumber(20013)}],
129 // attributeColumns: [
130 // {'col1': '表格存储'},
131 // {'col2': '2', 'timestamp': currentTimeStamp}, // 允许修改时间戳乐观锁功能实现暂不支持
132 // {'col3': 3.1},
133 // {'col4': -0.32},
134 // {'col5': Long.fromNumber(123456789)}
135 // ],
136 // primaryKey: [
137 // {'short_id': 'pk1'},
138 // {[AUTO_KEY_NAME]: TableStore.PK_AUTO_INCR}
139 // ],
140 // attributeColumns: [
141 // {'appcode': 'app1'}
142 // ],
143 returnContent: { returnType: TableStore.ReturnType.Primarykey }
144 };
145 // 拼接主键以及属性字段值
146 params.primaryKey = [{ 'id': id }];
147 for (k in kvt) {
148 xassert(k != 'id' && k != 'timestamp'); // 两个预留内部标识符不可作为属性名
149 if (_.isString(kvt[k])) {
150 params.attributeColumns.push((_a = {},
151 _a[k] = kvt[k],
152 _a));
153 }
154 else {
155 params.attributeColumns.push((_b = {},
156 _b[k] = kvt[k]['value'],
157 _b.timestamp = kvt[k]['timestamp'],
158 _b));
159 }
160 }
161 return [2 /*return*/, new Promise(function (resolve, reject) {
162 try {
163 __this__._client.putRow(params, function (err, out) {
164 if (err) {
165 xthrow(new Error(err), reject, { params: params, out: out });
166 return;
167 }
168 // 正常返回的数据格式
169 //{"consumed":{"capacity_unit":{"read":0,"write":1}},"row":{
170 // "primaryKey":[{"name":"short_id","value":"abcd"},{"name":"id","value":1520765502347000}],
171 // "attributes":[]},
172 // "RequestId":"00056720-cf8d-d4a8-8ae8-970a17894ce6"}
173 resolve(out);
174 });
175 }
176 catch (err) {
177 xthrow(err, reject);
178 }
179 })];
180 });
181 });
182 };
183 NoSqlAliyunTablestore.prototype.update = function (id, kvt) {
184 return __awaiter(this, void 0, void 0, function () {
185 return __generator(this, function (_a) {
186 switch (_a.label) {
187 case 0: return [4 /*yield*/, this._update_or_replace(id, kvt, false)];
188 case 1: return [2 /*return*/, _a.sent()];
189 }
190 });
191 });
192 };
193 NoSqlAliyunTablestore.prototype.replace = function (id, kvt) {
194 return __awaiter(this, void 0, void 0, function () {
195 return __generator(this, function (_a) {
196 switch (_a.label) {
197 case 0: return [4 /*yield*/, this._update_or_replace(id, kvt, true)];
198 case 1: return [2 /*return*/, _a.sent()];
199 }
200 });
201 });
202 };
203 // 条件更新必须要填写主键记录值(仅仅允许更新属性字段而主键字段是不允许更新的,
204 // 整列更新和删除列属于运维操作禁止应用中使用需要单独接口以及权限认证)
205 NoSqlAliyunTablestore.prototype._update_or_replace = function (id, kvt, isIgnoreRowNonExist) {
206 if (isIgnoreRowNonExist === void 0) { isIgnoreRowNonExist = false; }
207 return __awaiter(this, void 0, void 0, function () {
208 var _a, _b, __this__, params, PUT, DELETE, DELETE_ALL, k;
209 return __generator(this, function (_c) {
210 xassert(Object.keys(kvt).length > 0 && Object.keys(kvt).length <= 128); // 规避跨行限制总计属性128个
211 __this__ = this;
212 params = {
213 tableName: this._table,
214 condition: new TableStore.Condition(isIgnoreRowNonExist ?
215 TableStore.RowExistenceExpectation.IGNORE :
216 TableStore.RowExistenceExpectation.EXPECT_EXIST, null),
217 primaryKey: [{ id: id }],
218 // updateOfAttributeColumns: [{'PUT': [{'col1': 'test6'}]}]
219 updateOfAttributeColumns: []
220 // updateOfAttributeColumns: [
221 // { 'PUT': [{ 'col4': Long.fromNumber(4) }, { 'col5': '5' }, { 'col6': Long.fromNumber(6) }] },
222 // { 'DELETE': [{ 'col1': Long.fromNumber(1496826473186) }] }, // 删除指定时间戳版本数据
223 // { 'DELETE_ALL': ['col2'] } // 删除所有版本的字段数据
224 // ]
225 };
226 PUT = [];
227 DELETE = [];
228 DELETE_ALL = [];
229 for (k in kvt) {
230 // 如果变量值为null类型则表示删除对应的字段值,如果为整数表示删除指定时间戳版本,否则表示添加或更新对应字段值。
231 if (!kvt[k]) {
232 DELETE_ALL.push(k);
233 }
234 else if (_.isInteger(kvt[k])) {
235 DELETE.push((_a = {}, _a[k] = Long.fromNumber(kvt[k]), _a));
236 }
237 else if (_.isString(kvt[k])) {
238 PUT.push((_b = {}, _b[k] = kvt[k], _b));
239 }
240 else {
241 xassert(false, ERR$PARAM, { id: id, kvt: kvt });
242 }
243 }
244 if (PUT.length > 0)
245 params.updateOfAttributeColumns.push({ PUT: PUT });
246 if (DELETE.length > 0)
247 params.updateOfAttributeColumns.push({ DELETE: DELETE });
248 if (DELETE_ALL.length > 0)
249 params.updateOfAttributeColumns.push({ DELETE_ALL: DELETE_ALL });
250 return [2 /*return*/, new Promise(function (resolve, reject) {
251 try {
252 __this__._client.updateRow(params, function (err, data) {
253 if (err) {
254 xthrow(new Error(err), reject, { params: params, data: data });
255 return;
256 }
257 resolve();
258 });
259 }
260 catch (err) {
261 xthrow(err, reject);
262 }
263 })];
264 });
265 });
266 };
267 // 以主键作为条件删除记录值
268 NoSqlAliyunTablestore.prototype.delete = function (id) {
269 return __awaiter(this, void 0, void 0, function () {
270 var __this__, params;
271 return __generator(this, function (_a) {
272 __this__ = this;
273 params = {
274 tableName: this._table,
275 condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, null),
276 // primaryKey: [{ 'gid': Long.fromNumber(8) }, { 'uid': Long.fromNumber(80) }]
277 primaryKey: [{ id: id }]
278 };
279 return [2 /*return*/, new Promise(function (resolve, reject) {
280 try {
281 __this__._client.deleteRow(params, function (err, data) {
282 if (err) {
283 xthrow(new Error(err), reject, { params: params, data: data });
284 return;
285 }
286 resolve();
287 });
288 }
289 catch (err) {
290 xthrow(err, reject);
291 }
292 })];
293 });
294 });
295 };
296 // 范围查询需要数据自动同步到opensearch进行索引同步后进行各种复杂的查询操作实现免运维系统的实现
297 // 单表逻辑条件的简单and与equal的查询,返回满足条件的第一条记录 (合并为一个查询兼容mongodb的查询扩展)
298 NoSqlAliyunTablestore.prototype.query = function (id, keys, max_version) {
299 if (keys === void 0) { keys = null; }
300 if (max_version === void 0) { max_version = 1; }
301 return __awaiter(this, void 0, void 0, function () {
302 var __this__, params;
303 return __generator(this, function (_a) {
304 __this__ = this;
305 params = {
306 tableName: this._table,
307 columnsToGet: keys,
308 // columns_to_get 获取期望的列最多128个一次获取总数,应用上应该将KEY视为分组总数。
309 // 如何规避宽表的分页限制?? FIXME 先从应用上规避限制一个应用最多不超过128个属性,通过JSON进行扩展存储。
310 primaryKey: [{ id: id }],
311 // primaryKey: [{'gid': Long.fromNumber(20013)}, {'uid': Long.fromNumber(20013)}],
312 columnFilter: null,
313 maxVersions: max_version,
314 };
315 return [2 /*return*/, new Promise(function (resolve, reject) {
316 __this__._client.getRow(params, function (err, data) {
317 if (err) {
318 xthrow(new Error(err), reject, { params: params, data: data });
319 return;
320 }
321 // 返回数据格式类型进行转换处理
322 // {"consumed":{"capacity_unit":{"read":1,"write":0}},
323 // "row":{"primaryKey":[{"name":"gid","value":20013},{"name":"uid","value":20013}],
324 // "attributes":[{"columnName":"col1","columnValue":"表格存储","timestamp":1520734520286},
325 // {"columnName":"col2","columnValue":"2","timestamp":1520734520064},
326 // {"columnName":"col3","columnValue":3.1,"timestamp":1520734520286},
327 // {"columnName":"col4","columnValue":-0.32,"timestamp":1520734520286},
328 // {"columnName":"col5","columnValue":123456789,"timestamp":1520734520286}]
329 // },
330 // "next_token":null,"RequestId":"00056719-e2ad-73b1-dbd8-970a19522f4b"}
331 // 将数据结果进行转换处理合并为一个普通对象给应用使用
332 try {
333 var out = {};
334 if (!data.row) {
335 return resolve(null);
336 }
337 if (data.row.primaryKey) {
338 for (var k in data.row.primaryKey) {
339 out[data.row.primaryKey[k].name] = data.row.primaryKey[k].value;
340 }
341 }
342 if (data.row.attributes) {
343 for (var k in data.row.attributes) {
344 out[data.row.attributes[k].columnName] = data.row.attributes[k].columnValue;
345 }
346 }
347 // xlog(data) // TODO 当存在多个版本数据的时候解析不正确,应该是多个版本的属性值字段的组合才正确。
348 resolve(_.isEmpty(out) ? null : out);
349 }
350 catch (err) {
351 xthrow(new Error(err), reject, { params: params, data: data });
352 return;
353 }
354 });
355 })];
356 });
357 });
358 };
359 // 销毁表
360 NoSqlAliyunTablestore.prototype.destroy = function () {
361 return __awaiter(this, void 0, void 0, function () {
362 var err_1, i, out, err_2;
363 return __generator(this, function (_a) {
364 switch (_a.label) {
365 case 0:
366 _a.trys.push([0, 2, , 3]);
367 return [4 /*yield*/, this._destroy()];
368 case 1:
369 _a.sent();
370 return [3 /*break*/, 3];
371 case 2:
372 err_1 = _a.sent();
373 return [2 /*return*/];
374 case 3:
375 i = 0;
376 _a.label = 4;
377 case 4:
378 if (!(i < 100)) return [3 /*break*/, 9];
379 _a.label = 5;
380 case 5:
381 _a.trys.push([5, 6, , 8]);
382 out = this.describe();
383 xlog(out);
384 return [3 /*break*/, 8];
385 case 6:
386 err_2 = _a.sent();
387 return [4 /*yield*/, xsleep(100)];
388 case 7:
389 _a.sent();
390 return [3 /*break*/, 9];
391 case 8:
392 i++;
393 return [3 /*break*/, 4];
394 case 9: return [2 /*return*/];
395 }
396 });
397 });
398 };
399 NoSqlAliyunTablestore.prototype._destroy = function () {
400 return __awaiter(this, void 0, void 0, function () {
401 var __this__, params;
402 return __generator(this, function (_a) {
403 __this__ = this;
404 params = {
405 tableName: this._table
406 };
407 return [2 /*return*/, new Promise(function (resolve, reject) {
408 __this__._client.deleteTable(params, function (err, data) {
409 if (err) {
410 xthrow(new Error(err), reject, { params: params });
411 return;
412 }
413 resolve();
414 });
415 })];
416 });
417 });
418 };
419 // 创建表
420 NoSqlAliyunTablestore.prototype.create = function (timeout, max_versions) {
421 if (timeout === void 0) { timeout = -1; }
422 if (max_versions === void 0) { max_versions = 1; }
423 return __awaiter(this, void 0, void 0, function () {
424 var i, out, err_3;
425 return __generator(this, function (_a) {
426 switch (_a.label) {
427 case 0: return [4 /*yield*/, this._create(timeout, max_versions)
428 // 10秒钟等待超时创建表正常完成
429 ];
430 case 1:
431 _a.sent();
432 i = 0;
433 _a.label = 2;
434 case 2:
435 if (!(i < 100)) return [3 /*break*/, 8];
436 _a.label = 3;
437 case 3:
438 _a.trys.push([3, 4, , 6]);
439 out = this.describe();
440 xlog(out);
441 return [3 /*break*/, 6];
442 case 4:
443 err_3 = _a.sent();
444 return [4 /*yield*/, xsleep(100)];
445 case 5:
446 _a.sent();
447 return [3 /*break*/, 7];
448 case 6: return [3 /*break*/, 8];
449 case 7:
450 i++;
451 return [3 /*break*/, 2];
452 case 8: return [2 /*return*/];
453 }
454 });
455 });
456 };
457 NoSqlAliyunTablestore.prototype._create = function (timeout, max_versions) {
458 if (timeout === void 0) { timeout = -1; }
459 if (max_versions === void 0) { max_versions = 1; }
460 return __awaiter(this, void 0, void 0, function () {
461 var __this__, params, k, obj, out;
462 return __generator(this, function (_a) {
463 switch (_a.label) {
464 case 0:
465 // OTS最长超时时间为1天的兼容处理
466 if (timeout != -1 && timeout < 86400) {
467 timeout = 86400;
468 }
469 __this__ = this;
470 params = {
471 tableMeta: {
472 tableName: this._table,
473 primaryKey: [],
474 },
475 reservedThroughput: {
476 capacityUnit: {
477 read: 0,
478 write: 0
479 }
480 },
481 tableOptions: {
482 timeToLive: timeout,
483 maxVersions: max_versions,
484 }
485 };
486 // 自动转换schema定义为OTS的数据结构
487 for (k in this._schema.KEYS) {
488 obj = {
489 name: k,
490 type: _.upperCase(this._schema.KEYS[k])
491 };
492 // if (k == AUTO_KEY_NAME) {
493 // obj['option'] = 'AUTO_INCREMENT'
494 // }
495 params.tableMeta.primaryKey.push(obj);
496 }
497 return [4 /*yield*/, new Promise(function (resolve, reject) {
498 __this__._client.createTable(params, function (err, data) {
499 if (err) {
500 xthrow(new Error(err), reject, { params: params, data: data });
501 return;
502 }
503 resolve();
504 });
505 })
506 // FIXME 表创建后有一定的延时时间才能生效,需要维持一定的等待时间确保正常执行完成。
507 // TODO 延时算法自动完成时间戳的处理。
508 ];
509 case 1:
510 out = _a.sent();
511 // FIXME 表创建后有一定的延时时间才能生效,需要维持一定的等待时间确保正常执行完成。
512 // TODO 延时算法自动完成时间戳的处理。
513 return [2 /*return*/, out];
514 }
515 });
516 });
517 };
518 // 查询当前表的描述信息
519 NoSqlAliyunTablestore.prototype.describe = function () {
520 return __awaiter(this, void 0, void 0, function () {
521 var __this__, params;
522 return __generator(this, function (_a) {
523 __this__ = this;
524 params = {
525 tableName: this._table
526 };
527 return [2 /*return*/, new Promise(function (resolve, reject) {
528 __this__._client.describeTable(params, function (err, data) {
529 if (err) {
530 xthrow(new Error(err), reject, { params: params });
531 return;
532 }
533 resolve(data);
534 });
535 })];
536 });
537 });
538 };
539 // 表配置信息的更新处理(时间戳以及版本号)
540 NoSqlAliyunTablestore.prototype.change = function (param) {
541 return __awaiter(this, void 0, void 0, function () {
542 var __this__, params;
543 return __generator(this, function (_a) {
544 __this__ = this;
545 params = {
546 tableName: this._table,
547 tableOptions: {
548 // 保存的最大版本数, 设置为1即代表每列上最多保存一个版本(保存最新的版本).
549 maxVersions: param.maxVersions ? param.maxVersions : 1,
550 // 数据的过期时间, 单位秒, -1代表永不过期. 假如设置过期时间为一年, 即为 365 * 24 * 3600
551 timeToLive: param.timeoutSeconds ? param.timeoutSeconds : -1,
552 },
553 reservedThroughput: {
554 capacityUnit: {
555 // 为了提升并发度确保预留最小读写数量的配置避免服务共享可能产生的资源竞争不稳定问题
556 read: param.reservedThroughputRead ? param.reservedThroughputRead : 0,
557 write: param.reservedThroughputWrite ? param.reservedThroughputWrite : 0,
558 }
559 },
560 };
561 return [2 /*return*/, new Promise(function (resolve, reject) {
562 __this__._client.updateTable(params, function (err, data) {
563 if (err) {
564 xthrow(new Error(err), reject, { params: params });
565 return;
566 }
567 resolve(data);
568 });
569 })];
570 });
571 });
572 };
573 // 重置表
574 NoSqlAliyunTablestore.prototype.reset = function () {
575 return __awaiter(this, void 0, void 0, function () {
576 var err_4;
577 return __generator(this, function (_a) {
578 switch (_a.label) {
579 case 0:
580 _a.trys.push([0, 2, , 3]);
581 return [4 /*yield*/, this.destroy()];
582 case 1:
583 _a.sent();
584 return [3 /*break*/, 3];
585 case 2:
586 err_4 = _a.sent();
587 return [3 /*break*/, 3];
588 case 3: return [4 /*yield*/, this.create()];
589 case 4:
590 _a.sent();
591 return [2 /*return*/];
592 }
593 });
594 });
595 };
596 return NoSqlAliyunTablestore;
597}(NoSqlInterface));
598exports.NoSqlAliyunTablestore = NoSqlAliyunTablestore;
599//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxpeXVuX290cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFsaXl1bl9vdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTs7R0FFRztBQUNILElBQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQTtBQUN4QyxJQUFNLElBQUksR0FBRyxVQUFVLENBQUMsSUFBSSxDQUFBO0FBQzVCLElBQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUUzQjtJQUNJLHdCQUFZLEtBQWEsRUFBRSxNQUFpQztRQUFqQyx1QkFBQSxFQUFBLGtCQUFpQztJQUM1RCxDQUFDO0lBaUNMLHFCQUFDO0FBQUQsQ0FBQyxBQW5DRCxJQW1DQztBQUVELGlDQUFpQztBQUNqQyw2REFBNkQ7QUFDN0Qsd0NBQXdDO0FBQ3hDLHFEQUFxRDtBQUNyRCxnR0FBZ0c7QUFDaEcsaUVBQWlFO0FBQ2pFLHNFQUFzRTtBQUN0RSx5Q0FBeUM7QUFDekMsRUFBRTtBQUNGLGNBQWM7QUFDZCw0RkFBNEY7QUFDNUYsK0NBQStDO0FBQy9DLHFEQUFxRDtBQUNyRCxnREFBZ0Q7QUFDaEQsRUFBRTtBQUNGLDRDQUE0QztBQUM1QywwR0FBMEc7QUFDMUcsMEVBQTBFO0FBQzFFLDZDQUE2QztBQUM3QywwQ0FBMEM7QUFDMUMsb0JBQW9CO0FBQ3BCLGlCQUFpQjtBQUNqQixJQUFJO0FBRUosMERBQTBEO0FBQzFELCtEQUErRDtBQUMvRDtJQUEyQyx5Q0FBYztJQVNyRCwrQkFBWSxLQUFhLEVBQUUsTUFBMEI7UUFBMUIsdUJBQUEsRUFBQSxrQkFBMEI7UUFBckQsWUFDSSxrQkFBTSxLQUFLLEVBQUUsTUFBTSxDQUFDLFNBaUJ2QjtRQWhCRyxJQUFNLFNBQVMsR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUE7UUFDMUMsT0FBTyxDQUFDLFNBQVMsSUFBSSxDQUFDLENB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RCxDQUFDLEFBamFELENBQTJDLGNBQWMsR0FpYXhEO0FBamFZLHNEQUFxQiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICog56CU56m26Zi/6YeM5LqR55qET1RT6KGo5qC86K6+6K6h5bCGc2Vzc2lvbuOAgWNhY2hl44CBdXNlcuS4ieenjee8k+WtmOS/oeaBr+eul+azleaehOW7uuWcqOatpOS5i+S4iuOAglxuICovXG5jb25zdCBUYWJsZVN0b3JlID0gcmVxdWlyZSgndGFibGVzdG9yZScpXG5jb25zdCBMb25nID0gVGFibGVTdG9yZS5Mb25nXG5jb25zdCBfID0gcmVxdWlyZSgnbG9kYXNoJylcblxuYWJzdHJhY3QgY2xhc3MgTm9TcWxJbnRlcmZhY2Uge1xuICAgIGNvbnN0cnVjdG9yKHRhYmxlOiBzdHJpbmcsIGNvbmZpZzogc3RyaW5nIHwge31bXSA9ICdkZWZhdWx0Jykge1xuICAgIH1cblxuICAgIC8vIOe6puWumuaJgOacieihqOmDvemcgOimgeacieiHquWinuS4u+mUrmlk5L2c5Li65YaF6YOo5ZSv5LiA5qCH6K+G56CB77yM5YW25L2Z5LiJ5Liq5Li76ZSu5b+F6aG75YWo6YOo5Li65a2X56ym5Liy44CC77yI5ZCO56uv6ZyA6KaB5omp5bGVaW505ZKMZGF0ZeWfuuacrOaVsOaNruexu+Wei+S7peWPiuaTjeS9nOespumHjei9veWunueOsOS8mOWMluW8gOWPke+8iVxuICAgIC8vIOWxnuaAp+Wtl+auteWPr+S7peagueaNruS4muWKoea8lOWPmOS7u+aEj+eahOaJqeWxleWinuWKoOeUseS4muWKoeS7o+eggeWvueS6juiAgeaVsOaNruS4jeWtmOWcqOaWsOWinuWtl+auteWAvOeahOaDheWGteWBmuWFvOWuueWkhOeQhlxuICAgIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBpbnNlcnQoaWQsIGt2dDogeyBbaW5kZXg6IHN0cmluZ106IHN0cmluZyB8IHsgdmFsdWU6IHN0cmluZywgdGltZXN0YW1wOiBudW1iZXIgfSB9KSA7XG5cbiAgICAvLyDmnaHku7bmm7TmlrDlv4XpobvopoHloavlhpnkuLvplK7orrDlvZXlgLwo5LuF5LuF5YWB6K645pu05paw5bGe5oCn5a2X5q616ICM5Li76ZSu5a2X5q615piv5LiN5YWB6K645pu05paw55qE77yMXG4gICAgLy8gICAgICDmlbTliJfmm7TmlrDlkozliKDpmaTliJflsZ7kuo7ov5Dnu7Tmk43kvZznpoHmraLlupTnlKjkuK3kvb/nlKjpnIDopoHljZXni6zmjqXlj6Pku6Xlj4rmnYPpmZDorqTor4EpXG4gICAgcHVibGljIGFic3RyYWN0IGFzeW5jIHVwZGF0ZShpZDogc3RyaW5nLCBrdnQ6IHsgW2luZGV4OiBzdHJpbmddOiBzdHJpbmcgfCBudWxsIHwgbnVtYmVyIH0pIDtcblxuICAgIC8vIOS7peS4u+mUruS9nOS4uuadoeS7tuWIoOmZpOiusOW9leWAvFxuICAgIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBkZWxldGUoaWQ6IHN0cmluZyk7XG5cbiAgICAvLyDliIbpobXmn6Xor6LkuIDmrKHmo4DntKJO5p2h6K6w5b2VXG4gICAgcHVibGljIGFic3RyYWN0IGFzeW5jIHF1ZXJ5KGlkOiBzdHJpbmcsIGtleXM6IHN0cmluZ1tdIHwgbnVsbCwgbWF4X3ZlcnNpb246IG51bWJlcik6IFByb21pc2U8YW55PjtcblxuICAgIC8vIOmUgOavgeihqFxuICAgIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBkZXN0cm95KCk7XG5cbiAgICAvLyDliJvlu7rooahcbiAgICBwdWJsaWMgYWJzdHJhY3QgYXN5bmMgY3JlYXRlKCk7XG5cbiAgICAvLyDmn6Xor6LlvZPliY3ooajnmoTmj4/ov7Dkv6Hmga9cbiAgICBwdWJsaWMgYWJzdHJhY3QgYXN5bmMgZGVzY3JpYmUoKTtcblxuICAgIC8vIOWPmOabtOihqFxuICAgIHB1YmxpYyBhYnN0cmFjdCBhc3luYyBjaGFuZ2UocGFyYW06IHtcbiAgICAgICAgbWF4VmVyc2lvbnM/OiBudW1iZXIsIHRpbWVvdXRTZWNvbmRzOiBudW1iZXIsXG4gICAgICAgIHJlc2VydmVkVGhyb3VnaHB1dFJlYWQ/OiBudW1iZXIsIHJlc2VydmVkVGhyb3VnaHB1dFdyaXRlPzogbnVtYmVyXG4gICAgfSk7XG5cbiAgICAvLyDph43nva7ooahcbiAgICBwdWJsaWMgYWJzdHJhY3QgYXN5bmMgcmVzZXQoKTtcbn1cblxuLy8gZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3QoKSB7XG4vLyAgICAgY29uc3Qgb3RzID0gbmV3IE5vU3FsQWxpeXVuVGFibGVzdG9yZSgnc2Vzc2lvbl90ZXN0MycpXG4vLyAgICAgLy8gbGV0IG91dCA9IGF3YWl0IG90cy5jcmVhdGUoNjApXG4vLyAgICAgLy8gRklYTUUg6aaW5qyh5Yib5bu66KGo6ZyA6KaB5pyJ5LiA5a6a55qE57O757uf5bu26L+f5pe26Ze077yM6ZyA6KaB5pS+5YiwaW5zdGFsbOi/h+eoi+S4rei/m+ihjOe7tOaKpOOAglxuLy8gICAgIC8vIGxldCBvdXQgPSBhd2FpdCBvdHMuaW5zZXJ0KCd4Jywge2E6ICdhYWEnLCBiOiB7dmFsdWU6ICdiYmJiJywgdGltZXN0YW1wOiBEYXRlLm5vdygpfX0pXG4vLyAgICAgLy8gbGV0IG91dCA9IGF3YWl0IG90cy51cGRhdGUoJ3gnLCB7YTogJ2FhYTInLCBiOiAnYmJiMid9KVxuLy8gICAgIC8vIGxldCBvdXQgPSBhd2FpdCBvdHMudXBkYXRlKCd4Jywge2E6IG51bGwsIGI6IDE1Mjk2NjYwNTMxMDB9KVxuLy8gICAgIC8vIGxldCBvdXQgPSBhd2FpdCBvdHMuZGVsZXRlKCd4Jylcbi8vXG4vLyAgICAgbGV0IG91dFxuLy8gICAgIC8vIG91dCA9IGF3YWl0IG90cy5pbnNlcnQoJ3gnLCB7YTogJ2FhYScsIGI6IHt2YWx1ZTogJ2JiYmInLCB0aW1lc3RhbXA6IERhdGUubm93KCl9fSlcbi8vICAgICAvLyBvdXQgPSBhd2FpdCBvdHMucXVlcnkoJ3gnKSAgLy8g5Y+W5YWo6YOo55qE5a2X5q61XG4vLyAgICAgLy8gb3V0ID0gYXdhaXQgb3RzLnF1ZXJ5KCd4JywgWydhJ10pICAvLyDlj5bpg6jliIblrZfmrrVcbi8vICAgICAvLyBvdXQgPSBhd2FpdCBvdHMucXVlcnkoJ3knKSAgLy8g5Y+W5LiN5a2Y5Zyo55qE5Li76ZSuXG4vL1xuLy8gICAgIC8vIG91dCA9IGF3YWl0IG90cy5jcmVhdGUoMjQqNjAqNjAsMilcbi8vICAgICAvLyBvdXQgPSBhd2FpdCBvdHMuaW5zZXJ0KCd6Jywge2E6ICdhYWEnK0RhdGUoKSwgYjoge3ZhbHVlOiAnYmJiYicrRGF0ZSgpLCB0aW1lc3RhbXA6IERhdGUubm93KCl9fSlcbi8vICAgICAvLyBvdXQgPSBhd2FpdCBvdHMudXBkYXRlKCd6Jywge2E6ICdhYWEnK0RhdGUoKSwgYjogJ2JiYmInK0RhdGUoKX0pXG4vLyAgICAgLy8gb3V0ID0gYXdhaXQgb3RzLnF1ZXJ5KCd6JywgbnVsbCwgMilcbi8vICAgICBvdXQgPSBhd2FpdCBvdHMucXVlcnkoJ3onLCBudWxsLCAxKVxuLy8gICAgIC8vIOeUqOacgOS9s+aWueahiOWOu+WunueOsOWtl+autVxuLy8gICAgIHJldHVybiBvdXRcbi8vIH1cblxuLy8g5a+55LqO6Zi/6YeM5LqRdGFibGVzdG9yZeeahOWNleihqOWKn+iDveeugOWNleWwgeijheWkhOeQhu+8iOS4gOS4quS4u+mUruW5tuS9nOS4uuWIhuWMuuWUr+S4gOWMuuWIhuS4gOS4quiusOW9le+8jOS7heeUqOS6jue8k+WtmOWKn+iDveWunueOsOOAglxuLy8g5bCB6KOF54m554K577ya5q+P5Liq6K6w5b2V5LiA5p2h5Li76ZSu5bm25L2c5Li65YiG5Yy677yM5q+P5Liq6K6w5b2V5pyJ5peg5pWw5Liqa3blgLzlj6/kvpvphY3nva7vvIzmr4/kuKprduWAvOmDveacieS4gOS4quaXtumXtOaIs+i2heaXtuaXtumXtOWcqOihqOS4iuWNleeLrOmFjee9ruOAgu+8iVxuZXhwb3J0IGNsYXNzIE5vU3FsQWxpeXVuVGFibGVzdG9yZSBleHRlbmRzIE5vU3FsSW50ZXJmYWNlIHtcbiAgICBwcml2YXRlIF90YWJsZTogc3RyaW5nXG4gICAgcHJpdmF0ZSBfY2xpZW50OiBhbnlcbiAgICBwcml2YXRlIF9zY2hlbWE6IGFueVxuXG4gICAgc2V0IHRhYmxlKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX3RhYmxlID0gdmFsdWVcbiAgICB9XG5cbiAgICBjb25zdHJ1Y3Rvcih0YWJsZTogc3RyaW5nLCBjb25maWc6IHN0cmluZyA9ICdkZWZhdWx0Jykge1xuICAgICAgICBzdXBlcih0YWJsZSwgY29uZmlnKVxuICAgICAgICBjb25zdCBpbnN0YW5jZXMgPSB4Y29uZmlnKCdwbHVnaW5zLm5vc3FsJylcbiAgICAgICAgeGFzc2VydChpbnN0YW5jZXMgJiYgXy5pc1BsYWluT2JqZWN0KGluc3RhbmNlcykgJiYgY29uZmlnIGluIGluc3RhbmNlcyxcbiAgICAgICAgICAgIEVSUiRDT05GSUcsIHtpbnN0YW5jZXN9KVxuICAgICAgICB0aGlzLl90YWJsZSA9IHRhYmxlXG4gICAgICAgIHRoaXMuX3NjaGVtYSA9IHtcbiAgICAgICAgICAgIEtFWVM6IHtcbiAgICAgICAgICAgICAgICBpZDogJ3N0cmluZycgLy8g6KGo55qE5ZSv5LiA6K6w5b2V5Li76ZSu5YC85ZCM5pe25Lmf5piv5YiG5Yy6XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9jbGllbnQgPSBuZXcgVGFibGVTdG9yZS5DbGllbnQoe1xuICAgICAgICAgICAgYWNjZXNzS2V5SWQ6IGluc3RhbmNlc1tjb25maWddLk9UU19BQ0NFU1NfS0VZX0lELFxuICAgICAgICAgICAgc2VjcmV0QWNjZXNzS2V5OiBpbnN0YW5jZXNbY29uZmlnXS5PVFNfU0VDUkVURV9BQ0NFU1NfS0VZLFxuICAgICAgICAgICAgZW5kcG9pbnQ6IGluc3RhbmNlc1tjb25maWddLk9UU19FTkRQT0lOVCxcbiAgICAgICAgICAgIGluc3RhbmNlbmFtZTogaW5zdGFuY2VzW2NvbmZpZ10uT1RTX0lOU1RBTkNFTkFNRVxuICAgICAgICB9KVxuICAgIH1cblxuICAgIC8vIOe6puWumuaJgOacieihqOmDvemcgOimgeacieiHquWinuS4u+mUrmlk5L2c5Li65YaF6YOo5ZSv5LiA5qCH6K+G56CB77yM5YW25L2Z5LiJ5Liq5Li76ZSu5b+F6aG75YWo6YOo5Li65a2X56ym5Liy44CC77yI5ZCO56uv6ZyA6KaB5omp5bGVaW505ZKMZGF0ZeWfuuacrOaVsOaNruexu+Wei+S7peWPiuaTjeS9nOespumHjei9veWunueOsOS8mOWMluW8gOWPke+8iVxuICAgIC8vIOWxnuaAp+Wtl+auteWPr+S7peagueaNruS4muWKoea8lOWPmOS7u+aEj+eahOaJqeWxleWinuWKoOeUseS4muWKoeS7o+eggeWvueS6juiAgeaVsOaNruS4jeWtmOWcqOaWsOWinuWtl+auteWAvOeahOaDheWGteWBmuWFvOWuueWkhOeQhlxuICAgIHB1YmxpYyBhc3luYyBpbnNlcnQoaWQ6IHN0cmluZywga3Z0OiB7IFtpbmRleDogc3RyaW5nXTogc3RyaW5nIHwgeyB2YWx1ZTogc3RyaW5nLCB0aW1lc3RhbXA6IG51bWJlciB9IH0pIHtcbiAgICAgICAgeGFzc2VydChPYmplY3Qua2V5cyhrdnQpLmxlbmd0aCA8PSAxMjgpIC8vIOinhOmBv+i3qOihjOmZkOWItuaAu+iuoeWxnuaApzEyOOS4qlxuICAgICAgICBjb25zdCBfX3RoaXNfXyA9IHRoaXNcbiAgICAgICAgLy8gdmFyIGN1cnJlbnRUaW1lU3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICB0YWJsZU5hbWU6IHRoaXMuX3RhYmxlLFxuICAgICAgICAgICAgLy8g5o+S5YWl55qE5pe25YCZ6ZyA6KaB56Gu5L+d5LiN5a2Y5Zyo5a+55bqU55qE5pWw5o2u5Lul6Ziy5q2i5Ye66ZSZXG4gICAgICAgICAgICBjb25kaXRpb246IG5ldyBUYWJsZVN0b3JlLkNvbmRpdGlvbihUYWJsZVN0b3JlLlJvd0V4aXN0ZW5jZUV4cGVjdGF0aW9uLkVYUEVDVF9OT1RfRVhJU1QsIG51bGwpLFxuICAgICAgICAgICAgcHJpbWFyeUtleTogW10sXG4gICAgICAgICAgICBhdHRyaWJ1dGVDb2x1bW5zOiBbXSxcbiAgICAgICAgICAgIC8vIOaMieeFp+S4i+mdouaVsOaNruagvOW8j+i/m+ihjHNjaGVtYeWumuS5ieeahOmqjOivgeS7peWPiuaVsOaNruexu+Wei+i9rOaNolxuICAgICAgICAgICAgLy8gcHJpbWFyeUtleTogW3snZ2lkJzogTG9uZy5mcm9tTnVtYmVyKDIwMDEzKX0sIHsndWlkJzogTG9uZy5mcm9tTnVtYmVyKDIwMDEzKX1dLFxuICAgICAgICAgICAgLy8gYXR0cmlidXRlQ29sdW1uczogW1xuICAgICAgICAgICAgLy8gICAgIHsnY29sMSc6ICfooajmoLzlrZjlgqgnfSxcbiAgICAgICAgICAgIC8vICAgICB7J2NvbDInOiAnMicsICd0aW1lc3RhbXAnOiBjdXJyZW50VGltZVN0YW1wfSwgLy8g5YWB6K645L+u5pS55pe26Ze05oiz5LmQ6KeC6ZSB5Yqf6IO95a6e546w5pqC5LiN5pSv5oyBXG4gICAgICAgICAgICAvLyAgICAgeydjb2wzJzogMy4xfSxcbiAgICAgICAgICAgIC8vICAgICB7J2NvbDQnOiAtMC4zMn0sXG4gICAgICAgICAgICAvLyAgICAgeydjb2w1JzogTG9uZy5mcm9tTnVtYmVyKDEyMzQ1Njc4OSl9XG4gICAgICAgICAgICAvLyBdLFxuICAgICAgICAgICAgLy8gcHJpbWFyeUtleTogW1xuICAgICAgICAgICAgLy8gICAgIHsnc2hvcnRfaWQnOiAncGsxJ30sXG4gICAgICAgICAgICAvLyAgICAge1tBVVRPX0tFWV9OQU1FXTogVGFibGVTdG9yZS5QS19BVVRPX0lOQ1J9XG4gICAgICAgICAgICAvLyBdLFxuICAgICAgICAgICAgLy8gYXR0cmlidXRlQ29sdW1uczogW1xuICAgICAgICAgICAgLy8gICAgIHsnYXBwY29kZSc6ICdhcHAxJ31cbiAgICAgICAgICAgIC8vIF0sXG4gICAgICAgICAgICByZXR1cm5Db250ZW50OiB7cmV0dXJuVHlwZTogVGFibGVTdG9yZS5SZXR1cm5UeXBlLlByaW1hcnlrZXl9XG4gICAgICAgIH1cblxuICAgICAgICAvLyDmi7zmjqXkuLvplK7ku6Xlj4rlsZ7mgKflrZfmrrXlgLxcbiAgICAgICAgcGFyYW1zLnByaW1hcnlLZXkgPSBbeydpZCc6IGlkfV1cbiAgICAgICAgZm9yIChsZXQgayBpbiBrdnQpIHtcbiAgICAgICAgICAgIHhhc3NlcnQoayAhPSAnaWQnICYmIGsgIT0gJ3RpbWVzdGFtcCcpIC8vIOS4pOS4qumihOeVmeWGhemDqOagh+ivhuespuS4jeWPr+S9nOS4uuWxnuaAp+WQjVxuICAgICAgICAgICAgaWYgKF8uaXNTdHJpbmcoa3Z0W2tdKSkge1xuICAgICAgICAgICAgICAgIHBhcmFtcy5hdHRyaWJ1dGVDb2x1bW5zLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBba106IGt2dFtrXVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcmFtcy5hdHRyaWJ1dGVDb2x1bW5zLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBba106IGt2dFtrXVsndmFsdWUnXSxcbiAgICAgICAgICAgICAgICAgICAgdGltZXN0YW1wOiBrdnRba11bJ3RpbWVzdGFtcCddXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIF9fdGhpc19fLl9jbGllbnQucHV0Um93KHBhcmFtcywgZnVuY3Rpb24gKGVyciwgb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHh0aHJvdyhuZXcgRXJyb3IoZXJyKSwgcmVqZWN0LCB7cGFyYW1zLCBvdXR9KVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8g5q2j5bi46L+U5Zue55qE5pWw5o2u5qC85byPXG4gICAgICAgICAgICAgICAgICAgIC8ve1wiY29uc3VtZWRcIjp7XCJjYXBhY2l0eV91bml0XCI6e1wicmVhZFwiOjAsXCJ3cml0ZVwiOjF9fSxcInJvd1wiOntcbiAgICAgICAgICAgICAgICAgICAgLy8gIFwicHJpbWFyeUtleVwiOlt7XCJuYW1lXCI6XCJzaG9ydF9pZFwiLFwidmFsdWVcIjpcImFiY2RcIn0se1wibmFtZVwiOlwiaWRcIixcInZhbHVlXCI6MTUyMDc2NTUwMjM0NzAwMH1dLFxuICAgICAgICAgICAgICAgICAgICAvLyAgXCJhdHRyaWJ1dGVzXCI6W119LFxuICAgICAgICAgICAgICAgICAgICAvLyBcIlJlcXVlc3RJZFwiOlwiMDAwNTY3MjAtY2Y4ZC1kNGE4LThhZTgtOTcwYTE3ODk0Y2U2XCJ9XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUob3V0KVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB4dGhyb3coZXJyLCByZWplY3QpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIHVwZGF0ZShpZDogc3RyaW5nLCBrdnQ6IHsgW2luZGV4OiBzdHJpbmddOiBzdHJpbmcgfCBudWxsIHwgbnVtYmVyIH0pIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX3VwZGF0ZV9vcl9yZXBsYWNlKGlkLCBrdnQsIGZhbHNlKVxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyByZXBsYWNlKGlkOiBzdHJpbmcsIGt2dDogeyBbaW5kZXg6IHN0cmluZ106IHN0cmluZyB8IG51bGwgfCBudW1iZXIgfSkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5fdXBkYXRlX29yX3JlcGxhY2UoaWQsIGt2dCwgdHJ1ZSlcbiAgICB9XG5cbiAgICAvLyDmnaHku7bmm7TmlrDlv4XpobvopoHloavlhpnkuLvplK7orrDlvZXlgLwo5LuF5LuF5YWB6K645pu05paw5bGe5oCn5a2X5q616ICM5Li76ZSu5a2X5q615piv5LiN5YWB6K645pu05paw55qE77yMXG4gICAgLy8gICAgICDmlbTliJfmm7TmlrDlkozliKDpmaTliJflsZ7kuo7ov5Dnu7Tmk43kvZznpoHmraLlupTnlKjkuK3kvb/nlKjpnIDopoHljZXni6zmjqXlj6Pku6Xlj4rmnYPpmZDorqTor4EpXG4gICAgcHJpdmF0ZSBhc3luYyBfdXBkYXRlX29yX3JlcGxhY2UoaWQ6IHN0cmluZywga3Z0OiB7IFtpbmRleDogc3RyaW5nXTogc3RyaW5nIHwgbnVsbCB8IG51bWJlciB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzSWdub3JlUm93Tm9uRXhpc3Q6IGJvb2xlYW4gPSBmYWxzZSkge1xuICAgICAgICB4YXNzZXJ0KE9iamVjdC5rZXlzKGt2dCkubGVuZ3RoID4gMCAmJiBPYmplY3Qua2V5cyhrdnQpLmxlbmd0aCA8PSAxMjgpIC8vIOinhOmBv+i3qOihjOmZkOWItuaAu+iuoeWxnuaApzEyOOS4qlxuICAgICAgICBjb25zdCBfX3RoaXNfXyA9IHRoaXNcbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgdGFibGVOYW1lOiB0aGlzLl90YWJsZSxcbiAgICAgICAgICAgIGNvbmRpdGlvbjogbmV3IFRhYmxlU3RvcmUuQ29uZGl0aW9uKGlzSWdub3JlUm93Tm9uRXhpc3QgP1xuICAgICAgICAgICAgICAgIFRhYmxlU3RvcmUuUm93RXhpc3RlbmNlRXhwZWN0YXRpb24uSUdOT1JFIDpcbiAgICAgICAgICAgICAgICBUYWJsZVN0b3JlLlJvd0V4aXN0ZW5jZUV4cGVjdGF0aW9uLkVYUEVDVF9FWElTVCwgbnVsbCksXG4gICAgICAgICAgICBwcmltYXJ5S2V5OiBbe2lkfV0sXG4gICAgICAgICAgICAvLyB1cGRhdGVPZkF0dHJpYnV0ZUNvbHVtbnM6IFt7J1BVVCc6IFt7J2NvbDEnOiAndGVzdDYnfV19XVxuICAgICAgICAgICAgdXBkYXRlT2ZBdHRyaWJ1dGVDb2x1bW5zOiBbXVxuICAgICAgICAgICAgLy8gdXBkYXRlT2ZBdHRyaWJ1dGVDb2x1bW5zOiBbXG4gICAgICAgICAgICAvLyAgICAgeyAnUFVUJzogW3sgJ2NvbDQnOiBMb25nLmZyb21OdW1iZXIoNCkgfSwgeyAnY29sNSc6ICc1JyB9LCB7ICdjb2w2JzogTG9uZy5mcm9tTnVtYmVyKDYpIH1dIH0sXG4gICAgICAgICAgICAvLyAgICAgeyAnREVMRVRFJzogW3sgJ2NvbDEnOiBMb25nLmZyb21OdW1iZXIoMTQ5NjgyNjQ3MzE4NikgfV0gfSwgLy8g5Yig6Zmk5oyH5a6a5pe26Ze05oiz54mI5pys5pWw5o2uXG4gICAgICAgICAgICAvLyAgICAgeyAnREVMRVRFX0FMTCc6IFsnY29sMiddIH0gLy8g5Yig6Zmk5omA5pyJ54mI5pys55qE5a2X5q615pWw5o2uXG4gICAgICAgICAgICAvLyBdXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBQVVQgPSBbXVxuICAgICAgICBjb25zdCBERUxFVEUgPSBbXVxuICAgICAgICBjb25zdCBERUxFVEVfQUxMID0gW11cbiAgICAgICAgZm9yIChsZXQgayBpbiBrdnQpIHtcbiAgICAgICAgICAgIC8vIOWmguaenOWPmOmHj+WAvOS4um51bGznsbvlnovliJnooajnpLrliKDpmaTlr7nlupTnmoTlrZfmrrXlgLzvvIzlpoLmnpzkuLrmlbTmlbDooajnpLrliKDpmaTmjIflrprml7bpl7TmiLPniYjmnKzvvIzlkKbliJnooajnpLrmt7vliqDmiJbmm7TmlrDlr7nlupTlrZfmrrXlgLzjgIJcbiAgICAgICAgICAgIGlmICgha3Z0W2tdKSB7XG4gICAgICAgICAgICAgICAgREVMRVRFX0FMTC5wdXNoKGspXG4gICAgICAgICAgICB9IGVsc2UgaWYgKF8uaXNJbnRlZ2VyKGt2dFtrXSkpIHtcbiAgICAgICAgICAgICAgICBERUxFVEUucHVzaCh7W2tdOiBMb25nLmZyb21OdW1iZXIoa3Z0W2tdKX0pXG4gICAgICAgICAgICB9IGVsc2UgaWYgKF8uaXNTdHJpbmcoa3Z0W2tdKSkge1xuICAgICAgICAgICAgICAgIFBVVC5wdXNoKHtba106IGt2dFtrXX0pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHhhc3NlcnQoZmFsc2UsIEVSUiRQQVJBTSwge2lkLCBrdnR9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChQVVQubGVuZ3RoID4gMCkgcGFyYW1zLnVwZGF0ZU9mQXR0cmlidXRlQ29sdW1ucy5wdXNoKHtQVVR9KVxuICAgICAgICBpZiAoREVMRVRFLmxlbmd0aCA+IDApIHBhcmFtcy51cGRhdGVPZkF0dHJpYnV0ZUNvbHVtbnMucHVzaCh7REVMRVRFfSlcbiAgICAgICAgaWYgKERFTEVURV9BTEwubGVuZ3RoID4gMCkgcGFyYW1zLnVwZGF0ZU9mQXR0cmlidXRlQ29sdW1ucy5wdXNoKHtERUxFVEVfQUxMfSlcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBfX3RoaXNfXy5fY2xpZW50LnVwZGF0ZVJvdyhwYXJhbXMsIGZ1bmN0aW9uIChlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXMsIGRhdGF9KVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIHh0aHJvdyhlcnIsIHJlamVjdClcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICB9XG5cbiAgICAvLyDku6XkuLvplK7kvZzkuLrmnaHku7bliKDpmaTorrDlvZXlgLxcbiAgICBwdWJsaWMgYXN5bmMgZGVsZXRlKGlkOiBzdHJpbmcpIHtcbiAgICAgICAgY29uc3QgX190aGlzX18gPSB0aGlzXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgIHRhYmxlTmFtZTogdGhpcy5fdGFibGUsXG4gICAgICAgICAgICBjb25kaXRpb246IG5ldyBUYWJsZVN0b3JlLkNvbmRpdGlvbihUYWJsZVN0b3JlLlJvd0V4aXN0ZW5jZUV4cGVjdGF0aW9uLklHTk9SRSwgbnVsbCksXG4gICAgICAgICAgICAvLyBwcmltYXJ5S2V5OiBbeyAnZ2lkJzogTG9uZy5mcm9tTnVtYmVyKDgpIH0sIHsgJ3VpZCc6IExvbmcuZnJvbU51bWJlcig4MCkgfV1cbiAgICAgICAgICAgIHByaW1hcnlLZXk6IFt7aWR9XVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgX190aGlzX18uX2NsaWVudC5kZWxldGVSb3cocGFyYW1zLCBmdW5jdGlvbiAoZXJyLCBkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHh0aHJvdyhuZXcgRXJyb3IoZXJyKSwgcmVqZWN0LCB7cGFyYW1zLCBkYXRhfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVyblxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICB4dGhyb3coZXJyLCByZWplY3QpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8g6IyD5Zu05p+l6K+i6ZyA6KaB5pWw5o2u6Ieq5Yqo5ZCM5q2l5Yiwb3BlbnNlYXJjaOi/m+ihjOe0ouW8leWQjOatpeWQjui/m+ihjOWQhOenjeWkjeadgueahOafpeivouaTjeS9nOWunueOsOWFjei/kOe7tOezu+e7n+eahOWunueOsFxuICAgIC8vIOWNleihqOmAu+i+keadoeS7tueahOeugOWNlWFuZOS4jmVxdWFs55qE5p+l6K+i77yM6L+U5Zue5ruh6Laz5p2h5Lu255qE56ys5LiA5p2h6K6w5b2VIO+8iOWQiOW5tuS4uuS4gOS4quafpeivouWFvOWuuW1vbmdvZGLnmoTmn6Xor6LmianlsZXvvIlcbiAgICBwdWJsaWMgYXN5bmMgcXVlcnkoaWQ6IHN0cmluZywga2V5czogc3RyaW5nW10gfCBudWxsID0gbnVsbCwgbWF4X3ZlcnNpb246IG51bWJlciA9IDEpOiBQcm9taXNlPGFueT4ge1xuXG4gICAgICAgIGNvbnN0IF9fdGhpc19fID0gdGhpc1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICB0YWJsZU5hbWU6IHRoaXMuX3RhYmxlLFxuICAgICAgICAgICAgY29sdW1uc1RvR2V0OiBrZXlzLFxuICAgICAgICAgICAgLy8gY29sdW1uc190b19nZXQg6I635Y+W5pyf5pyb55qE5YiX5pyA5aSaMTI45Liq5LiA5qyh6I635Y+W5oC75pWw77yM5bqU55So5LiK5bqU6K+l5bCGS0VZ6KeG5Li65YiG57uE5oC75pWw44CCXG4gICAgICAgICAgICAvLyDlpoLkvZXop4Tpgb/lrr3ooajnmoTliIbpobXpmZDliLbvvJ/vvJ8gRklYTUUg5YWI5LuO5bqU55So5LiK6KeE6YG/6ZmQ5Yi25LiA5Liq5bqU55So5pyA5aSa5LiN6LaF6L+HMTI45Liq5bGe5oCn77yM6YCa6L+HSlNPTui/m+ihjOaJqeWxleWtmOWCqOOAglxuICAgICAgICAgICAgcHJpbWFyeUtleTogW3tpZH1dLFxuICAgICAgICAgICAgLy8gcHJpbWFyeUtleTogW3snZ2lkJzogTG9uZy5mcm9tTnVtYmVyKDIwMDEzKX0sIHsndWlkJzogTG9uZy5mcm9tTnVtYmVyKDIwMDEzKX1dLFxuICAgICAgICAgICAgY29sdW1uRmlsdGVyOiBudWxsLFxuICAgICAgICAgICAgbWF4VmVyc2lvbnM6IG1heF92ZXJzaW9uLFxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIF9fdGhpc19fLl9jbGllbnQuZ2V0Um93KHBhcmFtcywgZnVuY3Rpb24gKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXMsIGRhdGF9KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyDov5Tlm57mlbDmja7moLzlvI/nsbvlnovov5vooYzovazmjaLlpITnkIZcbiAgICAgICAgICAgICAgICAvLyB7XCJjb25zdW1lZFwiOntcImNhcGFjaXR5X3VuaXRcIjp7XCJyZWFkXCI6MSxcIndyaXRlXCI6MH19LFxuICAgICAgICAgICAgICAgIC8vICBcInJvd1wiOntcInByaW1hcnlLZXlcIjpbe1wibmFtZVwiOlwiZ2lkXCIsXCJ2YWx1ZVwiOjIwMDEzfSx7XCJuYW1lXCI6XCJ1aWRcIixcInZhbHVlXCI6MjAwMTN9XSxcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgICBcImF0dHJpYnV0ZXNcIjpbe1wiY29sdW1uTmFtZVwiOlwiY29sMVwiLFwiY29sdW1uVmFsdWVcIjpcIuihqOagvOWtmOWCqFwiLFwidGltZXN0YW1wXCI6MTUyMDczNDUyMDI4Nn0sXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAge1wiY29sdW1uTmFtZVwiOlwiY29sMlwiLFwiY29sdW1uVmFsdWVcIjpcIjJcIixcInRpbWVzdGFtcFwiOjE1MjA3MzQ1MjAwNjR9LFxuICAgICAgICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAge1wiY29sdW1uTmFtZVwiOlwiY29sM1wiLFwiY29sdW1uVmFsdWVcIjozLjEsXCJ0aW1lc3RhbXBcIjoxNTIwNzM0NTIwMjg2fSxcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgIHtcImNvbHVtbk5hbWVcIjpcImNvbDRcIixcImNvbHVtblZhbHVlXCI6LTAuMzIsXCJ0aW1lc3RhbXBcIjoxNTIwNzM0NTIwMjg2fSxcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgIHtcImNvbHVtbk5hbWVcIjpcImNvbDVcIixcImNvbHVtblZhbHVlXCI6MTIzNDU2Nzg5LFwidGltZXN0YW1wXCI6MTUyMDczNDUyMDI4Nn1dXG4gICAgICAgICAgICAgICAgLy8gICAgICAgIH0sXG4gICAgICAgICAgICAgICAgLy8gXCJuZXh0X3Rva2VuXCI6bnVsbCxcIlJlcXVlc3RJZFwiOlwiMDAwNTY3MTktZTJhZC03M2IxLWRiZDgtOTcwYTE5NTIyZjRiXCJ9XG5cbiAgICAgICAgICAgICAgICAvLyDlsIbmlbDmja7nu5Pmnpzov5vooYzovazmjaLlpITnkIblkIjlubbkuLrkuIDkuKrmma7pgJrlr7nosaHnu5nlupTnlKjkvb/nlKhcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgb3V0OiBhbnkgPSB7fVxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRhdGEucm93KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShudWxsKVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChkYXRhLnJvdy5wcmltYXJ5S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBrIGluIGRhdGEucm93LnByaW1hcnlLZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRbZGF0YS5yb3cucHJpbWFyeUtleVtrXS5uYW1lXSA9IGRhdGEucm93LnByaW1hcnlLZXlba10udmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoZGF0YS5yb3cuYXR0cmlidXRlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgayBpbiBkYXRhLnJvdy5hdHRyaWJ1dGVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0W2RhdGEucm93LmF0dHJpYnV0ZXNba10uY29sdW1uTmFtZV0gPSBkYXRhLnJvdy5hdHRyaWJ1dGVzW2tdLmNvbHVtblZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8geGxvZyhkYXRhKSAvLyBUT0RPIOW9k+WtmOWcqOWkmuS4queJiOacrOaVsOaNrueahOaXtuWAmeino+aekOS4jeato+ehru+8jOW6lOivpeaYr+WkmuS4queJiOacrOeahOWxnuaAp+WAvOWtl+auteeahOe7hOWQiOaJjeato+ehruOAglxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKF8uaXNFbXB0eShvdXQpID8gbnVsbCA6IG91dClcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXMsIGRhdGF9KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICB9KVxuICAgIH1cblxuICAgIC8vIOmUgOavgeihqFxuICAgIHB1YmxpYyBhc3luYyBkZXN0cm95KCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5fZGVzdHJveSgpXG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgLy8gMTDnp5Lpkp/nrYnlvoXotoXml7bplIDmr4HooajmraPluLjlrozmiJBcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDA7IGkrKykge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgb3V0ID0gdGhpcy5kZXNjcmliZSgpXG4gICAgICAgICAgICAgICAgeGxvZyhvdXQpXG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBhd2FpdCB4c2xlZXAoMTAwKVxuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIF9kZXN0cm95KCkge1xuICAgICAgICBjb25zdCBfX3RoaXNfXyA9IHRoaXNcbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgdGFibGVOYW1lOiB0aGlzLl90YWJsZVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBfX3RoaXNfXy5fY2xpZW50LmRlbGV0ZVRhYmxlKHBhcmFtcywgZnVuY3Rpb24gKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXN9KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpXG4gICAgICAgICAgICB9KVxuICAgICAgICB9KVxuICAgIH1cblxuICAgIC8vIOWIm+W7uuihqFxuICAgIHB1YmxpYyBhc3luYyBjcmVhdGUodGltZW91dCA9IC0xLCBtYXhfdmVyc2lvbnMgPSAxKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuX2NyZWF0ZSh0aW1lb3V0LCBtYXhfdmVyc2lvbnMpXG4gICAgICAgIC8vIDEw56eS6ZKf562J5b6F6LaF5pe25Yib5bu66KGo5q2j5bi45a6M5oiQXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTAwOyBpKyspIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbGV0IG91dCA9IHRoaXMuZGVzY3JpYmUoKVxuICAgICAgICAgICAgICAgIHhsb2cob3V0KVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgeHNsZWVwKDEwMClcbiAgICAgICAgICAgICAgICBjb250aW51ZVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgYXN5bmMgX2NyZWF0ZSh0aW1lb3V0ID0gLTEsIG1heF92ZXJzaW9ucyA9IDEpIHtcbiAgICAgICAgLy8gT1RT5pyA6ZW/6LaF5pe25pe26Ze05Li6MeWkqeeahOWFvOWuueWkhOeQhlxuICAgICAgICBpZiAodGltZW91dCAhPSAtMSAmJiB0aW1lb3V0IDwgODY0MDApIHtcbiAgICAgICAgICAgIHRpbWVvdXQgPSA4NjQwMFxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IF9fdGhpc19fID0gdGhpc1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICAgICAgICB0YWJsZU1ldGE6IHtcbiAgICAgICAgICAgICAgICB0YWJsZU5hbWU6IHRoaXMuX3RhYmxlLFxuICAgICAgICAgICAgICAgIHByaW1hcnlLZXk6IFtdIGFzIGFueVtdLFxuICAgICAgICAgICAgICAgIC8vIHByaW1hcnlLZXk6IFtcbiAgICAgICAgICAgICAgICAvLyAgICAge1xuICAgICAgICAgICAgICAgIC8vICAgICAgICAgbmFtZTogJ3Nob3J0X2lkJyxcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgIHR5cGU6ICdTVFJJTkcnXG4gICAgICAgICAgICAgICAgLy8gICAgIH0sXG4gICAgICAgICAgICAgICAgLy8gICAgIHtcbiAgICAgICAgICAgICAgICAvLyAgICAgICAgIG5hbWU6IEFVVE9fS0VZX05BTUUsXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICB0eXBlOiAnSU5URUdFUicsXG4gICAgICAgICAgICAgICAgLy8gICAgICAgICBvcHRpb246ICdBVVRPX0lOQ1JFTUVOVCcsXG4gICAgICAgICAgICAgICAgLy8gICAgIH1cbiAgICAgICAgICAgICAgICAvLyBdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVzZXJ2ZWRUaHJvdWdocHV0OiB7XG4gICAgICAgICAgICAgICAgY2FwYWNpdHlVbml0OiB7XG4gICAgICAgICAgICAgICAgICAgIHJlYWQ6IDAsXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlOiAwXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRhYmxlT3B0aW9uczoge1xuICAgICAgICAgICAgICAgIHRpbWVUb0xpdmU6IHRpbWVvdXQsLy8g5pWw5o2u55qE6L+H5pyf5pe26Ze0LCDljZXkvY3np5IsIC0x5Luj6KGo5rC45LiN6L+H5pyfLiDlgYflpoLorr7nva7ov4fmnJ/ml7bpl7TkuLrkuIDlubQsIOWNs+S4uiAzNjUgKiAyNCAqIDM2MDAuXG4gICAgICAgICAgICAgICAgbWF4VmVyc2lvbnM6IG1heF92ZXJzaW9ucywvLyDkv53lrZjnmoTmnIDlpKfniYjmnKzmlbAsIOiuvue9ruS4ujHljbPku6Pooajmr4/liJfkuIrmnIDlpJrkv53lrZjkuIDkuKrniYjmnKwo5L+d5a2Y5pyA5paw55qE54mI5pysKS5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyDoh6rliqjovazmjaJzY2hlbWHlrprkuYnkuLpPVFPnmoTmlbDmja7nu5PmnoRcbiAgICAgICAgZm9yIChsZXQgayBpbiB0aGlzLl9zY2hlbWEuS0VZUykge1xuICAgICAgICAgICAgbGV0IG9iaiA9IHtcbiAgICAgICAgICAgICAgICBuYW1lOiBrLFxuICAgICAgICAgICAgICAgIHR5cGU6IF8udXBwZXJDYXNlKHRoaXMuX3NjaGVtYS5LRVlTW2tdKVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gaWYgKGsgPT0gQVVUT19LRVlfTkFNRSkge1xuICAgICAgICAgICAgLy8gICAgIG9ialsnb3B0aW9uJ10gPSAnQVVUT19JTkNSRU1FTlQnXG4gICAgICAgICAgICAvLyB9XG4gICAgICAgICAgICBwYXJhbXMudGFibGVNZXRhLnByaW1hcnlLZXkucHVzaChvYmopXG4gICAgICAgIH1cbiAgICAgICAgLy8gYnVnZml46Kej5Yaz56ys5LiA5Liq5YiG5Yy66ZSu5LiN6IO95Li66Ieq5aKe5Li76ZSu55qE6Zeu6aKY6buY6K6k6KGl5LiK5LiA5LiqX2lk5a2X5q615YC855qE6Zeu6aKY77yI5Y+q5YGa5o+Q56S65pqC5LiN6Kej5Yaz57qm5a6a5LiA5LiqX2lk5YiG5Yy66ZSu5by65Yi26K6+572u77yJXG4gICAgICAgIC8vIFwiNDAwOiBcXG5cXHUwMDEzT1RTUGFyYW1ldGVySW52YWxpZFxcdTAwMTIqZmlyc3QgcHJpbWFyeSBrZXkgY2FuJ3QgYmUgQVVUT19JTkNSRU1FTlQuXCJcblxuICAgICAgICBsZXQgb3V0ID0gYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgX190aGlzX18uX2NsaWVudC5jcmVhdGVUYWJsZShwYXJhbXMsIGZ1bmN0aW9uIChlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHh0aHJvdyhuZXcgRXJyb3IoZXJyKSwgcmVqZWN0LCB7cGFyYW1zLCBkYXRhfSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSlcblxuICAgICAgICAvLyBGSVhNRSDooajliJvlu7rlkI7mnInkuIDlrprnmoTlu7bml7bml7bpl7TmiY3og73nlJ/mlYjvvIzpnIDopoHnu7TmjIHkuIDlrprnmoTnrYnlvoXml7bpl7Tnoa7kv53mraPluLjmiafooYzlrozmiJDjgIJcbiAgICAgICAgLy8gVE9ETyDlu7bml7bnrpfms5Xoh6rliqjlrozmiJDml7bpl7TmiLPnmoTlpITnkIbjgIJcbiAgICAgICAgcmV0dXJuIG91dFxuICAgIH1cblxuICAgIC8vIOafpeivouW9k+WJjeihqOeahOaPj+i/sOS/oeaBr1xuICAgIHB1YmxpYyBhc3luYyBkZXNjcmliZSgpIHtcbiAgICAgICAgY29uc3QgX190aGlzX18gPSB0aGlzXG4gICAgICAgIGNvbnN0IHBhcmFtcyA9IHtcbiAgICAgICAgICAgIHRhYmxlTmFtZTogdGhpcy5fdGFibGVcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgX190aGlzX18uX2NsaWVudC5kZXNjcmliZVRhYmxlKHBhcmFtcywgZnVuY3Rpb24gKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgeHRocm93KG5ldyBFcnJvcihlcnIpLCByZWplY3QsIHtwYXJhbXN9KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShkYXRhKVxuICAgICAgICAgICAgfSlcbiAgICAgICAgfSlcbiAgICB9XG5cbiAgICAvLyDooajphY3nva7kv6Hmga/nmoTmm7TmlrDlpITnkIYo5pe26Ze05oiz5Lul5Y+K54mI5pys5Y+3KVxuICAgIHB1YmxpYyBhc3luYyBjaGFuZ2UocGFyYW06IHtcbiAgICAgICAgbWF4VmVyc2lvbnM/OiBudW1iZXIsIHRpbWVvdXRTZWNvbmRzOiBudW1iZXIsXG4gICAgICAgIHJlc2VydmVkVGhyb3VnaHB1dFJlYWQ/OiBudW1iZXIsIHJlc2VydmVkVGhyb3VnaHB1dFdyaXRlPzogbnVtYmVyXG4gICAgfSkge1xuICAgICAgICBjb25zdCBfX3RoaXNfXyA9IHRoaXNcbiAgICAgICAgY29uc3QgcGFyYW1zID0ge1xuICAgICAgICAgICAgdGFibGVOYW1lOiB0aGlzLl90YWJsZSxcbiAgICAgICAgICAgIHRhYmxlT3B0aW9uczoge1xuICAgICAgICAgICAgICAgIC8vIOS/neWtmOeahOacgOWkp+eJiOacrOaVsCwg6K6+572u5Li6MeWNs+S7o+ihqOavj+WIl+S4iuacgOWkmuS/neWtmOS4gOS4queJiOacrCjkv53lrZjmnIDmlrDnmoTniYjmnKwpLlxuICAgICAgICAgICAgICAgIG1heFZlcnNpb25zOiBwYXJhbS5tYXhWZXJzaW9ucyA/IHBhcmFtLm1heFZlcnNpb25zIDogMSxcbiAgICAgICAgICAgICAgICAvLyDmlbDmja7nmoTov4fmnJ/ml7bpl7QsIOWNleS9jeenkiwgLTHku6PooajmsLjkuI3ov4fmnJ8uIOWBh+Wmguiuvue9rui/h+acn+aXtumXtOS4uuS4gOW5tCwg5Y2z5Li6IDM2NSAqIDI0ICogMzYwMFxuICAgICAgICAgICAgICAgIHRpbWVUb0xpdmU6IHBhcmFtLnRpbWVvdXRTZWNvbmRzID8gcGFyYW0udGltZW91dFNlY29uZHMgOiAtMSxcblxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc2VydmVkVGhyb3VnaHB1dDoge1xuICAgICAgICAgICAgICAgIGNhcGFjaXR5VW5pdDoge1xuICAgICAgICAgICAgICAgICAgICAvLyDkuLrkuobmj5DljYflubblj5Hluqbnoa7kv53pooTnlZnmnIDlsI/or7vlhpnmlbDph4/nmoTphY3nva7pgb/lhY3mnI3liqHlhbHkuqvlj6/og73kuqfnlJ/nmoTotYTmupDnq57kuonkuI3nqLPlrprpl67pophcbiAgICAgICAgICAgICAgICAgICAgcmVhZDogcGFyYW0ucmVzZXJ2ZWRUaHJvdWdocHV0UmVhZCA/IHBhcmFtLnJlc2VydmVkVGhyb3VnaHB1dFJlYWQgOiAwLFxuICAgICAgICAgICAgICAgICAgICB3cml0ZTogcGFyYW0ucmVzZXJ2ZWRUaHJvdWdocHV0V3JpdGUgPyBwYXJhbS5yZXNlcnZlZFRocm91Z2hwdXRXcml0ZSA6IDAsXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgX190aGlzX18uX2NsaWVudC51cGRhdGVUYWJsZShwYXJhbXMsIGZ1bmN0aW9uIChlcnIsIGRhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgIHh0aHJvdyhuZXcgRXJyb3IoZXJyKSwgcmVqZWN0LCB7cGFyYW1zfSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJlc29sdmUoZGF0YSlcbiAgICAgICAgICAgIH0pXG4gICAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8g6YeN572u6KGoXG4gICAgcHVibGljIGFzeW5jIHJlc2V0KCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgdGhpcy5kZXN0cm95KClcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAvLyBpZ25vcmUgZXJyb3JcbiAgICAgICAgfVxuICAgICAgICBhd2FpdCB0aGlzLmNyZWF0ZSgpXG4gICAgfVxufVxuIl19
\No newline at end of file