@yibozhang/pro-table 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/bundles/yibozhang-pro-table.umd.js +3110 -0
- package/bundles/yibozhang-pro-table.umd.js.map +1 -0
- package/bundles/yibozhang-pro-table.umd.min.js +2 -0
- package/bundles/yibozhang-pro-table.umd.min.js.map +1 -0
- package/esm2015/lib/components/colmuns-setting/colmuns-setting.component.js +158 -0
- package/esm2015/lib/components/dynamic-search-field/dynamic-search-field.component.js +101 -0
- package/esm2015/lib/constants.js +89 -0
- package/esm2015/lib/page-container/page-container.component.js +21 -0
- package/esm2015/lib/page-container/page-container.module.js +25 -0
- package/esm2015/lib/page-public/antd-form.js +734 -0
- package/esm2015/lib/plate-input/plate-input.component.js +155 -0
- package/esm2015/lib/plate-input/plate-input.module.js +26 -0
- package/esm2015/lib/plate-input/plate-prefix-load.service.js +41 -0
- package/esm2015/lib/pro-table.component.js +983 -0
- package/esm2015/lib/pro-table.module.js +73 -0
- package/esm2015/lib/table-search-bar/table-search-bar-module.js +27 -0
- package/esm2015/lib/table-search-bar/table-search-bar.component.js +51 -0
- package/esm2015/lib/tokens.js +4 -0
- package/esm2015/lib/type.js +2 -0
- package/esm2015/public-api.js +12 -0
- package/esm2015/yibozhang-pro-table.js +13 -0
- package/fesm2015/yibozhang-pro-table.js +2448 -0
- package/fesm2015/yibozhang-pro-table.js.map +1 -0
- package/lib/components/colmuns-setting/colmuns-setting.component.d.ts +35 -0
- package/lib/components/colmuns-setting/colmuns-setting.component.d.ts.map +1 -0
- package/lib/components/dynamic-search-field/dynamic-search-field.component.d.ts +22 -0
- package/lib/components/dynamic-search-field/dynamic-search-field.component.d.ts.map +1 -0
- package/lib/constants.d.ts +20 -0
- package/lib/constants.d.ts.map +1 -0
- package/lib/page-container/page-container.component.d.ts +9 -0
- package/lib/page-container/page-container.component.d.ts.map +1 -0
- package/lib/page-container/page-container.module.d.ts +3 -0
- package/lib/page-container/page-container.module.d.ts.map +1 -0
- package/lib/page-public/antd-form.d.ts +99 -0
- package/lib/page-public/antd-form.d.ts.map +1 -0
- package/lib/plate-input/plate-input.component.d.ts +31 -0
- package/lib/plate-input/plate-input.component.d.ts.map +1 -0
- package/lib/plate-input/plate-input.module.d.ts +3 -0
- package/lib/plate-input/plate-input.module.d.ts.map +1 -0
- package/lib/plate-input/plate-prefix-load.service.d.ts +13 -0
- package/lib/plate-input/plate-prefix-load.service.d.ts.map +1 -0
- package/lib/pro-table.component.d.ts +122 -0
- package/lib/pro-table.component.d.ts.map +1 -0
- package/lib/pro-table.module.d.ts +3 -0
- package/lib/pro-table.module.d.ts.map +1 -0
- package/lib/table-search-bar/table-search-bar-module.d.ts +3 -0
- package/lib/table-search-bar/table-search-bar-module.d.ts.map +1 -0
- package/lib/table-search-bar/table-search-bar.component.d.ts +15 -0
- package/lib/table-search-bar/table-search-bar.component.d.ts.map +1 -0
- package/lib/tokens.d.ts +36 -0
- package/lib/tokens.d.ts.map +1 -0
- package/lib/type.d.ts +226 -0
- package/lib/type.d.ts.map +1 -0
- package/package.json +40 -0
- package/public-api.d.ts +9 -0
- package/public-api.d.ts.map +1 -0
- package/src/lib/styles/custom-antd.less +114 -0
- package/src/lib/styles/margin.css +90 -0
- package/src/lib/styles/theme.less +42 -0
- package/yibozhang-pro-table.d.ts +13 -0
- package/yibozhang-pro-table.d.ts.map +1 -0
- package/yibozhang-pro-table.metadata.json +1 -0
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
import { __rest } from "tslib";
|
|
2
|
+
import { Injectable } from "@angular/core";
|
|
3
|
+
import { FormArray, FormBuilder, FormGroup, } from "@angular/forms";
|
|
4
|
+
import { debounceTime, distinctUntilChanged } from "rxjs/operators";
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "@angular/forms";
|
|
7
|
+
// ==================== 服务类 ====================
|
|
8
|
+
export class AntdFormService {
|
|
9
|
+
// ==================== 构造函数 ====================
|
|
10
|
+
constructor(fb) {
|
|
11
|
+
this.fb = fb;
|
|
12
|
+
// ==================== 公共属性 ====================
|
|
13
|
+
this.formStore = {};
|
|
14
|
+
this.formModifyType = "create";
|
|
15
|
+
// ==================== 私有属性 ====================
|
|
16
|
+
this.labelWidth = "120px";
|
|
17
|
+
this.labelAlign = "right";
|
|
18
|
+
this.labelObservers = {};
|
|
19
|
+
this.errorMessageStore = {};
|
|
20
|
+
this.formArrayConfigStore = {};
|
|
21
|
+
this.INTERNAL_ID_FIELD = "__formItemId";
|
|
22
|
+
this.classPrefix = "ant-form-";
|
|
23
|
+
this.defaultErrorMessages = {
|
|
24
|
+
required: "该字段为必填项",
|
|
25
|
+
minlength: "输入长度不足",
|
|
26
|
+
maxlength: "输入长度超限",
|
|
27
|
+
email: "请输入合法的邮箱地址",
|
|
28
|
+
pattern: "输入格式不正确",
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// ==================== 表单创建和初始化 ====================
|
|
32
|
+
// 初始化表单(支持 FormArray)
|
|
33
|
+
createFormGroup(name, config, options) {
|
|
34
|
+
const groupConfig = {};
|
|
35
|
+
this.errorMessageStore[name] = {};
|
|
36
|
+
Object.entries(config).forEach(([key, field]) => {
|
|
37
|
+
var _a, _b, _c;
|
|
38
|
+
if (this.isFormArrayConfig(field)) {
|
|
39
|
+
// FormArray 配置处理
|
|
40
|
+
if (!this.formArrayConfigStore[name]) {
|
|
41
|
+
this.formArrayConfigStore[name] = {};
|
|
42
|
+
}
|
|
43
|
+
this.formArrayConfigStore[name][key] = {
|
|
44
|
+
itemConfig: field.itemConfig,
|
|
45
|
+
uniqueIdField: field.uniqueIdField,
|
|
46
|
+
};
|
|
47
|
+
const formArray = this.createFormArrayFromConfig(name, key, field.itemConfig, field.initialItems || [], field.uniqueIdField);
|
|
48
|
+
groupConfig[key] = formArray;
|
|
49
|
+
// 存储 FormArray 字段的错误消息配置,格式:arrayName[].fieldName
|
|
50
|
+
if (field.errorMessages) {
|
|
51
|
+
Object.entries(field.errorMessages).forEach(([fieldName, errorMessages]) => {
|
|
52
|
+
const errorMessageKey = `${key}[].${fieldName}`;
|
|
53
|
+
this.errorMessageStore[name][errorMessageKey] = errorMessages;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// 普通字段配置
|
|
59
|
+
const fieldConfig = field;
|
|
60
|
+
groupConfig[key] = [
|
|
61
|
+
{ value: fieldConfig.value, disabled: (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : false },
|
|
62
|
+
(_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
|
|
63
|
+
];
|
|
64
|
+
if (fieldConfig.errorMessages) {
|
|
65
|
+
this.errorMessageStore[name][key] = fieldConfig.errorMessages;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
if (options === null || options === void 0 ? void 0 : options.labelWidth) {
|
|
70
|
+
this.labelWidth = options.labelWidth;
|
|
71
|
+
}
|
|
72
|
+
if (options === null || options === void 0 ? void 0 : options.labelAlign) {
|
|
73
|
+
this.labelAlign = options.labelAlign;
|
|
74
|
+
}
|
|
75
|
+
this.formStore[name] = this.fb.group(groupConfig);
|
|
76
|
+
this.setCSSVariablesToTarget(name);
|
|
77
|
+
return this.formStore[name];
|
|
78
|
+
}
|
|
79
|
+
// ==================== 表单操作 ====================
|
|
80
|
+
// 重置表单
|
|
81
|
+
resetFormGroup(name, value) {
|
|
82
|
+
var _a;
|
|
83
|
+
(_a = this.formStore[name]) === null || _a === void 0 ? void 0 : _a.reset(value);
|
|
84
|
+
}
|
|
85
|
+
// 批量添加字段配置
|
|
86
|
+
addFieldsConfig(formName, fieldsConfig, options) {
|
|
87
|
+
var _a;
|
|
88
|
+
const result = {
|
|
89
|
+
success: true,
|
|
90
|
+
added: [],
|
|
91
|
+
failed: [],
|
|
92
|
+
};
|
|
93
|
+
// 1. 验证表单是否存在
|
|
94
|
+
const formGroup = this.formStore[formName];
|
|
95
|
+
if (!formGroup) {
|
|
96
|
+
// 如果表单不存在,所有字段都失败
|
|
97
|
+
Object.keys(fieldsConfig).forEach((fieldName) => {
|
|
98
|
+
var _a;
|
|
99
|
+
const error = `Form "${formName}" not found`;
|
|
100
|
+
result.failed.push({
|
|
101
|
+
fieldName,
|
|
102
|
+
error,
|
|
103
|
+
});
|
|
104
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
|
|
105
|
+
});
|
|
106
|
+
result.success = false;
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
// 2. 初始化 errorMessageStore 和 formArrayConfigStore(如果不存在)
|
|
110
|
+
if (!this.errorMessageStore[formName]) {
|
|
111
|
+
this.errorMessageStore[formName] = {};
|
|
112
|
+
}
|
|
113
|
+
if (!this.formArrayConfigStore[formName]) {
|
|
114
|
+
this.formArrayConfigStore[formName] = {};
|
|
115
|
+
}
|
|
116
|
+
// 3. 批量构建控件配置
|
|
117
|
+
const controlsToAdd = {};
|
|
118
|
+
const errorMessagesToAdd = {};
|
|
119
|
+
const formArrayConfigsToAdd = {};
|
|
120
|
+
// 4. 遍历所有字段配置,进行验证和构建
|
|
121
|
+
Object.entries(fieldsConfig).forEach(([fieldName, fieldConfig]) => {
|
|
122
|
+
var _a, _b, _c, _d, _e;
|
|
123
|
+
try {
|
|
124
|
+
// 4.1 检查字段是否已存在
|
|
125
|
+
if (formGroup.get(fieldName)) {
|
|
126
|
+
const error = `Field "${fieldName}" already exists`;
|
|
127
|
+
result.failed.push({
|
|
128
|
+
fieldName,
|
|
129
|
+
error,
|
|
130
|
+
});
|
|
131
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
// 4.2 根据字段类型创建控件
|
|
135
|
+
if (this.isFormArrayConfig(fieldConfig)) {
|
|
136
|
+
// FormArray 处理
|
|
137
|
+
const formArray = this.createFormArrayFromConfig(formName, fieldName, fieldConfig.itemConfig, fieldConfig.initialItems || [], fieldConfig.uniqueIdField);
|
|
138
|
+
controlsToAdd[fieldName] = formArray;
|
|
139
|
+
// 存储 FormArray 配置
|
|
140
|
+
formArrayConfigsToAdd[fieldName] = {
|
|
141
|
+
itemConfig: fieldConfig.itemConfig,
|
|
142
|
+
uniqueIdField: fieldConfig.uniqueIdField,
|
|
143
|
+
};
|
|
144
|
+
// 存储错误消息
|
|
145
|
+
if (fieldConfig.errorMessages) {
|
|
146
|
+
Object.entries(fieldConfig.errorMessages).forEach(([itemFieldName, errorMessages]) => {
|
|
147
|
+
const errorMessageKey = `${fieldName}[].${itemFieldName}`;
|
|
148
|
+
errorMessagesToAdd[errorMessageKey] = errorMessages;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// 普通字段处理
|
|
154
|
+
const fieldConfigTyped = fieldConfig;
|
|
155
|
+
const controlOptions = {
|
|
156
|
+
validators: (_c = (_b = fieldConfigTyped.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfigTyped)) !== null && _c !== void 0 ? _c : [],
|
|
157
|
+
};
|
|
158
|
+
const control = this.fb.control(fieldConfigTyped.value, controlOptions);
|
|
159
|
+
// 设置 disabled 状态
|
|
160
|
+
if (fieldConfigTyped.disabled) {
|
|
161
|
+
control.disable();
|
|
162
|
+
}
|
|
163
|
+
controlsToAdd[fieldName] = control;
|
|
164
|
+
// 存储错误消息
|
|
165
|
+
if (fieldConfigTyped.errorMessages) {
|
|
166
|
+
errorMessagesToAdd[fieldName] = fieldConfigTyped.errorMessages;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
result.added.push(fieldName);
|
|
170
|
+
(_d = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _d === void 0 ? void 0 : _d.call(options, fieldName, true);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
const errorMessage = (error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.toString()) || "Unknown error";
|
|
174
|
+
result.failed.push({
|
|
175
|
+
fieldName,
|
|
176
|
+
error: errorMessage,
|
|
177
|
+
});
|
|
178
|
+
(_e = options === null || options === void 0 ? void 0 : options.onFieldAdded) === null || _e === void 0 ? void 0 : _e.call(options, fieldName, false, errorMessage);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// 5. 批量添加到 FormGroup
|
|
182
|
+
if (Object.keys(controlsToAdd).length > 0) {
|
|
183
|
+
Object.entries(controlsToAdd).forEach(([fieldName, control]) => {
|
|
184
|
+
formGroup.addControl(fieldName, control);
|
|
185
|
+
});
|
|
186
|
+
// 6. 批量存储错误消息
|
|
187
|
+
Object.entries(errorMessagesToAdd).forEach(([key, messages]) => {
|
|
188
|
+
this.errorMessageStore[formName][key] = messages;
|
|
189
|
+
});
|
|
190
|
+
// 7. 批量存储 FormArray 配置
|
|
191
|
+
Object.entries(formArrayConfigsToAdd).forEach(([fieldName, config]) => {
|
|
192
|
+
this.formArrayConfigStore[formName][fieldName] = config;
|
|
193
|
+
});
|
|
194
|
+
// 8. 更新表单验证状态
|
|
195
|
+
if (options === null || options === void 0 ? void 0 : options.updateValueAndValidity) {
|
|
196
|
+
formGroup.updateValueAndValidity({
|
|
197
|
+
emitEvent: (_a = options === null || options === void 0 ? void 0 : options.emitEvent) !== null && _a !== void 0 ? _a : true,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// 9. 判断整体是否成功
|
|
202
|
+
result.success = result.failed.length === 0;
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
// 批量删除字段配置
|
|
206
|
+
removeFieldsConfig(formName, fieldNames, options) {
|
|
207
|
+
const result = {
|
|
208
|
+
success: true,
|
|
209
|
+
removed: [],
|
|
210
|
+
failed: [],
|
|
211
|
+
};
|
|
212
|
+
// 1. 验证表单是否存在
|
|
213
|
+
const formGroup = this.formStore[formName];
|
|
214
|
+
if (!formGroup) {
|
|
215
|
+
fieldNames.forEach((fieldName) => {
|
|
216
|
+
var _a;
|
|
217
|
+
const error = `Form "${formName}" not found`;
|
|
218
|
+
result.failed.push({
|
|
219
|
+
fieldName,
|
|
220
|
+
error,
|
|
221
|
+
});
|
|
222
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldRemoved) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
|
|
223
|
+
});
|
|
224
|
+
result.success = false;
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
// 2. 批量收集需要清理的信息
|
|
228
|
+
const fieldsToRemove = [];
|
|
229
|
+
const errorMessageKeysToRemove = [];
|
|
230
|
+
const formArrayFields = [];
|
|
231
|
+
// 3. 验证每个字段并收集信息
|
|
232
|
+
fieldNames.forEach((fieldName) => {
|
|
233
|
+
var _a;
|
|
234
|
+
const control = formGroup.get(fieldName);
|
|
235
|
+
if (!control) {
|
|
236
|
+
const error = `Field "${fieldName}" not found`;
|
|
237
|
+
result.failed.push({
|
|
238
|
+
fieldName,
|
|
239
|
+
error,
|
|
240
|
+
});
|
|
241
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldRemoved) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, error);
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
// 判断是否是 FormArray
|
|
245
|
+
if (control instanceof FormArray) {
|
|
246
|
+
formArrayFields.push(fieldName);
|
|
247
|
+
// 收集 FormArray 相关的错误消息键(格式:arrayName[].fieldName)
|
|
248
|
+
if (this.errorMessageStore[formName]) {
|
|
249
|
+
Object.keys(this.errorMessageStore[formName]).forEach((key) => {
|
|
250
|
+
if (key.startsWith(`${fieldName}[].`)) {
|
|
251
|
+
errorMessageKeysToRemove.push(key);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
// 普通字段的错误消息键
|
|
258
|
+
errorMessageKeysToRemove.push(fieldName);
|
|
259
|
+
}
|
|
260
|
+
fieldsToRemove.push(fieldName);
|
|
261
|
+
});
|
|
262
|
+
// 4. 批量执行删除操作
|
|
263
|
+
try {
|
|
264
|
+
// 4.1 从 FormGroup 中移除控件
|
|
265
|
+
fieldsToRemove.forEach((fieldName) => {
|
|
266
|
+
var _a;
|
|
267
|
+
formGroup.removeControl(fieldName);
|
|
268
|
+
result.removed.push(fieldName);
|
|
269
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldRemoved) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, true);
|
|
270
|
+
});
|
|
271
|
+
// 4.2 批量删除错误消息
|
|
272
|
+
if (this.errorMessageStore[formName]) {
|
|
273
|
+
errorMessageKeysToRemove.forEach((key) => {
|
|
274
|
+
delete this.errorMessageStore[formName][key];
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
// 4.3 批量删除 FormArray 配置
|
|
278
|
+
if (this.formArrayConfigStore[formName]) {
|
|
279
|
+
formArrayFields.forEach((fieldName) => {
|
|
280
|
+
delete this.formArrayConfigStore[formName][fieldName];
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
// 如果批量删除过程中出错,标记为失败
|
|
286
|
+
fieldsToRemove.forEach((fieldName) => {
|
|
287
|
+
var _a;
|
|
288
|
+
if (!result.removed.includes(fieldName)) {
|
|
289
|
+
const errorMessage = (error === null || error === void 0 ? void 0 : error.message) || (error === null || error === void 0 ? void 0 : error.toString()) || "Failed to remove field";
|
|
290
|
+
result.failed.push({
|
|
291
|
+
fieldName,
|
|
292
|
+
error: errorMessage,
|
|
293
|
+
});
|
|
294
|
+
(_a = options === null || options === void 0 ? void 0 : options.onFieldRemoved) === null || _a === void 0 ? void 0 : _a.call(options, fieldName, false, errorMessage);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
// 5. 判断整体是否成功
|
|
299
|
+
result.success = result.failed.length === 0;
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
302
|
+
// 局部赋值(支持 FormArray 的智能更新,统一根据 action 字段判断操作类型)
|
|
303
|
+
patchFormValues(name, values, options) {
|
|
304
|
+
var _a;
|
|
305
|
+
const formGroup = this.formStore[name];
|
|
306
|
+
if (!formGroup) {
|
|
307
|
+
console.warn(`[AntdFormService] patchFormValues: form "${name}" not found.`);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const processedValues = {};
|
|
311
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
312
|
+
const control = formGroup.get(key);
|
|
313
|
+
// 检测是否是 FormArray
|
|
314
|
+
if (control instanceof FormArray && Array.isArray(value)) {
|
|
315
|
+
this.patchFormArray(name, key, value);
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
// 普通字段,直接加入
|
|
319
|
+
processedValues[key] = value;
|
|
320
|
+
});
|
|
321
|
+
// 处理普通字段
|
|
322
|
+
if (Object.keys(processedValues).length > 0) {
|
|
323
|
+
formGroup.patchValue(processedValues, {
|
|
324
|
+
emitEvent: (_a = options === null || options === void 0 ? void 0 : options.emitEvent) !== null && _a !== void 0 ? _a : true,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
// 表单校验(自动过滤内部字段)
|
|
329
|
+
validateForm(name, options) {
|
|
330
|
+
var _a, _b;
|
|
331
|
+
if (this.formStore[name].valid) {
|
|
332
|
+
const rawValue = this.formStore[name].getRawValue();
|
|
333
|
+
return this.excludeInternalFields(rawValue);
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
// 递归校验所有控件,包括 FormArray 中的项
|
|
337
|
+
this.markAllControlsAsDirty(this.formStore[name], (_a = options === null || options === void 0 ? void 0 : options.emitEvent) !== null && _a !== void 0 ? _a : true, (_b = options === null || options === void 0 ? void 0 : options.onlySelf) !== null && _b !== void 0 ? _b : false);
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// 递归标记所有无效控件为 dirty(包括 FormArray 中的项)
|
|
342
|
+
markAllControlsAsDirty(control, emitEvent, onlySelf) {
|
|
343
|
+
if (control.invalid) {
|
|
344
|
+
control.markAsDirty();
|
|
345
|
+
control.updateValueAndValidity({
|
|
346
|
+
emitEvent,
|
|
347
|
+
onlySelf,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
// 如果是 FormGroup,递归处理所有子控件
|
|
351
|
+
if (control instanceof FormGroup) {
|
|
352
|
+
Object.values(control.controls).forEach((childControl) => {
|
|
353
|
+
this.markAllControlsAsDirty(childControl, emitEvent, onlySelf);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
// 如果是 FormArray,递归处理数组中的每一项
|
|
357
|
+
if (control instanceof FormArray) {
|
|
358
|
+
control.controls.forEach((childControl) => {
|
|
359
|
+
this.markAllControlsAsDirty(childControl, emitEvent, onlySelf);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// ==================== 错误消息相关 ====================
|
|
364
|
+
// 获取字段首条错误提示,支持普通字段和 FormArray 字段(格式:arrayName.index.fieldName)
|
|
365
|
+
getFieldErrorMessage(name, controlName) {
|
|
366
|
+
var _a;
|
|
367
|
+
const formGroup = this.formStore[name];
|
|
368
|
+
if (!formGroup) {
|
|
369
|
+
console.warn(`[AntdFormService] getFieldErrorMessage: form "${name}" not found.`);
|
|
370
|
+
return "";
|
|
371
|
+
}
|
|
372
|
+
const control = formGroup.get(controlName);
|
|
373
|
+
if (!control) {
|
|
374
|
+
console.warn(`[AntdFormService] getFieldErrorMessage: control "${controlName}" not found in form "${name}".`);
|
|
375
|
+
return "";
|
|
376
|
+
}
|
|
377
|
+
if (!control.errors) {
|
|
378
|
+
return "";
|
|
379
|
+
}
|
|
380
|
+
// 解析 controlName,支持 FormArray 格式:arrayName.index.fieldName
|
|
381
|
+
let errorMessageKey = controlName;
|
|
382
|
+
const arrayMatch = controlName.match(/^(.+)\.(\d+)\.(.+)$/);
|
|
383
|
+
if (arrayMatch) {
|
|
384
|
+
// FormArray 格式:arrayName.index.fieldName -> 使用 arrayName[].fieldName 作为 key
|
|
385
|
+
const [, arrayName, , fieldName] = arrayMatch;
|
|
386
|
+
errorMessageKey = `${arrayName}[].${fieldName}`;
|
|
387
|
+
}
|
|
388
|
+
// 从 errorMessageStore 获取错误消息配置
|
|
389
|
+
const errorMessages = (_a = this.errorMessageStore[name]) === null || _a === void 0 ? void 0 : _a[errorMessageKey];
|
|
390
|
+
const mergedMessages = Object.assign(Object.assign({}, this.defaultErrorMessages), (errorMessages !== null && errorMessages !== void 0 ? errorMessages : {}));
|
|
391
|
+
for (const errorKey of Object.keys(control.errors)) {
|
|
392
|
+
const message = mergedMessages[errorKey];
|
|
393
|
+
if (message) {
|
|
394
|
+
// 不再支持函数形式,只返回字符串
|
|
395
|
+
return typeof message === "string" ? message : "";
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return "";
|
|
399
|
+
}
|
|
400
|
+
// ==================== 监听相关 ====================
|
|
401
|
+
// 监听表单所有字段变更
|
|
402
|
+
watchFormChanges(name, handler, options) {
|
|
403
|
+
const formGroup = this.formStore[name];
|
|
404
|
+
if (!formGroup) {
|
|
405
|
+
console.warn(`[AntdFormService] watchFormChanges: form "${name}" not found.`);
|
|
406
|
+
return undefined;
|
|
407
|
+
}
|
|
408
|
+
return this.setupValueChangeSubscription(formGroup, handler, options);
|
|
409
|
+
}
|
|
410
|
+
// 监听指定字段变更
|
|
411
|
+
watchFieldChanges(name, controlName, handler, options) {
|
|
412
|
+
const formGroup = this.formStore[name];
|
|
413
|
+
if (!formGroup) {
|
|
414
|
+
console.warn(`[AntdFormService] watchFieldChanges: form "${name}" not found.`);
|
|
415
|
+
return undefined;
|
|
416
|
+
}
|
|
417
|
+
const control = formGroup.get(controlName);
|
|
418
|
+
if (!control) {
|
|
419
|
+
console.warn(`[AntdFormService] watchFieldChanges: control "${controlName}" not found in form "${name}".`);
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
return this.setupValueChangeSubscription(control, handler, options);
|
|
423
|
+
}
|
|
424
|
+
// ==================== 工具方法 ====================
|
|
425
|
+
// 获取表单类名
|
|
426
|
+
getFormClassName(name) {
|
|
427
|
+
return `${this.classPrefix}${name}`;
|
|
428
|
+
}
|
|
429
|
+
// 设置 CSS 变量到目标元素(支持持久化监听动态添加的元素)
|
|
430
|
+
setCSSVariablesToTarget(name) {
|
|
431
|
+
const selector = `.${this.getFormClassName(name)} .ant-form-item-label`;
|
|
432
|
+
const formContainerSelector = `.${this.getFormClassName(name)}`;
|
|
433
|
+
const applyStyles = () => {
|
|
434
|
+
const dom = document.querySelectorAll(selector);
|
|
435
|
+
if (!dom.length) {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
let appliedCount = 0;
|
|
439
|
+
dom.forEach((item) => {
|
|
440
|
+
const target = item;
|
|
441
|
+
if (target.style.width !== this.labelWidth ||
|
|
442
|
+
target.style.textAlign !== this.labelAlign) {
|
|
443
|
+
target.style.width = this.labelWidth;
|
|
444
|
+
target.style.textAlign = this.labelAlign;
|
|
445
|
+
appliedCount++;
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
return appliedCount > 0;
|
|
449
|
+
};
|
|
450
|
+
if (this.labelObservers[name]) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
let timeout = null;
|
|
454
|
+
const observer = new MutationObserver(() => {
|
|
455
|
+
cancelAnimationFrame(timeout);
|
|
456
|
+
timeout = requestAnimationFrame(() => {
|
|
457
|
+
setTimeout(() => {
|
|
458
|
+
applyStyles();
|
|
459
|
+
}, 0);
|
|
460
|
+
});
|
|
461
|
+
});
|
|
462
|
+
const formContainer = document.querySelector(formContainerSelector);
|
|
463
|
+
observer.observe(formContainer || document.body, {
|
|
464
|
+
childList: true,
|
|
465
|
+
subtree: true,
|
|
466
|
+
attributes: true,
|
|
467
|
+
});
|
|
468
|
+
this.labelObservers[name] = observer;
|
|
469
|
+
}
|
|
470
|
+
// ==================== 私有方法 ====================
|
|
471
|
+
// 获取 FormArray
|
|
472
|
+
getFormArray(formName, arrayName) {
|
|
473
|
+
const formGroup = this.formStore[formName];
|
|
474
|
+
if (!formGroup) {
|
|
475
|
+
console.warn(`[AntdFormService] getFormArray: form "${formName}" not found.`);
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
const control = formGroup.get(arrayName);
|
|
479
|
+
if (!control || !(control instanceof FormArray)) {
|
|
480
|
+
console.warn(`[AntdFormService] getFormArray: array "${arrayName}" not found in form "${formName}".`);
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
return control;
|
|
484
|
+
}
|
|
485
|
+
// 判断是否是 FormArray 配置
|
|
486
|
+
isFormArrayConfig(field) {
|
|
487
|
+
return field.type === "array";
|
|
488
|
+
}
|
|
489
|
+
// 从配置创建 FormArray
|
|
490
|
+
createFormArrayFromConfig(formName, arrayName, itemConfig, initialItems, uniqueIdField) {
|
|
491
|
+
const formArray = this.fb.array([]);
|
|
492
|
+
initialItems.forEach((item) => {
|
|
493
|
+
const itemGroup = this.createItemFormGroup(itemConfig, item, uniqueIdField);
|
|
494
|
+
formArray.push(itemGroup);
|
|
495
|
+
});
|
|
496
|
+
return formArray;
|
|
497
|
+
}
|
|
498
|
+
// 生成内部ID(使用业务唯一字段或生成临时ID)
|
|
499
|
+
generateInternalId(itemData, uniqueIdField) {
|
|
500
|
+
// 优先使用业务唯一字段
|
|
501
|
+
if (uniqueIdField && (itemData === null || itemData === void 0 ? void 0 : itemData[uniqueIdField]) !== undefined) {
|
|
502
|
+
const businessId = itemData[uniqueIdField];
|
|
503
|
+
if (businessId !== null &&
|
|
504
|
+
businessId !== undefined &&
|
|
505
|
+
businessId !== "") {
|
|
506
|
+
return `business-${uniqueIdField}-${businessId}`;
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
// 如果没有业务ID,生成临时ID(用于新添加的项)
|
|
510
|
+
return `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
511
|
+
}
|
|
512
|
+
// 创建单个项的 FormGroup
|
|
513
|
+
createItemFormGroup(itemConfig, itemData, uniqueIdField) {
|
|
514
|
+
const groupConfig = {};
|
|
515
|
+
// 添加内部ID字段
|
|
516
|
+
const itemId = this.generateInternalId(itemData, uniqueIdField);
|
|
517
|
+
groupConfig[this.INTERNAL_ID_FIELD] = [
|
|
518
|
+
{ value: itemId, disabled: true },
|
|
519
|
+
[],
|
|
520
|
+
];
|
|
521
|
+
// 添加业务字段
|
|
522
|
+
Object.entries(itemConfig).forEach(([key, field]) => {
|
|
523
|
+
var _a, _b, _c;
|
|
524
|
+
// itemConfig 中的字段应该是 FieldConfig,不应该包含 FormArrayConfig
|
|
525
|
+
if (this.isFormArrayConfig(field)) {
|
|
526
|
+
console.warn(`[AntdFormService] createItemFormGroup: FormArrayConfig is not allowed in itemConfig. Skipping field "${key}".`);
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
const fieldConfig = field;
|
|
530
|
+
const value = (itemData === null || itemData === void 0 ? void 0 : itemData[key]) !== undefined ? itemData[key] : fieldConfig.value;
|
|
531
|
+
groupConfig[key] = [
|
|
532
|
+
{ value: value, disabled: (_a = fieldConfig.disabled) !== null && _a !== void 0 ? _a : false },
|
|
533
|
+
(_c = (_b = fieldConfig.validators) === null || _b === void 0 ? void 0 : _b.call(fieldConfig)) !== null && _c !== void 0 ? _c : [],
|
|
534
|
+
];
|
|
535
|
+
});
|
|
536
|
+
return this.fb.group(groupConfig);
|
|
537
|
+
}
|
|
538
|
+
// 通过业务唯一字段查找内部ID
|
|
539
|
+
findFormArrayItemIdByBusinessField(formName, arrayName, uniqueIdField, businessIdValue) {
|
|
540
|
+
const formArray = this.getFormArray(formName, arrayName);
|
|
541
|
+
if (!formArray)
|
|
542
|
+
return null;
|
|
543
|
+
for (let i = 0; i < formArray.length; i++) {
|
|
544
|
+
const item = formArray.at(i);
|
|
545
|
+
const itemValue = item.getRawValue();
|
|
546
|
+
const internalId = itemValue[this.INTERNAL_ID_FIELD];
|
|
547
|
+
// 检查内部ID是否匹配业务ID
|
|
548
|
+
if (internalId && internalId.startsWith(`business-${uniqueIdField}-`)) {
|
|
549
|
+
const idInInternalId = internalId.replace(`business-${uniqueIdField}-`, "");
|
|
550
|
+
if (String(idInInternalId) === String(businessIdValue)) {
|
|
551
|
+
return internalId;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
// 也检查当前业务字段值是否匹配(处理业务ID更新的情况)
|
|
555
|
+
if (itemValue[uniqueIdField] === businessIdValue) {
|
|
556
|
+
return internalId;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
// 通过内部ID查找项
|
|
562
|
+
findFormArrayItemById(formName, arrayName, itemId) {
|
|
563
|
+
var _a;
|
|
564
|
+
const formArray = this.getFormArray(formName, arrayName);
|
|
565
|
+
if (!formArray)
|
|
566
|
+
return null;
|
|
567
|
+
for (let i = 0; i < formArray.length; i++) {
|
|
568
|
+
const item = formArray.at(i);
|
|
569
|
+
const id = (_a = item.get(this.INTERNAL_ID_FIELD)) === null || _a === void 0 ? void 0 : _a.value;
|
|
570
|
+
if (id === itemId) {
|
|
571
|
+
return { index: i, formGroup: item };
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return null;
|
|
575
|
+
}
|
|
576
|
+
// 获取操作类型(必须明确指定 action 字段)
|
|
577
|
+
getOperationType(itemData) {
|
|
578
|
+
if (!itemData || typeof itemData !== "object")
|
|
579
|
+
return null;
|
|
580
|
+
const action = itemData.action;
|
|
581
|
+
if (action === "delete" || action === "update" || action === "create") {
|
|
582
|
+
return action;
|
|
583
|
+
}
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
// 过滤操作字段(action 字段不保存到表单中)
|
|
587
|
+
filterOperationFields(itemData) {
|
|
588
|
+
if (!itemData || typeof itemData !== "object")
|
|
589
|
+
return itemData;
|
|
590
|
+
const filtered = {};
|
|
591
|
+
Object.entries(itemData).forEach(([key, value]) => {
|
|
592
|
+
if (key !== "action") {
|
|
593
|
+
filtered[key] = value;
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
return filtered;
|
|
597
|
+
}
|
|
598
|
+
// 处理 FormArray 的更新(统一根据 action 字段判断操作类型)
|
|
599
|
+
patchFormArray(formName, arrayName, newValues) {
|
|
600
|
+
var _a;
|
|
601
|
+
const formArray = this.getFormArray(formName, arrayName);
|
|
602
|
+
if (!formArray) {
|
|
603
|
+
console.warn(`[AntdFormService] patchFormArray: array "${arrayName}" not found in form "${formName}".`);
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
const config = (_a = this.formArrayConfigStore[formName]) === null || _a === void 0 ? void 0 : _a[arrayName];
|
|
607
|
+
if (!config) {
|
|
608
|
+
console.warn(`[AntdFormService] patchFormArray: config not found for array "${arrayName}" in form "${formName}".`);
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const { itemConfig, uniqueIdField } = config;
|
|
612
|
+
// 统一根据 action 字段判断操作类型
|
|
613
|
+
const itemsToDelete = new Set();
|
|
614
|
+
const itemsToUpdate = new Map();
|
|
615
|
+
const itemsToAdd = [];
|
|
616
|
+
newValues.forEach((itemData) => {
|
|
617
|
+
if (!itemData || typeof itemData !== "object")
|
|
618
|
+
return;
|
|
619
|
+
const operationType = this.getOperationType(itemData);
|
|
620
|
+
if (!operationType) {
|
|
621
|
+
console.warn(`[AntdFormService] patchFormArray: Item missing required "action" field. Skipping.`, itemData);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
// 删除操作
|
|
625
|
+
if (operationType === "delete") {
|
|
626
|
+
if (uniqueIdField && itemData[uniqueIdField] !== undefined) {
|
|
627
|
+
const businessId = itemData[uniqueIdField];
|
|
628
|
+
const internalId = this.findFormArrayItemIdByBusinessField(formName, arrayName, uniqueIdField, businessId);
|
|
629
|
+
if (internalId) {
|
|
630
|
+
itemsToDelete.add(internalId);
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
console.warn(`[AntdFormService] patchFormArray: Cannot delete item with ${uniqueIdField}=${businessId}, item not found.`);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
console.warn(`[AntdFormService] patchFormArray: Cannot delete item, missing required uniqueIdField "${uniqueIdField}".`);
|
|
638
|
+
}
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
// 更新操作
|
|
642
|
+
if (operationType === "update") {
|
|
643
|
+
if (uniqueIdField && itemData[uniqueIdField] !== undefined) {
|
|
644
|
+
const businessId = itemData[uniqueIdField];
|
|
645
|
+
const internalId = this.findFormArrayItemIdByBusinessField(formName, arrayName, uniqueIdField, businessId);
|
|
646
|
+
if (internalId) {
|
|
647
|
+
const filteredData = this.filterOperationFields(itemData);
|
|
648
|
+
itemsToUpdate.set(internalId, filteredData);
|
|
649
|
+
}
|
|
650
|
+
else {
|
|
651
|
+
console.warn(`[AntdFormService] patchFormArray: Cannot update item with ${uniqueIdField}=${businessId}, item not found. Skipping.`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
console.warn(`[AntdFormService] patchFormArray: Cannot update item, missing required uniqueIdField "${uniqueIdField}". Skipping.`);
|
|
656
|
+
}
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
// 创建操作
|
|
660
|
+
if (operationType === "create") {
|
|
661
|
+
const filteredData = this.filterOperationFields(itemData);
|
|
662
|
+
itemsToAdd.push(filteredData);
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
// 执行删除(需要从后往前删除,避免索引变化)
|
|
666
|
+
const deleteIndices = [];
|
|
667
|
+
itemsToDelete.forEach((itemId) => {
|
|
668
|
+
const found = this.findFormArrayItemById(formName, arrayName, itemId);
|
|
669
|
+
if (found) {
|
|
670
|
+
deleteIndices.push(found.index);
|
|
671
|
+
}
|
|
672
|
+
});
|
|
673
|
+
deleteIndices
|
|
674
|
+
.sort((a, b) => b - a)
|
|
675
|
+
.forEach((index) => {
|
|
676
|
+
formArray.removeAt(index);
|
|
677
|
+
});
|
|
678
|
+
// 执行更新
|
|
679
|
+
itemsToUpdate.forEach((itemData, itemId) => {
|
|
680
|
+
const found = this.findFormArrayItemById(formName, arrayName, itemId);
|
|
681
|
+
if (found) {
|
|
682
|
+
const _a = itemData, _b = this.INTERNAL_ID_FIELD, _ = _a[_b], dataToUpdate = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
|
|
683
|
+
found.formGroup.patchValue(dataToUpdate);
|
|
684
|
+
}
|
|
685
|
+
});
|
|
686
|
+
// 执行添加
|
|
687
|
+
itemsToAdd.forEach((itemData) => {
|
|
688
|
+
const newItem = this.createItemFormGroup(itemConfig, itemData, uniqueIdField);
|
|
689
|
+
formArray.push(newItem);
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
// 过滤内部字段(递归处理对象和数组)
|
|
693
|
+
excludeInternalFields(value) {
|
|
694
|
+
if (value === null || value === undefined) {
|
|
695
|
+
return value;
|
|
696
|
+
}
|
|
697
|
+
if (Array.isArray(value)) {
|
|
698
|
+
return value.map((item) => this.excludeInternalFields(item));
|
|
699
|
+
}
|
|
700
|
+
if (typeof value !== "object") {
|
|
701
|
+
return value;
|
|
702
|
+
}
|
|
703
|
+
const filtered = {};
|
|
704
|
+
Object.entries(value).forEach(([key, val]) => {
|
|
705
|
+
// 过滤以 __ 开头的内部字段和 action 字段
|
|
706
|
+
if (!key.startsWith("__") && key !== "action") {
|
|
707
|
+
filtered[key] = this.excludeInternalFields(val);
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
return filtered;
|
|
711
|
+
}
|
|
712
|
+
// 设置值变更订阅
|
|
713
|
+
setupValueChangeSubscription(target, handler, options) {
|
|
714
|
+
let valueChanges$ = target.valueChanges;
|
|
715
|
+
if ((options === null || options === void 0 ? void 0 : options.debounce) != null) {
|
|
716
|
+
valueChanges$ = valueChanges$.pipe(debounceTime(options.debounce));
|
|
717
|
+
}
|
|
718
|
+
if ((options === null || options === void 0 ? void 0 : options.distinctUntilChanged) !== false) {
|
|
719
|
+
valueChanges$ = valueChanges$.pipe(distinctUntilChanged());
|
|
720
|
+
}
|
|
721
|
+
if (options === null || options === void 0 ? void 0 : options.emitInitial) {
|
|
722
|
+
handler(target.value);
|
|
723
|
+
}
|
|
724
|
+
return valueChanges$.subscribe(handler);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
AntdFormService.ɵprov = i0.ɵɵdefineInjectable({ factory: function AntdFormService_Factory() { return new AntdFormService(i0.ɵɵinject(i1.FormBuilder)); }, token: AntdFormService, providedIn: "root" });
|
|
728
|
+
AntdFormService.decorators = [
|
|
729
|
+
{ type: Injectable, args: [{ providedIn: "root" },] }
|
|
730
|
+
];
|
|
731
|
+
AntdFormService.ctorParameters = () => [
|
|
732
|
+
{ type: FormBuilder }
|
|
733
|
+
];
|
|
734
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW50ZC1mb3JtLmpzIiwic291cmNlUm9vdCI6IkQ6L3Byb2plY3RzL3Zwcy1mcm9udC9Gcm9udC9EYXNQTVNXZWIvcHJvamVjdHMvcHJvLXRhYmxlL3NyYy8iLCJzb3VyY2VzIjpbImxpYi9wYWdlLXB1YmxpYy9hbnRkLWZvcm0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUdMLFNBQVMsRUFDVCxXQUFXLEVBQ1gsU0FBUyxHQUVWLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLFlBQVksRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7QUFxRXBFLGdEQUFnRDtBQUdoRCxNQUFNLE9BQU8sZUFBZTtJQTJCMUIsaURBQWlEO0lBQ2pELFlBQW9CLEVBQWU7UUFBZixPQUFFLEdBQUYsRUFBRSxDQUFhO1FBM0JuQyxpREFBaUQ7UUFDakQsY0FBUyxHQUE4QixFQUFFLENBQUM7UUFDMUMsbUJBQWMsR0FBbUIsUUFBUSxDQUFDO1FBRTFDLGlEQUFpRDtRQUN6QyxlQUFVLEdBQVcsT0FBTyxDQUFDO1FBQzdCLGVBQVUsR0FBVyxPQUFPLENBQUM7UUFDN0IsbUJBQWMsR0FBcUMsRUFBRSxDQUFDO1FBQ3RELHNCQUFpQixHQUdyQixFQUFFLENBQUM7UUFDQyx5QkFBb0IsR0FHeEIsRUFBRSxDQUFDO1FBQ1Usc0JBQWlCLEdBQUcsY0FBYyxDQUFDO1FBQzVDLGdCQUFXLEdBQUcsV0FBVyxDQUFDO1FBQ2pCLHlCQUFvQixHQUF1QjtZQUMxRCxRQUFRLEVBQUUsU0FBUztZQUNuQixTQUFTLEVBQUUsUUFBUTtZQUNuQixTQUFTLEVBQUUsUUFBUTtZQUNuQixLQUFLLEVBQUUsWUFBWTtZQUNuQixPQUFPLEVBQUUsU0FBUztTQUNuQixDQUFDO0lBR29DLENBQUM7SUFFdkMscURBQXFEO0lBRXJELHNCQUFzQjtJQUN0QixlQUFlLENBQ2IsSUFBWSxFQUNa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QUMzQyw0QkFBNEI7WUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLFFBQVEsRUFBRTtnQkFDN0MsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxHQUFHLENBQUMsQ0FBQzthQUNqRDtRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUVELFVBQVU7SUFDRiw0QkFBNEIsQ0FDbEMsTUFBeUMsRUFDekMsT0FBMkIsRUFDM0IsT0FBc0I7UUFFdEIsSUFBSSxhQUFhLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQztRQUV4QyxJQUFJLENBQUEsT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLFFBQVEsS0FBSSxJQUFJLEVBQUU7WUFDN0IsYUFBYSxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1NBQ3BFO1FBRUQsSUFBSSxDQUFBLE9BQU8sYUFBUCxPQUFPLHVCQUFQLE9BQU8sQ0FBRSxvQkFBb0IsTUFBSyxLQUFLLEVBQUU7WUFDM0MsYUFBYSxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO1NBQzVEO1FBRUQsSUFBSSxPQUFPLGFBQVAsT0FBTyx1QkFBUCxPQUFPLENBQUUsV0FBVyxFQUFFO1lBQ3hCLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7U0FDdkI7UUFFRCxPQUFPLGFBQWEsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDMUMsQ0FBQzs7OztZQTM3QkYsVUFBVSxTQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRTs7O1lBNUVoQyxXQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7XHJcbiAgQWJzdHJhY3RDb250cm9sLFxyXG4gIEFic3RyYWN0Q29udHJvbE9wdGlvbnMsXHJcbiAgRm9ybUFycmF5LFxyXG4gIEZvcm1CdWlsZGVyLFxyXG4gIEZvcm1Hcm91cCxcclxuICBWYWxpZGF0b3JGbixcclxufSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcclxuaW1wb3J0IHsgU3Vic2NyaXB0aW9uIH0gZnJvbSBcInJ4anNcIjtcclxuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCB9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xyXG5cclxuLy8gPT09PT09PT09PT09PT09PT09PT0g57G75Z6L5a6a5LmJID09PT09PT09PT09PT09PT09PT09XHJcblxyXG4vLyDlrZfmrrXplJnor6/mtojmga/nsbvlnovvvIjlrZfnrKbkuLLmiJblh73mlbDvvIlcclxuZXhwb3J0IHR5cGUgRmllbGRFcnJvck1lc3NhZ2UgPVxyXG4gIHwgc3RyaW5nXHJcbiAgfCAoKGNvbnRleHQ6IHsgY29udHJvbDogQWJzdHJhY3RDb250cm9sOyBjb250cm9sTmFtZTogc3RyaW5nIH0pID0+IHN0cmluZyk7XHJcblxyXG4vLyDlrZfmrrXplJnor6/mtojmga/pm4blkIhcclxuZXhwb3J0IHR5cGUgRmllbGRFcnJvck1lc3NhZ2VzID0gUmVjb3JkPHN0cmluZywgRmllbGRFcnJvck1lc3NhZ2U+O1xyXG5cclxuLy8g5a2X5q616YWN572uXHJcbmV4cG9ydCB0eXBlIEZpZWxkQ29uZmlnID0ge1xyXG4gIHZhbHVlOiBhbnk7XHJcbiAgZGlzYWJsZWQ/OiBib29sZWFuO1xyXG4gIHZhbGlkYXRvcnM/OiAoKSA9PiBWYWxpZGF0b3JGbltdO1xyXG4gIGVycm9yTWVzc2FnZXM/OiBGaWVsZEVycm9yTWVzc2FnZXM7XHJcbn07XHJcblxyXG4vLyBGb3JtQXJyYXkg6YWN572u57G75Z6LXHJcbmV4cG9ydCB0eXBlIEZvcm1BcnJheUNvbmZpZyA9IHtcclxuICB0eXBlOiBcImFycmF5XCI7XHJcbiAgaXRlbUNvbmZpZzogRm9ybUNvbmZpZzsgLy8g5q+P6KGM55qE6KGo5Y2V6YWN572uXHJcbiAgaW5pdGlhbEl0ZW1zPzogYW55W107IC8vIOWIneWni+aVsOaNrumhuVxyXG4gIGVycm9yTWVzc2FnZXM/OiBSZWNvcmQ8c3RyaW5nLCBGaWVsZEVycm9yTWVzc2FnZXM+OyAvLyDooYzlrZfmrrXnmoTplJnor6/mtojmga/phY3nva5cclxuICB1bmlxdWVJZEZpZWxkPzogc3RyaW5nOyAvLyDkuJrliqHllK/kuIDmoIfor4blrZfmrrXvvIjlpoIgJ2RpY3RJZCcsICdpZCcg562J77yJXHJcbn07XHJcblxyXG4vLyDooajljZXkv67mlLnnsbvlnotcclxuZXhwb3J0IHR5cGUgRm9ybU1vZGlmeVR5cGUgPSBcImNyZWF0ZVwiIHwgXCJ1cGRhdGVcIjtcclxuXHJcbi8vIOihqOWNlemFjee9ru+8iOaUr+aMgeaZrumAmuWtl+auteWSjCBGb3JtQXJyYXnvvIlcclxuZXhwb3J0IHR5cGUgRm9ybUNvbmZpZyA9IFJlY29yZDxzdHJpbmcsIEZpZWxkQ29uZmlnIHwgRm9ybUFycmF5Q29uZmlnPjtcclxuXHJcbi8vIOebkeWQrOmAiemhuVxyXG5leHBvcnQgdHlwZSBXYXRjaE9wdGlvbnMgPSB7XHJcbiAgZGVib3VuY2U/OiBudW1iZXI7XHJcbiAgZGlzdGluY3RVbnRpbENoYW5nZWQ/OiBib29sZWFuO1xyXG4gIGVtaXRJbml0aWFsPzogYm9vbGVhbjtcclxufTtcclxuXHJcbi8vIOaJuemHj+a3u+WKoOWtl+autemFjee9rumAiemhuVxyXG5leHBvcnQgdHlwZSBBZGRGaWVsZHNDb25maWdPcHRpb25zID0ge1xyXG4gIGVtaXRFdmVudD86IGJvb2xlYW47XHJcbiAgdXBkYXRlVmFsdWVBbmRWYWxpZGl0eT86IGJvb2xlYW47XHJcbiAgb25GaWVsZEFkZGVkPzogKGZpZWxkTmFtZTogc3RyaW5nLCBzdWNjZXNzOiBib29sZWFuLCBlcnJvcj86IHN0cmluZykgPT4gdm9pZDsgLy8g5q+P5Liq5a2X5q615re75Yqg55qE5Zue6LCDXHJcbn07XHJcblxyXG4vLyDmibnph4/mt7vliqDlrZfmrrXphY3nva7nu5PmnpxcclxuZXhwb3J0IHR5cGUgQWRkRmllbGRzQ29uZmlnUmVzdWx0ID0ge1xyXG4gIHN1Y2Nlc3M6IGJvb2xlYW47XHJcbiAgYWRkZWQ6IHN0cmluZ1tdOyAvLyDmiJDlip/mt7vliqDnmoTlrZfmrrXlkI3liJfooahcclxuICBmYWlsZWQ6IEFycmF5PHsgZmllbGROYW1lOiBzdHJpbmc7IGVycm9yOiBzdHJpbmcgfT47IC8vIOWksei0peeahOWtl+auteWPiumUmeivr+S/oeaBr1xyXG59O1xyXG5cclxuLy8g5om56YeP5Yig6Zmk5a2X5q616YWN572u6YCJ6aG5XHJcbmV4cG9ydCB0eXBlIFJlbW92ZUZpZWxkc0NvbmZpZ09wdGlvbnMgPSB7XHJcbiAgZW1pdEV2ZW50PzogYm9vbGVhbjtcclxuICBvbkZpZWxkUmVtb3ZlZD86IChmaWVsZE5hbWU6IHN0cmluZywgc3VjY2VzczogYm9vbGVhbiwgZXJyb3I/OiBzdHJpbmcpID0+IHZvaWQ7IC8vIOavj+S4quWtl+auteWIoOmZpOeahOWbnuiwg1xyXG59O1xyXG5cclxuLy8g5om56YeP5Yig6Zmk5a2X5q616YWN572u57uT5p6cXHJcbmV4cG9ydCB0eXBlIFJlbW92ZUZpZWxkc0NvbmZpZ1Jlc3VsdCA9IHtcclxuICBzdWNjZXNzOiBib29sZWFuO1xyXG4gIHJlbW92ZWQ6IHN0cmluZ1tdOyAvLyDmiJDlip/liKDpmaTnmoTlrZfmrrXlkI3liJfooahcclxuICBmYWlsZWQ6IEFycmF5PHsgZmllbGROYW1lOiBzdHJpbmc7IGVycm9yOiBzdHJpbmcgfT47IC8vIOWksei0peeahOWtl+auteWPiumUmeivr+S/oeaBr1xyXG59O1xyXG5cclxuLy8gPT09PT09PT09PT09PT09PT09PT0g5pyN5Yqh57G7ID09PT09PT09PT09PT09PT09PT09XHJcblxyXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46IFwicm9vdFwiIH0pXHJcbmV4cG9ydCBjbGFzcyBBbnRkRm9ybVNlcnZpY2Uge1xyXG4gIC8vID09PT09PT09PT09PT09PT09PT09IOWFrOWFseWxnuaApyA9PT09PT09PT09PT09PT09PT09PVxyXG4gIGZvcm1TdG9yZTogUmVjb3JkPHN0cmluZywgRm9ybUdyb3VwPiA9IHt9O1xyXG4gIGZvcm1Nb2RpZnlUeXBlOiBGb3JtTW9kaWZ5VHlwZSA9IFwiY3JlYXRlXCI7XHJcblxyXG4gIC8vID09PT09PT09PT09PT09PT09PT09IOengeacieWxnuaApyA9PT09PT09PT09PT09PT09PT09PVxyXG4gIHByaXZhdGUgbGFiZWxXaWR0aDogc3RyaW5nID0gXCIxMjBweFwiO1xyXG4gIHByaXZhdGUgbGFiZWxBbGlnbjogc3RyaW5nID0gXCJyaWdodFwiO1xyXG4gIHByaXZhdGUgbGFiZWxPYnNlcnZlcnM6IFJlY29yZDxzdHJpbmcsIE11dGF0aW9uT2JzZXJ2ZXI+ID0ge307XHJcbiAgcHJpdmF0ZSBlcnJvck1lc3NhZ2VTdG9yZTogUmVjb3JkPFxyXG4gICAgc3RyaW5nLFxyXG4gICAgUmVjb3JkPHN0cmluZywgRmllbGRFcnJvck1lc3NhZ2VzPlxyXG4gID4gPSB7fTtcclxuICBwcml2YXRlIGZvcm1BcnJheUNvbmZpZ1N0b3JlOiBSZWNvcmQ8XHJcbiAgICBzdHJpbmcsXHJcbiAgICBSZWNvcmQ8c3RyaW5nLCB7IGl0ZW1Db25maWc6IEZvcm1Db25maWc7IHVuaXF1ZUlkRmllbGQ/OiBzdHJpbmcgfT5cclxuICA+ID0ge307XHJcbiAgcHJpdmF0ZSByZWFkb25seSBJTlRFUk5BTF9JRF9GSUVMRCA9IFwiX19mb3JtSXRlbUlkXCI7XHJcbiAgcHJpdmF0ZSBjbGFzc1ByZWZpeCA9IFwiYW50LWZvcm0tXCI7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0RXJyb3JNZXNzYWdlczogRmllbGRFcnJvck1lc3NhZ2VzID0ge1xyXG4gICAgcmVxdWlyZWQ6IFwi6K+l5a2X5q615Li65b+F5aGr6aG5XCIsXHJcbiAgICBtaW5sZW5ndGg6IFwi6L6T5YWl6ZW/5bqm5LiN6LazXCIsXHJcbiAgICBtYXhsZW5ndGg6IFwi6L6T5YWl6ZW/5bqm6LaF6ZmQXCIsXHJcbiAgICBlbWFpbDogXCLor7fovpPlhaXlkIjms5XnmoTpgq7nrrHlnLDlnYBcIixcclxuICAgIHBhdHRlcm46IFwi6L6T5YWl5qC85byP5LiN5q2j56GuXCIsXHJcbiAgfTtcclxuXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT0g5p6E6YCg5Ye95pWwID09PT09PT09PT09PT09PT09PT09XHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBmYjogRm9ybUJ1aWxkZXIpIHt9XHJcblxyXG4gIC8vID09PT09PT09PT09PT09PT09PT09IOihqOWNleWIm+W7uuWSjOWIneWni+WMliA9PT09PT09PT09PT09PT09PT09PVxyXG5cclxuICAvLyDliJ3lp4vljJbooajljZXvvIjmlK/mjIEgRm9ybUFycmF577yJXHJcbiAgY3JlYXRlRm9ybUdyb3VwKFxyXG4gICAgbmFtZTogc3RyaW5nLFxyXG4gICAgY29uZmlnOiBGb3JtQ29uZmlnLFxyXG4gICAgb3B0aW9ucz86IHsgbGFiZWxXaWR0aD86IHN0cmluZzsgbGFiZWxBbGlnbj86IHN0cmluZyB9XHJcbiAgKTogRm9ybUdyb3VwIHtcclxuICAgIGNvbnN0IGdyb3VwQ29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XHJcbiAgICB0aGlzLmVycm9yTWVzc2FnZVN0b3JlW25hbWVdID0ge307XHJcblxyXG4gICAgT2JqZWN0LmVudHJpZXMoY29uZmlnKS5mb3JFYWNoKChba2V5LCBmaWVsZF0pID0+IHtcclxuICAgICAgaWYgKHRoaXMuaXNGb3JtQXJyYXlDb25maWcoZmllbGQpKSB7XHJcbiAgICAgICAgLy8gRm9ybUFycmF5IOmFjee9ruWkhOeQhlxyXG4gICAgICAgIGlmICghdGhpcy5mb3JtQXJyYXlDb25maWdTdG9yZVtuYW1lXSkge1xyXG4gICAgICAgICAgdGhpcy5mb3JtQXJyYXlDb25maWdTdG9yZVtuYW1lXSA9IHt9O1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmZvcm1BcnJheUNvbmZpZ1N0b3JlW25hbWVdW2tleV0gPSB7XHJcbiAgICAgICAgICBpdGVtQ29uZmlnOiBmaWVsZC5pdGVtQ29uZmlnLFxyXG4gICAgICAgICAgdW5pcXVlSWRGaWVsZDogZmllbGQudW5pcXVlSWRGaWVsZCxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBmb3JtQXJyYXkgPSB0aGlzLmNyZWF0ZUZvcm1BcnJheUZyb21Db25maWcoXHJcbiAgICAgICAgICBuYW1lLFxyXG4gICAgICAgICAga2V5LFxyXG4gICAgICAgICAgZmllbGQuaXRlbUNvbmZpZyxcclxuICAgICAgICAgIGZpZWxkLmluaXRpYWxJdGVtcyB8fCBbXSxcclxuICAgICAgICAgIGZpZWxkLnVuaXF1ZUlkRmllbGRcclxuICAgICAgICApO1xyXG4gICAgICAgIGdyb3VwQ29uZmlnW2tleV0gPSBmb3JtQXJyYXk7XHJcblxyXG4gICAgICAgIC8vIOWtmOWCqCBGb3JtQXJyYXkg5a2X5q6155qE6ZSZ6K+v5raI5oGv6YWN572u77yM5qC85byP77yaYXJyYXlOYW1lW10uZmllbGROYW1lXHJcbiAgICAgICAgaWYgKGZpZWxkLmVycm9yTWVzc2FnZXMpIHtcclxuICAgICAgICAgIE9iamVjdC5lbnRyaWVzKGZpZWxkLmVycm9yTWVzc2FnZXMpLmZvckVhY2goXHJcbiAgICAgICAgICAgIChbZmllbGROYW1lLCBlcnJvck1lc3NhZ2VzXSkgPT4ge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZUtleSA9IGAke2tleX1bXS4ke2ZpZWxkTmFtZX1gO1xyXG4gICAgICAgICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlU3RvcmVbbmFtZV1bZXJyb3JNZXNzYWdlS2V5XSA9IGVycm9yTWVzc2FnZXM7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIOaZrumAmuWtl+autemFjee9rlxyXG4gICAgICAgIGNvbnN0IGZpZWxkQ29uZmlnID0gZmllbGQgYXMgRmllbGRDb25maWc7XHJcbiAgICAgICAgZ3JvdXBDb25maWdba2V5XSA9IFtcclxuICAgICAgICAgIHsgdmFsdWU6IGZpZWxkQ29uZmlnLnZhbHVlLCBkaXNhYmxlZDogZmllbGRDb25maWcuZGlzYWJsZWQgPz8gZmFsc2UgfSxcclxuICAgICAgICAgIGZpZWxkQ29uZmlnLnZhbGlkYXRvcnM/LigpID8/IFtdLFxyXG4gICAgICAgIF07XHJcbiAgICAgICAgaWYgKGZpZWxkQ29uZmlnLmVycm9yTWVzc2FnZXMpIHtcclxuICAgICAgICAgIHRoaXMuZXJyb3JNZXNzYWdlU3RvcmVbbmFtZV1ba2V5XSA9IGZpZWxkQ29uZmlnLmVycm9yTWVzc2FnZXM7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBpZiAob3B0aW9ucz8ubGFiZWxXaWR0aCkge1xyXG4gICAgICB0aGlzLmxhYmVsV2lkdGggPSBvcHRpb25zLmxhYmVsV2lkdGg7XHJcbiAgICB9XHJcbiAgICBpZiAob3B0aW9ucz8ubGFiZWxBbGlnbikge1xyXG4gICAgICB0aGlzLmxhYmVsQWxpZ24gPSBvcHRpb25zLmxhYmVsQWxpZ247XHJcbiAgICB9XHJcbiAgICB0aGlzLmZvcm1TdG9yZVtuYW1lXSA9IHRoaXMuZmIuZ3JvdXAoZ3JvdXBDb25maWcpO1xyXG4gICAgdGhpcy5zZXRDU1NWYXJpYWJsZXNUb1RhcmdldChuYW1lKTtcclxuICAgIHJldHVybiB0aGlzLmZvcm1TdG9yZVtuYW1lXTtcclxuICB9XHJcblxyXG4gIC8vID09PT09PT09PT09PT09PT09PT09IOihqOWNleaTjeS9nCA9PT09PT09PT09PT09PT09PT09PVxyXG5cclxuICAvLyDph43nva7ooajljZVcclxuICByZXNldEZvcm1Hcm91cChuYW1lOiBzdHJpbmcsIHZhbHVlPzogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLmZvcm1TdG9yZVtuYW1lXT8ucmVzZXQodmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLy8g5om56YeP5re75Yqg5a2X5q616YWN572uXHJcbiAgYWRkRmllbGRzQ29uZmlnKFxyXG4gICAgZm9ybU5hbWU6IHN0cmluZyxcclxuICAgIGZpZWxkc0NvbmZpZzogRm9ybUNvbmZpZyxcclxuICAgIG9wdGlvbnM/OiBBZGRGaWVsZHNDb25maWdPcHRpb25zXHJcbiAgKTogQWRkRmllbGRzQ29uZmlnUmVzdWx0IHtcclxuICAgIGNvbnN0IHJlc3VsdDogQWRkRmllbGRzQ29uZmlnUmVzdWx0ID0ge1xyXG4gICAgICBzdWNjZXNzOiB0cnVlLFxyXG4gICAgICBhZGRlZDogW10sXHJcbiAgICAgIGZhaWxlZDogW10sXHJcbiAgICB9O1xyXG5cclxuICAgIC8vIDEuIOmqjOivgeihqOWNleaYr+WQpuWtmOWcqFxyXG4gICAgY29uc3QgZm9ybUdyb3VwID0gdGhpcy5mb3JtU3RvcmVbZm9ybU5hbWVdO1xyXG4gICAgaWYgKCFmb3JtR3JvdXApIHtcclxuICAgICAgLy8g5aaC5p6c6KGo5Y2V5LiN5a2Y5Zyo77yM5omA5pyJ5a2X5q616YO95aSx6LSlXHJcbiAgICAgIE9iamVjdC5rZXlzKGZpZWxkc0NvbmZpZykuZm9yRWFjaCgoZmllbGROYW1lKSA9PiB7XHJcbiAgICAgICAgY29uc3QgZXJyb3IgPSBgRm9ybSBcIiR7Zm9ybU5hbWV9XCIgbm90IGZvdW5kYDtcclxuICAgICAgICByZXN1bHQuZmFpbGVkLnB1c2goe1xyXG4gICAgICAgICAgZmllbGROYW1lLFxyXG4gICAgICAgICAgZXJyb3IsXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgb3B0aW9ucz8ub25GaWVsZEFkZGVkPy4oZmllbGROYW1lLCBmYWxzZSwgZXJyb3IpO1xyXG4gICAgICB9KTtcclxuICAgICAgcmVzdWx0LnN1Y2Nlc3MgPSBmYWxzZTtcclxuICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICAvLyAyLiDliJ3lp4vljJYgZXJyb3JNZXNzYWdlU3RvcmUg5ZKMIGZvcm1BcnJheUNvbmZpZ1N0b3Jl77yI5aaC5p6c5LiN5a2Y5Zyo77yJXHJcbiAgICBpZiAoIXRoaXMuZXJyb3JNZXNzYWdlU3RvcmVbZm9ybU5hbWVdKSB7XHJcbiAgICAgIHRoaXMuZXJyb3JNZXNzYWdlU3RvcmVbZm9ybU5hbWVdID0ge307XHJcbiAgICB9XHJcbiAgICBpZiAoIXRoaXMuZm9ybUFycmF5Q29uZmlnU3RvcmVbZm9ybU5hbWVdKSB7XHJcbiAgICAgIHRoaXMuZm9ybUFycmF5Q29uZmlnU3RvcmVbZm9ybU5hbWVdID0ge307XHJcbiAgICB9XHJcblxyXG4gICAgLy8gMy4g5om56YeP5p6E5bu65o6n5Lu26YWN572uXHJcbiAgICBjb25zdCBjb250cm9sc1RvQWRkOiBSZWNvcmQ8c3RyaW5nLCBBYnN0cmFjdENvbnRyb2w+ID0ge307XHJcbiAgICBjb25zdCBlcnJvck1lc3NhZ2VzVG9BZGQ6IFJlY29yZDxzdHJpbmcsIEZpZWxkRXJyb3JNZXNzYWdlcz4gPSB7fTtcclxuICAgIGNvbnN0IGZvcm1BcnJheUNvbmZpZ3NUb0FkZDogUmVjb3JkPFxyXG4gICAgICBzdHJpbmcsXHJcbiAgICAgIHsgaXRlbUNvbmZpZzogRm9ybUNvbmZpZzsgdW5pcXVlSWRGaWVsZD86IHN0cmluZyB9XHJcbiAgICA+ID0ge307XHJcblxyXG4gICAgLy8gNC4g6YGN5Y6G5omA5pyJ5a2X5q616YWN572u77yM6L+b6KGM6aqM6K+B5ZKM5p6E5bu6XHJcbiAgICBPYmplY3QuZW50cmllcyhmaWVsZHNDb25maWcpLmZvckVhY2goKFtmaWVsZE5hbWUsIGZpZWxkQ29uZmlnXSkgPT4ge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIC8vIDQuMSDmo4Dmn6XlrZfmrrXmmK/lkKblt7LlrZjlnKhcclxuICAgICAgICBpZiAoZm9ybUdyb3VwLmdldChmaWVsZE5hbWUpKSB7XHJcbiAgICAgICAgICBjb25zdCBlcnJvciA9IGBGaWVsZCBcIiR7ZmllbGROYW1lfVwiIGFscmVhZHkgZXhpc3RzYDtcclxuICAgICAgICAgIHJlc3VsdC5mYWlsZWQucHVzaCh7XHJcbiAgICAgICAgICAgIGZpZWxkTmFtZSxcclxuICAgICAgICAgICAgZXJyb3IsXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICAgIG9wdGlvbnM/Lm9uRmllbGRBZGRlZD8uKGZpZWxkTmFtZSwgZmFsc2UsIGVycm9yKTtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIDQuMiDmoLnmja7lrZfmrrXnsbvlnovliJvlu7rmjqfku7ZcclxuICAgICAgICBpZiAodGhpcy5pc0Zvcm1BcnJheUNvbmZpZyhmaWVsZENvbmZpZykpIHtcclxuICAgICAgICAgIC8vIEZvcm1BcnJheSDlpITnkIZcclxuICAgICAgICAgIGNvbnN0IGZvcm1BcnJheSA9IHRoaXMuY3JlYXRlRm9ybUFycmF5RnJvbUNvbmZpZyhcclxuICAgICAgICAgICAgZm9ybU5hbWUsXHJcbiAgICAgICAgICAgIGZpZWxkTmFtZSxcclxuICAgICAgICAgICAgZmllbGRDb25maWcuaXRlbUNvbmZpZyxcclxuICAgICAgICAgICAgZmllbGRDb25maWcuaW5pdGlhbEl0ZW1zIHx8IFtdLFxyXG4gICAgICAgICAgICBmaWVsZENvbmZpZy51bmlxdWVJZEZpZWxkXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgY29udHJvbHNUb0FkZFtmaWVsZE5hbWVdID0gZm9ybUFycmF5O1xyXG5cclxuICAgICAgICAgIC8vIOWtmOWCqCBGb3JtQXJyYXkg6YWN572uXHJcbiAgICAgICAgICBmb3JtQXJyYXlDb25maWdzVG9BZGRbZmllbGROYW1lXSA9IHtcclxuICAgICAgICAgICAgaXRlbUNvbmZpZzogZmllbGRDb25maWcuaXRlbUNvbmZpZyxcclxuICAgICAgICAgICAgdW5pcXVlSWRGaWVsZDogZmllbGRDb25maWcudW5pcXVlSWRGaWVsZCxcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgLy8g5a2Y5YKo6ZSZ6K+v5raI5oGvXHJcbiAgICAgICAgICBpZiAoZmllbGRDb25maWcuZXJyb3JNZXNzYWdlcykge1xyXG4gICAgICAgICAgICBPYmplY3QuZW50cmllcyhmaWVsZENvbmZpZy5lcnJvck1lc3NhZ2VzKS5mb3JFYWNoKFxyXG4gICAgICAgICAgICAgIChbaXRlbUZpZWxkTmFtZSwgZXJyb3JNZXNzYWdlc10pID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTWVzc2FnZUtleSA9IGAke2ZpZWxkTmFtZX1bXS4ke2l0ZW1GaWVsZE5hbWV9YDtcclxuICAgICAgICAgICAgICAgIGVycm9yTWVzc2FnZXNUb0FkZFtlcnJvck1lc3NhZ2VLZXldID0gZXJyb3JNZXNzYWdlcztcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vIOaZrumAmuWtl+auteWkhOeQhlxyXG4gICAgICAgICAgY29uc3QgZmllbGRDb25maWdUeXBlZCA9IGZpZWxkQ29uZmlnIGFzIEZpZWxkQ29uZmlnO1xyXG4gICAgICAgICAgY29uc3QgY29udHJvbE9wdGlvbnM6IEFic3RyYWN0Q29udHJvbE9wdGlvbnMgPSB7XHJcbiAgICAgICAgICAgIHZhbGlkYXRvcnM6IGZpZWxkQ29uZmlnVHlwZWQudmFsaWRhdG9ycz8uKCkgPz8gW10sXHJcbiAgICAgICAgICB9O1xyXG4gICAgICAgICAgY29uc3QgY29udHJvbCA9IHRoaXMuZmIuY29udHJvbChcclxuICAgICAgICAgICAgZmllbGRDb25maWdUeXBlZC52YWx1ZSxcclxuICAgICAgICAgICAgY29udHJvbE9wdGlvbnNcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgICAvLyDorr7nva4gZGlzYWJsZWQg54q25oCBXHJcbiAgICAgICAgICBpZiAoZmllbGRDb25maWdUeXBlZC5kaXNhYmxlZCkge1xyXG4gICAgICAgICAgICBjb250cm9sLmRpc2FibGUoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGNvbnRyb2xzVG9BZGRbZmllbGROYW1lXSA9IGNvbnRyb2w7XHJcblxyXG4gICAgICAgICAgLy8g5a2Y5YKo6ZSZ6K+v5raI5oGvXHJcbiAgICAgICAgICBpZiAoZmllbGRDb25maWdUeXBlZC5lcnJvck1lc3NhZ2VzKSB7XHJcbiAgICAgICAgICAgIGVycm9yTWVzc2FnZXNUb0FkZFtmaWVsZE5hbWVdID0gZmllbGRDb25maWdUeXBlZC5lcnJvck1lc3NhZ2VzO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmVzdWx0LmFkZGVkLnB1c2goZmllbGROYW1lKTtcclxuICAgICAgICBvcHRpb25zPy5vbkZpZWxkQWRkZWQ/LihmaWVsZE5hbWUsIHRydWUpO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XHJcbiAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID1cclxuICAgICAgICAgIGVycm9yPy5tZXNzYWdlIHx8IGVycm9yPy50b1N0cmluZygpIHx8IFwiVW5rbm93biBlcnJvclwiO1xyXG4gICAgICAgIHJlc3VsdC5mYWlsZWQucHVzaCh7XHJcbiAgICAgICAgICBmaWVsZE5hbWUsXHJcbiAgICAgICAgICBlcnJvcjogZXJyb3JNZXNzYWdlLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIG9wdGlvbnM/Lm9uRmllbGRBZGRlZD8uKGZpZWxkTmFtZSwgZmFsc2UsIGVycm9yTWVzc2FnZSk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIC8vIDUuIOaJuemHj+a3u+WKoOWIsCBGb3JtR3JvdXBcclxuICAgIGlmIChPYmplY3Qua2V5cyhjb250cm9sc1RvQWRkKS5sZW5ndGggPiAwKSB7XHJcbiAgICAgIE9iamVjdC5lbnRyaWVzKGNvbnRyb2xzVG9BZGQpLmZvckVhY2goKFtmaWVsZE5hbWUsIGNvbnRyb2xdKSA9PiB7XHJcbiAgICAgICAgZm9ybUdyb3VwLmFkZENvbnRyb2woZmllbGROYW1lLCBjb250cm9sKTtcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyA2LiDmibnph4/lrZjlgqjplJnor6/mtojmga9cclxuICAgICAgT2JqZWN0LmVudHJpZXMoZXJyb3JNZXNzYWdlc1RvQWRkKS5mb3JFYWNoKChba2V5LCBtZXNzYWdlc10pID0+IHtcclxuICAgICAgICB0aGlzLmVycm9yTWVzc2FnZVN0b3JlW2Zvcm1OYW1lXVtrZXldID0gbWVzc2FnZXM7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy8gNy4g5om56YeP5a2Y5YKoIEZvcm1BcnJheSDphY3nva5cclxuICAgICAgT2JqZWN0LmVudHJpZXMoZm9ybUFycmF5Q29uZmlnc1RvQWRkKS5mb3JFYWNoKChbZmllbGROYW1lLCBjb25maWddKSA9PiB7XHJcbiAgICAgICAgdGhpcy5mb3JtQXJyYXlDb25maWdTdG9yZVtmb3JtTmFtZV1bZmllbGROYW1lXSA9IGNvbmZpZztcclxuICAgICAgfSk7XHJcblxyXG4gICAgICAvLyA4LiDmm7TmlrDooajljZXpqozor4HnirbmgIFcclxuICAgICAgaWYgKG9wdGlvbnM/LnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkpIHtcclxuICAgICAgICBmb3JtR3JvdXAudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7XHJcbiAgICAgICAgICBlbWl0RXZlbnQ6IG9wdGlvbnM/LmVtaXRFdmVudCA/PyB0cnVlLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gOS4g5Yik5pat5pW05L2T5piv5ZCm5oiQ5YqfXHJcbiAgICByZXN1bHQuc3VjY2VzcyA9IHJlc3VsdC5mYWlsZWQubGVuZ3RoID09PSAwO1xyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvLyDmibnph4/liKDpmaTlrZfmrrXphY3nva5cclxuICByZW1vdmVGaWVsZHNDb25maWcoXHJcbiAgICBmb3JtTmFtZTogc3RyaW5nLFxyXG4gICAgZmllbGROYW1lczogc3RyaW5nW10sXHJcbiAgICBvcHRpb25zPzogUmVtb3ZlRmllbGRzQ29uZmlnT3B0aW9uc1xyXG4gICk6IFJlbW92ZUZpZWxkc0NvbmZpZ1Jlc3VsdCB7XHJcbiAgICBjb25zdCByZXN1bHQ6IFJlbW92ZUZpZWxkc0NvbmZpZ1Jlc3VsdCA9IHtcclxuICAgICAgc3VjY2VzczogdHJ1ZSxcclxuICAgICAgcmVtb3ZlZDogW10sXHJcbiAgICAgIGZhaWxlZDogW10sXHJcbiAgICB9O1xyXG5cclxuICAgIC8vIDEuIOmqjOivgeihqOWNleaYr+WQpuWtmOWcqFxyXG4gICAgY29uc3QgZm9ybUdyb3VwID0gdGhpcy5mb3JtU3RvcmVbZm9ybU5hbWVdO1xyXG4gICAgaWYgKCFmb3JtR3JvdXApIHtcclxuICAgICAgZmllbGROYW1lcy5mb3JFYWNoKChmaWVsZE5hbWUpID0+IHtcclxuICAgICAgICBjb25zdCBlcnJvciA9IGBGb3JtIFwiJHtmb3JtTmFtZX1cIiBub3QgZm91bmRgO1xyXG4gICAgICAgIHJlc3VsdC5mYWlsZWQucHVzaCh7XHJcbiAgICAgICAgICBmaWVsZE5hbWUsXHJcbiAgICAgICAgICBlcnJvcixcclxuICAgICAgICB9KTtcclxuICAgICAgICBvcHRpb25zPy5vbkZpZWxkUmVtb3ZlZD8uKGZpZWxkTmFtZSwgZmFsc2UsIGVycm9yKTtcclxuICAgICAgfSk7XHJcbiAgICAgIHJlc3VsdC5zdWNjZXNzID0gZmFsc2U7XHJcbiAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gMi4g5om56YeP5pS26ZuG6ZyA6KaB5riF55CG55qE5L+h5oGvXHJcbiAgICBjb25zdCBmaWVsZHNUb1JlbW92ZTogc3RyaW5nW10gPSBbXTtcclxuICAgIGNvbnN0IGVycm9yTWVzc2FnZUtleXNUb1JlbW92ZTogc3RyaW5nW10gPSBbXTtcclxuICAgIGNvbnN0IGZvcm1BcnJheUZpZWxkczogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgICAvLyAzLiDpqozor4Hmr4/kuKrlrZfmrrXlubbmlLbpm4bkv6Hmga9cclxuICAgIGZpZWxkTmFtZXMuZm9yRWFjaCgoZmllbGROYW1lKSA9PiB7XHJcbiAgICAgIGNvbnN0IGNvbnRyb2wgPSBmb3JtR3JvdXAuZ2V0KGZpZWxkTmFtZSk7XHJcblxyXG4gICAgICBpZiAoIWNvbnRyb2wpIHtcclxuICAgICAgICBjb25zdCBlcnJvciA9IGBGaWVsZCBcIiR7ZmllbGROYW1lfVwiIG5vdCBmb3VuZGA7XHJcbiAgICAgICAgcmVzdWx0LmZhaWxlZC5wdXNoKHtcclxuICAgICAgICAgIGZpZWxkTmFtZSxcclxuICAgICAgICAgIGVycm9yLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIG9wdGlvbnM/Lm9uRmllbGRSZW1vdmVkPy4oZmllbGROYW1lLCBmYWxzZSwgZXJyb3IpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8g5Yik5pat5piv5ZCm5pivIEZvcm1BcnJheVxyXG4gICAgICBpZiAoY29udHJvbCBpbnN0YW5jZW9mIEZvcm1BcnJheSkge1xyXG4gICAgICAgIGZvcm1BcnJheUZpZWxkcy5wdXNoKGZpZWxkTmFtZSk7XHJcblxyXG4gICAgICAgIC8vIOaUtumbhiBGb3JtQXJyYXkg55u45YWz55qE6ZSZ6K+v5raI5oGv6ZSu77yI5qC85byP77yaYXJyYXlOYW1lW10uZmllbGROYW1l77yJXHJcbiAgICAgICAgaWYgKHRoaXMuZXJyb3JNZXNzYWdlU3RvcmVbZm9ybU5hbWVdKSB7XHJcbiAgICAgICAgICBPYmplY3Qua2V5cyh0aGlzLmVycm9yTWVzc2FnZVN0b3JlW2Zvcm1OYW1lXSkuZm9yRWFjaCgoa2V5KSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChrZXkuc3RhcnRzV2l0aChgJHtmaWVsZE5hbWV9W10uYCkpIHtcclxuICAgICAgICAgICAgICBlcnJvck1lc3NhZ2VLZXlzVG9SZW1vdmUucHVzaChrZXkpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8g5pmu6YCa5a2X5q6155qE6ZSZ6K+v5raI5oGv6ZSuXHJcbiAgICAgICAgZXJyb3JNZXNzYWdlS2V5c1RvUmVtb3ZlLnB1c2goZmllbGROYW1lKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgZmllbGRzVG9SZW1vdmUucHVzaChmaWVsZE5hbWUpO1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gNC4g5om56YeP5omn6KGM5Yig6Zmk5pON5L2cXHJcbiAgICB0cnkge1xyXG4gICAgICAvLyA0LjEg5LuOIEZvcm1Hcm91cCDkuK3np7vpmaTmjqfku7ZcclxuICAgICAgZmllbGRzVG9SZW1vdmUuZm9yRWFjaCgoZmllbGROYW1lKSA9PiB7XHJcbiAgICAgICAgZm9ybUdyb3VwLnJlbW92ZUNvbnRyb2woZmllbGROYW1lKTtcclxuICAgICAgICByZXN1bHQucmVtb3ZlZC5wdXNoKGZpZWxkTmFtZSk7XHJcbiAgICAgICAgb3B0aW9ucz8ub25GaWVsZFJlbW92ZWQ/LihmaWVsZE5hbWUsIHRydWUpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIDQuMiDmibnph4/liKDpmaTplJnor6/mtojmga9cclxuICAgICAgaWYgKHRoaXMuZXJyb3JNZXNzYWdlU3RvcmVbZm9ybU5hbWVdKSB7XHJcbiAgICAgICAgZXJyb3JNZXNzYWdlS2V5c1RvUmVtb3ZlLmZvckVhY2goKGtleSkgPT4ge1xyXG4gICAgICAgICAgZGVsZXRlIHRoaXMuZXJyb3JNZXNzYWdlU3RvcmVbZm9ybU5hbWVdW2tleV07XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIDQuMyDmibnph4/liKDpmaQgRm9ybUFycmF5IOmFjee9rlxyXG4gICAgICBpZiAodGhpcy5mb3JtQXJyYXlDb25maWdTdG9yZVtmb3JtTmFtZV0pIHtcclxuICAgICAgICBmb3JtQXJyYXlGaWVsZHMuZm9yRWFjaCgoZmllbGROYW1lKSA9PiB7XHJcbiAgICAgICAgICBkZWxldGUgdGhpcy5mb3JtQXJyYXlDb25maWdTdG9yZVtmb3JtTmFtZV1bZmllbGROYW1lXTtcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xyXG4gICAgICAvLyDlpoLmnpzmibnph4/liKDpmaTov4fnqIvkuK3lh7rplJnvvIzmoIforrDkuLrlpLHotKVcclxuICAgICAgZmllbGRzVG9SZW1vdmUuZm9yRWFjaCgoZmllbGROYW1lKSA9PiB7XHJcbiAgICAgICAgaWYgKCFyZXN1bHQucmVtb3ZlZC5pbmNsdWRlcyhmaWVsZE5hbWUpKSB7XHJcbiAgICAgICAgICBjb25zdCBlcnJvck1lc3NhZ2UgPVxyXG4gICAgICAgICAgICBlcnJvcj8ubWVzc2FnZSB8fCBlcnJvcj8udG9TdHJpbmcoKSB8fCBcIkZhaWxlZCB0byByZW1vdmUgZmllbGRcIjtcclxuICAgICAgICAgIHJlc3VsdC5mYWlsZWQucHVzaCh7XHJcbiAgICAgICAgICAgIGZpZWxkTmFtZSxcclxuICAgICAgICAgICAgZXJyb3I6IGVycm9yTWVzc2FnZSxcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgb3B0aW9ucz8ub25GaWVsZFJlbW92ZWQ/LihmaWVsZE5hbWUsIGZhbHNlLCBlcnJvck1lc3NhZ2UpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gNS4g5Yik5pat5pW05L2T5piv5ZCm5oiQ5YqfXHJcbiAgICByZXN1bHQuc3VjY2VzcyA9IHJlc3VsdC5mYWlsZWQubGVuZ3RoID09PSAwO1xyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvLyDlsYDpg6jotYvlgLzvvIjmlK/mjIEgRm9ybUFycmF5IOeahOaZuuiDveabtOaWsO+8jOe7n+S4gOagueaNriBhY3Rpb24g5a2X5q615Yik5pat5pON5L2c57G75Z6L77yJXHJcbiAgcGF0Y2hGb3JtVmFsdWVzKFxyXG4gICAgbmFtZTogc3RyaW5nLFxyXG4gICAgdmFsdWVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxyXG4gICAgb3B0aW9ucz86IHsgZW1pdEV2ZW50PzogYm9vbGVhbiB9XHJcbiAgKTogdm9pZCB7XHJcbiAgICBjb25zdCBmb3JtR3JvdXAgPSB0aGlzLmZvcm1TdG9yZVtuYW1lXTtcclxuICAgIGlmICghZm9ybUdyb3VwKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICBgW0FudGRGb3JtU2VydmljZV0gcGF0Y2hGb3JtVmFsdWVzOiBmb3JtIFwiJHtuYW1lfVwiIG5vdCBmb3VuZC5gXHJcbiAgICAgICk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBwcm9jZXNzZWRWYWx1ZXM6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcclxuXHJcbiAgICBPYmplY3QuZW50cmllcyh2YWx1ZXMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xyXG4gICAgICBjb25zdCBjb250cm9sID0gZm9ybUdyb3VwLmdldChrZXkpO1xyXG5cclxuICAgICAgLy8g5qOA5rWL5piv5ZCm5pivIEZvcm1BcnJheVxyXG4gICAgICBpZiAoY29udHJvbCBpbnN0YW5jZW9mIEZvcm1BcnJheSAmJiBBcnJheS5pc0FycmF5KHZhbHVlKSkge1xyXG4gICAgICAgIHRoaXMucGF0Y2hGb3JtQXJyYXkobmFtZSwga2V5LCB2YWx1ZSk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyDmma7pgJrlrZfmrrXvvIznm7TmjqXliqDlhaVcclxuICAgICAgcHJvY2Vzc2VkVmFsdWVzW2tleV0gPSB2YWx1ZTtcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIOWkhOeQhuaZrumAmuWtl+autVxyXG4gICAgaWYgKE9iamVjdC5rZXlzKHByb2Nlc3NlZFZhbHVlcykubGVuZ3RoID4gMCkge1xyXG4gICAgICBmb3JtR3JvdXAucGF0Y2hWYWx1ZShwcm9jZXNzZWRWYWx1ZXMsIHtcclxuICAgICAgICBlbWl0RXZlbnQ6IG9wdGlvbnM/LmVtaXRFdmVudCA/PyB0cnVlLFxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIOihqOWNleagoemqjO+8iOiHquWKqOi/h+a7pOWGhemDqOWtl+aute+8iVxyXG4gIHZhbGlkYXRlRm9ybShcclxuICAgIG5hbWU6IHN0cmluZyxcclxuICAgIG9wdGlvbnM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW47IG9ubHlTZWxmPzogYm9vbGVhbiB9XHJcbiAgKTogYm9vbGVhbiB8IFJlY29yZDxzdHJpbmcsIGFueT4ge1xyXG4gICAgaWYgKHRoaXMuZm9ybVN0b3JlW25hbWVdLnZhbGlkKSB7XHJcbiAgICAgIGNvbnN0IHJhd1ZhbHVlID0gdGhpcy5mb3JtU3RvcmVbbmFtZV0uZ2V0UmF3VmFsdWUoKTtcclxuICAgICAgcmV0dXJuIHRoaXMuZXhjbHVkZUludGVybmFsRmllbGRzKHJhd1ZhbHVlKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIOmAkuW9kuagoemqjOaJgOacieaOp+S7tu+8jOWMheaLrCBGb3JtQXJyYXkg5Lit55qE6aG5XHJcbiAgICAgIHRoaXMubWFya0FsbENvbnRyb2xzQXNEaXJ0eShcclxuICAgICAgICB0aGlzLmZvcm1TdG9yZVtuYW1lXSxcclxuICAgICAgICBvcHRpb25zPy5lbWl0RXZlbnQgPz8gdHJ1ZSxcclxuICAgICAgICBvcHRpb25zPy5vbmx5U2VsZiA/PyBmYWxzZVxyXG4gICAgICApO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyDpgJLlvZLmoIforrDmiYDmnInml6DmlYjmjqfku7bkuLogZGlydHnvvIjljIXmi6wgRm9ybUFycmF5IOS4reeahOmhue+8iVxyXG4gIHByaXZhdGUgbWFya0FsbENvbnRyb2xzQXNEaXJ0eShcclxuICAgIGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCxcclxuICAgIGVtaXRFdmVudDogYm9vbGVhbixcclxuICAgIG9ubHlTZWxmOiBib29sZWFuXHJcbiAgKTogdm9pZCB7XHJcbiAgICBpZiAoY29udHJvbC5pbnZhbGlkKSB7XHJcbiAgICAgIGNvbnRyb2wubWFya0FzRGlydHkoKTtcclxuICAgICAgY29udHJvbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHtcclxuICAgICAgICBlbWl0RXZlbnQsXHJcbiAgICAgICAgb25seVNlbGYsXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOWmguaenOaYryBGb3JtR3JvdXDvvIzpgJLlvZLlpITnkIbmiYDmnInlrZDmjqfku7ZcclxuICAgIGlmIChjb250cm9sIGluc3RhbmNlb2YgRm9ybUdyb3VwKSB7XHJcbiAgICAgIE9iamVjdC52YWx1ZXMoY29udHJvbC5jb250cm9scykuZm9yRWFjaCgoY2hpbGRDb250cm9sKSA9PiB7XHJcbiAgICAgICAgdGhpcy5tYXJrQWxsQ29udHJvbHNBc0RpcnR5KGNoaWxkQ29udHJvbCwgZW1pdEV2ZW50LCBvbmx5U2VsZik7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOWmguaenOaYryBGb3JtQXJyYXnvvIzpgJLlvZLlpITnkIbmlbDnu4TkuK3nmoTmr4/kuIDpoblcclxuICAgIGlmIChjb250cm9sIGluc3RhbmNlb2YgRm9ybUFycmF5KSB7XHJcbiAgICAgIGNvbnRyb2wuY29udHJvbHMuZm9yRWFjaCgoY2hpbGRDb250cm9sKSA9PiB7XHJcbiAgICAgICAgdGhpcy5tYXJrQWxsQ29udHJvbHNBc0RpcnR5KGNoaWxkQ29udHJvbCwgZW1pdEV2ZW50LCBvbmx5U2VsZik7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT0g6ZSZ6K+v5raI5oGv55u45YWzID09PT09PT09PT09PT09PT09PT09XHJcblxyXG4gIC8vIOiOt+WPluWtl+autemmluadoemUmeivr+aPkOekuu+8jOaUr+aMgeaZrumAmuWtl+auteWSjCBGb3JtQXJyYXkg5a2X5q6177yI5qC85byP77yaYXJyYXlOYW1lLmluZGV4LmZpZWxkTmFtZe+8iVxyXG4gIGdldEZpZWxkRXJyb3JNZXNzYWdlKG5hbWU6IHN0cmluZywgY29udHJvbE5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBmb3JtR3JvdXAgPSB0aGlzLmZvcm1TdG9yZVtuYW1lXTtcclxuICAgIGlmICghZm9ybUdyb3VwKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICBgW0FudGRGb3JtU2VydmljZV0gZ2V0RmllbGRFcnJvck1lc3NhZ2U6IGZvcm0gXCIke25hbWV9XCIgbm90IGZvdW5kLmBcclxuICAgICAgKTtcclxuICAgICAgcmV0dXJuIFwiXCI7XHJcbiAgICB9XHJcbiAgICBjb25zdCBjb250cm9sID0gZm9ybUdyb3VwLmdldChjb250cm9sTmFtZSk7XHJcbiAgICBpZiAoIWNvbnRyb2wpIHtcclxuICAgICAgY29uc29sZS53YXJuKFxyXG4gICAgICAgIGBbQW50ZEZvcm1TZXJ2aWNlXSBnZXRGaWVsZEVycm9yTWVzc2FnZTogY29udHJvbCBcIiR7Y29udHJvbE5hbWV9XCIgbm90IGZvdW5kIGluIGZvcm0gXCIke25hbWV9XCIuYFxyXG4gICAgICApO1xyXG4gICAgICByZXR1cm4gXCJcIjtcclxuICAgIH1cclxuICAgIGlmICghY29udHJvbC5lcnJvcnMpIHtcclxuICAgICAgcmV0dXJuIFwiXCI7XHJcbiAgICB9XHJcblxyXG4gICAgLy8g6Kej5p6QIGNvbnRyb2xOYW1l77yM5pSv5oyBIEZvcm1BcnJheSDmoLzlvI/vvJphcnJheU5hbWUuaW5kZXguZmllbGROYW1lXHJcbiAgICBsZXQgZXJyb3JNZXNzYWdlS2V5ID0gY29udHJvbE5hbWU7XHJcbiAgICBjb25zdCBhcnJheU1hdGNoID0gY29udHJvbE5hbWUubWF0Y2goL14oLispXFwuKFxcZCspXFwuKC4rKSQvKTtcclxuICAgIGlmIChhcnJheU1hdGNoKSB7XHJcbiAgICAgIC8vIEZvcm1BcnJheSDmoLzlvI/vvJphcnJheU5hbWUuaW5kZXguZmllbGROYW1lIC0+IOS9v+eUqCBhcnJheU5hbWVbXS5maWVsZE5hbWUg5L2c5Li6IGtleVxyXG4gICAgICBjb25zdCBbLCBhcnJheU5hbWUsICwgZmllbGROYW1lXSA9IGFycmF5TWF0Y2g7XHJcbiAgICAgIGVycm9yTWVzc2FnZUtleSA9IGAke2FycmF5TmFtZX1bXS4ke2ZpZWxkTmFtZX1gO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIOS7jiBlcnJvck1lc3NhZ2VTdG9yZSDojrflj5bplJnor6/mtojmga/phY3nva5cclxuICAgIGNvbnN0IGVycm9yTWVzc2FnZXMgPSB0aGlzLmVycm9yTWVzc2FnZVN0b3JlW25hbWVdPy5bZXJyb3JNZXNzYWdlS2V5XTtcclxuICAgIGNvbnN0IG1lcmdlZE1lc3NhZ2VzID0ge1xyXG4gICAgICAuLi50aGlzLmRlZmF1bHRFcnJvck1lc3NhZ2VzLFxyXG4gICAgICAuLi4oZXJyb3JNZXNzYWdlcyA/PyB7fSksXHJcbiAgICB9O1xyXG5cclxuICAgIGZvciAoY29uc3QgZXJyb3JLZXkgb2YgT2JqZWN0LmtleXMoY29udHJvbC5lcnJvcnMpKSB7XHJcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBtZXJnZWRNZXNzYWdlc1tlcnJvcktleV07XHJcbiAgICAgIGlmIChtZXNzYWdlKSB7XHJcbiAgICAgICAgLy8g5LiN5YaN5pSv5oyB5Ye95pWw5b2i5byP77yM5Y+q6L+U5Zue5a2X56ym5LiyXHJcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBtZXNzYWdlID09PSBcInN0cmluZ1wiID8gbWVzc2FnZSA6IFwiXCI7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBcIlwiO1xyXG4gIH1cclxuXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT0g55uR5ZCs55u45YWzID09PT09PT09PT09PT09PT09PT09XHJcblxyXG4gIC8vIOebkeWQrOihqOWNleaJgOacieWtl+auteWPmOabtFxyXG4gIHdhdGNoRm9ybUNoYW5nZXM8VCA9IGFueT4oXHJcbiAgICBuYW1lOiBzdHJpbmcsXHJcbiAgICBoYW5kbGVyOiAodmFsdWU6IFQpID0+IHZvaWQsXHJcbiAgICBvcHRpb25zPzogV2F0Y2hPcHRpb25zXHJcbiAgKTogU3Vic2NyaXB0aW9uIHwgdW5kZWZpbmVkIHtcclxuICAgIGNvbnN0IGZvcm1Hcm91cCA9IHRoaXMuZm9ybVN0b3JlW25hbWVdO1xyXG4gICAgaWYgKCFmb3JtR3JvdXApIHtcclxuICAgICAgY29uc29sZS53YXJuKFxyXG4gICAgICAgIGBbQW50ZEZvcm1TZXJ2aWNlXSB3YXRjaEZvcm1DaGFuZ2VzOiBmb3JtIFwiJHtuYW1lfVwiIG5vdCBmb3VuZC5gXHJcbiAgICAgICk7XHJcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRoaXMuc2V0dXBWYWx1ZUNoYW5nZVN1YnNjcmlwdGlvbihmb3JtR3JvdXAsIGhhbmRsZXIsIG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLy8g55uR5ZCs5oyH5a6a5a2X5q615Y+Y5pu0XHJcbiAgd2F0Y2hGaWVsZENoYW5nZXM8VCA9IGFueT4oXHJcbiAgICBuYW1lOiBzdHJpbmcsXHJcbiAgICBjb250cm9sTmFtZTogc3RyaW5nLFxyXG4gICAgaGFuZGxlcjogKHZhbHVlOiBUKSA9PiB2b2lkLFxyXG4gICAgb3B0aW9ucz86IFdhdGNoT3B0aW9uc1xyXG4gICk6IFN1YnNjcmlwdGlvbiB8IHVuZGVmaW5lZCB7XHJcbiAgICBjb25zdCBmb3JtR3JvdXAgPSB0aGlzLmZvcm1TdG9yZVtuYW1lXTtcclxuICAgIGlmICghZm9ybUdyb3VwKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICBgW0FudGRGb3JtU2VydmljZV0gd2F0Y2hGaWVsZENoYW5nZXM6IGZvcm0gXCIke25hbWV9XCIgbm90IGZvdW5kLmBcclxuICAgICAgKTtcclxuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjb250cm9sID0gZm9ybUdyb3VwLmdldChjb250cm9sTmFtZSk7XHJcbiAgICBpZiAoIWNvbnRyb2wpIHtcclxuICAgICAgY29uc29sZS53YXJuKFxyXG4gICAgICAgIGBbQW50ZEZvcm1TZXJ2aWNlXSB3YXRjaEZpZWxkQ2hhbmdlczogY29udHJvbCBcIiR7Y29udHJvbE5hbWV9XCIgbm90IGZvdW5kIGluIGZvcm0gXCIke25hbWV9XCIuYFxyXG4gICAgICApO1xyXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLnNldHVwVmFsdWVDaGFuZ2VTdWJzY3JpcHRpb24oY29udHJvbCwgaGFuZGxlciwgb3B0aW9ucyk7XHJcbiAgfVxyXG5cclxuICAvLyA9PT09PT09PT09PT09PT09PT09PSDlt6Xlhbfmlrnms5UgPT09PT09PT09PT09PT09PT09PT1cclxuXHJcbiAgLy8g6I635Y+W6KGo5Y2V57G75ZCNXHJcbiAgZ2V0Rm9ybUNsYXNzTmFtZShuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIGAke3RoaXMuY2xhc3NQcmVmaXh9JHtuYW1lfWA7XHJcbiAgfVxyXG5cclxuICAvLyDorr7nva4gQ1NTIOWPmOmHj+WIsOebruagh+WFg+e0oO+8iOaUr+aMgeaMgeS5heWMluebkeWQrOWKqOaAgea3u+WKoOeahOWFg+e0oO+8iVxyXG4gIHNldENTU1ZhcmlhYmxlc1RvVGFyZ2V0KG5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3Qgc2VsZWN0b3IgPSBgLiR7dGhpcy5nZXRGb3JtQ2xhc3NOYW1lKG5hbWUpfSAuYW50LWZvcm0taXRlbS1sYWJlbGA7XHJcbiAgICBjb25zdCBmb3JtQ29udGFpbmVyU2VsZWN0b3IgPSBgLiR7dGhpcy5nZXRGb3JtQ2xhc3NOYW1lKG5hbWUpfWA7XHJcbiAgICBjb25zdCBhcHBseVN0eWxlcyA9ICgpOiBib29sZWFuID0+IHtcclxuICAgICAgY29uc3QgZG9tID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7XHJcbiAgICAgIGlmICghZG9tLmxlbmd0aCkge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgICBsZXQgYXBwbGllZENvdW50ID0gMDtcclxuICAgICAgZG9tLmZvckVhY2goKGl0ZW0pID0+IHtcclxuICAgICAgICBjb25zdCB0YXJnZXQgPSBpdGVtIGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgIHRhcmdldC5zdHlsZS53aWR0aCAhPT0gdGhpcy5sYWJlbFdpZHRoIHx8XHJcbiAgICAgICAgICB0YXJnZXQuc3R5bGUudGV4dEFsaWduICE9PSB0aGlzLmxhYmVsQWxpZ25cclxuICAgICAgICApIHtcclxuICAgICAgICAgIHRhcmdldC5zdHlsZS53aWR0aCA9IHRoaXMubGFiZWxXaWR0aDtcclxuICAgICAgICAgIHRhcmdldC5zdHlsZS50ZXh0QWxpZ24gPSB0aGlzLmxhYmVsQWxpZ247XHJcbiAgICAgICAgICBhcHBsaWVkQ291bnQrKztcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXR1cm4gYXBwbGllZENvdW50ID4gMDtcclxuICAgIH07XHJcbiAgICBpZiAodGhpcy5sYWJlbE9ic2VydmVyc1tuYW1lXSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBsZXQgdGltZW91dDogYW55ID0gbnVsbDtcclxuICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IE11dGF0aW9uT2JzZXJ2ZXIoKCkgPT4ge1xyXG4gICAgICBjYW5jZWxBbmltYXRpb25GcmFtZSh0aW1lb3V0KTtcclxuICAgICAgdGltZW91dCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICBhcHBseVN0eWxlcygpO1xyXG4gICAgICAgIH0sIDApO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgY29uc3QgZm9ybUNvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZm9ybUNvbnRhaW5lclNlbGVjdG9yKTtcclxuICAgIG9ic2VydmVyLm9ic2VydmUoZm9ybUNvbnRhaW5lciB8fCBkb2N1bWVudC5ib2R5LCB7XHJcbiAgICAgIGNoaWxkTGlzdDogdHJ1ZSxcclxuICAgICAgc3VidHJlZTogdHJ1ZSxcclxuICAgICAgYXR0cmlidXRlczogdHJ1ZSxcclxuICAgIH0pO1xyXG4gICAgdGhpcy5sYWJlbE9ic2VydmVyc1tuYW1lXSA9IG9ic2VydmVyO1xyXG4gIH1cclxuXHJcbiAgLy8gPT09PT09PT09PT09PT09PT09PT0g56eB5pyJ5pa55rOVID09PT09PT09PT09PT09PT09PT09XHJcblxyXG4gIC8vIOiOt+WPliBGb3JtQXJyYXlcclxuICBwcml2YXRlIGdldEZvcm1BcnJheShmb3JtTmFtZTogc3RyaW5nLCBhcnJheU5hbWU6IHN0cmluZyk6IEZvcm1BcnJheSB8IG51bGwge1xyXG4gICAgY29uc3QgZm9ybUdyb3VwID0gdGhpcy5mb3JtU3RvcmVbZm9ybU5hbWVdO1xyXG4gICAgaWYgKCFmb3JtR3JvdXApIHtcclxuICAgICAgY29uc29sZS53YXJuKFxyXG4gICAgICAgIGBbQW50ZEZvcm1TZXJ2aWNlXSBnZXRGb3JtQXJyYXk6IGZvcm0gXCIke2Zvcm1OYW1lfVwiIG5vdCBmb3VuZC5gXHJcbiAgICAgICk7XHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGNvbnRyb2wgPSBmb3JtR3JvdXAuZ2V0KGFycmF5TmFtZSk7XHJcbiAgICBpZiAoIWNvbnRyb2wgfHwgIShjb250cm9sIGluc3RhbmNlb2YgRm9ybUFycmF5KSkge1xyXG4gICAgICBjb25zb2xlLndhcm4oXHJcbiAgICAgICAgYFtBbnRkRm9ybVNlcnZpY2VdIGdldEZvcm1BcnJheTogYXJyYXkgXCIke2FycmF5TmFtZX1cIiBub3QgZm91bmQgaW4gZm9ybSBcIiR7Zm9ybU5hbWV9XCIuYFxyXG4gICAgICApO1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gY29udHJvbCBhcyBGb3JtQXJyYXk7XHJcbiAgfVxyXG5cclxuICAvLyDliKTmlq3mmK/lkKbmmK8gRm9ybUFycmF5IOmFjee9rlxyXG4gIHByaXZhdGUgaXNGb3JtQXJyYXlDb25maWcoXHJcbiAgICBmaWVsZDogRmllbGRDb25maWcgfCBGb3JtQXJyYXlDb25maWdcclxuICApOiBmaWVsZCBpcyBGb3JtQXJyYXlDb25maWcge1xyXG4gICAgcmV0dXJuIChmaWVsZCBhcyBGb3JtQXJyYXlDb25maWcpLnR5cGUgPT09IFwiYXJyYXlcIjtcclxuICB9XHJcblxyXG4gIC8vIOS7jumFjee9ruWIm+W7uiBGb3JtQXJyYXlcclxuICBwcml2YXRlIGNyZWF0ZUZvcm1BcnJheUZyb21Db25maWcoXHJcbiAgICBmb3JtTmFtZTogc3RyaW5nLFxyXG4gICAgYXJyYXlOYW1lOiBzdHJpbmcsXHJcbiAgICBpdGVtQ29uZmlnOiBGb3JtQ29uZmlnLFxyXG4gICAgaW5pdGlhbEl0ZW1zOiBhbnlbXSxcclxuICAgIHVuaXF1ZUlkRmllbGQ/OiBzdHJpbmdcclxuICApOiBGb3JtQXJyYXkge1xyXG4gICAgY29uc3QgZm9ybUFycmF5ID0gdGhpcy5mYi5hcnJheShbXSk7XHJcblxyXG4gICAgaW5pdGlhbEl0ZW1zLmZvckVhY2goKGl0ZW0pID0+IHtcclxuICAgICAgY29uc3QgaXRlbUdyb3VwID0gdGhpcy5jcmVhdGVJdGVtRm9ybUdyb3VwKFxyXG4gICAgICAgIGl0ZW1Db25maWcsXHJcbiAgICAgICAgaXRlbSxcclxuICAgICAgICB1bmlxdWVJZEZpZWxkXHJcbiAgICAgICk7XHJcbiAgICAgIGZvcm1BcnJheS5wdXNoKGl0ZW1Hcm91cCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICByZXR1cm4gZm9ybUFycmF5O1xyXG4gIH1cclxuXHJcbiAgLy8g55Sf5oiQ5YaF6YOoSUTvvIjkvb/nlKjkuJrliqHllK/kuIDlrZfmrrXmiJbnlJ/miJDkuLTml7ZJRO+8iVxyXG4gIHByaXZhdGUgZ2VuZXJhdGVJbnRlcm5hbElkKGl0ZW1EYXRhOiBhbnksIHVuaXF1ZUlkRmllbGQ/OiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgLy8g5LyY5YWI5L2/55So5Lia5Yqh5ZSv5LiA5a2X5q61XHJcbiAgICBpZiAodW5pcXVlSWRGaWVsZCAmJiBpdGVtRGF0YT8uW3VuaXF1ZUlkRmllbGRdICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgY29uc3QgYnVzaW5lc3NJZCA9IGl0ZW1EYXRhW3VuaXF1ZUlkRmllbGRdO1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgYnVzaW5lc3NJZCAhPT0gbnVsbCAmJlxyXG4gICAgICAgIGJ1c2luZXNzSWQgIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgIGJ1c2luZXNzSWQgIT09IFwiXCJcclxuICAgICAgKSB7XHJcbiAgICAgICAgcmV0dXJuIGBidXNpbmVzcy0ke3VuaXF1ZUlkRmllbGR9LSR7YnVzaW5lc3NJZH1gO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8g5aaC5p6c5rKh5pyJ5Lia5YqhSUTvvIznlJ/miJDkuLTml7ZJRO+8iOeUqOS6juaWsOa3u+WKoOeahOmhue+8iVxyXG4gICAgcmV0dXJuIGB0ZW1wLSR7RGF0ZS5ub3coKX0tJHtNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDM2KS5zdWJzdHIoMiwgOSl9YDtcclxuICB9XHJcblxyXG4gIC8vIOWIm+W7uuWNleS4qumhueeahCBGb3JtR3JvdXBcclxuICBwcml2YXRlIGNyZWF0ZUl0ZW1Gb3JtR3JvdXAoXHJcbiAgICBpdGVtQ29uZmlnOiBGb3JtQ29uZmlnLFxyXG4gICAgaXRlbURhdGE6IGFueSxcclxuICAgIHVuaXF1ZUlkRmllbGQ/OiBzdHJpbmdcclxuICApOiBGb3JtR3JvdXAge1xyXG4gICAgY29uc3QgZ3JvdXBDb25maWc6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcclxuXHJcbiAgICAvLyDmt7vliqDlhoXpg6hJROWtl+autVxyXG4gICAgY29uc3QgaXRlbUlkID0gdGhpcy5nZW5lcmF0ZUludGVybmFsSWQoaXRlbURhdGEsIHVuaXF1ZUlkRmllbGQpO1xyXG4gICAgZ3JvdXBDb25maWdbdGhpcy5JTlRFUk5BTF9JRF9GSUVMRF0gPSBbXHJcbiAgICAgIHsgdmFsdWU6IGl0ZW1JZCwgZGlzYWJsZWQ6IHRydWUgfSxcclxuICAgICAgW10sXHJcbiAgICBdO1xyXG5cclxuICAgIC8vIOa3u+WKoOS4muWKoeWtl+autVxyXG4gICAgT2JqZWN0LmVudHJpZXMoaXRlbUNvbmZpZykuZm9yRWFjaCgoW2tleSwgZmllbGRdKSA9PiB7XHJcbiAgICAgIC8vIGl0ZW1Db25maWcg5Lit55qE5a2X5q615bqU6K+l5pivIEZpZWxkQ29uZmln77yM5LiN5bqU6K+l5YyF5ZCrIEZvcm1BcnJheUNvbmZpZ1xyXG4gICAgICBpZiAodGhpcy5pc0Zvcm1BcnJheUNvbmZpZyhmaWVsZCkpIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oXHJcbiAgICAgICAgICBgW0FudGRGb3JtU2VydmljZV0gY3JlYXRlSXRlbUZvcm1Hcm91cDogRm9ybUFycmF5Q29uZmlnIGlzIG5vdCBhbGxvd2VkIGluIGl0ZW1Db25maWcuIFNraXBwaW5nIGZpZWxkIFwiJHtrZXl9XCIuYFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCBmaWVsZENvbmZpZyA9IGZpZWxkIGFzIEZpZWxkQ29uZmlnO1xyXG4gICAgICBjb25zdCB2YWx1ZSA9XHJcbiAgICAgICAgaXRlbURhdGE/LltrZXldICE9PSB1bmRlZmluZWQgPyBpdGVtRGF0YVtrZXldIDogZmllbGRDb25maWcudmFsdWU7XHJcbiAgICAgIGdyb3VwQ29uZmlnW2tleV0gPSBbXHJcbiAgICAgICAgeyB2YWx1ZTogdmFsdWUsIGRpc2FibGVkOiBmaWVsZENvbmZpZy5kaXNhYmxlZCA/PyBmYWxzZSB9LFxyXG4gICAgICAgIGZpZWxkQ29uZmlnLnZhbGlkYXRvcnM/LigpID8/IFtdLFxyXG4gICAgICBdO1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gdGhpcy5mYi5ncm91cChncm91cENvbmZpZyk7XHJcbiAgfVxyXG5cclxuICAvLyDpgJrov4fkuJrliqHllK/kuIDlrZfmrrXmn6Xmib7lhoXpg6hJRFxyXG4gIHByaXZhdGUgZmluZEZvcm1BcnJheUl0ZW1JZEJ5QnVzaW5lc3NGaWVsZChcclxuICAgIGZvcm1OYW1lOiBzdHJpbmcsXHJcbiAgICBhcnJheU5hbWU6IHN0cmluZyxcclxuICAgIHVuaXF1ZUlkRmllbGQ6IHN0cmluZyxcclxuICAgIGJ1c2luZXNzSWRWYWx1ZTogYW55XHJcbiAgKTogc3RyaW5nIHwgbnVsbCB7XHJcbiAgICBjb25zdCBmb3JtQXJyYXkgPSB0aGlzLmdldEZvcm1BcnJheShmb3JtTmFtZSwgYXJyYXlOYW1lKTtcclxuICAgIGlmICghZm9ybUFycmF5KSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZvcm1BcnJheS5sZW5ndGg7IGkrKykge1xyXG4gICAgICBjb25zdCBpdGVtID0gZm9ybUFycmF5LmF0KGkpIGFzIEZvcm1Hcm91cDtcclxuICAgICAgY29uc3QgaXRlbVZhbHVlID0gaXRlbS5nZXRSYXdWYWx1ZSgpO1xyXG4gICAgICBjb25zdCBpbnRlcm5hbElkID0gaXRlbVZhbHVlW3RoaXMuSU5URVJOQUxfSURfRklFTERdO1xyXG5cclxuICAgICAgLy8g5qOA5p+l5YaF6YOoSUTmmK/lkKbljLnphY3kuJrliqFJRFxyXG4gICAgICBpZiAoaW50ZXJuYWxJZCAmJiBpbnRlcm5hbElkLnN0YXJ0c1dpdGgoYGJ1c2luZXNzLSR7dW5pcXVlSWRGaWVsZH0tYCkpIHtcclxuICAgICAgICBjb25zdCBpZEluSW50ZXJuYWxJZCA9IGludGVybmFsSWQucmVwbGFjZShcclxuICAgICAgICAgIGBidXNpbmVzcy0ke3VuaXF1ZUlkRmllbGR9LWAsXHJcbiAgICAgICAgICBcIlwiXHJcbiAgICAgICAgKTtcclxuICAgICAgICBpZiAoU3RyaW5nKGlkSW5JbnRlcm5hbElkKSA9PT0gU3RyaW5nKGJ1c2luZXNzSWRWYWx1ZSkpIHtcclxuICAgICAgICAgIHJldHVybiBpbnRlcm5hbElkO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLy8g5Lmf5qOA5p+l5b2T5YmN5Lia5Yqh5a2X5q615YC85piv5ZCm5Yy56YWN77yI5aSE55CG5Lia5YqhSUTmm7TmlrDnmoTmg4XlhrXvvIlcclxuICAgICAgaWYgKGl0ZW1WYWx1ZVt1bmlxdWVJZEZpZWxkXSA9PT0gYnVzaW5lc3NJZFZhbHVlKSB7XHJcbiAgICAgICAgcmV0dXJuIGludGVybmFsSWQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLy8g6YCa6L+H5YaF6YOoSUTmn6Xmib7poblcclxuICBwcml2YXRlIGZpbmRGb3JtQXJyYXlJdGVtQnlJZChcclxuICAgIGZvcm1OYW1lOiBzdHJpbmcsXHJcbiAgICBhcnJheU5hbWU6IHN0cmluZyxcclxuICAgIGl0ZW1JZDogc3RyaW5nXHJcbiAgKTogeyBpbmRleDogbnVtYmVyOyBmb3JtR3JvdXA6IEZvcm1Hcm91cCB9IHwgbnVsbCB7XHJcbiAgICBjb25zdCBmb3JtQXJyYXkgPSB0aGlzLmdldEZvcm1BcnJheShmb3JtTmFtZSwgYXJyYXlOYW1lKTtcclxuICAgIGlmICghZm9ybUFycmF5KSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZvcm1BcnJheS5sZW5ndGg7IGkrKykge1xyXG4gICAgICBjb25zdCBpdGVtID0gZm9ybUFycmF5LmF0KGkpIGFzIEZvcm1Hcm91cDtcclxuICAgICAgY29uc3QgaWQgPSBpdGVtLmdldCh0aGlzLklOVEVSTkFMX0lEX0ZJRUxEKT8udmFsdWU7XHJcbiAgICAgIGlmIChpZCA9PT0gaXRlbUlkKSB7XHJcbiAgICAgICAgcmV0dXJuIHsgaW5kZXg6IGksIGZvcm1Hcm91cDogaXRlbSB9O1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9XHJcblxyXG4gIC8vIOiOt+WPluaTjeS9nOexu+Wei++8iOW/hemhu+aYjuehruaMh+WumiBhY3Rpb24g5a2X5q6177yJXHJcbiAgcHJpdmF0ZSBnZXRPcGVyYXRpb25UeXBlKFxyXG4gICAgaXRlbURhdGE6IGFueVxyXG4gICk6IFwiY3JlYXRlXCIgfCBcInVwZGF0ZVwiIHwgXCJkZWxldGVcIiB8IG51bGwge1xyXG4gICAgaWYgKCFpdGVtRGF0YSB8fCB0eXBlb2YgaXRlbURhdGEgIT09IFwib2JqZWN0XCIpIHJldHVybiBudWxsO1xyXG5cclxuICAgIGNvbnN0IGFjdGlvbiA9IGl0ZW1EYXRhLmFjdGlvbjtcclxuICAgIGlmIChhY3Rpb24gPT09IFwiZGVsZXRlXCIgfHwgYWN0aW9uID09PSBcInVwZGF0ZVwiIHx8IGFjdGlvbiA9PT0gXCJjcmVhdGVcIikge1xyXG4gICAgICByZXR1cm4gYWN0aW9uO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLy8g6L+H5ruk5pON5L2c5a2X5q6177yIYWN0aW9uIOWtl+auteS4jeS/neWtmOWIsOihqOWNleS4re+8iVxyXG4gIHByaXZhdGUgZmlsdGVyT3BlcmF0aW9uRmllbGRzKGl0ZW1EYXRhOiBhbnkpOiBhbnkge1xyXG4gICAgaWYgKCFpdGVtRGF0YSB8fCB0eXBlb2YgaXRlbURhdGEgIT09IFwib2JqZWN0XCIpIHJldHVybiBpdGVtRGF0YTtcclxuXHJcbiAgICBjb25zdCBmaWx0ZXJlZDogYW55ID0ge307XHJcbiAgICBPYmplY3QuZW50cmllcyhpdGVtRGF0YSkuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XHJcbiAgICAgIGlmIChrZXkgIT09IFwiYWN0aW9uXCIpIHtcclxuICAgICAgICBmaWx0ZXJlZFtrZXldID0gdmFsdWU7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGZpbHRlcmVkO1xyXG4gIH1cclxuXHJcbiAgLy8g5aSE55CGIEZvcm1BcnJheSDnmoTmm7TmlrDvvIjnu5/kuIDmoLnmja4gYWN0aW9uIOWtl+auteWIpOaWreaTjeS9nOexu+Wei++8iVxyXG4gIHByaXZhdGUgcGF0Y2hGb3JtQXJyYXkoXHJcbiAgICBmb3JtTmFtZTogc3RyaW5nLFxyXG4gICAgYXJyYXlOYW1lOiBzdHJpbmcsXHJcbiAgICBuZXdWYWx1ZXM6IGFueVtdXHJcbiAgKTogdm9pZCB7XHJcbiAgICBjb25zdCBmb3JtQXJyYXkgPSB0aGlzLmdldEZvcm1BcnJheShmb3JtTmFtZSwgYXJyYXlOYW1lKTtcclxuICAgIGlmICghZm9ybUFycmF5KSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICBgW0FudGRGb3JtU2VydmljZV0gcGF0Y2hGb3JtQXJyYXk6IGFycmF5IFwiJHthcnJheU5hbWV9XCIgbm90IGZvdW5kIGluIGZvcm0gXCIke2Zvcm1OYW1lfVwiLmBcclxuICAgICAgKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMuZm9ybUFycmF5Q29uZmlnU3RvcmVbZm9ybU5hbWVdPy5bYXJyYXlOYW1lXTtcclxuICAgIGlmICghY29uZmlnKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICBgW0FudGRGb3JtU2VydmljZV0gcGF0Y2hGb3JtQXJyYXk6IGNvbmZpZyBub3QgZm91bmQgZm9yIGFycmF5IFwiJHthcnJheU5hbWV9XCIgaW4gZm9ybSBcIiR7Zm9ybU5hbWV9XCIuYFxyXG4gICAgICApO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgeyBpdGVtQ29uZmlnLCB1bmlxdWVJZEZpZWxkIH0gPSBjb25maWc7XHJcblxyXG4gICAgLy8g57uf5LiA5qC55o2uIGFjdGlvbiDlrZfmrrXliKTmlq3mk43kvZznsbvlnotcclxuICAgIGNvbnN0IGl0ZW1zVG9EZWxldGUgPSBuZXcgU2V0PHN0cmluZz4oKTtcclxuICAgIGNvbnN0IGl0ZW1zVG9VcGRhdGUgPSBuZXcgTWFwPHN0cmluZywgYW55PigpO1xyXG4gICAgY29uc3QgaXRlbXNUb0FkZDogYW55W10gPSBbXTtcclxuXHJcbiAgICBuZXdWYWx1ZXMuZm9yRWFjaCgoaXRlbURhdGEpID0+IHtcclxuICAgICAgaWYgKCFpdGVtRGF0YSB8fCB0eXBlb2YgaXRlbURhdGEgIT09IFwib2JqZWN0XCIpIHJldHVybjtcclxuXHJcbiAgICAgIGNvbnN0IG9wZXJhdGlvblR5cGUgPSB0aGlzLmdldE9wZXJhdGlvblR5cGUoaXRlbURhdGEpO1xyXG4gICAgICBpZiAoIW9wZXJhdGlvblR5cGUpIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oXHJcbiAgICAgICAgICBgW0FudGRGb3JtU2VydmljZV0gcGF0Y2hGb3JtQXJyYXk6IEl0ZW0gbWlzc2luZyByZXF1aXJlZCBcImFjdGlvblwiIGZpZWxkLiBTa2lwcGluZy5gLFxyXG4gICAgICAgICAgaXRlbURhdGFcclxuICAgICAgICApO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8g5Yig6Zmk5pON5L2cXHJcbiAgICAgIGlmIChvcGVyYXRpb25UeXBlID09PSBcImRlbGV0ZVwiKSB7XHJcbiAgICAgICAgaWYgKHVuaXF1ZUlkRmllbGQgJiYgaXRlbURhdGFbdW5pcXVlSWRGaWVsZF0gIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgY29uc3QgYnVzaW5lc3NJZCA9IGl0ZW1EYXRhW3VuaXF1ZUlkRmllbGRdO1xyXG4gICAgICAgICAgY29uc3QgaW50ZXJuYWxJZCA9IHRoaXMuZmluZEZvcm1BcnJheUl0ZW1JZEJ5QnVzaW5lc3NGaWVsZChcclxuICAgICAgICAgICAgZm9ybU5hbWUsXHJcbiAgICAgICAgICAgIGFycmF5TmFtZSxcclxuICAgICAgICAgICAgdW5pcXVlSWRGaWVsZCxcclxuICAgICAgICAgICAgYnVzaW5lc3NJZFxyXG4gICAgICAgICAgKTtcclxuICAgICAgICAgIGlmIChpbnRlcm5hbElkKSB7XHJcbiAgICAgICAgICAgIGl0ZW1zVG9EZWxldGUuYWRkKGludGVybmFsSWQpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc29sZS53YXJuKFxyXG4gICAgICAgICAgICAgIGBbQW50ZEZvcm1TZXJ2aWNlXSBwYXRjaEZvcm1BcnJheTogQ2Fubm90IGRlbGV0ZSBpdGVtIHdpdGggJHt1bmlxdWVJZEZpZWxkfT0ke2J1c2luZXNzSWR9LCBpdGVtIG5vdCBmb3VuZC5gXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICAgICAgYFtBbnRkRm9ybVNlcnZpY2VdIHBhdGNoRm9ybUFycmF5OiBDYW5ub3QgZGVsZXRlIGl0ZW0sIG1pc3NpbmcgcmVxdWlyZWQgdW5pcXVlSWRGaWVsZCBcIiR7dW5pcXVlSWRGaWVsZH1cIi5gXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIOabtOaWsOaTjeS9nFxyXG4gICAgICBpZiAob3BlcmF0aW9uVHlwZSA9PT0gXCJ1cGRhdGVcIikge1xyXG4gICAgICAgIGlmICh1bmlxdWVJZEZpZWxkICYmIGl0ZW1EYXRhW3VuaXF1ZUlkRmllbGRdICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgIGNvbnN0IGJ1c2luZXNzSWQgPSBpdGVtRGF0YVt1bmlxdWVJZEZpZWxkXTtcclxuICAgICAgICAgIGNvbnN0IGludGVybmFsSWQgPSB0aGlzLmZpbmRGb3JtQXJyYXlJdGVtSWRCeUJ1c2luZXNzRmllbGQoXHJcbiAgICAgICAgICAgIGZvcm1OYW1lLFxyXG4gICAgICAgICAgICBhcnJheU5hbWUsXHJcbiAgICAgICAgICAgIHVuaXF1ZUlkRmllbGQsXHJcbiAgICAgICAgICAgIGJ1c2luZXNzSWRcclxuICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgaWYgKGludGVybmFsSWQpIHtcclxuICAgICAgICAgICAgY29uc3QgZmlsdGVyZWREYXRhID0gdGhpcy5maWx0ZXJPcGVyYXRpb25GaWVsZHMoaXRlbURhdGEpO1xyXG4gICAgICAgICAgICBpdGVtc1RvVXBkYXRlLnNldChpbnRlcm5hbElkLCBmaWx0ZXJlZERhdGEpO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc29sZS53YXJuKFxyXG4gICAgICAgICAgICAgIGBbQW50ZEZvcm1TZXJ2aWNlXSBwYXRjaEZvcm1BcnJheTogQ2Fubm90IHVwZGF0ZSBpdGVtIHdpdGggJHt1bmlxdWVJZEZpZWxkfT0ke2J1c2luZXNzSWR9LCBpdGVtIG5vdCBmb3VuZC4gU2tpcHBpbmcuYFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zb2xlLndhcm4oXHJcbiAgICAgICAgICAgIGBbQW50ZEZvcm1TZXJ2aWNlXSBwYXRjaEZvcm1BcnJheTogQ2Fubm90IHVwZGF0ZSBpdGVtLCBtaXNzaW5nIHJlcXVpcmVkIHVuaXF1ZUlkRmllbGQgXCIke3VuaXF1ZUlkRmllbGR9XCIuIFNraXBwaW5nLmBcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8g5Yib5bu65pON5L2cXHJcbiAgICAgIGlmIChvcGVyYXRpb25UeXBlID09PSBcImNyZWF0ZVwiKSB7XHJcbiAgICAgICAgY29uc3QgZmlsdGVyZWREYXRhID0gdGhpcy5maWx0ZXJPcGVyYXRpb25GaWVsZHMoaXRlbURhdGEpO1xyXG4gICAgICAgIGl0ZW1zVG9BZGQucHVzaChmaWx0ZXJlZERhdGEpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyDmiafooYzliKDpmaTvvIjpnIDopoHku47lkI7lvoDliY3liKDpmaTvvIzpgb/lhY3ntKLlvJXlj5jljJbvvIlcclxuICAgIGNvbnN0IGRlbGV0ZUluZGljZXM6IG51bWJlcltdID0gW107XHJcbiAgICBpdGVtc1RvRGVsZXRlLmZvckVhY2goKGl0ZW1JZCkgPT4ge1xyXG4gICAgICBjb25zdCBmb3VuZCA9IHRoaXMuZmluZEZvcm1BcnJheUl0ZW1CeUlkKGZvcm1OYW1lLCBhcnJheU5hbWUsIGl0ZW1JZCk7XHJcbiAgICAgIGlmIChmb3VuZCkge1xyXG4gICAgICAgIGRlbGV0ZUluZGljZXMucHVzaChmb3VuZC5pbmRleCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgZGVsZXRlSW5kaWNlc1xyXG4gICAgICAuc29ydCgoYSwgYikgPT4gYiAtIGEpXHJcbiAgICAgIC5mb3JFYWNoKChpbmRleCkgPT4ge1xyXG4gICAgICAgIGZvcm1BcnJheS5yZW1vdmVBdChpbmRleCk7XHJcbiAgICAgIH0pO1xyXG5cclxuICAgIC8vIOaJp+ihjOabtOaWsFxyXG4gICAgaXRlbXNUb1VwZGF0ZS5mb3JFYWNoKChpdGVtRGF0YSwgaXRlbUlkKSA9PiB7XHJcbiAgICAgIGNvbnN0IGZvdW5kID0gdGhpcy5maW5kRm9ybUFycmF5SXRlbUJ5SWQoZm9ybU5hbWUsIGFycmF5TmFtZSwgaXRlbUlkKTtcclxuICAgICAgaWYgKGZvdW5kKSB7XHJcbiAgICAgICAgY29uc3QgeyBbdGhpcy5JTlRFUk5BTF9JRF9GSUVMRF06IF8sIC4uLmRhdGFUb1VwZGF0ZSB9ID0gaXRlbURhdGE7XHJcbiAgICAgICAgZm91bmQuZm9ybUdyb3VwLnBhdGNoVmFsdWUoZGF0YVRvVXBkYXRlKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8g5omn6KGM5re75YqgXHJcbiAgICBpdGVtc1RvQWRkLmZvckVhY2goKGl0ZW1EYXRhKSA9PiB7XHJcbiAgICAgIGNvbnN0IG5ld0l0ZW0gPSB0aGlzLmNyZWF0ZUl0ZW1Gb3JtR3JvdXAoXHJcbiAgICAgICAgaXRlbUNvbmZpZyxcclxuICAgICAgICBpdGVtRGF0YSxcclxuICAgICAgICB1bmlxdWVJZEZpZWxkXHJcbiAgICAgICk7XHJcbiAgICAgIGZvcm1BcnJheS5wdXNoKG5ld0l0ZW0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyDov4fmu6TlhoXpg6jlrZfmrrXvvIjpgJLlvZLlpITnkIblr7nosaHlkozmlbDnu4TvvIlcclxuICBwcml2YXRlIGV4Y2x1ZGVJbnRlcm5hbEZpZWxkcyh2YWx1ZTogYW55KTogYW55IHtcclxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcclxuICAgICAgcmV0dXJuIHZhbHVlLm1hcCgoaXRlbSkgPT4gdGhpcy5leGNsdWRlSW50ZXJuYWxGaWVsZHMoaXRlbSkpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIpIHtcclxuICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZpbHRlcmVkOiBhbnkgPSB7fTtcclxuICAgIE9iamVjdC5lbnRyaWVzKHZhbHVlKS5mb3JFYWNoKChba2V5LCB2YWxdKSA9PiB7XHJcbiAgICAgIC8vIOi/h+a7pOS7pSBfXyDlvIDlpLTnmoTlhoXpg6jlrZfmrrXlkowgYWN0aW9uIOWtl+autVxyXG4gICAgICBpZiAoIWtleS5zdGFydHNXaXRoKFwiX19cIikgJiYga2V5ICE9PSBcImFjdGlvblwiKSB7XHJcbiAgICAgICAgZmlsdGVyZWRba2V5XSA9IHRoaXMuZXhjbHVkZUludGVybmFsRmllbGRzKHZhbCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGZpbHRlcmVkO1xyXG4gIH1cclxuXHJcbiAgLy8g6K6+572u5YC85Y+Y5pu06K6i6ZiFXHJcbiAgcHJpdmF0ZSBzZXR1cFZhbHVlQ2hhbmdlU3Vic2NyaXB0aW9uPFQ+KFxyXG4gICAgdGFyZ2V0OiB7IHZhbHVlQ2hhbmdlczogYW55OyB2YWx1ZTogYW55IH0sXHJcbiAgICBoYW5kbGVyOiAodmFsdWU6IFQpID0+IHZvaWQsXHJcbiAgICBvcHRpb25zPzogV2F0Y2hPcHRpb25zXHJcbiAgKTogU3Vic2NyaXB0aW9uIHtcclxuICAgIGxldCB2YWx1ZUNoYW5nZXMkID0gdGFyZ2V0LnZhbHVlQ2hhbmdlcztcclxuXHJcbiAgICBpZiAob3B0aW9ucz8uZGVib3VuY2UgIT0gbnVsbCkge1xyXG4gICAgICB2YWx1ZUNoYW5nZXMkID0gdmFsdWVDaGFuZ2VzJC5waXBlKGRlYm91bmNlVGltZShvcHRpb25zLmRlYm91bmNlKSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG9wdGlvbnM/LmRpc3RpbmN0VW50aWxDaGFuZ2VkICE9PSBmYWxzZSkge1xyXG4gICAgICB2YWx1ZUNoYW5nZXMkID0gdmFsdWVDaGFuZ2VzJC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCkpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChvcHRpb25zPy5lbWl0SW5pdGlhbCkge1xyXG4gICAgICBoYW5kbGVyKHRhcmdldC52YWx1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHZhbHVlQ2hhbmdlcyQuc3Vic2NyaWJlKGhhbmRsZXIpO1xyXG4gIH1cclxufSJdfQ==
|