@cqa-lib/cqa-ui 1.1.194 → 1.1.196
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/esm2020/lib/step-builder/step-builder-ai-agent/step-builder-ai-agent.component.mjs +87 -4
- package/esm2020/lib/step-builder/step-builder-database/step-builder-database.component.mjs +531 -13
- package/esm2020/lib/ui-kit.module.mjs +9 -1
- package/fesm2015/cqa-lib-cqa-ui.mjs +640 -35
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +638 -35
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/step-builder/step-builder-ai-agent/step-builder-ai-agent.component.d.ts +19 -3
- package/lib/step-builder/step-builder-database/step-builder-database.component.d.ts +105 -5
- package/lib/ui-kit.module.d.ts +7 -5
- package/package.json +1 -1
- package/styles.css +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
-
import { Validators } from '@angular/forms';
|
|
1
|
+
import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
|
|
2
|
+
import { FormGroup, Validators } from '@angular/forms';
|
|
3
3
|
import * as i0 from "@angular/core";
|
|
4
4
|
import * as i1 from "@angular/forms";
|
|
5
5
|
import * as i2 from "../../dynamic-select/dynamic-select-field.component";
|
|
@@ -7,10 +7,19 @@ import * as i3 from "../../button/button.component";
|
|
|
7
7
|
import * as i4 from "../../badge/badge.component";
|
|
8
8
|
import * as i5 from "../../custom-textarea/custom-textarea.component";
|
|
9
9
|
import * as i6 from "../../custom-input/custom-input.component";
|
|
10
|
-
import * as i7 from "@angular/
|
|
10
|
+
import * as i7 from "@angular/material/button";
|
|
11
|
+
import * as i8 from "@angular/material/icon";
|
|
12
|
+
import * as i9 from "@angular/material/table";
|
|
13
|
+
import * as i10 from "@angular/material/form-field";
|
|
14
|
+
import * as i11 from "@angular/material/select";
|
|
15
|
+
import * as i12 from "@angular/material/core";
|
|
16
|
+
import * as i13 from "@angular/common";
|
|
17
|
+
import * as i14 from "@angular/material/input";
|
|
18
|
+
import * as i15 from "@angular/material/tooltip";
|
|
11
19
|
export class StepBuilderDatabaseComponent {
|
|
12
|
-
constructor(fb) {
|
|
20
|
+
constructor(fb, cdr) {
|
|
13
21
|
this.fb = fb;
|
|
22
|
+
this.cdr = cdr;
|
|
14
23
|
/** Options for DB environment dropdown */
|
|
15
24
|
this.dbEnvironmentOptions = [];
|
|
16
25
|
/** Initial queries list */
|
|
@@ -29,8 +38,67 @@ export class StepBuilderDatabaseComponent {
|
|
|
29
38
|
this.addQuery = new EventEmitter();
|
|
30
39
|
/** Emit when query is deleted */
|
|
31
40
|
this.deleteQuery = new EventEmitter();
|
|
41
|
+
/** Emit when assertion data changes for a query */
|
|
42
|
+
this.assertionDataChange = new EventEmitter();
|
|
43
|
+
/** Emit when selected query index changes */
|
|
44
|
+
this.selectedQueryIndexChange = new EventEmitter();
|
|
45
|
+
/** Emit when active tab changes */
|
|
46
|
+
this.activeTabChange = new EventEmitter();
|
|
32
47
|
this.selectedTab = 'output';
|
|
33
48
|
this.selectedQueryIndex = 0;
|
|
49
|
+
// Assertions form management - one form per query
|
|
50
|
+
this.assertionsForms = new Map();
|
|
51
|
+
this.displayedColumns = ['jsonPath', 'verificationType', 'expectedType', 'expectedValue', 'actions'];
|
|
52
|
+
this.defaultExpectedType = 'string';
|
|
53
|
+
this.formSubscriptions = new Map();
|
|
54
|
+
/**
|
|
55
|
+
* Expected value validator
|
|
56
|
+
*/
|
|
57
|
+
this.expectedValueValidator = (control) => {
|
|
58
|
+
const expectedType = control.parent?.get('expectedType')?.value;
|
|
59
|
+
if (!expectedType || expectedType === 'null')
|
|
60
|
+
return null;
|
|
61
|
+
const value = control.value;
|
|
62
|
+
if (!value && value !== 0 && value !== false)
|
|
63
|
+
return null;
|
|
64
|
+
if (expectedType === 'number') {
|
|
65
|
+
if (isNaN(Number(value))) {
|
|
66
|
+
return { invalidType: true, message: 'Invalid number value' };
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (expectedType === 'boolean') {
|
|
70
|
+
if (value !== 'true' && value !== 'false' && value !== true && value !== false) {
|
|
71
|
+
return { invalidType: true, message: 'Invalid boolean value' };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else if (expectedType === 'array') {
|
|
75
|
+
if (typeof value === 'string' && value.trim()) {
|
|
76
|
+
try {
|
|
77
|
+
const parsed = JSON.parse(value);
|
|
78
|
+
if (!Array.isArray(parsed)) {
|
|
79
|
+
return { invalidType: true, message: 'Value must be a valid JSON array' };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
return { invalidType: true, message: 'Invalid Array value - must be valid JSON' };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (expectedType === 'object') {
|
|
88
|
+
if (typeof value === 'string' && value.trim() && value.trim() !== '{}') {
|
|
89
|
+
try {
|
|
90
|
+
const parsed = JSON.parse(value);
|
|
91
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
92
|
+
return { invalidType: true, message: 'Value must be a valid JSON object' };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
return { invalidType: true, message: 'Invalid Object value - must be valid JSON' };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
};
|
|
34
102
|
this.databaseForm = this.fb.group({
|
|
35
103
|
dbEnvironment: ['', Validators.required],
|
|
36
104
|
queries: this.fb.array([])
|
|
@@ -46,9 +114,29 @@ export class StepBuilderDatabaseComponent {
|
|
|
46
114
|
while (queriesArray.length !== 0) {
|
|
47
115
|
queriesArray.removeAt(0);
|
|
48
116
|
}
|
|
49
|
-
|
|
117
|
+
// Clear old assertions forms
|
|
118
|
+
this.assertionsForms.forEach((form, index) => {
|
|
119
|
+
if (this.formSubscriptions.has(index)) {
|
|
120
|
+
this.formSubscriptions.get(index).unsubscribe();
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
this.assertionsForms.clear();
|
|
124
|
+
this.formSubscriptions.clear();
|
|
125
|
+
// Rebuild queries and assertions forms
|
|
126
|
+
this.queries.forEach((query, index) => {
|
|
127
|
+
// Ensure assertion data is initialized
|
|
128
|
+
if (!query.assertionData) {
|
|
129
|
+
query.assertionData = [];
|
|
130
|
+
}
|
|
50
131
|
this.addQueryToForm(query);
|
|
132
|
+
// Initialize assertions form for each query
|
|
133
|
+
this.ensureAssertionDataInitialized(index);
|
|
51
134
|
});
|
|
135
|
+
// Ensure selected query index is valid
|
|
136
|
+
if (this.selectedQueryIndex >= this.queries.length) {
|
|
137
|
+
this.selectedQueryIndex = Math.max(0, this.queries.length - 1);
|
|
138
|
+
}
|
|
139
|
+
this.cdr.detectChanges();
|
|
52
140
|
}
|
|
53
141
|
if (changes['initialDbEnvironment'] && changes['initialDbEnvironment'].currentValue) {
|
|
54
142
|
this.databaseForm.patchValue({ dbEnvironment: changes['initialDbEnvironment'].currentValue });
|
|
@@ -65,9 +153,16 @@ export class StepBuilderDatabaseComponent {
|
|
|
65
153
|
}
|
|
66
154
|
else {
|
|
67
155
|
this.queries.forEach((query, index) => {
|
|
156
|
+
// Ensure assertion data is initialized
|
|
157
|
+
if (!query.assertionData) {
|
|
158
|
+
query.assertionData = [];
|
|
159
|
+
}
|
|
68
160
|
this.addQueryToForm(query);
|
|
161
|
+
// Initialize assertions form for each query
|
|
162
|
+
this.ensureAssertionDataInitialized(index);
|
|
69
163
|
if (index === 0) {
|
|
70
164
|
this.selectedQueryIndex = 0;
|
|
165
|
+
this.selectedQueryIndexChange.emit(0);
|
|
71
166
|
}
|
|
72
167
|
});
|
|
73
168
|
}
|
|
@@ -80,12 +175,18 @@ export class StepBuilderDatabaseComponent {
|
|
|
80
175
|
id: `query_${Date.now()}`,
|
|
81
176
|
query: '',
|
|
82
177
|
variable: '',
|
|
83
|
-
status: 'pending'
|
|
178
|
+
status: 'pending',
|
|
179
|
+
assertionData: [] // Initialize with empty assertion data
|
|
84
180
|
};
|
|
85
181
|
this.queries.push(newQuery);
|
|
86
182
|
this.addQueryToForm(newQuery);
|
|
87
|
-
|
|
183
|
+
const newIndex = this.queries.length - 1;
|
|
184
|
+
this.selectedQueryIndex = newIndex;
|
|
185
|
+
// Initialize assertions form for the new query
|
|
186
|
+
this.ensureAssertionDataInitialized(newIndex);
|
|
187
|
+
this.selectedQueryIndexChange.emit(this.selectedQueryIndex);
|
|
88
188
|
this.addQuery.emit();
|
|
189
|
+
this.cdr.detectChanges();
|
|
89
190
|
}
|
|
90
191
|
addQueryToForm(query) {
|
|
91
192
|
const queryGroup = this.fb.group({
|
|
@@ -98,12 +199,44 @@ export class StepBuilderDatabaseComponent {
|
|
|
98
199
|
deleteQueryById(queryId) {
|
|
99
200
|
const index = this.queries.findIndex(q => q.id === queryId);
|
|
100
201
|
if (index !== -1) {
|
|
202
|
+
// Clean up assertions form and subscription for this query
|
|
203
|
+
if (this.formSubscriptions.has(index)) {
|
|
204
|
+
this.formSubscriptions.get(index).unsubscribe();
|
|
205
|
+
this.formSubscriptions.delete(index);
|
|
206
|
+
}
|
|
207
|
+
this.assertionsForms.delete(index);
|
|
208
|
+
// Reindex remaining forms and subscriptions
|
|
209
|
+
const formsToReindex = new Map();
|
|
210
|
+
const subscriptionsToReindex = new Map();
|
|
211
|
+
this.assertionsForms.forEach((form, oldIndex) => {
|
|
212
|
+
if (oldIndex > index) {
|
|
213
|
+
formsToReindex.set(oldIndex - 1, form);
|
|
214
|
+
}
|
|
215
|
+
else if (oldIndex < index) {
|
|
216
|
+
formsToReindex.set(oldIndex, form);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
this.formSubscriptions.forEach((sub, oldIndex) => {
|
|
220
|
+
if (oldIndex > index) {
|
|
221
|
+
subscriptionsToReindex.set(oldIndex - 1, sub);
|
|
222
|
+
}
|
|
223
|
+
else if (oldIndex < index) {
|
|
224
|
+
subscriptionsToReindex.set(oldIndex, sub);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
this.assertionsForms = formsToReindex;
|
|
228
|
+
this.formSubscriptions = subscriptionsToReindex;
|
|
101
229
|
this.queries.splice(index, 1);
|
|
102
230
|
this.queriesFormArray.removeAt(index);
|
|
103
231
|
if (this.selectedQueryIndex >= this.queries.length) {
|
|
104
232
|
this.selectedQueryIndex = Math.max(0, this.queries.length - 1);
|
|
233
|
+
// Ensure assertions form is initialized for the new selected query
|
|
234
|
+
if (this.selectedQueryIndex >= 0) {
|
|
235
|
+
this.ensureAssertionDataInitialized(this.selectedQueryIndex);
|
|
236
|
+
}
|
|
105
237
|
}
|
|
106
238
|
this.deleteQuery.emit(queryId);
|
|
239
|
+
this.cdr.detectChanges();
|
|
107
240
|
}
|
|
108
241
|
}
|
|
109
242
|
getDbEnvironmentConfig() {
|
|
@@ -145,10 +278,33 @@ export class StepBuilderDatabaseComponent {
|
|
|
145
278
|
}
|
|
146
279
|
}
|
|
147
280
|
onSelectQuery(index) {
|
|
281
|
+
// Ensure assertion data is initialized for the selected query
|
|
282
|
+
this.ensureAssertionDataInitialized(index);
|
|
148
283
|
this.selectedQueryIndex = index;
|
|
284
|
+
this.selectedQueryIndexChange.emit(index);
|
|
285
|
+
// Trigger change detection to ensure assertions form is displayed
|
|
286
|
+
this.cdr.detectChanges();
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Get the currently selected query index
|
|
290
|
+
*/
|
|
291
|
+
getSelectedQueryIndex() {
|
|
292
|
+
return this.selectedQueryIndex;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Get the currently active tab
|
|
296
|
+
*/
|
|
297
|
+
getActiveTab() {
|
|
298
|
+
return this.selectedTab;
|
|
149
299
|
}
|
|
150
300
|
onTabChange(tab) {
|
|
151
301
|
this.selectedTab = tab;
|
|
302
|
+
this.activeTabChange.emit(tab);
|
|
303
|
+
// Ensure assertions form is initialized when switching to verification tab
|
|
304
|
+
if (tab === 'verification') {
|
|
305
|
+
this.ensureAssertionDataInitialized(this.selectedQueryIndex);
|
|
306
|
+
this.cdr.detectChanges();
|
|
307
|
+
}
|
|
152
308
|
}
|
|
153
309
|
onCopyResults() {
|
|
154
310
|
// Copy query results to clipboard
|
|
@@ -173,7 +329,8 @@ export class StepBuilderDatabaseComponent {
|
|
|
173
329
|
id: query.id,
|
|
174
330
|
query: queryFormGroup.get('query')?.value || '',
|
|
175
331
|
variable: queryFormGroup.get('variable')?.value || '',
|
|
176
|
-
status: query.status
|
|
332
|
+
status: query.status,
|
|
333
|
+
assertionData: query.assertionData || [] // Include assertion data
|
|
177
334
|
};
|
|
178
335
|
})
|
|
179
336
|
};
|
|
@@ -186,13 +343,365 @@ export class StepBuilderDatabaseComponent {
|
|
|
186
343
|
}
|
|
187
344
|
return Object.keys(this.queryResults[0]);
|
|
188
345
|
}
|
|
346
|
+
/**
|
|
347
|
+
* Get assertion data for a specific query
|
|
348
|
+
*/
|
|
349
|
+
getAssertionDataForQuery(queryIndex) {
|
|
350
|
+
if (this.queries[queryIndex] && this.queries[queryIndex].assertionData) {
|
|
351
|
+
return this.queries[queryIndex].assertionData;
|
|
352
|
+
}
|
|
353
|
+
return [];
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Handle assertion data change from external component
|
|
357
|
+
*/
|
|
358
|
+
onAssertionDataChange(assertionData, queryIndex) {
|
|
359
|
+
if (this.queries[queryIndex]) {
|
|
360
|
+
// Create a deep copy to ensure each query has its own data
|
|
361
|
+
if (assertionData && assertionData.length > 0) {
|
|
362
|
+
this.queries[queryIndex].assertionData = assertionData.map((item) => {
|
|
363
|
+
// Ensure expectedValue is properly formatted
|
|
364
|
+
const expectedType = item.expectedType || 'string';
|
|
365
|
+
let expectedValue = item.expectedValue;
|
|
366
|
+
// For object/array types, ensure expectedValue is an object/array, not a string
|
|
367
|
+
if (expectedType === 'object' && typeof expectedValue === 'string' && expectedValue.trim()) {
|
|
368
|
+
try {
|
|
369
|
+
expectedValue = JSON.parse(expectedValue);
|
|
370
|
+
}
|
|
371
|
+
catch (e) {
|
|
372
|
+
// If parsing fails, keep as string
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
else if (expectedType === 'array' && typeof expectedValue === 'string' && expectedValue.trim()) {
|
|
376
|
+
try {
|
|
377
|
+
expectedValue = JSON.parse(expectedValue);
|
|
378
|
+
}
|
|
379
|
+
catch (e) {
|
|
380
|
+
// If parsing fails, keep as string
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
else if (expectedType === 'number' && typeof expectedValue === 'string') {
|
|
384
|
+
expectedValue = expectedValue !== '' ? Number(expectedValue) : null;
|
|
385
|
+
}
|
|
386
|
+
else if (expectedType === 'boolean') {
|
|
387
|
+
if (expectedValue === 'true' || expectedValue === true) {
|
|
388
|
+
expectedValue = true;
|
|
389
|
+
}
|
|
390
|
+
else if (expectedValue === 'false' || expectedValue === false) {
|
|
391
|
+
expectedValue = false;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return {
|
|
395
|
+
jsonPath: item.jsonPath || '',
|
|
396
|
+
verificationType: item.verificationType || 'equals',
|
|
397
|
+
expectedType: expectedType,
|
|
398
|
+
expectedValue: expectedValue
|
|
399
|
+
};
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
this.queries[queryIndex].assertionData = [];
|
|
404
|
+
}
|
|
405
|
+
// Emit the change to parent
|
|
406
|
+
this.assertionDataChange.emit({
|
|
407
|
+
queryIndex: queryIndex,
|
|
408
|
+
assertionData: this.queries[queryIndex].assertionData || []
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Initialize assertion data for a query if it doesn't exist
|
|
414
|
+
*/
|
|
415
|
+
ensureAssertionDataInitialized(queryIndex) {
|
|
416
|
+
if (this.queries[queryIndex] && !this.queries[queryIndex].assertionData) {
|
|
417
|
+
this.queries[queryIndex].assertionData = [];
|
|
418
|
+
}
|
|
419
|
+
// Initialize assertions form for this query if it doesn't exist
|
|
420
|
+
if (!this.assertionsForms.has(queryIndex)) {
|
|
421
|
+
this.initializeAssertionsForm(queryIndex);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Initialize assertions form for a specific query
|
|
426
|
+
*/
|
|
427
|
+
initializeAssertionsForm(queryIndex) {
|
|
428
|
+
const assertionsArray = this.fb.array([]);
|
|
429
|
+
const assertionsForm = this.fb.group({
|
|
430
|
+
assertions: assertionsArray
|
|
431
|
+
});
|
|
432
|
+
this.assertionsForms.set(queryIndex, assertionsForm);
|
|
433
|
+
// Load existing assertions if they exist
|
|
434
|
+
const query = this.queries[queryIndex];
|
|
435
|
+
if (query && query.assertionData && query.assertionData.length > 0) {
|
|
436
|
+
this.loadAssertionsForQuery(queryIndex);
|
|
437
|
+
}
|
|
438
|
+
// Subscribe to form changes
|
|
439
|
+
this.subscribeToAssertionsFormChanges(queryIndex);
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Get assertions form for current query
|
|
443
|
+
*/
|
|
444
|
+
getCurrentAssertionsForm() {
|
|
445
|
+
if (this.assertionsForms.has(this.selectedQueryIndex)) {
|
|
446
|
+
return this.assertionsForms.get(this.selectedQueryIndex);
|
|
447
|
+
}
|
|
448
|
+
// Initialize if it doesn't exist
|
|
449
|
+
this.ensureAssertionDataInitialized(this.selectedQueryIndex);
|
|
450
|
+
return this.assertionsForms.get(this.selectedQueryIndex) || null;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Get assertions form array for current query
|
|
454
|
+
*/
|
|
455
|
+
getAssertionsFormArray() {
|
|
456
|
+
const form = this.getCurrentAssertionsForm();
|
|
457
|
+
if (form) {
|
|
458
|
+
return form.get('assertions');
|
|
459
|
+
}
|
|
460
|
+
return this.fb.array([]);
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Load assertions into form for a specific query
|
|
464
|
+
*/
|
|
465
|
+
loadAssertionsForQuery(queryIndex) {
|
|
466
|
+
const form = this.assertionsForms.get(queryIndex);
|
|
467
|
+
if (!form)
|
|
468
|
+
return;
|
|
469
|
+
const formArray = form.get('assertions');
|
|
470
|
+
const query = this.queries[queryIndex];
|
|
471
|
+
if (!query || !query.assertionData)
|
|
472
|
+
return;
|
|
473
|
+
// Clear existing form array
|
|
474
|
+
while (formArray.length !== 0) {
|
|
475
|
+
formArray.removeAt(0);
|
|
476
|
+
}
|
|
477
|
+
// Load assertions
|
|
478
|
+
query.assertionData.forEach((assertion) => {
|
|
479
|
+
const expectedType = assertion.expectedType || 'string';
|
|
480
|
+
let expectedValue = '';
|
|
481
|
+
if (expectedType === 'null') {
|
|
482
|
+
expectedValue = null;
|
|
483
|
+
}
|
|
484
|
+
else if (expectedType === 'object' || expectedType === 'array') {
|
|
485
|
+
if (typeof assertion.expectedValue === 'object' && assertion.expectedValue !== null) {
|
|
486
|
+
expectedValue = JSON.stringify(assertion.expectedValue, null, 2);
|
|
487
|
+
}
|
|
488
|
+
else {
|
|
489
|
+
expectedValue = assertion.expectedValue || '';
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
else if (expectedType === 'boolean') {
|
|
493
|
+
expectedValue = (assertion.expectedValue === true || assertion.expectedValue === 'true') ? 'true' : 'false';
|
|
494
|
+
}
|
|
495
|
+
else if (expectedType === 'number') {
|
|
496
|
+
expectedValue = assertion.expectedValue !== null && assertion.expectedValue !== undefined
|
|
497
|
+
? String(assertion.expectedValue)
|
|
498
|
+
: '';
|
|
499
|
+
}
|
|
500
|
+
else {
|
|
501
|
+
expectedValue = assertion.expectedValue !== null && assertion.expectedValue !== undefined
|
|
502
|
+
? String(assertion.expectedValue)
|
|
503
|
+
: '';
|
|
504
|
+
}
|
|
505
|
+
const formGroup = this.fb.group({
|
|
506
|
+
jsonPath: [assertion.jsonPath || '', Validators.required],
|
|
507
|
+
verificationType: [assertion.verificationType || 'equals'],
|
|
508
|
+
expectedType: [expectedType],
|
|
509
|
+
expectedValue: [expectedValue, [Validators.required, this.expectedValueValidator]]
|
|
510
|
+
});
|
|
511
|
+
formArray.push(formGroup);
|
|
512
|
+
});
|
|
513
|
+
this.cdr.detectChanges();
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Subscribe to assertions form changes
|
|
517
|
+
*/
|
|
518
|
+
subscribeToAssertionsFormChanges(queryIndex) {
|
|
519
|
+
const form = this.assertionsForms.get(queryIndex);
|
|
520
|
+
if (!form)
|
|
521
|
+
return;
|
|
522
|
+
// Unsubscribe from previous subscription if exists
|
|
523
|
+
if (this.formSubscriptions.has(queryIndex)) {
|
|
524
|
+
this.formSubscriptions.get(queryIndex).unsubscribe();
|
|
525
|
+
}
|
|
526
|
+
const formArray = form.get('assertions');
|
|
527
|
+
const subscription = formArray.valueChanges.subscribe(() => {
|
|
528
|
+
this.emitAssertionDataForQuery(queryIndex);
|
|
529
|
+
});
|
|
530
|
+
this.formSubscriptions.set(queryIndex, subscription);
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Emit assertion data for a specific query
|
|
534
|
+
*/
|
|
535
|
+
emitAssertionDataForQuery(queryIndex) {
|
|
536
|
+
const form = this.assertionsForms.get(queryIndex);
|
|
537
|
+
if (!form)
|
|
538
|
+
return;
|
|
539
|
+
const formArray = form.get('assertions');
|
|
540
|
+
const assertionData = formArray.controls.map((control) => {
|
|
541
|
+
if (!(control instanceof FormGroup))
|
|
542
|
+
return null;
|
|
543
|
+
const value = control.value;
|
|
544
|
+
const expectedType = value.expectedType || 'string';
|
|
545
|
+
let expectedValue = value.expectedValue;
|
|
546
|
+
// Parse expectedValue based on type
|
|
547
|
+
if (expectedType === 'null') {
|
|
548
|
+
expectedValue = null;
|
|
549
|
+
}
|
|
550
|
+
else if (expectedType === 'number') {
|
|
551
|
+
expectedValue = expectedValue !== '' ? Number(expectedValue) : null;
|
|
552
|
+
}
|
|
553
|
+
else if (expectedType === 'boolean') {
|
|
554
|
+
expectedValue = (expectedValue === 'true' || expectedValue === true);
|
|
555
|
+
}
|
|
556
|
+
else if (expectedType === 'array' || expectedType === 'object') {
|
|
557
|
+
if (typeof expectedValue === 'string' && expectedValue.trim()) {
|
|
558
|
+
try {
|
|
559
|
+
expectedValue = JSON.parse(expectedValue);
|
|
560
|
+
}
|
|
561
|
+
catch (e) {
|
|
562
|
+
// Keep as string if parsing fails
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
expectedValue = String(expectedValue || '');
|
|
568
|
+
}
|
|
569
|
+
return {
|
|
570
|
+
jsonPath: (value.jsonPath || '').trim(),
|
|
571
|
+
verificationType: value.verificationType || 'equals',
|
|
572
|
+
expectedType: expectedType,
|
|
573
|
+
expectedValue: expectedValue
|
|
574
|
+
};
|
|
575
|
+
}).filter(item => item !== null && item.jsonPath);
|
|
576
|
+
// Update query's assertion data
|
|
577
|
+
if (this.queries[queryIndex]) {
|
|
578
|
+
this.queries[queryIndex].assertionData = assertionData;
|
|
579
|
+
}
|
|
580
|
+
// Emit to parent
|
|
581
|
+
this.assertionDataChange.emit({
|
|
582
|
+
queryIndex: queryIndex,
|
|
583
|
+
assertionData: assertionData
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Add a new assertion
|
|
588
|
+
*/
|
|
589
|
+
addAssertion() {
|
|
590
|
+
const formArray = this.getAssertionsFormArray();
|
|
591
|
+
const formGroup = this.fb.group({
|
|
592
|
+
jsonPath: ['', Validators.required],
|
|
593
|
+
verificationType: ['equals'],
|
|
594
|
+
expectedType: [this.defaultExpectedType],
|
|
595
|
+
expectedValue: ['', [Validators.required, this.expectedValueValidator]]
|
|
596
|
+
});
|
|
597
|
+
formArray.push(formGroup);
|
|
598
|
+
this.cdr.detectChanges();
|
|
599
|
+
if (this.assertionsTable) {
|
|
600
|
+
this.assertionsTable.renderRows();
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Remove an assertion
|
|
605
|
+
*/
|
|
606
|
+
removeAssertion(index) {
|
|
607
|
+
const formArray = this.getAssertionsFormArray();
|
|
608
|
+
formArray.removeAt(index);
|
|
609
|
+
this.cdr.detectChanges();
|
|
610
|
+
if (this.assertionsTable) {
|
|
611
|
+
this.assertionsTable.renderRows();
|
|
612
|
+
}
|
|
613
|
+
this.emitAssertionDataForQuery(this.selectedQueryIndex);
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* Get form control at specific index
|
|
617
|
+
*/
|
|
618
|
+
getFormControlAt(index, controlName) {
|
|
619
|
+
const formArray = this.getAssertionsFormArray();
|
|
620
|
+
if (index < 0 || index >= formArray.length)
|
|
621
|
+
return null;
|
|
622
|
+
const formGroup = formArray.at(index);
|
|
623
|
+
return formGroup?.get(controlName) || null;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Get expected type for an assertion
|
|
627
|
+
*/
|
|
628
|
+
getExpectedType(index) {
|
|
629
|
+
const formArray = this.getAssertionsFormArray();
|
|
630
|
+
if (index < 0 || index >= formArray.length)
|
|
631
|
+
return 'string';
|
|
632
|
+
const formGroup = formArray.at(index);
|
|
633
|
+
return formGroup?.get('expectedType')?.value || 'string';
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Get expected value placeholder
|
|
637
|
+
*/
|
|
638
|
+
getExpectedValuePlaceholder(index) {
|
|
639
|
+
const expectedType = this.getExpectedType(index);
|
|
640
|
+
switch (expectedType) {
|
|
641
|
+
case 'string': return 'Expected Value in String';
|
|
642
|
+
case 'array': return 'Expected Value in Array (JSON format)';
|
|
643
|
+
case 'object': return 'Expected Value in Object (JSON format)';
|
|
644
|
+
case 'null': return 'No value required for null type';
|
|
645
|
+
default: return 'Expected Value';
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Handle expected type change
|
|
650
|
+
*/
|
|
651
|
+
onExpectedTypeChange(index, value) {
|
|
652
|
+
const formArray = this.getAssertionsFormArray();
|
|
653
|
+
if (index < 0 || index >= formArray.length)
|
|
654
|
+
return;
|
|
655
|
+
const formGroup = formArray.at(index);
|
|
656
|
+
const expectedValueControl = formGroup.get('expectedValue');
|
|
657
|
+
if (!expectedValueControl)
|
|
658
|
+
return;
|
|
659
|
+
let newValue = '';
|
|
660
|
+
if (value === 'boolean') {
|
|
661
|
+
newValue = 'true';
|
|
662
|
+
}
|
|
663
|
+
else if (value === 'null') {
|
|
664
|
+
newValue = null;
|
|
665
|
+
}
|
|
666
|
+
expectedValueControl.clearValidators();
|
|
667
|
+
expectedValueControl.setValue(newValue, { emitEvent: false });
|
|
668
|
+
if (value === 'null') {
|
|
669
|
+
expectedValueControl.setValidators([this.expectedValueValidator]);
|
|
670
|
+
}
|
|
671
|
+
else if (value === 'object' || value === 'array') {
|
|
672
|
+
expectedValueControl.setValidators([Validators.required]);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
expectedValueControl.setValidators([Validators.required, this.expectedValueValidator]);
|
|
676
|
+
}
|
|
677
|
+
setTimeout(() => {
|
|
678
|
+
expectedValueControl.updateValueAndValidity({ emitEvent: false });
|
|
679
|
+
}, 100);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Get assertions data source for table
|
|
683
|
+
*/
|
|
684
|
+
get assertionsDataSource() {
|
|
685
|
+
return this.getAssertionsFormArray().controls;
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Track by function for table rows
|
|
689
|
+
*/
|
|
690
|
+
trackByIndex(index) {
|
|
691
|
+
return index;
|
|
692
|
+
}
|
|
693
|
+
ngOnDestroy() {
|
|
694
|
+
// Clean up subscriptions
|
|
695
|
+
this.formSubscriptions.forEach(sub => sub.unsubscribe());
|
|
696
|
+
this.formSubscriptions.clear();
|
|
697
|
+
}
|
|
189
698
|
}
|
|
190
|
-
StepBuilderDatabaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderDatabaseComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
191
|
-
StepBuilderDatabaseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderDatabaseComponent, selector: "cqa-step-builder-database", inputs: { dbEnvironmentOptions: "dbEnvironmentOptions", queries: "queries", queryResults: "queryResults", isLoading: "isLoading", initialDbEnvironment: "initialDbEnvironment", editMode: "editMode" }, outputs: { createStep: "createStep", cancelled: "cancelled", runQuery: "runQuery", addQuery: "addQuery", deleteQuery: "deleteQuery" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n {{ editMode ? 'Update Database Test Step' : 'Create Database Test Step' }}\n </h2>\n\n <!-- DB Environment Section (separator line only on bottom) -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-pb-[0.5rem] cqa-mb-4 cqa-border-0 cqa-border-b cqa-border-solid cqa-border-gray-200\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <div class=\"cqa-flex cqa-w-full cqa-flex-nowrap cqa-items-center cqa-justify-between cqa-gap-3\">\n <div class=\"cqa-min-w-0\" style=\"width: 280px;\">\n <cqa-dynamic-select [form]=\"databaseForm\" [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n </div>\n <cqa-button variant=\"filled\" text=\"Run Query\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\"\n [customClass]=\"'!cqa-bg-[#3F43EE] cqa-text-[#FBFCFF] cqa-text-sm cqa-font-semibold cqa-whitespace-nowrap !cqa-pt-[10px] !cqa-pb-[10px] !cqa-pl-[24px] !cqa-pr-[24px] !cqa-gap-[8px] cqa-rounded-lg cqa-min-h-[37px] hover:!cqa-bg-[#1B1FEB] cqa-flex-shrink-0'\">\n </cqa-button>\n </div>\n <p class=\"cqa-text-xs cqa-text-gray-500\">\n Uses Database environments from Environments.\n </p>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-[12px] cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div\n class=\"cqa-w-[175px] cqa-min-w-[175px] cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border-0 cqa-border-r cqa-border-r-[1px] cqa-border-solid cqa-border-[#E0E0E0] cqa-bg-[#FAFAFA] cqa-overflow-hidden\">\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-[10px] cqa-w-full cqa-pt-[14px] cqa-pb-[14px] cqa-pl-[16px] cqa-pr-[16px] cqa-rounded-[8px] cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\"\n [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\"\n [class.cqa-bg-grey-400]=\"selectedQueryIndex !== i\"\n (click)=\"onSelectQuery(i)\"\n style=\"height: 49px; min-height: 49px;\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-overflow-auto\">\n <div class=\"cqa-flex-1 cqa-flex cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-gap-[10px] cqa-mb-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-[6px]\" style=\"width: 50%;\">\n <div class=\"\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900 cqa-text-[14px]\">Query & Store Response</h3>\n </div>\n\n <div class=\"cqa-flex cqa-justify-between\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-min-w-0 cqa-w-full cqa-rounded-md cqa-bg-gray-50/50\">\n <cqa-custom-textarea [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\" [fullWidth]=\"true\" [rows]=\"8\"\n [textareaInlineStyle]=\"'padding: 1rem;'\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-flex cqa-flex-col cqa-gap-[10px] cqa-mb-[8px]\">\n\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block cqa-text-[14px] cqa-font-semibold\">\n Variable\n </label>\n <cqa-custom-input [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\" [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n <!-- Action Buttons (pinned to bottom) -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-mt-auto\">\n <cqa-button variant=\"outlined\" text=\"Add Query\" icon=\"add\" (clicked)=\"addNewQuery()\"\n [customClass]=\"'cqa-bg-white !cqa-border-[#414146] cqa-text-sm cqa-font-semibold cqa-text-[#414146] cqa-whitespace-nowrap !cqa-py-[10px] !cqa-px-[10px] !cqa-gap-[8px] cqa-rounded-lg hover:!cqa-border-[#414146] hover:cqa-bg-gray-50'\"\n [iconColor]=\"'#414146'\">\n </cqa-button>\n <cqa-button type=\"button\" variant=\"text\"\n [customClass]=\"'cqa-min-w-[40px] cqa-w-10 cqa-h-9 cqa-rounded cqa-bg-gray-100 cqa-flex cqa-items-center cqa-justify-center hover:cqa-bg-gray-200 cqa-p-0'\"\n [tooltip]=\"'Delete query'\" (clicked)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\" [attr.aria-label]=\"'Delete query'\">\n <svg class=\"cqa-flex-shrink-0\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"\n fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path\n d=\"M10.6663 6V12.6667H5.33301V6H10.6663ZM9.66634 2H6.33301L5.66634 2.66667H3.33301V4H12.6663V2.66667H10.333L9.66634 2ZM11.9997 4.66667H3.99967V12.6667C3.99967 13.4 4.59967 14 5.33301 14H10.6663C11.3997 14 11.9997 13.4 11.9997 12.6667V4.66667Z\"\n fill=\"#6B7280\" />\n </svg>\n </cqa-button>\n <cqa-button variant=\"filled\" text=\"Run\" icon=\"play_arrow\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!getCurrentQueryFormGroup()?.get('query')?.value || !databaseForm.get('dbEnvironment')?.value || isLoading\"\n [customClass]=\"'!cqa-bg-[#3F43EE] cqa-text-[#FBFCFF] cqa-text-sm cqa-font-semibold cqa-whitespace-nowrap !cqa-pt-[10px] !cqa-pb-[10px] !cqa-pl-[16px] !cqa-pr-[24px] !cqa-gap-[8px] cqa-rounded-lg cqa-min-h-[38px] hover:!cqa-bg-[#1B1FEB] !cqa-border-none'\"\n [iconColor]=\"'#FBFCFF'\">\n </cqa-button>\n </div>\n </div>\n </div>\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\" [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\" (click)=\"onTabChange('output')\">\n Output\n </button>\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\" (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button variant=\"text\" text=\"Copy\" icon=\"content_copy\" [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n\n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div *ngIf=\"!queryResults || queryResults.length === 0\"\n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">Verification settings will be available here.</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" [text]=\"editMode ? 'Update Step' : 'Create Step'\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>", components: [{ type: i2.DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { type: i3.ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: i4.BadgeComponent, selector: "cqa-badge", inputs: ["type", "label", "icon", "iconLibrary", "variant", "size", "backgroundColor", "textColor", "borderColor", "iconBackgroundColor", "iconColor", "iconSize", "inlineStyles", "key", "value", "keyTextColor", "valueTextColor", "isLoading"] }, { type: i5.CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused"] }, { type: i6.CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }], directives: [{ type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
699
|
+
StepBuilderDatabaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderDatabaseComponent, deps: [{ token: i1.FormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
700
|
+
StepBuilderDatabaseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderDatabaseComponent, selector: "cqa-step-builder-database", inputs: { dbEnvironmentOptions: "dbEnvironmentOptions", queries: "queries", queryResults: "queryResults", isLoading: "isLoading", initialDbEnvironment: "initialDbEnvironment", editMode: "editMode" }, outputs: { createStep: "createStep", cancelled: "cancelled", runQuery: "runQuery", addQuery: "addQuery", deleteQuery: "deleteQuery", assertionDataChange: "assertionDataChange", selectedQueryIndexChange: "selectedQueryIndexChange", activeTabChange: "activeTabChange" }, host: { classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "assertionsTable", first: true, predicate: ["assertionsTable"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n {{ editMode ? 'Update Database Test Step' : 'Create Database Test Step' }}\n </h2>\n\n <!-- DB Environment Section (separator line only on bottom) -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-pb-[0.5rem] cqa-mb-4 cqa-border-0 cqa-border-b cqa-border-solid cqa-border-gray-200\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <div class=\"cqa-flex cqa-w-full cqa-flex-nowrap cqa-items-center cqa-justify-between cqa-gap-3\">\n <div class=\"cqa-min-w-0\" style=\"width: 280px;\">\n <cqa-dynamic-select [form]=\"databaseForm\" [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n </div>\n <cqa-button variant=\"filled\" text=\"Run Query\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\"\n [customClass]=\"'!cqa-bg-[#3F43EE] cqa-text-[#FBFCFF] cqa-text-sm cqa-font-semibold cqa-whitespace-nowrap !cqa-pt-[10px] !cqa-pb-[10px] !cqa-pl-[24px] !cqa-pr-[24px] !cqa-gap-[8px] cqa-rounded-lg cqa-min-h-[37px] hover:!cqa-bg-[#1B1FEB] cqa-flex-shrink-0'\">\n </cqa-button>\n </div>\n <p class=\"cqa-text-xs cqa-text-gray-500\">\n Uses Database environments from Environments.\n </p>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-[12px] cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div\n class=\"cqa-w-[175px] cqa-min-w-[175px] cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border-0 cqa-border-r cqa-border-r-[1px] cqa-border-solid cqa-border-[#E0E0E0] cqa-bg-[#FAFAFA] cqa-overflow-hidden\">\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-[10px] cqa-w-full cqa-pt-[14px] cqa-pb-[14px] cqa-pl-[16px] cqa-pr-[16px] cqa-rounded-[8px] cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\"\n [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\"\n [class.cqa-bg-grey-400]=\"selectedQueryIndex !== i\"\n (click)=\"onSelectQuery(i)\"\n style=\"height: 49px; min-height: 49px;\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-overflow-auto\">\n <div class=\"cqa-flex-1 cqa-flex cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-gap-[10px] cqa-mb-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-[6px]\" style=\"width: 50%;\">\n <div class=\"\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900 cqa-text-[14px]\">Query & Store Response</h3>\n </div>\n\n <div class=\"cqa-flex cqa-justify-between\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-min-w-0 cqa-w-full cqa-rounded-md cqa-bg-gray-50/50\">\n <cqa-custom-textarea [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\" [fullWidth]=\"true\" [rows]=\"8\"\n [textareaInlineStyle]=\"'padding: 1rem;'\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-flex cqa-flex-col cqa-gap-[10px] cqa-mb-[8px]\">\n\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block cqa-text-[14px] cqa-font-semibold\">\n Variable\n </label>\n <cqa-custom-input [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\" [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n <!-- Action Buttons (pinned to bottom) -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-mt-auto\">\n <cqa-button variant=\"outlined\" text=\"Add Query\" icon=\"add\" (clicked)=\"addNewQuery()\"\n [customClass]=\"'cqa-bg-white !cqa-border-[#414146] cqa-text-sm cqa-font-semibold cqa-text-[#414146] cqa-whitespace-nowrap !cqa-py-[10px] !cqa-px-[10px] !cqa-gap-[8px] cqa-rounded-lg hover:!cqa-border-[#414146] hover:cqa-bg-gray-50'\"\n [iconColor]=\"'#414146'\">\n </cqa-button>\n <cqa-button type=\"button\" variant=\"text\"\n [customClass]=\"'cqa-min-w-[40px] cqa-w-10 cqa-h-9 cqa-rounded cqa-bg-gray-100 cqa-flex cqa-items-center cqa-justify-center hover:cqa-bg-gray-200 cqa-p-0'\"\n [tooltip]=\"'Delete query'\" (clicked)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\" [attr.aria-label]=\"'Delete query'\">\n <svg class=\"cqa-flex-shrink-0\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"\n fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path\n d=\"M10.6663 6V12.6667H5.33301V6H10.6663ZM9.66634 2H6.33301L5.66634 2.66667H3.33301V4H12.6663V2.66667H10.333L9.66634 2ZM11.9997 4.66667H3.99967V12.6667C3.99967 13.4 4.59967 14 5.33301 14H10.6663C11.3997 14 11.9997 13.4 11.9997 12.6667V4.66667Z\"\n fill=\"#6B7280\" />\n </svg>\n </cqa-button>\n <cqa-button variant=\"filled\" text=\"Run\" icon=\"play_arrow\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!getCurrentQueryFormGroup()?.get('query')?.value || !databaseForm.get('dbEnvironment')?.value || isLoading\"\n [customClass]=\"'!cqa-bg-[#3F43EE] cqa-text-[#FBFCFF] cqa-text-sm cqa-font-semibold cqa-whitespace-nowrap !cqa-pt-[10px] !cqa-pb-[10px] !cqa-pl-[16px] !cqa-pr-[24px] !cqa-gap-[8px] cqa-rounded-lg cqa-min-h-[38px] hover:!cqa-bg-[#1B1FEB] !cqa-border-none'\"\n [iconColor]=\"'#FBFCFF'\">\n </cqa-button>\n </div>\n </div>\n </div>\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\" [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\" (click)=\"onTabChange('output')\">\n Output\n </button>\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\" (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button variant=\"text\" text=\"Copy\" icon=\"content_copy\" [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n\n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div *ngIf=\"!queryResults || queryResults.length === 0\"\n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\" class=\"assertions-container\">\n <!-- Header Section -->\n <div class=\"assertions-header\">\n <div class=\"header-content\">\n <h3 class=\"header-title\">Assertions</h3>\n <p class=\"header-subtitle\">Use JSONPath to target values in the query output.</p>\n </div>\n <button \n mat-stroked-button \n color=\"primary\" \n class=\"add-assertion-button\"\n (click)=\"addAssertion()\">\n <mat-icon>add</mat-icon>\n Add Assertion\n </button>\n </div>\n\n <!-- Table Section -->\n <form *ngIf=\"getCurrentAssertionsForm()\" [formGroup]=\"getCurrentAssertionsForm()!\" class=\"assertions-form\">\n <div formArrayName=\"assertions\">\n <div class=\"table-scroll-container\">\n <table mat-table [dataSource]=\"assertionsDataSource\" class=\"assertions-table\" #assertionsTable>\n <!-- JSONPath Column -->\n <ng-container matColumnDef=\"jsonPath\">\n <th mat-header-cell *matHeaderCellDef>jsonPath</th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <ng-container [formGroupName]=\"i\">\n <mat-form-field appearance=\"outline\" class=\"full-width-field\">\n <input \n matInput \n formControlName=\"jsonPath\"\n placeholder=\"username\"\n required>\n <mat-error *ngIf=\"getFormControlAt(i, 'jsonPath')?.hasError('required') && \n getFormControlAt(i, 'jsonPath')?.touched\">\n JSONPath is required\n </mat-error>\n </mat-form-field>\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Verification Type Column -->\n <ng-container matColumnDef=\"verificationType\">\n <th mat-header-cell *matHeaderCellDef>verificationType</th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <ng-container [formGroupName]=\"i\">\n <mat-form-field appearance=\"outline\" class=\"full-width-field\">\n <mat-select formControlName=\"verificationType\">\n <mat-option value=\"equals\">Equals</mat-option>\n <mat-option value=\"not_equals\">Not Equals</mat-option>\n <mat-option value=\"contains\">Contains</mat-option>\n <mat-option value=\"not_contains\">Not Contains</mat-option>\n <mat-option value=\"greater_than\">Greater Than</mat-option>\n <mat-option value=\"less_than\">Less Than</mat-option>\n <mat-option value=\"greater_than_or_equals\">Greater Than Or Equals</mat-option>\n <mat-option value=\"less_than_or_equals\">Less Than Or Equals</mat-option>\n <mat-option value=\"exists\">Exists</mat-option>\n <mat-option value=\"not_exists\">Not Exists</mat-option>\n </mat-select>\n </mat-form-field>\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Expected Type Column -->\n <ng-container matColumnDef=\"expectedType\">\n <th mat-header-cell *matHeaderCellDef>expectedType</th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <ng-container [formGroupName]=\"i\">\n <mat-form-field appearance=\"outline\" class=\"full-width-field\">\n <mat-select \n formControlName=\"expectedType\"\n (selectionChange)=\"onExpectedTypeChange(i, $event.value)\">\n <mat-option value=\"string\">String</mat-option>\n <mat-option value=\"number\">Number</mat-option>\n <mat-option value=\"boolean\">Boolean</mat-option>\n <mat-option value=\"object\">Object</mat-option>\n <mat-option value=\"array\">Array</mat-option>\n <mat-option value=\"null\">Null</mat-option>\n </mat-select>\n </mat-form-field>\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Expected Value Column -->\n <ng-container matColumnDef=\"expectedValue\">\n <th mat-header-cell *matHeaderCellDef>expectedValue</th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <ng-container [formGroupName]=\"i\">\n <!-- String, Array, Object Input -->\n <mat-form-field \n *ngIf=\"getExpectedType(i) === 'string' || getExpectedType(i) === 'array' || getExpectedType(i) === 'object'\"\n appearance=\"outline\" \n class=\"full-width-field\">\n <textarea \n *ngIf=\"getExpectedType(i) === 'array' || getExpectedType(i) === 'object'\"\n matInput \n formControlName=\"expectedValue\"\n [placeholder]=\"getExpectedValuePlaceholder(i)\"\n rows=\"3\"\n required></textarea>\n <input \n *ngIf=\"getExpectedType(i) === 'string'\"\n matInput \n formControlName=\"expectedValue\"\n [placeholder]=\"getExpectedValuePlaceholder(i)\"\n required>\n <mat-error *ngIf=\"getFormControlAt(i, 'expectedValue')?.hasError('required') && \n getFormControlAt(i, 'expectedValue')?.touched\">\n Expected value is required\n </mat-error>\n <mat-error *ngIf=\"getFormControlAt(i, 'expectedValue')?.hasError('invalidType')\">\n {{ getFormControlAt(i, 'expectedValue')?.errors?.message }}\n </mat-error>\n </mat-form-field>\n\n <!-- Null Type Display -->\n <mat-form-field \n *ngIf=\"getExpectedType(i) === 'null'\"\n appearance=\"outline\" \n class=\"full-width-field\">\n <input \n matInput \n formControlName=\"expectedValue\"\n [placeholder]=\"getExpectedValuePlaceholder(i)\"\n [disabled]=\"true\">\n </mat-form-field>\n\n <!-- Number Input -->\n <mat-form-field \n *ngIf=\"getExpectedType(i) === 'number'\"\n appearance=\"outline\" \n class=\"full-width-field\">\n <input \n matInput \n type=\"number\"\n formControlName=\"expectedValue\"\n placeholder=\"Expected Value in Number\"\n required>\n <mat-error *ngIf=\"getFormControlAt(i, 'expectedValue')?.hasError('required') && \n getFormControlAt(i, 'expectedValue')?.touched\">\n Expected value is required\n </mat-error>\n </mat-form-field>\n\n <!-- Boolean Select -->\n <mat-form-field \n *ngIf=\"getExpectedType(i) === 'boolean'\"\n appearance=\"outline\" \n class=\"full-width-field\">\n <mat-select formControlName=\"expectedValue\" required>\n <mat-option value=\"true\">true</mat-option>\n <mat-option value=\"false\">false</mat-option>\n </mat-select>\n <mat-error *ngIf=\"getFormControlAt(i, 'expectedValue')?.hasError('required') && \n getFormControlAt(i, 'expectedValue')?.touched\">\n Expected value is required\n </mat-error>\n </mat-form-field>\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <button \n mat-icon-button \n color=\"warn\"\n class=\"delete-button\"\n (click)=\"removeAssertion(i)\"\n [matTooltip]=\"'Delete assertion'\">\n <mat-icon>delete</mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n\n <!-- Empty State -->\n <div *ngIf=\"getAssertionsFormArray().length === 0\" class=\"empty-state\">\n <p>No assertions added. Click \"Add Assertion\" to create one.</p>\n </div>\n </div>\n </form>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" [text]=\"editMode ? 'Update Step' : 'Create Step'\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>", components: [{ type: i2.DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }, { type: i3.ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: i4.BadgeComponent, selector: "cqa-badge", inputs: ["type", "label", "icon", "iconLibrary", "variant", "size", "backgroundColor", "textColor", "borderColor", "iconBackgroundColor", "iconColor", "iconSize", "inlineStyles", "key", "value", "keyTextColor", "valueTextColor", "isLoading"] }, { type: i5.CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused"] }, { type: i6.CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: i7.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { type: i10.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i11.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i12.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }], directives: [{ type: i13.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i13.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { type: i9.MatCellDef, selector: "[matCellDef]" }, { type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { type: i14.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i10.MatError, selector: "mat-error", inputs: ["id"] }, { type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i15.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }] });
|
|
192
701
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderDatabaseComponent, decorators: [{
|
|
193
702
|
type: Component,
|
|
194
|
-
args: [{ selector: 'cqa-step-builder-database', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n {{ editMode ? 'Update Database Test Step' : 'Create Database Test Step' }}\n </h2>\n\n <!-- DB Environment Section (separator line only on bottom) -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-pb-[0.5rem] cqa-mb-4 cqa-border-0 cqa-border-b cqa-border-solid cqa-border-gray-200\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <div class=\"cqa-flex cqa-w-full cqa-flex-nowrap cqa-items-center cqa-justify-between cqa-gap-3\">\n <div class=\"cqa-min-w-0\" style=\"width: 280px;\">\n <cqa-dynamic-select [form]=\"databaseForm\" [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n </div>\n <cqa-button variant=\"filled\" text=\"Run Query\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\"\n [customClass]=\"'!cqa-bg-[#3F43EE] cqa-text-[#FBFCFF] cqa-text-sm cqa-font-semibold cqa-whitespace-nowrap !cqa-pt-[10px] !cqa-pb-[10px] !cqa-pl-[24px] !cqa-pr-[24px] !cqa-gap-[8px] cqa-rounded-lg cqa-min-h-[37px] hover:!cqa-bg-[#1B1FEB] cqa-flex-shrink-0'\">\n </cqa-button>\n </div>\n <p class=\"cqa-text-xs cqa-text-gray-500\">\n Uses Database environments from Environments.\n </p>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-[12px] cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div\n class=\"cqa-w-[175px] cqa-min-w-[175px] cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border-0 cqa-border-r cqa-border-r-[1px] cqa-border-solid cqa-border-[#E0E0E0] cqa-bg-[#FAFAFA] cqa-overflow-hidden\">\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-[10px] cqa-w-full cqa-pt-[14px] cqa-pb-[14px] cqa-pl-[16px] cqa-pr-[16px] cqa-rounded-[8px] cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\"\n [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\"\n [class.cqa-bg-grey-400]=\"selectedQueryIndex !== i\"\n (click)=\"onSelectQuery(i)\"\n style=\"height: 49px; min-height: 49px;\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-overflow-auto\">\n <div class=\"cqa-flex-1 cqa-flex cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-gap-[10px] cqa-mb-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-[6px]\" style=\"width: 50%;\">\n <div class=\"\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900 cqa-text-[14px]\">Query & Store Response</h3>\n </div>\n\n <div class=\"cqa-flex cqa-justify-between\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-min-w-0 cqa-w-full cqa-rounded-md cqa-bg-gray-50/50\">\n <cqa-custom-textarea [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\" [fullWidth]=\"true\" [rows]=\"8\"\n [textareaInlineStyle]=\"'padding: 1rem;'\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-flex cqa-flex-col cqa-gap-[10px] cqa-mb-[8px]\">\n\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block cqa-text-[14px] cqa-font-semibold\">\n Variable\n </label>\n <cqa-custom-input [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\" [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n <!-- Action Buttons (pinned to bottom) -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-mt-auto\">\n <cqa-button variant=\"outlined\" text=\"Add Query\" icon=\"add\" (clicked)=\"addNewQuery()\"\n [customClass]=\"'cqa-bg-white !cqa-border-[#414146] cqa-text-sm cqa-font-semibold cqa-text-[#414146] cqa-whitespace-nowrap !cqa-py-[10px] !cqa-px-[10px] !cqa-gap-[8px] cqa-rounded-lg hover:!cqa-border-[#414146] hover:cqa-bg-gray-50'\"\n [iconColor]=\"'#414146'\">\n </cqa-button>\n <cqa-button type=\"button\" variant=\"text\"\n [customClass]=\"'cqa-min-w-[40px] cqa-w-10 cqa-h-9 cqa-rounded cqa-bg-gray-100 cqa-flex cqa-items-center cqa-justify-center hover:cqa-bg-gray-200 cqa-p-0'\"\n [tooltip]=\"'Delete query'\" (clicked)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\" [attr.aria-label]=\"'Delete query'\">\n <svg class=\"cqa-flex-shrink-0\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"\n fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path\n d=\"M10.6663 6V12.6667H5.33301V6H10.6663ZM9.66634 2H6.33301L5.66634 2.66667H3.33301V4H12.6663V2.66667H10.333L9.66634 2ZM11.9997 4.66667H3.99967V12.6667C3.99967 13.4 4.59967 14 5.33301 14H10.6663C11.3997 14 11.9997 13.4 11.9997 12.6667V4.66667Z\"\n fill=\"#6B7280\" />\n </svg>\n </cqa-button>\n <cqa-button variant=\"filled\" text=\"Run\" icon=\"play_arrow\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!getCurrentQueryFormGroup()?.get('query')?.value || !databaseForm.get('dbEnvironment')?.value || isLoading\"\n [customClass]=\"'!cqa-bg-[#3F43EE] cqa-text-[#FBFCFF] cqa-text-sm cqa-font-semibold cqa-whitespace-nowrap !cqa-pt-[10px] !cqa-pb-[10px] !cqa-pl-[16px] !cqa-pr-[24px] !cqa-gap-[8px] cqa-rounded-lg cqa-min-h-[38px] hover:!cqa-bg-[#1B1FEB] !cqa-border-none'\"\n [iconColor]=\"'#FBFCFF'\">\n </cqa-button>\n </div>\n </div>\n </div>\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\" [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\" (click)=\"onTabChange('output')\">\n Output\n </button>\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\" (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button variant=\"text\" text=\"Copy\" icon=\"content_copy\" [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n\n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div *ngIf=\"!queryResults || queryResults.length === 0\"\n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">Verification settings will be available here.</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" [text]=\"editMode ? 'Update Step' : 'Create Step'\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>", styles: [] }]
|
|
195
|
-
}], ctorParameters: function () { return [{ type: i1.FormBuilder }]; }, propDecorators: { dbEnvironmentOptions: [{
|
|
703
|
+
args: [{ selector: 'cqa-step-builder-database', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n {{ editMode ? 'Update Database Test Step' : 'Create Database Test Step' }}\n </h2>\n\n <!-- DB Environment Section (separator line only on bottom) -->\n <div class=\"cqa-flex cqa-flex-col cqa-gap-1.5 cqa-pb-[0.5rem] cqa-mb-4 cqa-border-0 cqa-border-b cqa-border-solid cqa-border-gray-200\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <div class=\"cqa-flex cqa-w-full cqa-flex-nowrap cqa-items-center cqa-justify-between cqa-gap-3\">\n <div class=\"cqa-min-w-0\" style=\"width: 280px;\">\n <cqa-dynamic-select [form]=\"databaseForm\" [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n </div>\n <cqa-button variant=\"filled\" text=\"Run Query\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\"\n [customClass]=\"'!cqa-bg-[#3F43EE] cqa-text-[#FBFCFF] cqa-text-sm cqa-font-semibold cqa-whitespace-nowrap !cqa-pt-[10px] !cqa-pb-[10px] !cqa-pl-[24px] !cqa-pr-[24px] !cqa-gap-[8px] cqa-rounded-lg cqa-min-h-[37px] hover:!cqa-bg-[#1B1FEB] cqa-flex-shrink-0'\">\n </cqa-button>\n </div>\n <p class=\"cqa-text-xs cqa-text-gray-500\">\n Uses Database environments from Environments.\n </p>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-[12px] cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div\n class=\"cqa-w-[175px] cqa-min-w-[175px] cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border-0 cqa-border-r cqa-border-r-[1px] cqa-border-solid cqa-border-[#E0E0E0] cqa-bg-[#FAFAFA] cqa-overflow-hidden\">\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-gap-[10px] cqa-w-full cqa-pt-[14px] cqa-pb-[14px] cqa-pl-[16px] cqa-pr-[16px] cqa-rounded-[8px] cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\"\n [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\"\n [class.cqa-bg-grey-400]=\"selectedQueryIndex !== i\"\n (click)=\"onSelectQuery(i)\"\n style=\"height: 49px; min-height: 49px;\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-overflow-auto\">\n <div class=\"cqa-flex-1 cqa-flex cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-gap-[10px] cqa-mb-4\">\n <div class=\"cqa-flex cqa-flex-col cqa-gap-[6px]\" style=\"width: 50%;\">\n <div class=\"\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900 cqa-text-[14px]\">Query & Store Response</h3>\n </div>\n\n <div class=\"cqa-flex cqa-justify-between\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-min-w-0 cqa-w-full cqa-rounded-md cqa-bg-gray-50/50\">\n <cqa-custom-textarea [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\" [fullWidth]=\"true\" [rows]=\"8\"\n [textareaInlineStyle]=\"'padding: 1rem;'\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-flex cqa-flex-col cqa-gap-[10px] cqa-mb-[8px]\">\n\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block cqa-text-[14px] cqa-font-semibold\">\n Variable\n </label>\n <cqa-custom-input [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\" [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n <!-- Action Buttons (pinned to bottom) -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-mt-auto\">\n <cqa-button variant=\"outlined\" text=\"Add Query\" icon=\"add\" (clicked)=\"addNewQuery()\"\n [customClass]=\"'cqa-bg-white !cqa-border-[#414146] cqa-text-sm cqa-font-semibold cqa-text-[#414146] cqa-whitespace-nowrap !cqa-py-[10px] !cqa-px-[10px] !cqa-gap-[8px] cqa-rounded-lg hover:!cqa-border-[#414146] hover:cqa-bg-gray-50'\"\n [iconColor]=\"'#414146'\">\n </cqa-button>\n <cqa-button type=\"button\" variant=\"text\"\n [customClass]=\"'cqa-min-w-[40px] cqa-w-10 cqa-h-9 cqa-rounded cqa-bg-gray-100 cqa-flex cqa-items-center cqa-justify-center hover:cqa-bg-gray-200 cqa-p-0'\"\n [tooltip]=\"'Delete query'\" (clicked)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\" [attr.aria-label]=\"'Delete query'\">\n <svg class=\"cqa-flex-shrink-0\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\"\n fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path\n d=\"M10.6663 6V12.6667H5.33301V6H10.6663ZM9.66634 2H6.33301L5.66634 2.66667H3.33301V4H12.6663V2.66667H10.333L9.66634 2ZM11.9997 4.66667H3.99967V12.6667C3.99967 13.4 4.59967 14 5.33301 14H10.6663C11.3997 14 11.9997 13.4 11.9997 12.6667V4.66667Z\"\n fill=\"#6B7280\" />\n </svg>\n </cqa-button>\n <cqa-button variant=\"filled\" text=\"Run\" icon=\"play_arrow\" (clicked)=\"onRunQuery()\"\n [disabled]=\"!getCurrentQueryFormGroup()?.get('query')?.value || !databaseForm.get('dbEnvironment')?.value || isLoading\"\n [customClass]=\"'!cqa-bg-[#3F43EE] cqa-text-[#FBFCFF] cqa-text-sm cqa-font-semibold cqa-whitespace-nowrap !cqa-pt-[10px] !cqa-pb-[10px] !cqa-pl-[16px] !cqa-pr-[24px] !cqa-gap-[8px] cqa-rounded-lg cqa-min-h-[38px] hover:!cqa-bg-[#1B1FEB] !cqa-border-none'\"\n [iconColor]=\"'#FBFCFF'\">\n </cqa-button>\n </div>\n </div>\n </div>\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\" [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\" (click)=\"onTabChange('output')\">\n Output\n </button>\n <button type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\" (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button variant=\"text\" text=\"Copy\" icon=\"content_copy\" [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n\n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div *ngIf=\"!queryResults || queryResults.length === 0\"\n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\" class=\"assertions-container\">\n <!-- Header Section -->\n <div class=\"assertions-header\">\n <div class=\"header-content\">\n <h3 class=\"header-title\">Assertions</h3>\n <p class=\"header-subtitle\">Use JSONPath to target values in the query output.</p>\n </div>\n <button \n mat-stroked-button \n color=\"primary\" \n class=\"add-assertion-button\"\n (click)=\"addAssertion()\">\n <mat-icon>add</mat-icon>\n Add Assertion\n </button>\n </div>\n\n <!-- Table Section -->\n <form *ngIf=\"getCurrentAssertionsForm()\" [formGroup]=\"getCurrentAssertionsForm()!\" class=\"assertions-form\">\n <div formArrayName=\"assertions\">\n <div class=\"table-scroll-container\">\n <table mat-table [dataSource]=\"assertionsDataSource\" class=\"assertions-table\" #assertionsTable>\n <!-- JSONPath Column -->\n <ng-container matColumnDef=\"jsonPath\">\n <th mat-header-cell *matHeaderCellDef>jsonPath</th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <ng-container [formGroupName]=\"i\">\n <mat-form-field appearance=\"outline\" class=\"full-width-field\">\n <input \n matInput \n formControlName=\"jsonPath\"\n placeholder=\"username\"\n required>\n <mat-error *ngIf=\"getFormControlAt(i, 'jsonPath')?.hasError('required') && \n getFormControlAt(i, 'jsonPath')?.touched\">\n JSONPath is required\n </mat-error>\n </mat-form-field>\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Verification Type Column -->\n <ng-container matColumnDef=\"verificationType\">\n <th mat-header-cell *matHeaderCellDef>verificationType</th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <ng-container [formGroupName]=\"i\">\n <mat-form-field appearance=\"outline\" class=\"full-width-field\">\n <mat-select formControlName=\"verificationType\">\n <mat-option value=\"equals\">Equals</mat-option>\n <mat-option value=\"not_equals\">Not Equals</mat-option>\n <mat-option value=\"contains\">Contains</mat-option>\n <mat-option value=\"not_contains\">Not Contains</mat-option>\n <mat-option value=\"greater_than\">Greater Than</mat-option>\n <mat-option value=\"less_than\">Less Than</mat-option>\n <mat-option value=\"greater_than_or_equals\">Greater Than Or Equals</mat-option>\n <mat-option value=\"less_than_or_equals\">Less Than Or Equals</mat-option>\n <mat-option value=\"exists\">Exists</mat-option>\n <mat-option value=\"not_exists\">Not Exists</mat-option>\n </mat-select>\n </mat-form-field>\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Expected Type Column -->\n <ng-container matColumnDef=\"expectedType\">\n <th mat-header-cell *matHeaderCellDef>expectedType</th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <ng-container [formGroupName]=\"i\">\n <mat-form-field appearance=\"outline\" class=\"full-width-field\">\n <mat-select \n formControlName=\"expectedType\"\n (selectionChange)=\"onExpectedTypeChange(i, $event.value)\">\n <mat-option value=\"string\">String</mat-option>\n <mat-option value=\"number\">Number</mat-option>\n <mat-option value=\"boolean\">Boolean</mat-option>\n <mat-option value=\"object\">Object</mat-option>\n <mat-option value=\"array\">Array</mat-option>\n <mat-option value=\"null\">Null</mat-option>\n </mat-select>\n </mat-form-field>\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Expected Value Column -->\n <ng-container matColumnDef=\"expectedValue\">\n <th mat-header-cell *matHeaderCellDef>expectedValue</th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <ng-container [formGroupName]=\"i\">\n <!-- String, Array, Object Input -->\n <mat-form-field \n *ngIf=\"getExpectedType(i) === 'string' || getExpectedType(i) === 'array' || getExpectedType(i) === 'object'\"\n appearance=\"outline\" \n class=\"full-width-field\">\n <textarea \n *ngIf=\"getExpectedType(i) === 'array' || getExpectedType(i) === 'object'\"\n matInput \n formControlName=\"expectedValue\"\n [placeholder]=\"getExpectedValuePlaceholder(i)\"\n rows=\"3\"\n required></textarea>\n <input \n *ngIf=\"getExpectedType(i) === 'string'\"\n matInput \n formControlName=\"expectedValue\"\n [placeholder]=\"getExpectedValuePlaceholder(i)\"\n required>\n <mat-error *ngIf=\"getFormControlAt(i, 'expectedValue')?.hasError('required') && \n getFormControlAt(i, 'expectedValue')?.touched\">\n Expected value is required\n </mat-error>\n <mat-error *ngIf=\"getFormControlAt(i, 'expectedValue')?.hasError('invalidType')\">\n {{ getFormControlAt(i, 'expectedValue')?.errors?.message }}\n </mat-error>\n </mat-form-field>\n\n <!-- Null Type Display -->\n <mat-form-field \n *ngIf=\"getExpectedType(i) === 'null'\"\n appearance=\"outline\" \n class=\"full-width-field\">\n <input \n matInput \n formControlName=\"expectedValue\"\n [placeholder]=\"getExpectedValuePlaceholder(i)\"\n [disabled]=\"true\">\n </mat-form-field>\n\n <!-- Number Input -->\n <mat-form-field \n *ngIf=\"getExpectedType(i) === 'number'\"\n appearance=\"outline\" \n class=\"full-width-field\">\n <input \n matInput \n type=\"number\"\n formControlName=\"expectedValue\"\n placeholder=\"Expected Value in Number\"\n required>\n <mat-error *ngIf=\"getFormControlAt(i, 'expectedValue')?.hasError('required') && \n getFormControlAt(i, 'expectedValue')?.touched\">\n Expected value is required\n </mat-error>\n </mat-form-field>\n\n <!-- Boolean Select -->\n <mat-form-field \n *ngIf=\"getExpectedType(i) === 'boolean'\"\n appearance=\"outline\" \n class=\"full-width-field\">\n <mat-select formControlName=\"expectedValue\" required>\n <mat-option value=\"true\">true</mat-option>\n <mat-option value=\"false\">false</mat-option>\n </mat-select>\n <mat-error *ngIf=\"getFormControlAt(i, 'expectedValue')?.hasError('required') && \n getFormControlAt(i, 'expectedValue')?.touched\">\n Expected value is required\n </mat-error>\n </mat-form-field>\n </ng-container>\n </td>\n </ng-container>\n\n <!-- Actions Column -->\n <ng-container matColumnDef=\"actions\">\n <th mat-header-cell *matHeaderCellDef></th>\n <td mat-cell *matCellDef=\"let assertion; let i = index\">\n <button \n mat-icon-button \n color=\"warn\"\n class=\"delete-button\"\n (click)=\"removeAssertion(i)\"\n [matTooltip]=\"'Delete assertion'\">\n <mat-icon>delete</mat-icon>\n </button>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n </div>\n\n <!-- Empty State -->\n <div *ngIf=\"getAssertionsFormArray().length === 0\" class=\"empty-state\">\n <p>No assertions added. Click \"Add Assertion\" to create one.</p>\n </div>\n </div>\n </form>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button class=\"cqa-w-1/2\" variant=\"outlined\" text=\"Cancel\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button class=\"cqa-w-1/2\" variant=\"filled\" [text]=\"editMode ? 'Update Step' : 'Create Step'\" [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>", styles: [] }]
|
|
704
|
+
}], ctorParameters: function () { return [{ type: i1.FormBuilder }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { dbEnvironmentOptions: [{
|
|
196
705
|
type: Input
|
|
197
706
|
}], queries: [{
|
|
198
707
|
type: Input
|
|
@@ -214,5 +723,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
214
723
|
type: Output
|
|
215
724
|
}], deleteQuery: [{
|
|
216
725
|
type: Output
|
|
726
|
+
}], assertionDataChange: [{
|
|
727
|
+
type: Output
|
|
728
|
+
}], selectedQueryIndexChange: [{
|
|
729
|
+
type: Output
|
|
730
|
+
}], activeTabChange: [{
|
|
731
|
+
type: Output
|
|
732
|
+
}], assertionsTable: [{
|
|
733
|
+
type: ViewChild,
|
|
734
|
+
args: ['assertionsTable']
|
|
217
735
|
}] } });
|
|
218
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1idWlsZGVyLWRhdGFiYXNlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc3RlcC1idWlsZGVyL3N0ZXAtYnVpbGRlci1kYXRhYmFzZS9zdGVwLWJ1aWxkZXItZGF0YWJhc2UuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zdGVwLWJ1aWxkZXIvc3RlcC1idWlsZGVyLWRhdGFiYXNlL3N0ZXAtYnVpbGRlci1kYXRhYmFzZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFvQyxNQUFNLGVBQWUsQ0FBQztBQUN6RyxPQUFPLEVBQWtELFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7Ozs7QUFxQjVGLE1BQU0sT0FBTyw0QkFBNEI7SUFzQ3ZDLFlBQW9CLEVBQWU7UUFBZixPQUFFLEdBQUYsRUFBRSxDQUFhO1FBckNuQywwQ0FBMEM7UUFDakMseUJBQW9CLEdBQW1CLEVBQUUsQ0FBQztRQUVuRCwyQkFBMkI7UUFDbEIsWUFBTyxHQUFvQixFQUFFLENBQUM7UUFFdkMseUJBQXlCO1FBQ2hCLGlCQUFZLEdBQVUsRUFBRSxDQUFDO1FBRWxDLG9CQUFvQjtRQUNYLGNBQVMsR0FBWSxLQUFLLENBQUM7UUFRcEMsZ0NBQWdDO1FBQ3RCLGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBb0IsQ0FBQztRQUU1RCwwQkFBMEI7UUFDaEIsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFL0MsNkJBQTZCO1FBQ25CLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBOEQsQ0FBQztRQUVwRywrQkFBK0I7UUFDckIsYUFBUSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFOUMsaUNBQWlDO1FBQ3ZCLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQVUs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QUFTO3NCQUFsQixNQUFNO2dCQUdHLFFBQVE7c0JBQWpCLE1BQU07Z0JBR0csUUFBUTtzQkFBakIsTUFBTTtnQkFHRyxXQUFXO3NCQUFwQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE9uSW5pdCwgT25DaGFuZ2VzLCBTaW1wbGVDaGFuZ2VzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBGb3JtQXJyYXksIEZvcm1Db250cm9sLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgRHluYW1pY1NlbGVjdEZpZWxkQ29uZmlnLCBTZWxlY3RPcHRpb24gfSBmcm9tICcuLi8uLi9keW5hbWljLXNlbGVjdC9keW5hbWljLXNlbGVjdC1maWVsZC5jb21wb25lbnQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIERhdGFiYXNlUXVlcnkge1xuICBpZDogc3RyaW5nO1xuICBxdWVyeTogc3RyaW5nO1xuICB2YXJpYWJsZTogc3RyaW5nO1xuICBzdGF0dXM/OiAncGFzc2VkJyB8ICdmYWlsZWQnIHwgJ3BlbmRpbmcnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIERhdGFiYXNlRm9ybURhdGEge1xuICBkYkVudmlyb25tZW50OiBzdHJpbmc7XG4gIHF1ZXJpZXM6IERhdGFiYXNlUXVlcnlbXTtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY3FhLXN0ZXAtYnVpbGRlci1kYXRhYmFzZScsXG4gIHRlbXBsYXRlVXJsOiAnLi9zdGVwLWJ1aWxkZXItZGF0YWJhc2UuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFtdLFxuICBob3N0OiB7IGNsYXNzOiAnY3FhLXVpLXJvb3QnIH1cbn0pXG5leHBvcnQgY2xhc3MgU3RlcEJ1aWxkZXJEYXRhYmFzZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgLyoqIE9wdGlvbnMgZm9yIERCIGVudmlyb25tZW50IGRyb3Bkb3duICovXG4gIEBJbnB1dCgpIGRiRW52aXJvbm1lbnRPcHRpb25zOiBTZWxlY3RPcHRpb25bXSA9IFtdO1xuXG4gIC8qKiBJbml0aWFsIHF1ZXJpZXMgbGlzdCAqL1xuICBASW5wdXQoKSBxdWVyaWVzOiBEYXRhYmFzZVF1ZXJ5W10gPSBbXTtcblxuICAvKiogUXVlcnkgcmVzdWx0cyBkYXRhICovXG4gIEBJbnB1dCgpIHF1ZXJ5UmVzdWx0czogYW55W10gPSBbXTtcblxuICAvKiogTG9hZGluZyBzdGF0ZSAqL1xuICBASW5wdXQoKSBpc0xvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogSW5pdGlhbCBEQiBlbnZpcm9ubWVudCBmb3IgZWRpdCBtb2RlICovXG4gIEBJbnB1dCgpIGluaXRpYWxEYkVudmlyb25tZW50Pzogc3RyaW5nO1xuXG4gIC8qKiBXaGV0aGVyIGluIGVkaXQgbW9kZSAqL1xuICBASW5wdXQoKSBlZGl0TW9kZT86IGJvb2xlYW47XG5cbiAgLyoqIEVtaXQgd2hlbiBzdGVwIGlzIGNyZWF0ZWQgKi9cbiAgQE91dHB1dCgpIGNyZWF0ZVN0ZXAgPSBuZXcgRXZlbnRFbWl0dGVyPERhdGFiYXNlRm9ybURhdGE+KCk7XG5cbiAgLyoqIEVtaXQgd2hlbiBjYW5jZWxsZWQgKi9cbiAgQE91dHB1dCgpIGNhbmNlbGxlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAvKiogRW1pdCB3aGVuIHF1ZXJ5IGlzIHJ1biAqL1xuICBAT3V0cHV0KCkgcnVuUXVlcnkgPSBuZXcgRXZlbnRFbWl0dGVyPHsgcXVlcnk6IHN0cmluZzsgdmFyaWFibGU6IHN0cmluZzsgZGJFbnZpcm9ubWVudDogc3RyaW5nIH0+KCk7XG5cbiAgLyoqIEVtaXQgd2hlbiBxdWVyeSBpcyBhZGRlZCAqL1xuICBAT3V0cHV0KCkgYWRkUXVlcnkgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgLyoqIEVtaXQgd2hlbiBxdWVyeSBpcyBkZWxldGVkICovXG4gIEBPdXRwdXQoKSBkZWxldGVRdWVyeSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIGRhdGFiYXNlRm9ybTogRm9ybUdyb3VwO1xuICBzZWxlY3RlZFRhYjogJ291dHB1dCcgfCAndmVyaWZpY2F0aW9uJyA9ICdvdXRwdXQnO1xuICBzZWxlY3RlZFF1ZXJ5SW5kZXg6IG51bWJlciA9IDA7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBmYjogRm9ybUJ1aWxkZXIpIHtcbiAgICB0aGlzLmRhdGFiYXNlRm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgZGJFbnZpcm9ubWVudDogWycnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgIHF1ZXJpZXM6IHRoaXMuZmIuYXJyYXkoW10pXG4gICAgfSk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmluaXRpYWxpemVGb3JtV2l0aEluaXRpYWxWYWx1ZXMoKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBpZiAoY2hhbmdlc1sncXVlcmllcyddICYmICFjaGFuZ2VzWydxdWVyaWVzJ10uZmlyc3RDaGFuZ2UpIHtcbiAgICAgIC8vIFJlYnVpbGQgZm9ybSBhcnJheSB3aGVuIHF1ZXJpZXMgY2hhbmdlXG4gICAgICBjb25zdCBxdWVyaWVzQXJyYXkgPSB0aGlzLmRhdGFiYXNlRm9ybS5nZXQoJ3F1ZXJpZXMnKSBhcyBGb3JtQXJyYXk7XG4gICAgICB3aGlsZSAocXVlcmllc0FycmF5Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICBxdWVyaWVzQXJyYXkucmVtb3ZlQXQoMCk7XG4gICAgICB9XG4gICAgICB0aGlzLnF1ZXJpZXMuZm9yRWFjaChxdWVyeSA9PiB7XG4gICAgICAgIHRoaXMuYWRkUXVlcnlUb0Zvcm0ocXVlcnkpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWydpbml0aWFsRGJFbnZpcm9ubWVudCddICYmIGNoYW5nZXNbJ2luaXRpYWxEYkVudmlyb25tZW50J10uY3VycmVudFZhbHVlKSB7XG4gICAgICB0aGlzLmRhdGFiYXNlRm9ybS5wYXRjaFZhbHVlKHsgZGJFbnZpcm9ubWVudDogY2hhbmdlc1snaW5pdGlhbERiRW52aXJvbm1lbnQnXS5jdXJyZW50VmFsdWUgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpbml0aWFsaXplRm9ybVdpdGhJbml0aWFsVmFsdWVzKCk6IHZvaWQge1xuICAgIC8vIFNldCBpbml0aWFsIERCIGVudmlyb25tZW50IGlmIHByb3ZpZGVkXG4gICAgaWYgKHRoaXMuaW5pdGlhbERiRW52aXJvbm1lbnQpIHtcbiAgICAgIHRoaXMuZGF0YWJhc2VGb3JtLnBhdGNoVmFsdWUoeyBkYkVudmlyb25tZW50OiB0aGlzLmluaXRpYWxEYkVudmlyb25tZW50IH0pO1xuICAgIH1cblxuICAgIC8vIEluaXRpYWxpemUgd2l0aCBxdWVyaWVzIGlmIHByb3ZpZGVkLCBvdGhlcndpc2UgYWRkIGRlZmF1bHQgcXVlcnlcbiAgICBpZiAodGhpcy5xdWVyaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5hZGROZXdRdWVyeSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnF1ZXJpZXMuZm9yRWFjaCgocXVlcnksIGluZGV4KSA9PiB7XG4gICAgICAgIHRoaXMuYWRkUXVlcnlUb0Zvcm0ocXVlcnkpO1xuICAgICAgICBpZiAoaW5kZXggPT09IDApIHtcbiAgICAgICAgICB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA9IDA7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGdldCBxdWVyaWVzRm9ybUFycmF5KCk6IEZvcm1BcnJheSB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YWJhc2VGb3JtLmdldCgncXVlcmllcycpIGFzIEZvcm1BcnJheTtcbiAgfVxuXG4gIGFkZE5ld1F1ZXJ5KCk6IHZvaWQge1xuICAgIGNvbnN0IG5ld1F1ZXJ5OiBEYXRhYmFzZVF1ZXJ5ID0ge1xuICAgICAgaWQ6IGBxdWVyeV8ke0RhdGUubm93KCl9YCxcbiAgICAgIHF1ZXJ5OiAnJyxcbiAgICAgIHZhcmlhYmxlOiAnJyxcbiAgICAgIHN0YXR1czogJ3BlbmRpbmcnXG4gICAgfTtcbiAgICB0aGlzLnF1ZXJpZXMucHVzaChuZXdRdWVyeSk7XG4gICAgdGhpcy5hZGRRdWVyeVRvRm9ybShuZXdRdWVyeSk7XG4gICAgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPSB0aGlzLnF1ZXJpZXMubGVuZ3RoIC0gMTtcbiAgICB0aGlzLmFkZFF1ZXJ5LmVtaXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkUXVlcnlUb0Zvcm0ocXVlcnk6IERhdGFiYXNlUXVlcnkpOiB2b2lkIHtcbiAgICBjb25zdCBxdWVyeUdyb3VwID0gdGhpcy5mYi5ncm91cCh7XG4gICAgICBpZDogW3F1ZXJ5LmlkXSxcbiAgICAgIHF1ZXJ5OiBbcXVlcnkucXVlcnksIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgdmFyaWFibGU6IFtxdWVyeS52YXJpYWJsZSwgVmFsaWRhdG9ycy5yZXF1aXJlZF1cbiAgICB9KTtcbiAgICB0aGlzLnF1ZXJpZXNGb3JtQXJyYXkucHVzaChxdWVyeUdyb3VwKTtcbiAgfVxuXG4gIGRlbGV0ZVF1ZXJ5QnlJZChxdWVyeUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBpbmRleCA9IHRoaXMucXVlcmllcy5maW5kSW5kZXgocSA9PiBxLmlkID09PSBxdWVyeUlkKTtcbiAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICB0aGlzLnF1ZXJpZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIHRoaXMucXVlcmllc0Zvcm1BcnJheS5yZW1vdmVBdChpbmRleCk7XG4gICAgICBpZiAodGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPj0gdGhpcy5xdWVyaWVzLmxlbmd0aCkge1xuICAgICAgICB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA9IE1hdGgubWF4KDAsIHRoaXMucXVlcmllcy5sZW5ndGggLSAxKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuZGVsZXRlUXVlcnkuZW1pdChxdWVyeUlkKTtcbiAgICB9XG4gIH1cblxuICBnZXREYkVudmlyb25tZW50Q29uZmlnKCk6IER5bmFtaWNTZWxlY3RGaWVsZENvbmZpZyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGtleTogJ2RiRW52aXJvbm1lbnQnLFxuICAgICAgcGxhY2Vob2xkZXI6ICdTZWxlY3QgREIgZW52aXJvbm1lbnQnLFxuICAgICAgbXVsdGlwbGU6IGZhbHNlLFxuICAgICAgc2VhcmNoYWJsZTogZmFsc2UsXG4gICAgICBvcHRpb25zOiB0aGlzLmRiRW52aXJvbm1lbnRPcHRpb25zXG4gICAgfTtcbiAgfVxuXG4gIGdldEN1cnJlbnRRdWVyeSgpOiBEYXRhYmFzZVF1ZXJ5IHwgbnVsbCB7XG4gICAgaWYgKHRoaXMucXVlcmllcy5sZW5ndGggPiAwICYmIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4ID49IDAgJiYgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPCB0aGlzLnF1ZXJpZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcy5xdWVyaWVzW3RoaXMuc2VsZWN0ZWRRdWVyeUluZGV4XTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBnZXRDdXJyZW50UXVlcnlGb3JtR3JvdXAoKTogRm9ybUdyb3VwIHwgbnVsbCB7XG4gICAgaWYgKHRoaXMucXVlcmllc0Zvcm1BcnJheSAmJiB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA+PSAwICYmIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4IDwgdGhpcy5xdWVyaWVzRm9ybUFycmF5Lmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHRoaXMucXVlcmllc0Zvcm1BcnJheS5hdCh0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCkgYXMgRm9ybUdyb3VwO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIG9uUnVuUXVlcnkoKTogdm9pZCB7XG4gICAgY29uc3QgZGJFbnZpcm9ubWVudCA9IHRoaXMuZGF0YWJhc2VGb3JtLmdldCgnZGJFbnZpcm9ubWVudCcpPy52YWx1ZTtcbiAgICBjb25zdCBjdXJyZW50UXVlcnkgPSB0aGlzLmdldEN1cnJlbnRRdWVyeSgpO1xuICAgIGNvbnN0IHF1ZXJ5Rm9ybUdyb3VwID0gdGhpcy5nZXRDdXJyZW50UXVlcnlGb3JtR3JvdXAoKTtcblxuICAgIGlmIChjdXJyZW50UXVlcnkgJiYgcXVlcnlGb3JtR3JvdXAgJiYgZGJFbnZpcm9ubWVudCkge1xuICAgICAgY29uc3QgcXVlcnkgPSBxdWVyeUZvcm1Hcm91cC5nZXQoJ3F1ZXJ5Jyk/LnZhbHVlIHx8ICcnO1xuICAgICAgY29uc3QgdmFyaWFibGUgPSBxdWVyeUZvcm1Hcm91cC5nZXQoJ3ZhcmlhYmxlJyk/LnZhbHVlIHx8ICcnO1xuICAgICAgXG4gICAgICAvLyBVcGRhdGUgdGhlIHF1ZXJ5IG9iamVjdFxuICAgICAgY3VycmVudFF1ZXJ5LnF1ZXJ5ID0gcXVlcnk7XG4gICAgICBjdXJyZW50UXVlcnkudmFyaWFibGUgPSB2YXJpYWJsZTtcblxuICAgICAgdGhpcy5ydW5RdWVyeS5lbWl0KHtcbiAgICAgICAgcXVlcnksXG4gICAgICAgIHZhcmlhYmxlLFxuICAgICAgICBkYkVudmlyb25tZW50XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBvblNlbGVjdFF1ZXJ5KGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA9IGluZGV4O1xuICB9XG5cbiAgb25UYWJDaGFuZ2UodGFiOiAnb3V0cHV0JyB8ICd2ZXJpZmljYXRpb24nKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZFRhYiA9IHRhYjtcbiAgfVxuXG4gIG9uQ29weVJlc3VsdHMoKTogdm9pZCB7XG4gICAgLy8gQ29weSBxdWVyeSByZXN1bHRzIHRvIGNsaXBib2FyZFxuICAgIGlmICh0aGlzLnF1ZXJ5UmVzdWx0cyAmJiB0aGlzLnF1ZXJ5UmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCB0ZXh0ID0gSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeVJlc3VsdHMsIG51bGwsIDIpO1xuICAgICAgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQodGV4dCkudGhlbigoKSA9PiB7XG4gICAgICAgIC8vIENvdWxkIGVtaXQgYW4gZXZlbnQgb3Igc2hvdyBhIHRvYXN0IG5vdGlmaWNhdGlvblxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgb25DYW5jZWwoKTogdm9pZCB7XG4gICAgdGhpcy5jYW5jZWxsZWQuZW1pdCgpO1xuICB9XG5cbiAgb25DcmVhdGVTdGVwKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRhdGFiYXNlRm9ybS52YWxpZCkge1xuICAgICAgY29uc3QgZm9ybVZhbHVlID0gdGhpcy5kYXRhYmFzZUZvcm0udmFsdWU7XG4gICAgICBjb25zdCBzdGVwRGF0YTogRGF0YWJhc2VGb3JtRGF0YSA9IHtcbiAgICAgICAgZGJFbnZpcm9ubWVudDogZm9ybVZhbHVlLmRiRW52aXJvbm1lbnQsXG4gICAgICAgIHF1ZXJpZXM6IHRoaXMucXVlcmllcy5tYXAoKHF1ZXJ5LCBpbmRleCkgPT4ge1xuICAgICAgICAgIGNvbnN0IHF1ZXJ5Rm9ybUdyb3VwID0gdGhpcy5xdWVyaWVzRm9ybUFycmF5LmF0KGluZGV4KSBhcyBGb3JtR3JvdXA7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGlkOiBxdWVyeS5pZCxcbiAgICAgICAgICAgIHF1ZXJ5OiBxdWVyeUZvcm1Hcm91cC5nZXQoJ3F1ZXJ5Jyk/LnZhbHVlIHx8ICcnLFxuICAgICAgICAgICAgdmFyaWFibGU6IHF1ZXJ5Rm9ybUdyb3VwLmdldCgndmFyaWFibGUnKT8udmFsdWUgfHwgJycsXG4gICAgICAgICAgICBzdGF0dXM6IHF1ZXJ5LnN0YXR1c1xuICAgICAgICAgIH07XG4gICAgICAgIH0pXG4gICAgICB9O1xuICAgICAgdGhpcy5jcmVhdGVTdGVwLmVtaXQoc3RlcERhdGEpO1xuICAgIH1cbiAgfVxuXG4gIGdldFRhYmxlQ29sdW1ucygpOiBzdHJpbmdbXSB7XG4gICAgaWYgKCF0aGlzLnF1ZXJ5UmVzdWx0cyB8fCB0aGlzLnF1ZXJ5UmVzdWx0cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMucXVlcnlSZXN1bHRzWzBdKTtcbiAgfVxufVxuXG4iLCI8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1oLWZ1bGwgY3FhLWJnLXdoaXRlIGNxYS1weC00IGNxYS1weS0yXCI+XG4gIDwhLS0gSGVhZGVyIC0tPlxuICA8aDIgY2xhc3M9XCJjcWEtdGV4dC1bMTJweF0gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtYmxhY2stMTAwIGNxYS1tYi00XCI+XG4gICAge3sgZWRpdE1vZGUgPyAnVXBkYXRlIERhdGFiYXNlIFRlc3QgU3RlcCcgOiAnQ3JlYXRlIERhdGFiYXNlIFRlc3QgU3RlcCcgfX1cbiAgPC9oMj5cblxuICA8IS0tIERCIEVudmlyb25tZW50IFNlY3Rpb24gKHNlcGFyYXRvciBsaW5lIG9ubHkgb24gYm90dG9tKSAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtZ2FwLTEuNSBjcWEtcGItWzAuNXJlbV0gY3FhLW1iLTQgY3FhLWJvcmRlci0wIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLXNvbGlkIGNxYS1ib3JkZXItZ3JheS0yMDBcIj5cbiAgICA8bGFiZWwgY2xhc3M9XCJjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRleHQtZ3JheS03MDAgY3FhLWJsb2NrXCI+XG4gICAgICBEQiBFbnZpcm9ubWVudCA8c3BhbiBjbGFzcz1cImNxYS10ZXh0LXJlZC01MDBcIj4qPC9zcGFuPlxuICAgIDwvbGFiZWw+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS13LWZ1bGwgY3FhLWZsZXgtbm93cmFwIGNxYS1pdGVtcy1jZW50ZXIgY3FhLWp1c3RpZnktYmV0d2VlbiBjcWEtZ2FwLTNcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjcWEtbWluLXctMFwiIHN0eWxlPVwid2lkdGg6IDI4MHB4O1wiPlxuICAgICAgICA8Y3FhLWR5bmFtaWMtc2VsZWN0IFtmb3JtXT1cImRhdGFiYXNlRm9ybVwiIFtjb25maWddPVwiZ2V0RGJFbnZpcm9ubWVudENvbmZpZygpXCI+XG4gICAgICAgIDwvY3FhLWR5bmFtaWMtc2VsZWN0PlxuICAgICAgPC9kaXY+XG4gICAgICA8Y3FhLWJ1dHRvbiB2YXJpYW50PVwiZmlsbGVkXCIgdGV4dD1cIlJ1biBRdWVyeVwiIChjbGlja2VkKT1cIm9uUnVuUXVlcnkoKVwiXG4gICAgICAgIFtkaXNhYmxlZF09XCIhZGF0YWJhc2VGb3JtLmdldCgnZGJFbnZpcm9ubWVudCcpPy52YWx1ZSB8fCBpc0xvYWRpbmdcIlxuICAgICAgICBbY3VzdG9tQ2xhc3NdPVwiJyFjcWEtYmctWyMzRjQzRUVdIGNxYS10ZXh0LVsjRkJGQ0ZGXSBjcWEtdGV4dC1zbSBjcWEtZm9udC1zZW1pYm9sZCBjcWEtd2hpdGVzcGFjZS1ub3dyYXAgIWNxYS1wdC1bMTBweF0gIWNxYS1wYi1bMTBweF0gIWNxYS1wbC1bMjRweF0gIWNxYS1wci1bMjRweF0gIWNxYS1nYXAtWzhweF0gY3FhLXJvdW5kZWQtbGcgY3FhLW1pbi1oLVszN3B4XSBob3ZlcjohY3FhLWJnLVsjMUIxRkVCXSBjcWEtZmxleC1zaHJpbmstMCdcIj5cbiAgICAgIDwvY3FhLWJ1dHRvbj5cbiAgICA8L2Rpdj5cbiAgICA8cCBjbGFzcz1cImNxYS10ZXh0LXhzIGNxYS10ZXh0LWdyYXktNTAwXCI+XG4gICAgICBVc2VzIERhdGFiYXNlIGVudmlyb25tZW50cyBmcm9tIEVudmlyb25tZW50cy5cbiAgICA8L3A+XG4gIDwvZGl2PlxuXG4gIDwhLS0gTWFpbiBDb250ZW50OiBUd28gQ29sdW1uIExheW91dCAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1nYXAtWzEycHhdIGNxYS1mbGV4LTEgY3FhLW92ZXJmbG93LWhpZGRlbiBjcWEtbWItNlwiPlxuICAgIDwhLS0gTGVmdCBQYW5lbDogUXVlcnkgTGlzdCAtLT5cbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cImNxYS13LVsxNzVweF0gY3FhLW1pbi13LVsxNzVweF0gY3FhLWZsZXgtc2hyaW5rLTAgY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1ib3JkZXItMCBjcWEtYm9yZGVyLXIgY3FhLWJvcmRlci1yLVsxcHhdIGNxYS1ib3JkZXItc29saWQgY3FhLWJvcmRlci1bI0UwRTBFMF0gY3FhLWJnLVsjRkFGQUZBXSBjcWEtb3ZlcmZsb3ctaGlkZGVuXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXgtMSBjcWEtb3ZlcmZsb3cteS1hdXRvIGNxYS1wLTJcIj5cbiAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgcXVlcnkgb2YgcXVlcmllczsgbGV0IGkgPSBpbmRleFwiXG4gICAgICAgICAgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1qdXN0aWZ5LWJldHdlZW4gY3FhLWdhcC1bMTBweF0gY3FhLXctZnVsbCBjcWEtcHQtWzE0cHhdIGNxYS1wYi1bMTRweF0gY3FhLXBsLVsxNnB4XSBjcWEtcHItWzE2cHhdIGNxYS1yb3VuZGVkLVs4cHhdIGNxYS1jdXJzb3ItcG9pbnRlciBjcWEtbWItMVwiXG4gICAgICAgICAgW2NsYXNzLmNxYS1iZy1ibHVlLTUwXT1cInNlbGVjdGVkUXVlcnlJbmRleCA9PT0gaVwiXG4gICAgICAgICAgW2NsYXNzLmNxYS1ib3JkZXJdPVwic2VsZWN0ZWRRdWVyeUluZGV4ID09PSBpXCJcbiAgICAgICAgICBbY2xhc3MuY3FhLWJvcmRlci1ibHVlLTUwMF09XCJzZWxlY3RlZFF1ZXJ5SW5kZXggPT09IGlcIlxuICAgICAgICAgIFtjbGFzcy5jcWEtYmctZ3JleS00MDBdPVwic2VsZWN0ZWRRdWVyeUluZGV4ICE9PSBpXCJcbiAgICAgICAgICAoY2xpY2spPVwib25TZWxlY3RRdWVyeShpKVwiXG4gICAgICAgICAgc3R5bGU9XCJoZWlnaHQ6IDQ5cHg7IG1pbi1oZWlnaHQ6IDQ5cHg7XCI+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRleHQtZ3JheS05MDBcIj5RdWVyeSB7eyBpICsgMSB9fTwvc3Bhbj5cbiAgICAgICAgICA8Y3FhLWJhZGdlICpuZ0lmPVwicXVlcnkuc3RhdHVzXCJcbiAgICAgICAgICAgIFtsYWJlbF09XCJxdWVyeS5zdGF0dXMgPT09ICdwYXNzZWQnID8gJ1Bhc3NlZCcgOiBxdWVyeS5zdGF0dXMgPT09ICdmYWlsZWQnID8gJ0ZhaWxlZCcgOiAnUGVuZGluZydcIlxuICAgICAgICAgICAgW3ZhcmlhbnRdPVwicXVlcnkuc3RhdHVzID09PSAncGFzc2VkJyA/ICdzdWNjZXNzJyA6IHF1ZXJ5LnN0YXR1cyA9PT0gJ2ZhaWxlZCcgPyAnZXJyb3InIDogJ2RlZmF1bHQnXCJcbiAgICAgICAgICAgIHNpemU9XCJzbWFsbFwiPlxuICAgICAgICAgIDwvY3FhLWJhZGdlPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBSaWdodCBQYW5lbDogUXVlcnkgRWRpdG9yIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleC0xIGNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtb3ZlcmZsb3ctYXV0b1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTEgY3FhLWZsZXggY3FhLWJvcmRlciBjcWEtYm9yZGVyLWdyYXktMjAwIGNxYS1yb3VuZGVkLWxnIGNxYS1nYXAtWzEwcHhdIGNxYS1tYi00XCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWdhcC1bNnB4XVwiIHN0eWxlPVwid2lkdGg6IDUwJTtcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiXCI+XG4gICAgICAgICAgICA8aDMgY2xhc3M9XCJjcWEtdGV4dC1zbSBjcWEtZm9udC1zZW1pYm9sZCBjcWEtdGV4dC1ncmF5LTkwMCBjcWEtdGV4dC1bMTRweF1cIj5RdWVyeSAmIFN0b3JlIFJlc3BvbnNlPC9oMz5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtanVzdGlmeS1iZXR3ZWVuXCI+XG4gICAgICAgICAgICA8IS0tIFNRTCBRdWVyeSBUZXh0YXJlYSAtLT5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleC0xIGNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtbWluLXctMCBjcWEtdy1mdWxsIGNxYS1yb3VuZGVkLW1kIGNxYS1iZy1ncmF5LTUwLzUwXCI+XG4gICAgICAgICAgICAgIDxjcWEtY3VzdG9tLXRleHRhcmVhIFtwbGFjZWhvbGRlcl09XCInRW50ZXIgeW91ciBTUUwgcXVlcnkgaGVyZS4uLidcIlxuICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJnZXRDdXJyZW50UXVlcnlGb3JtR3JvdXAoKT8uZ2V0KCdxdWVyeScpPy52YWx1ZSB8fCAnJ1wiIFtmdWxsV2lkdGhdPVwidHJ1ZVwiIFtyb3dzXT1cIjhcIlxuICAgICAgICAgICAgICAgIFt0ZXh0YXJlYUlubGluZVN0eWxlXT1cIidwYWRkaW5nOiAxcmVtOydcIlxuICAgICAgICAgICAgICAgICh2YWx1ZUNoYW5nZSk9XCJnZXRDdXJyZW50UXVlcnlGb3JtR3JvdXAoKT8uZ2V0KCdxdWVyeScpPy5zZXRWYWx1ZSgkZXZlbnQpXCI+XG4gICAgICAgICAgICAgIDwvY3FhLWN1c3RvbS10ZXh0YXJlYT5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXgtMSBjcWEtb3ZlcmZsb3cteS1hdXRvIGNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtZ2FwLVsxMHB4XSBjcWEtbWItWzhweF1cIj5cblxuXG4gICAgICAgICAgPCEtLSBWYXJpYWJsZSBJbnB1dCAtLT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWdhcC00XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXgtMVwiPlxuICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRleHQtZ3JheS03MDAgY3FhLW1iLTEuNSBjcWEtYmxvY2sgY3FhLXRleHQtWzE0cHhdIGNxYS1mb250LXNlbWlib2xkXCI+XG4gICAgICAgICAgICAgICAgVmFyaWFibGVcbiAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgPGNxYS1jdXN0b20taW5wdXQgW3BsYWNlaG9sZGVyXT1cIidWYXJpYWJsZSBuYW1lJ1wiXG4gICAgICAgICAgICAgICAgW3ZhbHVlXT1cImdldEN1cnJlbnRRdWVyeUZvcm1Hcm91cCgpPy5nZXQoJ3ZhcmlhYmxlJyk/LnZhbHVlIHx8ICcnXCIgW2Z1bGxXaWR0aF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiZ2V0Q3VycmVudFF1ZXJ5Rm9ybUdyb3VwKCk/LmdldCgndmFyaWFibGUnKT8uc2V0VmFsdWUoJGV2ZW50KVwiPlxuICAgICAgICAgICAgICA8L2NxYS1jdXN0b20taW5wdXQ+XG4gICAgICAgICAgICAgIDxwIGNsYXNzPVwiY3FhLXRleHQteHMgY3FhLXRleHQtZ3JheS01MDAgY3FhLW10LTFcIj5cbiAgICAgICAgICAgICAgICBVc2UgbGV0dGVycywgbnVtYmVycywgdW5kZXJzY29yZS4gTm8gc3BhY2VzLiBVbmlxdWUgcGVyIHN0ZXAuIENhc2Ugc2Vuc2l0aXZlLlxuICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8IS0tIEFjdGlvbiBCdXR0b25zIChwaW5uZWQgdG8gYm90dG9tKSAtLT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtZ2FwLTIgY3FhLW10LWF1dG9cIj5cbiAgICAgICAgICAgIDxjcWEtYnV0dG9uIHZhcmlhbnQ9XCJvdXRsaW5lZFwiIHRleHQ9XCJBZGQgUXVlcnlcIiBpY29uPVwiYWRkXCIgKGNsaWNrZWQpPVwiYWRkTmV3UXVlcnkoKVwiXG4gICAgICAgICAgICAgIFtjdXN0b21DbGFzc109XCInY3FhLWJnLXdoaXRlICFjcWEtYm9yZGVyLVsjNDE0MTQ2XSBjcWEtdGV4dC1zbSBjcWEtZm9udC1zZW1pYm9sZCBjcWEtdGV4dC1bIzQxNDE0Nl0gY3FhLXdoaXRlc3BhY2Utbm93cmFwICFjcWEtcHktWzEwcHhdICFjcWEtcHgtWzEwcHhdICFjcWEtZ2FwLVs4cHhdIGNxYS1yb3VuZGVkLWxnIGhvdmVyOiFjcWEtYm9yZGVyLVsjNDE0MTQ2XSBob3ZlcjpjcWEtYmctZ3JheS01MCdcIlxuICAgICAgICAgICAgICBbaWNvbkNvbG9yXT1cIicjNDE0MTQ2J1wiPlxuICAgICAgICAgICAgPC9jcWEtYnV0dG9uPlxuICAgICAgICAgICAgPGNxYS1idXR0b24gdHlwZT1cImJ1dHRvblwiIHZhcmlhbnQ9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgW2N1c3RvbUNsYXNzXT1cIidjcWEtbWluLXctWzQwcHhdIGNxYS13LTEwIGNxYS1oLTkgY3FhLXJvdW5kZWQgY3FhLWJnLWdyYXktMTAwIGNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWp1c3RpZnktY2VudGVyIGhvdmVyOmNxYS1iZy1ncmF5LTIwMCBjcWEtcC0wJ1wiXG4gICAgICAgICAgICAgIFt0b29sdGlwXT1cIidEZWxldGUgcXVlcnknXCIgKGNsaWNrZWQpPVwiZGVsZXRlUXVlcnlCeUlkKGdldEN1cnJlbnRRdWVyeSgpPy5pZCB8fCAnJylcIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwicXVlcmllcy5sZW5ndGggPD0gMVwiIFthdHRyLmFyaWEtbGFiZWxdPVwiJ0RlbGV0ZSBxdWVyeSdcIj5cbiAgICAgICAgICAgICAgPHN2ZyBjbGFzcz1cImNxYS1mbGV4LXNocmluay0wXCIgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAxNiAxNlwiXG4gICAgICAgICAgICAgICAgZmlsbD1cIm5vbmVcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+XG4gICAgICAgICAgICAgICAgPHBhdGhcbiAgICAgICAgICAgICAgICAgIGQ9XCJNMTAuNjY2MyA2VjEyLjY2NjdINS4zMzMwMVY2SDEwLjY2NjNaTTkuNjY2MzQgMkg2LjMzMzAxTDUuNjY2MzQgMi42NjY2N0gzLjMzMzAxVjRIMTIuNjY2M1YyLjY2NjY3SDEwLjMzM0w5LjY2NjM0IDJaTTExLjk5OTcgNC42NjY2N0gzLjk5OTY3VjEyLjY2NjdDMy45OTk2NyAxMy40IDQuNTk5NjcgMTQgNS4zMzMwMSAxNEgxMC42NjYzQzExLjM5OTcgMTQgMTEuOTk5NyAxMy40IDExLjk5OTcgMTIuNjY2N1Y0LjY2NjY3WlwiXG4gICAgICAgICAgICAgICAgICBmaWxsPVwiIzZCNzI4MFwiIC8+XG4gICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgPC9jcWEtYnV0dG9uPlxuICAgICAgICAgICAgPGNxYS1idXR0b24gdmFyaWFudD1cImZpbGxlZFwiIHRleHQ9XCJSdW5cIiBpY29uPVwicGxheV9hcnJvd1wiIChjbGlja2VkKT1cIm9uUnVuUXVlcnkoKVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZ2V0Q3VycmVudFF1ZXJ5Rm9ybUdyb3VwKCk/LmdldCgncXVlcnknKT8udmFsdWUgfHwgIWRhdGFiYXNlRm9ybS5nZXQoJ2RiRW52aXJvbm1lbnQnKT8udmFsdWUgfHwgaXNMb2FkaW5nXCJcbiAgICAgICAgICAgICAgW2N1c3RvbUNsYXNzXT1cIichY3FhLWJnLVsjM0Y0M0VFXSBjcWEtdGV4dC1bI0ZCRkNGRl0gY3FhLXRleHQtc20gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXdoaXRlc3BhY2Utbm93cmFwICFjcWEtcHQtWzEwcHhdICFjcWEtcGItWzEwcHhdICFjcWEtcGwtWzE2cHhdICFjcWEtcHItWzI0cHhdICFjcWEtZ2FwLVs4cHhdIGNxYS1yb3VuZGVkLWxnIGNxYS1taW4taC1bMzhweF0gaG92ZXI6IWNxYS1iZy1bIzFCMUZFQl0gIWNxYS1ib3JkZXItbm9uZSdcIlxuICAgICAgICAgICAgICBbaWNvbkNvbG9yXT1cIicjRkJGQ0ZGJ1wiPlxuICAgICAgICAgICAgPC9jcWEtYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPCEtLSBSZXN1bHRzIFNlY3Rpb24gLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1ib3JkZXIgY3FhLWJvcmRlci1ncmF5LTIwMCBjcWEtcm91bmRlZC1sZyBjcWEtbWItNlwiPlxuICAgICAgICA8IS0tIFRhYnMgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLWdyYXktMjAwIGNxYS1iZy1ncmF5LTUwXCI+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwiY3FhLXB4LTQgY3FhLXB5LTIgY3FhLXRleHQtc20gY3FhLWZvbnQtbWVkaXVtIGNxYS10cmFuc2l0aW9uLWNvbG9ycyBjcWEtYm9yZGVyLWItMlwiXG4gICAgICAgICAgICBbY2xhc3MuY3FhLXRleHQtYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICdvdXRwdXQnXCIgW2NsYXNzLmNxYS1ib3JkZXItYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICdvdXRwdXQnXCJcbiAgICAgICAgICAgIFtjbGFzcy5jcWEtdGV4dC1ncmF5LTYwMF09XCJzZWxlY3RlZFRhYiAhPT0gJ291dHB1dCdcIlxuICAgICAgICAgICAgW2NsYXNzLmNxYS1ib3JkZXItdHJhbnNwYXJlbnRdPVwic2VsZWN0ZWRUYWIgIT09ICdvdXRwdXQnXCIgKGNsaWNrKT1cIm9uVGFiQ2hhbmdlKCdvdXRwdXQnKVwiPlxuICAgICAgICAgICAgT3V0cHV0XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGNsYXNzPVwiY3FhLXB4LTQgY3FhLXB5LTIgY3FhLXRleHQtc20gY3FhLWZvbnQtbWVkaXVtIGNxYS10cmFuc2l0aW9uLWNvbG9ycyBjcWEtYm9yZGVyLWItMlwiXG4gICAgICAgICAgICBbY2xhc3MuY3FhLXRleHQtYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICd2ZXJpZmljYXRpb24nXCJcbiAgICAgICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLWJsdWUtNjAwXT1cInNlbGVjdGVkVGFiID09PSAndmVyaWZpY2F0aW9uJ1wiXG4gICAgICAgICAgICBbY2xhc3MuY3FhLXRleHQtZ3JheS02MDBdPVwic2VsZWN0ZWRUYWIgIT09ICd2ZXJpZmljYXRpb24nXCJcbiAgICAgICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLXRyYW5zcGFyZW50XT1cInNlbGVjdGVkVGFiICE9PSAndmVyaWZpY2F0aW9uJ1wiIChjbGljayk9XCJvblRhYkNoYW5nZSgndmVyaWZpY2F0aW9uJylcIj5cbiAgICAgICAgICAgIFZlcmlmaWNhdGlvblxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIFRhYiBDb250ZW50IC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLXAtNFwiPlxuICAgICAgICAgIDwhLS0gT3V0cHV0IFRhYiAtLT5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwic2VsZWN0ZWRUYWIgPT09ICdvdXRwdXQnXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtanVzdGlmeS1iZXR3ZWVuIGNxYS1tYi0zXCI+XG4gICAgICAgICAgICAgIDxoNCBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktOTAwXCI+UXVlcnkgUmVzdWx0czwvaDQ+XG4gICAgICAgICAgICAgIDxjcWEtYnV0dG9uIHZhcmlhbnQ9XCJ0ZXh0XCIgdGV4dD1cIkNvcHlcIiBpY29uPVwiY29udGVudF9jb3B5XCIgW2N1c3RvbUNsYXNzXT1cIidjcWEtdGV4dC1ibHVlLTYwMCdcIlxuICAgICAgICAgICAgICAgIChjbGlja2VkKT1cIm9uQ29weVJlc3VsdHMoKVwiPlxuICAgICAgICAgICAgICA8L2NxYS1idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPCEtLSBSZXN1bHRzIFRhYmxlIC0tPlxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cInF1ZXJ5UmVzdWx0cyAmJiBxdWVyeVJlc3VsdHMubGVuZ3RoID4gMFwiIGNsYXNzPVwiY3FhLW92ZXJmbG93LXgtYXV0b1wiPlxuICAgICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJjcWEtdy1mdWxsIGNxYS1ib3JkZXItY29sbGFwc2VcIj5cbiAgICAgICAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICAgICAgICA8dHIgY2xhc3M9XCJjcWEtYmctZ3JheS01MCBjcWEtYm9yZGVyLWIgY3FhLWJvcmRlci1ncmF5LTIwMFwiPlxuICAgICAgICAgICAgICAgICAgICA8dGggKm5nRm9yPVwibGV0IGtleSBvZiBnZXRUYWJsZUNvbHVtbnMoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJjcWEtcHgtNCBjcWEtcHktMiBjcWEtdGV4dC1sZWZ0IGNxYS10ZXh0LXhzIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktNzAwIGNxYS11cHBlcmNhc2VcIj5cbiAgICAgICAgICAgICAgICAgICAgICB7eyBrZXkgfX1cbiAgICAgICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICAgICAgICA8dHIgKm5nRm9yPVwibGV0IHJvdyBvZiBxdWVyeVJlc3VsdHNcIiBjbGFzcz1cImNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLWdyYXktMjAwIGhvdmVyOmNxYS1iZy1ncmF5LTUwXCI+XG4gICAgICAgICAgICAgICAgICAgIDx0ZCAqbmdGb3I9XCJsZXQga2V5IG9mIGdldFRhYmxlQ29sdW1ucygpXCIgY2xhc3M9XCJjcWEtcHgtNCBjcWEtcHktMiBjcWEtdGV4dC1zbSBjcWEtdGV4dC1ncmF5LTkwMFwiPlxuICAgICAgICAgICAgICAgICAgICAgIHt7IHJvd1trZXldIH19XG4gICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgICAgICAgIDwvdGFibGU+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPGRpdiAqbmdJZj1cIiFxdWVyeVJlc3VsdHMgfHwgcXVlcnlSZXN1bHRzLmxlbmd0aCA9PT0gMFwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiY3FhLXRleHQtY2VudGVyIGNxYS1weS04IGNxYS10ZXh0LWdyYXktNDAwIGNxYS10ZXh0LXNtXCI+XG4gICAgICAgICAgICAgIE5vIHJlc3VsdHMgeWV0LiBSdW4gYSBxdWVyeSB0byBzZWUgcmVzdWx0cy5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPCEtLSBWZXJpZmljYXRpb24gVGFiIC0tPlxuICAgICAgICAgIDxkaXYgKm5nSWY9XCJzZWxlY3RlZFRhYiA9PT0gJ3ZlcmlmaWNhdGlvbidcIj5cbiAgICAgICAgICAgIDxwIGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLXRleHQtZ3JheS02MDBcIj5WZXJpZmljYXRpb24gc2V0dGluZ3Mgd2lsbCBiZSBhdmFpbGFibGUgaGVyZS48L3A+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG5cblxuICA8IS0tIEFjdGlvbiBCdXR0b25zIC0tPlxuICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLXctZnVsbCBjcWEtZ2FwLTIgY3FhLW10LWF1dG8gY3FhLXB0LTQgY3FhLWJvcmRlci10IGNxYS1ib3JkZXItZ3JheS0yMDBcIj5cbiAgICA8Y3FhLWJ1dHRvbiBjbGFzcz1cImNxYS13LTEvMlwiIHZhcmlhbnQ9XCJvdXRsaW5lZFwiIHRleHQ9XCJDYW5jZWxcIiBbY3VzdG9tQ2xhc3NdPVwiJ2NxYS1mbGV4LTEgY3FhLXctZnVsbCdcIlxuICAgICAgKGNsaWNrZWQpPVwib25DYW5jZWwoKVwiPlxuICAgIDwvY3FhLWJ1dHRvbj5cbiAgICA8Y3FhLWJ1dHRvbiBjbGFzcz1cImNxYS13LTEvMlwiIHZhcmlhbnQ9XCJmaWxsZWRcIiBbdGV4dF09XCJlZGl0TW9kZSA/ICdVcGRhdGUgU3RlcCcgOiAnQ3JlYXRlIFN0ZXAnXCIgW2N1c3RvbUNsYXNzXT1cIidjcWEtZmxleC0xIGNxYS13LWZ1bGwnXCJcbiAgICAgIChjbGlja2VkKT1cIm9uQ3JlYXRlU3RlcCgpXCI+XG4gICAgPC9jcWEtYnV0dG9uPlxuICA8L2Rpdj5cbjwvZGl2PiJdfQ==
|
|
736
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1idWlsZGVyLWRhdGFiYXNlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc3RlcC1idWlsZGVyL3N0ZXAtYnVpbGRlci1kYXRhYmFzZS9zdGVwLWJ1aWxkZXItZGF0YWJhc2UuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zdGVwLWJ1aWxkZXIvc3RlcC1idWlsZGVyLWRhdGFiYXNlL3N0ZXAtYnVpbGRlci1kYXRhYmFzZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFvQyxTQUFTLEVBQWdDLE1BQU0sZUFBZSxDQUFDO0FBQ2xKLE9BQU8sRUFBZSxTQUFTLEVBQTBCLFVBQVUsRUFBbUIsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF3QjdHLE1BQU0sT0FBTyw0QkFBNEI7SUFzRHZDLFlBQ1UsRUFBZSxFQUNmLEdBQXNCO1FBRHRCLE9BQUUsR0FBRixFQUFFLENBQWE7UUFDZixRQUFHLEdBQUgsR0FBRyxDQUFtQjtRQXZEaEMsMENBQTBDO1FBQ2pDLHlCQUFvQixHQUFtQixFQUFFLENBQUM7UUFFbkQsMkJBQTJCO1FBQ2xCLFlBQU8sR0FBb0IsRUFBRSxDQUFDO1FBRXZDLHlCQUF5QjtRQUNoQixpQkFBWSxHQUFVLEVBQUUsQ0FBQztRQUVsQyxvQkFBb0I7UUFDWCxjQUFTLEdBQVksS0FBSyxDQUFDO1FBUXBDLGdDQUFnQztRQUN0QixlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQW9CLENBQUM7UUFFNUQsMEJBQTBCO1FBQ2hCLGNBQVMsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBRS9DLDZCQUE2QjtRQUNuQixhQUFRLEdBQUcsSUFBSSxZQUFZLEVBQThELENBQUM7UUFFcEcsK0JBQStCO1FBQ3JCLGFBQVEsR0FB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c0JBQXNCLEVBQUUsQ0FBQyxRQUFRLENBQUM7SUFDaEQsQ0FBQztJQUVEOztPQUVHO0lBQ0gsWUFBWSxDQUFDLEtBQWE7UUFDeEIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsV0FBVztRQUNULHlCQUF5QjtRQUN6QixJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2pDLENBQUM7O3lIQXB1QlUsNEJBQTRCOzZHQUE1Qiw0QkFBNEIsd3NCQ3pCekMsdWdyQkE2WE07MkZEcFdPLDRCQUE0QjtrQkFOeEMsU0FBUzsrQkFDRSwyQkFBMkIsUUFHL0IsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFO2tJQUlyQixvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBR0csT0FBTztzQkFBZixLQUFLO2dCQUdHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBR0csU0FBUztzQkFBakIsS0FBSztnQkFHRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBR0csUUFBUTtzQkFBaEIsS0FBSztnQkFHSSxVQUFVO3NCQUFuQixNQUFNO2dCQUdHLFNBQVM7c0JBQWxCLE1BQU07Z0JBR0csUUFBUTtzQkFBakIsTUFBTTtnQkFHRyxRQUFRO3NCQUFqQixNQUFNO2dCQUdHLFdBQVc7c0JBQXBCLE1BQU07Z0JBR0csbUJBQW1CO3NCQUE1QixNQUFNO2dCQUdHLHdCQUF3QjtzQkFBakMsTUFBTTtnQkFHRyxlQUFlO3NCQUF4QixNQUFNO2dCQVd1QixlQUFlO3NCQUE1QyxTQUFTO3VCQUFDLGlCQUFpQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBPbkluaXQsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcywgVmlld0NoaWxkLCBDaGFuZ2VEZXRlY3RvclJlZiwgT25EZXN0cm95IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBGb3JtQXJyYXksIEZvcm1Db250cm9sLCBWYWxpZGF0b3JzLCBBYnN0cmFjdENvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEeW5hbWljU2VsZWN0RmllbGRDb25maWcsIFNlbGVjdE9wdGlvbiB9IGZyb20gJy4uLy4uL2R5bmFtaWMtc2VsZWN0L2R5bmFtaWMtc2VsZWN0LWZpZWxkLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBNYXRUYWJsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3RhYmxlJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIERhdGFiYXNlUXVlcnkge1xuICBpZDogc3RyaW5nO1xuICBxdWVyeTogc3RyaW5nO1xuICB2YXJpYWJsZTogc3RyaW5nO1xuICBzdGF0dXM/OiAncGFzc2VkJyB8ICdmYWlsZWQnIHwgJ3BlbmRpbmcnO1xuICBhc3NlcnRpb25EYXRhPzogYW55W107IC8vIEFzc2VydGlvbiBkYXRhIGZvciB2ZXJpZmljYXRpb25cbn1cblxuZXhwb3J0IGludGVyZmFjZSBEYXRhYmFzZUZvcm1EYXRhIHtcbiAgZGJFbnZpcm9ubWVudDogc3RyaW5nO1xuICBxdWVyaWVzOiBEYXRhYmFzZVF1ZXJ5W107XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2NxYS1zdGVwLWJ1aWxkZXItZGF0YWJhc2UnLFxuICB0ZW1wbGF0ZVVybDogJy4vc3RlcC1idWlsZGVyLWRhdGFiYXNlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbXSxcbiAgaG9zdDogeyBjbGFzczogJ2NxYS11aS1yb290JyB9XG59KVxuZXhwb3J0IGNsYXNzIFN0ZXBCdWlsZGVyRGF0YWJhc2VDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgLyoqIE9wdGlvbnMgZm9yIERCIGVudmlyb25tZW50IGRyb3Bkb3duICovXG4gIEBJbnB1dCgpIGRiRW52aXJvbm1lbnRPcHRpb25zOiBTZWxlY3RPcHRpb25bXSA9IFtdO1xuXG4gIC8qKiBJbml0aWFsIHF1ZXJpZXMgbGlzdCAqL1xuICBASW5wdXQoKSBxdWVyaWVzOiBEYXRhYmFzZVF1ZXJ5W10gPSBbXTtcblxuICAvKiogUXVlcnkgcmVzdWx0cyBkYXRhICovXG4gIEBJbnB1dCgpIHF1ZXJ5UmVzdWx0czogYW55W10gPSBbXTtcblxuICAvKiogTG9hZGluZyBzdGF0ZSAqL1xuICBASW5wdXQoKSBpc0xvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogSW5pdGlhbCBEQiBlbnZpcm9ubWVudCBmb3IgZWRpdCBtb2RlICovXG4gIEBJbnB1dCgpIGluaXRpYWxEYkVudmlyb25tZW50Pzogc3RyaW5nO1xuXG4gIC8qKiBXaGV0aGVyIGluIGVkaXQgbW9kZSAqL1xuICBASW5wdXQoKSBlZGl0TW9kZT86IGJvb2xlYW47XG5cbiAgLyoqIEVtaXQgd2hlbiBzdGVwIGlzIGNyZWF0ZWQgKi9cbiAgQE91dHB1dCgpIGNyZWF0ZVN0ZXAgPSBuZXcgRXZlbnRFbWl0dGVyPERhdGFiYXNlRm9ybURhdGE+KCk7XG5cbiAgLyoqIEVtaXQgd2hlbiBjYW5jZWxsZWQgKi9cbiAgQE91dHB1dCgpIGNhbmNlbGxlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICAvKiogRW1pdCB3aGVuIHF1ZXJ5IGlzIHJ1biAqL1xuICBAT3V0cHV0KCkgcnVuUXVlcnkgPSBuZXcgRXZlbnRFbWl0dGVyPHsgcXVlcnk6IHN0cmluZzsgdmFyaWFibGU6IHN0cmluZzsgZGJFbnZpcm9ubWVudDogc3RyaW5nIH0+KCk7XG5cbiAgLyoqIEVtaXQgd2hlbiBxdWVyeSBpcyBhZGRlZCAqL1xuICBAT3V0cHV0KCkgYWRkUXVlcnkgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgLyoqIEVtaXQgd2hlbiBxdWVyeSBpcyBkZWxldGVkICovXG4gIEBPdXRwdXQoKSBkZWxldGVRdWVyeSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIC8qKiBFbWl0IHdoZW4gYXNzZXJ0aW9uIGRhdGEgY2hhbmdlcyBmb3IgYSBxdWVyeSAqL1xuICBAT3V0cHV0KCkgYXNzZXJ0aW9uRGF0YUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8eyBxdWVyeUluZGV4OiBudW1iZXI7IGFzc2VydGlvbkRhdGE6IGFueVtdIH0+KCk7XG5cbiAgLyoqIEVtaXQgd2hlbiBzZWxlY3RlZCBxdWVyeSBpbmRleCBjaGFuZ2VzICovXG4gIEBPdXRwdXQoKSBzZWxlY3RlZFF1ZXJ5SW5kZXhDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcblxuICAvKiogRW1pdCB3aGVuIGFjdGl2ZSB0YWIgY2hhbmdlcyAqL1xuICBAT3V0cHV0KCkgYWN0aXZlVGFiQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjwnb3V0cHV0JyB8ICd2ZXJpZmljYXRpb24nPigpO1xuXG4gIGRhdGFiYXNlRm9ybTogRm9ybUdyb3VwO1xuICBzZWxlY3RlZFRhYjogJ291dHB1dCcgfCAndmVyaWZpY2F0aW9uJyA9ICdvdXRwdXQnO1xuICBzZWxlY3RlZFF1ZXJ5SW5kZXg6IG51bWJlciA9IDA7XG5cbiAgLy8gQXNzZXJ0aW9ucyBmb3JtIG1hbmFnZW1lbnQgLSBvbmUgZm9ybSBwZXIgcXVlcnlcbiAgYXNzZXJ0aW9uc0Zvcm1zOiBNYXA8bnVtYmVyLCBGb3JtR3JvdXA+ID0gbmV3IE1hcCgpO1xuICBkaXNwbGF5ZWRDb2x1bW5zOiBzdHJpbmdbXSA9IFsnanNvblBhdGgnLCAndmVyaWZpY2F0aW9uVHlwZScsICdleHBlY3RlZFR5cGUnLCAnZXhwZWN0ZWRWYWx1ZScsICdhY3Rpb25zJ107XG4gIGRlZmF1bHRFeHBlY3RlZFR5cGUgPSAnc3RyaW5nJztcbiAgcHJpdmF0ZSBmb3JtU3Vic2NyaXB0aW9uczogTWFwPG51bWJlciwgU3Vic2NyaXB0aW9uPiA9IG5ldyBNYXAoKTtcbiAgQFZpZXdDaGlsZCgnYXNzZXJ0aW9uc1RhYmxlJykgYXNzZXJ0aW9uc1RhYmxlPzogTWF0VGFibGU8YW55PjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGZiOiBGb3JtQnVpbGRlcixcbiAgICBwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWZcbiAgKSB7XG4gICAgdGhpcy5kYXRhYmFzZUZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIGRiRW52aXJvbm1lbnQ6IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICBxdWVyaWVzOiB0aGlzLmZiLmFycmF5KFtdKVxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5pbml0aWFsaXplRm9ybVdpdGhJbml0aWFsVmFsdWVzKCk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ3F1ZXJpZXMnXSAmJiAhY2hhbmdlc1sncXVlcmllcyddLmZpcnN0Q2hhbmdlKSB7XG4gICAgICAvLyBSZWJ1aWxkIGZvcm0gYXJyYXkgd2hlbiBxdWVyaWVzIGNoYW5nZVxuICAgICAgY29uc3QgcXVlcmllc0FycmF5ID0gdGhpcy5kYXRhYmFzZUZvcm0uZ2V0KCdxdWVyaWVzJykgYXMgRm9ybUFycmF5O1xuICAgICAgd2hpbGUgKHF1ZXJpZXNBcnJheS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgcXVlcmllc0FycmF5LnJlbW92ZUF0KDApO1xuICAgICAgfVxuICAgICAgLy8gQ2xlYXIgb2xkIGFzc2VydGlvbnMgZm9ybXNcbiAgICAgIHRoaXMuYXNzZXJ0aW9uc0Zvcm1zLmZvckVhY2goKGZvcm0sIGluZGV4KSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmZvcm1TdWJzY3JpcHRpb25zLmhhcyhpbmRleCkpIHtcbiAgICAgICAgICB0aGlzLmZvcm1TdWJzY3JpcHRpb25zLmdldChpbmRleCkhLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy5hc3NlcnRpb25zRm9ybXMuY2xlYXIoKTtcbiAgICAgIHRoaXMuZm9ybVN1YnNjcmlwdGlvbnMuY2xlYXIoKTtcblxuICAgICAgLy8gUmVidWlsZCBxdWVyaWVzIGFuZCBhc3NlcnRpb25zIGZvcm1zXG4gICAgICB0aGlzLnF1ZXJpZXMuZm9yRWFjaCgocXVlcnksIGluZGV4KSA9PiB7XG4gICAgICAgIC8vIEVuc3VyZSBhc3NlcnRpb24gZGF0YSBpcyBpbml0aWFsaXplZFxuICAgICAgICBpZiAoIXF1ZXJ5LmFzc2VydGlvbkRhdGEpIHtcbiAgICAgICAgICBxdWVyeS5hc3NlcnRpb25EYXRhID0gW107XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5hZGRRdWVyeVRvRm9ybShxdWVyeSk7XG4gICAgICAgIC8vIEluaXRpYWxpemUgYXNzZXJ0aW9ucyBmb3JtIGZvciBlYWNoIHF1ZXJ5XG4gICAgICAgIHRoaXMuZW5zdXJlQXNzZXJ0aW9uRGF0YUluaXRpYWxpemVkKGluZGV4KTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBFbnN1cmUgc2VsZWN0ZWQgcXVlcnkgaW5kZXggaXMgdmFsaWRcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA+PSB0aGlzLnF1ZXJpZXMubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4ID0gTWF0aC5tYXgoMCwgdGhpcy5xdWVyaWVzLmxlbmd0aCAtIDEpO1xuICAgICAgfVxuICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlc1snaW5pdGlhbERiRW52aXJvbm1lbnQnXSAmJiBjaGFuZ2VzWydpbml0aWFsRGJFbnZpcm9ubWVudCddLmN1cnJlbnRWYWx1ZSkge1xuICAgICAgdGhpcy5kYXRhYmFzZUZvcm0ucGF0Y2hWYWx1ZSh7IGRiRW52aXJvbm1lbnQ6IGNoYW5nZXNbJ2luaXRpYWxEYkVudmlyb25tZW50J10uY3VycmVudFZhbHVlIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgaW5pdGlhbGl6ZUZvcm1XaXRoSW5pdGlhbFZhbHVlcygpOiB2b2lkIHtcbiAgICAvLyBTZXQgaW5pdGlhbCBEQiBlbnZpcm9ubWVudCBpZiBwcm92aWRlZFxuICAgIGlmICh0aGlzLmluaXRpYWxEYkVudmlyb25tZW50KSB7XG4gICAgICB0aGlzLmRhdGFiYXNlRm9ybS5wYXRjaFZhbHVlKHsgZGJFbnZpcm9ubWVudDogdGhpcy5pbml0aWFsRGJFbnZpcm9ubWVudCB9KTtcbiAgICB9XG5cbiAgICAvLyBJbml0aWFsaXplIHdpdGggcXVlcmllcyBpZiBwcm92aWRlZCwgb3RoZXJ3aXNlIGFkZCBkZWZhdWx0IHF1ZXJ5XG4gICAgaWYgKHRoaXMucXVlcmllcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMuYWRkTmV3UXVlcnkoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5xdWVyaWVzLmZvckVhY2goKHF1ZXJ5LCBpbmRleCkgPT4ge1xuICAgICAgICAvLyBFbnN1cmUgYXNzZXJ0aW9uIGRhdGEgaXMgaW5pdGlhbGl6ZWRcbiAgICAgICAgaWYgKCFxdWVyeS5hc3NlcnRpb25EYXRhKSB7XG4gICAgICAgICAgcXVlcnkuYXNzZXJ0aW9uRGF0YSA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYWRkUXVlcnlUb0Zvcm0ocXVlcnkpO1xuICAgICAgICAvLyBJbml0aWFsaXplIGFzc2VydGlvbnMgZm9ybSBmb3IgZWFjaCBxdWVyeVxuICAgICAgICB0aGlzLmVuc3VyZUFzc2VydGlvbkRhdGFJbml0aWFsaXplZChpbmRleCk7XG4gICAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4ID0gMDtcbiAgICAgICAgICB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleENoYW5nZS5lbWl0KDApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBnZXQgcXVlcmllc0Zvcm1BcnJheSgpOiBGb3JtQXJyYXkge1xuICAgIHJldHVybiB0aGlzLmRhdGFiYXNlRm9ybS5nZXQoJ3F1ZXJpZXMnKSBhcyBGb3JtQXJyYXk7XG4gIH1cblxuICBhZGROZXdRdWVyeSgpOiB2b2lkIHtcbiAgICBjb25zdCBuZXdRdWVyeTogRGF0YWJhc2VRdWVyeSA9IHtcbiAgICAgIGlkOiBgcXVlcnlfJHtEYXRlLm5vdygpfWAsXG4gICAgICBxdWVyeTogJycsXG4gICAgICB2YXJpYWJsZTogJycsXG4gICAgICBzdGF0dXM6ICdwZW5kaW5nJyxcbiAgICAgIGFzc2VydGlvbkRhdGE6IFtdIC8vIEluaXRpYWxpemUgd2l0aCBlbXB0eSBhc3NlcnRpb24gZGF0YVxuICAgIH07XG4gICAgdGhpcy5xdWVyaWVzLnB1c2gobmV3UXVlcnkpO1xuICAgIHRoaXMuYWRkUXVlcnlUb0Zvcm0obmV3UXVlcnkpO1xuICAgIGNvbnN0IG5ld0luZGV4ID0gdGhpcy5xdWVyaWVzLmxlbmd0aCAtIDE7XG4gICAgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPSBuZXdJbmRleDtcbiAgICAvLyBJbml0aWFsaXplIGFzc2VydGlvbnMgZm9ybSBmb3IgdGhlIG5ldyBxdWVyeVxuICAgIHRoaXMuZW5zdXJlQXNzZXJ0aW9uRGF0YUluaXRpYWxpemVkKG5ld0luZGV4KTtcbiAgICB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleENoYW5nZS5lbWl0KHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4KTtcbiAgICB0aGlzLmFkZFF1ZXJ5LmVtaXQoKTtcbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBwcml2YXRlIGFkZFF1ZXJ5VG9Gb3JtKHF1ZXJ5OiBEYXRhYmFzZVF1ZXJ5KTogdm9pZCB7XG4gICAgY29uc3QgcXVlcnlHcm91cCA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgaWQ6IFtxdWVyeS5pZF0sXG4gICAgICBxdWVyeTogW3F1ZXJ5LnF1ZXJ5LCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgIHZhcmlhYmxlOiBbcXVlcnkudmFyaWFibGUsIFZhbGlkYXRvcnMucmVxdWlyZWRdXG4gICAgfSk7XG4gICAgdGhpcy5xdWVyaWVzRm9ybUFycmF5LnB1c2gocXVlcnlHcm91cCk7XG4gIH1cblxuICBkZWxldGVRdWVyeUJ5SWQocXVlcnlJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLnF1ZXJpZXMuZmluZEluZGV4KHEgPT4gcS5pZCA9PT0gcXVlcnlJZCk7XG4gICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgLy8gQ2xlYW4gdXAgYXNzZXJ0aW9ucyBmb3JtIGFuZCBzdWJzY3JpcHRpb24gZm9yIHRoaXMgcXVlcnlcbiAgICAgIGlmICh0aGlzLmZvcm1TdWJzY3JpcHRpb25zLmhhcyhpbmRleCkpIHtcbiAgICAgICAgdGhpcy5mb3JtU3Vic2NyaXB0aW9ucy5nZXQoaW5kZXgpIS51bnN1YnNjcmliZSgpO1xuICAgICAgICB0aGlzLmZvcm1TdWJzY3JpcHRpb25zLmRlbGV0ZShpbmRleCk7XG4gICAgICB9XG4gICAgICB0aGlzLmFzc2VydGlvbnNGb3Jtcy5kZWxldGUoaW5kZXgpO1xuXG4gICAgICAvLyBSZWluZGV4IHJlbWFpbmluZyBmb3JtcyBhbmQgc3Vic2NyaXB0aW9uc1xuICAgICAgY29uc3QgZm9ybXNUb1JlaW5kZXggPSBuZXcgTWFwPG51bWJlciwgRm9ybUdyb3VwPigpO1xuICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uc1RvUmVpbmRleCA9IG5ldyBNYXA8bnVtYmVyLCBTdWJzY3JpcHRpb24+KCk7XG4gICAgICBcbiAgICAgIHRoaXMuYXNzZXJ0aW9uc0Zvcm1zLmZvckVhY2goKGZvcm0sIG9sZEluZGV4KSA9PiB7XG4gICAgICAgIGlmIChvbGRJbmRleCA+IGluZGV4KSB7XG4gICAgICAgICAgZm9ybXNUb1JlaW5kZXguc2V0KG9sZEluZGV4IC0gMSwgZm9ybSk7XG4gICAgICAgIH0gZWxzZSBpZiAob2xkSW5kZXggPCBpbmRleCkge1xuICAgICAgICAgIGZvcm1zVG9SZWluZGV4LnNldChvbGRJbmRleCwgZm9ybSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmZvcm1TdWJzY3JpcHRpb25zLmZvckVhY2goKHN1Yiwgb2xkSW5kZXgpID0+IHtcbiAgICAgICAgaWYgKG9sZEluZGV4ID4gaW5kZXgpIHtcbiAgICAgICAgICBzdWJzY3JpcHRpb25zVG9SZWluZGV4LnNldChvbGRJbmRleCAtIDEsIHN1Yik7XG4gICAgICAgIH0gZWxzZSBpZiAob2xkSW5kZXggPCBpbmRleCkge1xuICAgICAgICAgIHN1YnNjcmlwdGlvbnNUb1JlaW5kZXguc2V0KG9sZEluZGV4LCBzdWIpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdGhpcy5hc3NlcnRpb25zRm9ybXMgPSBmb3Jtc1RvUmVpbmRleDtcbiAgICAgIHRoaXMuZm9ybVN1YnNjcmlwdGlvbnMgPSBzdWJzY3JpcHRpb25zVG9SZWluZGV4O1xuXG4gICAgICB0aGlzLnF1ZXJpZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIHRoaXMucXVlcmllc0Zvcm1BcnJheS5yZW1vdmVBdChpbmRleCk7XG4gICAgICBpZiAodGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPj0gdGhpcy5xdWVyaWVzLmxlbmd0aCkge1xuICAgICAgICB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA9IE1hdGgubWF4KDAsIHRoaXMucXVlcmllcy5sZW5ndGggLSAxKTtcbiAgICAgICAgLy8gRW5zdXJlIGFzc2VydGlvbnMgZm9ybSBpcyBpbml0aWFsaXplZCBmb3IgdGhlIG5ldyBzZWxlY3RlZCBxdWVyeVxuICAgICAgICBpZiAodGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPj0gMCkge1xuICAgICAgICAgIHRoaXMuZW5zdXJlQXNzZXJ0aW9uRGF0YUluaXRpYWxpemVkKHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgdGhpcy5kZWxldGVRdWVyeS5lbWl0KHF1ZXJ5SWQpO1xuICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cbiAgfVxuXG4gIGdldERiRW52aXJvbm1lbnRDb25maWcoKTogRHluYW1pY1NlbGVjdEZpZWxkQ29uZmlnIHtcbiAgICByZXR1cm4ge1xuICAgICAga2V5OiAnZGJFbnZpcm9ubWVudCcsXG4gICAgICBwbGFjZWhvbGRlcjogJ1NlbGVjdCBEQiBlbnZpcm9ubWVudCcsXG4gICAgICBtdWx0aXBsZTogZmFsc2UsXG4gICAgICBzZWFyY2hhYmxlOiBmYWxzZSxcbiAgICAgIG9wdGlvbnM6IHRoaXMuZGJFbnZpcm9ubWVudE9wdGlvbnNcbiAgICB9O1xuICB9XG5cbiAgZ2V0Q3VycmVudFF1ZXJ5KCk6IERhdGFiYXNlUXVlcnkgfCBudWxsIHtcbiAgICBpZiAodGhpcy5xdWVyaWVzLmxlbmd0aCA+IDAgJiYgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPj0gMCAmJiB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA8IHRoaXMucXVlcmllcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0aGlzLnF1ZXJpZXNbdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXhdO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGdldEN1cnJlbnRRdWVyeUZvcm1Hcm91cCgpOiBGb3JtR3JvdXAgfCBudWxsIHtcbiAgICBpZiAodGhpcy5xdWVyaWVzRm9ybUFycmF5ICYmIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4ID49IDAgJiYgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPCB0aGlzLnF1ZXJpZXNGb3JtQXJyYXkubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcy5xdWVyaWVzRm9ybUFycmF5LmF0KHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4KSBhcyBGb3JtR3JvdXA7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgb25SdW5RdWVyeSgpOiB2b2lkIHtcbiAgICBjb25zdCBkYkVudmlyb25tZW50ID0gdGhpcy5kYXRhYmFzZUZvcm0uZ2V0KCdkYkVudmlyb25tZW50Jyk/LnZhbHVlO1xuICAgIGNvbnN0IGN1cnJlbnRRdWVyeSA9IHRoaXMuZ2V0Q3VycmVudFF1ZXJ5KCk7XG4gICAgY29uc3QgcXVlcnlGb3JtR3JvdXAgPSB0aGlzLmdldEN1cnJlbnRRdWVyeUZvcm1Hcm91cCgpO1xuXG4gICAgaWYgKGN1cnJlbnRRdWVyeSAmJiBxdWVyeUZvcm1Hcm91cCAmJiBkYkVudmlyb25tZW50KSB7XG4gICAgICBjb25zdCBxdWVyeSA9IHF1ZXJ5Rm9ybUdyb3VwLmdldCgncXVlcnknKT8udmFsdWUgfHwgJyc7XG4gICAgICBjb25zdCB2YXJpYWJsZSA9IHF1ZXJ5Rm9ybUdyb3VwLmdldCgndmFyaWFibGUnKT8udmFsdWUgfHwgJyc7XG4gICAgICBcbiAgICAgIC8vIFVwZGF0ZSB0aGUgcXVlcnkgb2JqZWN0XG4gICAgICBjdXJyZW50UXVlcnkucXVlcnkgPSBxdWVyeTtcbiAgICAgIGN1cnJlbnRRdWVyeS52YXJpYWJsZSA9IHZhcmlhYmxlO1xuXG4gICAgICB0aGlzLnJ1blF1ZXJ5LmVtaXQoe1xuICAgICAgICBxdWVyeSxcbiAgICAgICAgdmFyaWFibGUsXG4gICAgICAgIGRiRW52aXJvbm1lbnRcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9uU2VsZWN0UXVlcnkoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIC8vIEVuc3VyZSBhc3NlcnRpb24gZGF0YSBpcyBpbml0aWFsaXplZCBmb3IgdGhlIHNlbGVjdGVkIHF1ZXJ5XG4gICAgdGhpcy5lbnN1cmVBc3NlcnRpb25EYXRhSW5pdGlhbGl6ZWQoaW5kZXgpO1xuICAgIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4ID0gaW5kZXg7XG4gICAgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXhDaGFuZ2UuZW1pdChpbmRleCk7XG4gICAgLy8gVHJpZ2dlciBjaGFuZ2UgZGV0ZWN0aW9uIHRvIGVuc3VyZSBhc3NlcnRpb25zIGZvcm0gaXMgZGlzcGxheWVkXG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgY3VycmVudGx5IHNlbGVjdGVkIHF1ZXJ5IGluZGV4XG4gICAqL1xuICBnZXRTZWxlY3RlZFF1ZXJ5SW5kZXgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBjdXJyZW50bHkgYWN0aXZlIHRhYlxuICAgKi9cbiAgZ2V0QWN0aXZlVGFiKCk6ICdvdXRwdXQnIHwgJ3ZlcmlmaWNhdGlvbicge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkVGFiO1xuICB9XG5cbiAgb25UYWJDaGFuZ2UodGFiOiAnb3V0cHV0JyB8ICd2ZXJpZmljYXRpb24nKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZFRhYiA9IHRhYjtcbiAgICB0aGlzLmFjdGl2ZVRhYkNoYW5nZS5lbWl0KHRhYik7XG4gICAgLy8gRW5zdXJlIGFzc2VydGlvbnMgZm9ybSBpcyBpbml0aWFsaXplZCB3aGVuIHN3aXRjaGluZyB0byB2ZXJpZmljYXRpb24gdGFiXG4gICAgaWYgKHRhYiA9PT0gJ3ZlcmlmaWNhdGlvbicpIHtcbiAgICAgIHRoaXMuZW5zdXJlQXNzZXJ0aW9uRGF0YUluaXRpYWxpemVkKHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4KTtcbiAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICB9XG4gIH1cblxuICBvbkNvcHlSZXN1bHRzKCk6IHZvaWQge1xuICAgIC8vIENvcHkgcXVlcnkgcmVzdWx0cyB0byBjbGlwYm9hcmRcbiAgICBpZiAodGhpcy5xdWVyeVJlc3VsdHMgJiYgdGhpcy5xdWVyeVJlc3VsdHMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgdGV4dCA9IEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnlSZXN1bHRzLCBudWxsLCAyKTtcbiAgICAgIG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KHRleHQpLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyBDb3VsZCBlbWl0IGFuIGV2ZW50IG9yIHNob3cgYSB0b2FzdCBub3RpZmljYXRpb25cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9uQ2FuY2VsKCk6IHZvaWQge1xuICAgIHRoaXMuY2FuY2VsbGVkLmVtaXQoKTtcbiAgfVxuXG4gIG9uQ3JlYXRlU3RlcCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kYXRhYmFzZUZvcm0udmFsaWQpIHtcbiAgICAgIGNvbnN0IGZvcm1WYWx1ZSA9IHRoaXMuZGF0YWJhc2VGb3JtLnZhbHVlO1xuICAgICAgY29uc3Qgc3RlcERhdGE6IERhdGFiYXNlRm9ybURhdGEgPSB7XG4gICAgICAgIGRiRW52aXJvbm1lbnQ6IGZvcm1WYWx1ZS5kYkVudmlyb25tZW50LFxuICAgICAgICBxdWVyaWVzOiB0aGlzLnF1ZXJpZXMubWFwKChxdWVyeSwgaW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCBxdWVyeUZvcm1Hcm91cCA9IHRoaXMucXVlcmllc0Zvcm1BcnJheS5hdChpbmRleCkgYXMgRm9ybUdyb3VwO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpZDogcXVlcnkuaWQsXG4gICAgICAgICAgICBxdWVyeTogcXVlcnlGb3JtR3JvdXAuZ2V0KCdxdWVyeScpPy52YWx1ZSB8fCAnJyxcbiAgICAgICAgICAgIHZhcmlhYmxlOiBxdWVyeUZvcm1Hcm91cC5nZXQoJ3ZhcmlhYmxlJyk/LnZhbHVlIHx8ICcnLFxuICAgICAgICAgICAgc3RhdHVzOiBxdWVyeS5zdGF0dXMsXG4gICAgICAgICAgICBhc3NlcnRpb25EYXRhOiBxdWVyeS5hc3NlcnRpb25EYXRhIHx8IFtdIC8vIEluY2x1ZGUgYXNzZXJ0aW9uIGRhdGFcbiAgICAgICAgICB9O1xuICAgICAgICB9KVxuICAgICAgfTtcbiAgICAgIHRoaXMuY3JlYXRlU3RlcC5lbWl0KHN0ZXBEYXRhKTtcbiAgICB9XG4gIH1cblxuICBnZXRUYWJsZUNvbHVtbnMoKTogc3RyaW5nW10ge1xuICAgIGlmICghdGhpcy5xdWVyeVJlc3VsdHMgfHwgdGhpcy5xdWVyeVJlc3VsdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnF1ZXJ5UmVzdWx0c1swXSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFzc2VydGlvbiBkYXRhIGZvciBhIHNwZWNpZmljIHF1ZXJ5XG4gICAqL1xuICBnZXRBc3NlcnRpb25EYXRhRm9yUXVlcnkocXVlcnlJbmRleDogbnVtYmVyKTogYW55W10ge1xuICAgIGlmICh0aGlzLnF1ZXJpZXNbcXVlcnlJbmRleF0gJiYgdGhpcy5xdWVyaWVzW3F1ZXJ5SW5kZXhdLmFzc2VydGlvbkRhdGEpIHtcbiAgICAgIHJldHVybiB0aGlzLnF1ZXJpZXNbcXVlcnlJbmRleF0uYXNzZXJ0aW9uRGF0YTtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBhc3NlcnRpb24gZGF0YSBjaGFuZ2UgZnJvbSBleHRlcm5hbCBjb21wb25lbnRcbiAgICovXG4gIG9uQXNzZXJ0aW9uRGF0YUNoYW5nZShhc3NlcnRpb25EYXRhOiBhbnlbXSwgcXVlcnlJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucXVlcmllc1txdWVyeUluZGV4XSkge1xuICAgICAgLy8gQ3JlYXRlIGEgZGVlcCBjb3B5IHRvIGVuc3VyZSBlYWNoIHF1ZXJ5IGhhcyBpdHMgb3duIGRhdGFcbiAgICAgIGlmIChhc3NlcnRpb25EYXRhICYmIGFzc2VydGlvbkRhdGEubGVuZ3RoID4gMCkge1xuICAgICAgICB0aGlzLnF1ZXJpZXNbcXVlcnlJbmRleF0uYXNzZXJ0aW9uRGF0YSA9IGFzc2VydGlvbkRhdGEubWFwKChpdGVtOiBhbnkpID0+IHtcbiAgICAgICAgICAvLyBFbnN1cmUgZXhwZWN0ZWRWYWx1ZSBpcyBwcm9wZXJseSBmb3JtYXR0ZWRcbiAgICAgICAgICBjb25zdCBleHBlY3RlZFR5cGUgPSBpdGVtLmV4cGVjdGVkVHlwZSB8fCAnc3RyaW5nJztcbiAgICAgICAgICBsZXQgZXhwZWN0ZWRWYWx1ZSA9IGl0ZW0uZXhwZWN0ZWRWYWx1ZTtcblxuICAgICAgICAgIC8vIEZvciBvYmplY3QvYXJyYXkgdHlwZXMsIGVuc3VyZSBleHBlY3RlZFZhbHVlIGlzIGFuIG9iamVjdC9hcnJheSwgbm90IGEgc3RyaW5nXG4gICAgICAgICAgaWYgKGV4cGVjdGVkVHlwZSA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIGV4cGVjdGVkVmFsdWUgPT09ICdzdHJpbmcnICYmIGV4cGVjdGVkVmFsdWUudHJpbSgpKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICBleHBlY3RlZFZhbHVlID0gSlNPTi5wYXJzZShleHBlY3RlZFZhbHVlKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgLy8gSWYgcGFyc2luZyBmYWlscywga2VlcCBhcyBzdHJpbmdcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2UgaWYgKGV4cGVjdGVkVHlwZSA9PT0gJ2FycmF5JyAmJiB0eXBlb2YgZXhwZWN0ZWRWYWx1ZSA9PT0gJ3N0cmluZycgJiYgZXhwZWN0ZWRWYWx1ZS50cmltKCkpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgIGV4cGVjdGVkVmFsdWUgPSBKU09OLnBhcnNlKGV4cGVjdGVkVmFsdWUpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAvLyBJZiBwYXJzaW5nIGZhaWxzLCBrZWVwIGFzIHN0cmluZ1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoZXhwZWN0ZWRUeXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgZXhwZWN0ZWRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGV4cGVjdGVkVmFsdWUgPSBleHBlY3RlZFZhbHVlICE9PSAnJyA/IE51bWJlcihleHBlY3RlZFZhbHVlKSA6IG51bGw7XG4gICAgICAgICAgfSBlbHNlIGlmIChleHBlY3RlZFR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgaWYgKGV4cGVjdGVkVmFsdWUgPT09ICd0cnVlJyB8fCBleHBlY3RlZFZhbHVlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgIGV4cGVjdGVkVmFsdWUgPSB0cnVlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChleHBlY3RlZFZhbHVlID09PSAnZmFsc2UnIHx8IGV4cGVjdGVkVmFsdWUgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICAgIGV4cGVjdGVkVmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAganNvblBhdGg6IGl0ZW0uanNvblBhdGggfHwgJycsXG4gICAgICAgICAgICB2ZXJpZmljYXRpb25UeXBlOiBpdGVtLnZlcmlmaWNhdGlvblR5cGUgfHwgJ2VxdWFscycsXG4gICAgICAgICAgICBleHBlY3RlZFR5cGU6IGV4cGVjdGVkVHlwZSxcbiAgICAgICAgICAgIGV4cGVjdGVkVmFsdWU6IGV4cGVjdGVkVmFsdWVcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMucXVlcmllc1txdWVyeUluZGV4XS5hc3NlcnRpb25EYXRhID0gW107XG4gICAgICB9XG5cbiAgICAgIC8vIEVtaXQgdGhlIGNoYW5nZSB0byBwYXJlbnRcbiAgICAgIHRoaXMuYXNzZXJ0aW9uRGF0YUNoYW5nZS5lbWl0KHtcbiAgICAgICAgcXVlcnlJbmRleDogcXVlcnlJbmRleCxcbiAgICAgICAgYXNzZXJ0aW9uRGF0YTogdGhpcy5xdWVyaWVzW3F1ZXJ5SW5kZXhdLmFzc2VydGlvbkRhdGEgfHwgW11cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIGFzc2VydGlvbiBkYXRhIGZvciBhIHF1ZXJ5IGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICovXG4gIHByaXZhdGUgZW5zdXJlQXNzZXJ0aW9uRGF0YUluaXRpYWxpemVkKHF1ZXJ5SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh0aGlzLnF1ZXJpZXNbcXVlcnlJbmRleF0gJiYgIXRoaXMucXVlcmllc1txdWVyeUluZGV4XS5hc3NlcnRpb25EYXRhKSB7XG4gICAgICB0aGlzLnF1ZXJpZXNbcXVlcnlJbmRleF0uYXNzZXJ0aW9uRGF0YSA9IFtdO1xuICAgIH1cbiAgICAvLyBJbml0aWFsaXplIGFzc2VydGlvbnMgZm9ybSBmb3IgdGhpcyBxdWVyeSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgaWYgKCF0aGlzLmFzc2VydGlvbnNGb3Jtcy5oYXMocXVlcnlJbmRleCkpIHtcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZUFzc2VydGlvbnNGb3JtKHF1ZXJ5SW5kZXgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIGFzc2VydGlvbnMgZm9ybSBmb3IgYSBzcGVjaWZpYyBxdWVyeVxuICAgKi9cbiAgcHJpdmF0ZSBpbml0aWFsaXplQXNzZXJ0aW9uc0Zvcm0ocXVlcnlJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgYXNzZXJ0aW9uc0FycmF5ID0gdGhpcy5mYi5hcnJheShbXSk7XG4gICAgY29uc3QgYXNzZXJ0aW9uc0Zvcm0gPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIGFzc2VydGlvbnM6IGFzc2VydGlvbnNBcnJheVxuICAgIH0pO1xuICAgIHRoaXMuYXNzZXJ0aW9uc0Zvcm1zLnNldChxdWVyeUluZGV4LCBhc3NlcnRpb25zRm9ybSk7XG5cbiAgICAvLyBMb2FkIGV4aXN0aW5nIGFzc2VydGlvbnMgaWYgdGhleSBleGlzdFxuICAgIGNvbnN0IHF1ZXJ5ID0gdGhpcy5xdWVyaWVzW3F1ZXJ5SW5kZXhdO1xuICAgIGlmIChxdWVyeSAmJiBxdWVyeS5hc3NlcnRpb25EYXRhICYmIHF1ZXJ5LmFzc2VydGlvbkRhdGEubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5sb2FkQXNzZXJ0aW9uc0ZvclF1ZXJ5KHF1ZXJ5SW5kZXgpO1xuICAgIH1cblxuICAgIC8vIFN1YnNjcmliZSB0byBmb3JtIGNoYW5nZXNcbiAgICB0aGlzLnN1YnNjcmliZVRvQXNzZXJ0aW9uc0Zvcm1DaGFuZ2VzKHF1ZXJ5SW5kZXgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhc3NlcnRpb25zIGZvcm0gZm9yIGN1cnJlbnQgcXVlcnlcbiAgICovXG4gIGdldEN1cnJlbnRBc3NlcnRpb25zRm9ybSgpOiBGb3JtR3JvdXAgfCBudWxsIHtcbiAgICBpZiAodGhpcy5hc3NlcnRpb25zRm9ybXMuaGFzKHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4KSkge1xuICAgICAgcmV0dXJuIHRoaXMuYXNzZXJ0aW9uc0Zvcm1zLmdldCh0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCkhO1xuICAgIH1cbiAgICAvLyBJbml0aWFsaXplIGlmIGl0IGRvZXNuJ3QgZXhpc3RcbiAgICB0aGlzLmVuc3VyZUFzc2VydGlvbkRhdGFJbml0aWFsaXplZCh0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCk7XG4gICAgcmV0dXJuIHRoaXMuYXNzZXJ0aW9uc0Zvcm1zLmdldCh0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCkgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYXNzZXJ0aW9ucyBmb3JtIGFycmF5IGZvciBjdXJyZW50IHF1ZXJ5XG4gICAqL1xuICBnZXRBc3NlcnRpb25zRm9ybUFycmF5KCk6IEZvcm1BcnJheSB7XG4gICAgY29uc3QgZm9ybSA9IHRoaXMuZ2V0Q3VycmVudEFzc2VydGlvbnNGb3JtKCk7XG4gICAgaWYgKGZvcm0pIHtcbiAgICAgIHJldHVybiBmb3JtLmdldCgnYXNzZXJ0aW9ucycpIGFzIEZvcm1BcnJheTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZmIuYXJyYXkoW10pO1xuICB9XG5cbiAgLyoqXG4gICAqIExvYWQgYXNzZXJ0aW9ucyBpbnRvIGZvcm0gZm9yIGEgc3BlY2lmaWMgcXVlcnlcbiAgICovXG4gIHByaXZhdGUgbG9hZEFzc2VydGlvbnNGb3JRdWVyeShxdWVyeUluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBmb3JtID0gdGhpcy5hc3NlcnRpb25zRm9ybXMuZ2V0KHF1ZXJ5SW5kZXgpO1xuICAgIGlmICghZm9ybSkgcmV0dXJuO1xuXG4gICAgY29uc3QgZm9ybUFycmF5ID0gZm9ybS5nZXQoJ2Fzc2VydGlvbnMnKSBhcyBGb3JtQXJyYXk7XG4gICAgY29uc3QgcXVlcnkgPSB0aGlzLnF1ZXJpZXNbcXVlcnlJbmRleF07XG4gICAgaWYgKCFxdWVyeSB8fCAhcXVlcnkuYXNzZXJ0aW9uRGF0YSkgcmV0dXJuO1xuXG4gICAgLy8gQ2xlYXIgZXhpc3RpbmcgZm9ybSBhcnJheVxuICAgIHdoaWxlIChmb3JtQXJyYXkubGVuZ3RoICE9PSAwKSB7XG4gICAgICBmb3JtQXJyYXkucmVtb3ZlQXQoMCk7XG4gICAgfVxuXG4gICAgLy8gTG9hZCBhc3NlcnRpb25zXG4gICAgcXVlcnkuYXNzZXJ0aW9uRGF0YS5mb3JFYWNoKChhc3NlcnRpb246IGFueSkgPT4ge1xuICAgICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gYXNzZXJ0aW9uLmV4cGVjdGVkVHlwZSB8fCAnc3RyaW5nJztcbiAgICAgIGxldCBleHBlY3RlZFZhbHVlOiBhbnkgPSAnJztcblxuICAgICAgaWYgKGV4cGVjdGVkVHlwZSA9PT0gJ251bGwnKSB7XG4gICAgICAgIGV4cGVjdGVkVmFsdWUgPSBudWxsO1xuICAgICAgfSBlbHNlIGlmIChleHBlY3RlZFR5cGUgPT09ICdvYmplY3QnIHx8IGV4cGVjdGVkVHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICBpZiAodHlwZW9mIGFzc2VydGlvbi5leHBlY3RlZFZhbHVlID09PSAnb2JqZWN0JyAmJiBhc3NlcnRpb24uZXhwZWN0ZWRWYWx1ZSAhPT0gbnVsbCkge1xuICAgICAgICAgIGV4cGVjdGVkVmFsdWUgPSBKU09OLnN0cmluZ2lmeShhc3NlcnRpb24uZXhwZWN0ZWRWYWx1ZSwgbnVsbCwgMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXhwZWN0ZWRWYWx1ZSA9IGFzc2VydGlvbi5leHBlY3RlZFZhbHVlIHx8ICcnO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGV4cGVjdGVkVHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIGV4cGVjdGVkVmFsdWUgPSAoYXNzZXJ0aW9uLmV4cGVjdGVkVmFsdWUgPT09IHRydWUgfHwgYXNzZXJ0aW9uLmV4cGVjdGVkVmFsdWUgPT09ICd0cnVlJykgPyAndHJ1ZScgOiAnZmFsc2UnO1xuICAgICAgfSBlbHNlIGlmIChleHBlY3RlZFR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGV4cGVjdGVkVmFsdWUgPSBhc3NlcnRpb24uZXhwZWN0ZWRWYWx1ZSAhPT0gbnVsbCAmJiBhc3NlcnRpb24uZXhwZWN0ZWRWYWx1ZSAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyBTdHJpbmcoYXNzZXJ0aW9uLmV4cGVjdGVkVmFsdWUpXG4gICAgICAgICAgOiAnJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4cGVjdGVkVmFsdWUgPSBhc3NlcnRpb24uZXhwZWN0ZWRWYWx1ZSAhPT0gbnVsbCAmJiBhc3NlcnRpb24uZXhwZWN0ZWRWYWx1ZSAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgPyBTdHJpbmcoYXNzZXJ0aW9uLmV4cGVjdGVkVmFsdWUpXG4gICAgICAgICAgOiAnJztcbiAgICAgIH1cblxuICAgICAgY29uc3QgZm9ybUdyb3VwID0gdGhpcy5mYi5ncm91cCh7XG4gICAgICAgIGpzb25QYXRoOiBbYXNzZXJ0aW9uLmpzb25QYXRoIHx8ICcnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgICAgdmVyaWZpY2F0aW9uVHlwZTogW2Fzc2VydGlvbi52ZXJpZmljYXRpb25UeXBlIHx8ICdlcXVhbHMnXSxcbiAgICAgICAgZXhwZWN0ZWRUeXBlOiBbZXhwZWN0ZWRUeXBlXSxcbiAgICAgICAgZXhwZWN0ZWRWYWx1ZTogW2V4cGVjdGVkVmFsdWUsIFtWYWxpZGF0b3JzLnJlcXVpcmVkLCB0aGlzLmV4cGVjdGVkVmFsdWVWYWxpZGF0b3JdXVxuICAgICAgfSk7XG5cbiAgICAgIGZvcm1BcnJheS5wdXNoKGZvcm1Hcm91cCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogU3Vic2NyaWJlIHRvIGFzc2VydGlvbnMgZm9ybSBjaGFuZ2VzXG4gICAqL1xuICBwcml2YXRlIHN1YnNjcmliZVRvQXNzZXJ0aW9uc0Zvcm1DaGFuZ2VzKHF1ZXJ5SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGZvcm0gPSB0aGlzLmFzc2VydGlvbnNGb3Jtcy5nZXQocXVlcnlJbmRleCk7XG4gICAgaWYgKCFmb3JtKSByZXR1cm47XG5cbiAgICAvLyBVbnN1YnNjcmliZSBmcm9tIHByZXZpb3VzIHN1YnNjcmlwdGlvbiBpZiBleGlzdHNcbiAgICBpZiAodGhpcy5mb3JtU3Vic2NyaXB0aW9ucy5oYXMocXVlcnlJbmRleCkpIHtcbiAgICAgIHRoaXMuZm9ybVN1YnNjcmlwdGlvbnMuZ2V0KHF1ZXJ5SW5kZXgpIS51bnN1YnNjcmliZSgpO1xuICAgIH1cblxuICAgIGNvbnN0IGZvcm1BcnJheSA9IGZvcm0uZ2V0KCdhc3NlcnRpb25zJykgYXMgRm9ybUFycmF5O1xuICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IGZvcm1BcnJheS52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIHRoaXMuZW1pdEFzc2VydGlvbkRhdGFGb3JRdWVyeShxdWVyeUluZGV4KTtcbiAgICB9KTtcblxuICAgIHRoaXMuZm9ybVN1YnNjcmlwdGlvbnMuc2V0KHF1ZXJ5SW5kZXgsIHN1YnNjcmlwdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogRW1pdCBhc3NlcnRpb24gZGF0YSBmb3IgYSBzcGVjaWZpYyBxdWVyeVxuICAgKi9cbiAgcHJpdmF0ZSBlbWl0QXNzZXJ0aW9uRGF0YUZvclF1ZXJ5KHF1ZXJ5SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGZvcm0gPSB0aGlzLmFzc2VydGlvbnNGb3Jtcy5nZXQocXVlcnlJbmRleCk7XG4gICAgaWYgKCFmb3JtKSByZXR1cm47XG5cbiAgICBjb25zdCBmb3JtQXJyYXkgPSBmb3JtLmdldCgnYXNzZXJ0aW9ucycpIGFzIEZvcm1BcnJheTtcbiAgICBjb25zdCBhc3NlcnRpb25EYXRhID0gZm9ybUFycmF5LmNvbnRyb2xzLm1hcCgoY29udHJvbCkgPT4ge1xuICAgICAgaWYgKCEoY29udHJvbCBpbnN0YW5jZW9mIEZvcm1Hcm91cCkpIHJldHVybiBudWxsO1xuXG4gICAgICBjb25zdCB2YWx1ZSA9IGNvbnRyb2wudmFsdWU7XG4gICAgICBjb25zdCBleHBlY3RlZFR5cGUgPSB2YWx1ZS5leHBlY3RlZFR5cGUgfHwgJ3N0cmluZyc7XG4gICAgICBsZXQgZXhwZWN0ZWRWYWx1ZTogYW55ID0gdmFsdWUuZXhwZWN0ZWRWYWx1ZTtcblxuICAgICAgLy8gUGFyc2UgZXhwZWN0ZWRWYWx1ZSBiYXNlZCBvbiB0eXBlXG4gICAgICBpZiAoZXhwZWN0ZWRUeXBlID09PSAnbnVsbCcpIHtcbiAgICAgICAgZXhwZWN0ZWRWYWx1ZSA9IG51bGw7XG4gICAgICB9IGVsc2UgaWYgKGV4cGVjdGVkVHlwZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgZXhwZWN0ZWRWYWx1ZSA9IGV4cGVjdGVkVmFsdWUgIT09ICcnID8gTnVtYmVyKGV4cGVjdGVkVmFsdWUpIDogbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAoZXhwZWN0ZWRUeXBlID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgZXhwZWN0ZWRWYWx1ZSA9IChleHBlY3RlZFZhbHVlID09PSAndHJ1ZScgfHwgZXhwZWN0ZWRWYWx1ZSA9PT0gdHJ1ZSk7XG4gICAgICB9IGVsc2UgaWYgKGV4cGVjdGVkVHlwZSA9PT0gJ2FycmF5JyB8fCBleHBlY3RlZFR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZXhwZWN0ZWRWYWx1ZSA9PT0gJ3N0cmluZycgJiYgZXhwZWN0ZWRWYWx1ZS50cmltKCkpIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZXhwZWN0ZWRWYWx1ZSA9IEpTT04ucGFyc2UoZXhwZWN0ZWRWYWx1ZSk7XG4gICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gS2VlcCBhcyBzdHJpbmcgaWYgcGFyc2luZyBmYWlsc1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhwZWN0ZWRWYWx1ZSA9IFN0cmluZyhleHBlY3RlZFZhbHVlIHx8ICcnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAganNvblBhdGg6ICh2YWx1ZS5qc29uUGF0aCB8fCAnJykudHJpbSgpLFxuICAgICAgICB2ZXJpZmljYXRpb25UeXBlOiB2YWx1ZS52ZXJpZmljYXRpb25UeXBlIHx8ICdlcXVhbHMnLFxuICAgICAgICBleHBlY3RlZFR5cGU6IGV4cGVjdGVkVHlwZSxcbiAgICAgICAgZXhwZWN0ZWRWYWx1ZTogZXhwZWN0ZWRWYWx1ZVxuICAgICAgfTtcbiAgICB9KS5maWx0ZXIoaXRlbSA9PiBpdGVtICE9PSBudWxsICYmIGl0ZW0hLmpzb25QYXRoKSBhcyBhbnlbXTtcblxuICAgIC8vIFVwZGF0ZSBxdWVyeSdzIGFzc2VydGlvbiBkYXRhXG4gICAgaWYgKHRoaXMucXVlcmllc1txdWVyeUluZGV4XSkge1xuICAgICAgdGhpcy5xdWVyaWVzW3F1ZXJ5SW5kZXhdLmFzc2VydGlvbkRhdGEgPSBhc3NlcnRpb25EYXRhO1xuICAgIH1cblxuICAgIC8vIEVtaXQgdG8gcGFyZW50XG4gICAgdGhpcy5hc3NlcnRpb25EYXRhQ2hhbmdlLmVtaXQoe1xuICAgICAgcXVlcnlJbmRleDogcXVlcnlJbmRleCxcbiAgICAgIGFzc2VydGlvbkRhdGE6IGFzc2VydGlvbkRhdGFcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBuZXcgYXNzZXJ0aW9uXG4gICAqL1xuICBhZGRBc3NlcnRpb24oKTogdm9pZCB7XG4gICAgY29uc3QgZm9ybUFycmF5ID0gdGhpcy5nZXRBc3NlcnRpb25zRm9ybUFycmF5KCk7XG4gICAgY29uc3QgZm9ybUdyb3VwID0gdGhpcy5mYi5ncm91cCh7XG4gICAgICBqc29uUGF0aDogWycnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgIHZlcmlmaWNhdGlvblR5cGU6IFsnZXF1YWxzJ10sXG4gICAgICBleHBlY3RlZFR5cGU6IFt0aGlzLmRlZmF1bHRFeHBlY3RlZFR5cGVdLFxuICAgICAgZXhwZWN0ZWRWYWx1ZTogWycnLCBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgdGhpcy5leHBlY3RlZFZhbHVlVmFsaWRhdG9yXV1cbiAgICB9KTtcbiAgICBmb3JtQXJyYXkucHVzaChmb3JtR3JvdXApO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICBpZiAodGhpcy5hc3NlcnRpb25zVGFibGUpIHtcbiAgICAgIHRoaXMuYXNzZXJ0aW9uc1RhYmxlLnJlbmRlclJvd3MoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlIGFuIGFzc2VydGlvblxuICAgKi9cbiAgcmVtb3ZlQXNzZXJ0aW9uKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBmb3JtQXJyYXkgPSB0aGlzLmdldEFzc2VydGlvbnNGb3JtQXJyYXkoKTtcbiAgICBmb3JtQXJyYXkucmVtb3ZlQXQoaW5kZXgpO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICBpZiAodGhpcy5hc3NlcnRpb25zVGFibGUpIHtcbiAgICAgIHRoaXMuYXNzZXJ0aW9uc1RhYmxlLnJlbmRlclJvd3MoKTtcbiAgICB9XG4gICAgdGhpcy5lbWl0QXNzZXJ0aW9uRGF0YUZvclF1ZXJ5KHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgZm9ybSBjb250cm9sIGF0IHNwZWNpZmljIGluZGV4XG4gICAqL1xuICBnZXRGb3JtQ29udHJvbEF0KGluZGV4OiBudW1iZXIsIGNvbnRyb2xOYW1lOiBzdHJpbmcpOiBBYnN0cmFjdENvbnRyb2wgfCBudWxsIHtcbiAgICBjb25zdCBmb3JtQXJyYXkgPSB0aGlzLmdldEFzc2VydGlvbnNGb3JtQXJyYXkoKTtcbiAgICBpZiAoaW5kZXggPCAwIHx8IGluZGV4ID49IGZvcm1BcnJheS5sZW5ndGgpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IGZvcm1Hcm91cCA9IGZvcm1BcnJheS5hdChpbmRleCkgYXMgRm9ybUdyb3VwO1xuICAgIHJldHVybiBmb3JtR3JvdXA/LmdldChjb250cm9sTmFtZSkgfHwgbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgZXhwZWN0ZWQgdHlwZSBmb3IgYW4gYXNzZXJ0aW9uXG4gICAqL1xuICBnZXRFeHBlY3RlZFR5cGUoaW5kZXg6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgZm9ybUFycmF5ID0gdGhpcy5nZXRBc3NlcnRpb25zRm9ybUFycmF5KCk7XG4gICAgaWYgKGluZGV4IDwgMCB8fCBpbmRleCA+PSBmb3JtQXJyYXkubGVuZ3RoKSByZXR1cm4gJ3N0cmluZyc7XG4gICAgY29uc3QgZm9ybUdyb3VwID0gZm9ybUFycmF5LmF0KGluZGV4KSBhcyBGb3JtR3JvdXA7XG4gICAgcmV0dXJuIGZvcm1Hcm91cD8uZ2V0KCdleHBlY3RlZFR5cGUnKT8udmFsdWUgfHwgJ3N0cmluZyc7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGV4cGVjdGVkIHZhbHVlIHBsYWNlaG9sZGVyXG4gICAqL1xuICBnZXRFeHBlY3RlZFZhbHVlUGxhY2Vob2xkZXIoaW5kZXg6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgZXhwZWN0ZWRUeXBlID0gdGhpcy5nZXRFeHBlY3RlZFR5cGUoaW5kZXgpO1xuICAgIHN3aXRjaCAoZXhwZWN0ZWRUeXBlKSB7XG4gICAgICBjYXNlICdzdHJpbmcnOiByZXR1cm4gJ0V4cGVjdGVkIFZhbHVlIGluIFN0cmluZyc7XG4gICAgICBjYXNlICdhcnJheSc6IHJldHVybiAnRXhwZWN0ZWQgVmFsdWUgaW4gQXJyYXkgKEpTT04gZm9ybWF0KSc7XG4gICAgICBjYXNlICdvYmplY3QnOiByZXR1cm4gJ0V4cGVjdGVkIFZhbHVlIGluIE9iamVjdCAoSlNPTiBmb3JtYXQpJztcbiAgICAgIGNhc2UgJ251bGwnOiByZXR1cm4gJ05vIHZhbHVlIHJlcXVpcmVkIGZvciBudWxsIHR5cGUnO1xuICAgICAgZGVmYXVsdDogcmV0dXJuICdFeHBlY3RlZCBWYWx1ZSc7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEhhbmRsZSBleHBlY3RlZCB0eXBlIGNoYW5nZVxuICAgKi9cbiAgb25FeHBlY3RlZFR5cGVDaGFuZ2UoaW5kZXg6IG51bWJlciwgdmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGZvcm1BcnJheSA9IHRoaXMuZ2V0QXNzZXJ0aW9uc0Zvcm1BcnJheSgpO1xuICAgIGlmIChpbmRleCA8IDAgfHwgaW5kZXggPj0gZm9ybUFycmF5Lmxlbmd0aCkgcmV0dXJuO1xuXG4gICAgY29uc3QgZm9ybUdyb3VwID0gZm9ybUFycmF5LmF0KGluZGV4KSBhcyBGb3JtR3JvdXA7XG4gICAgY29uc3QgZXhwZWN0ZWRWYWx1ZUNvbnRyb2wgPSBmb3JtR3JvdXAuZ2V0KCdleHBlY3RlZFZhbHVlJyk7XG4gICAgaWYgKCFleHBlY3RlZFZhbHVlQ29udHJvbCkgcmV0dXJuO1xuXG4gICAgbGV0IG5ld1ZhbHVlOiBhbnkgPSAnJztcbiAgICBpZiAodmFsdWUgPT09ICdib29sZWFuJykge1xuICAgICAgbmV3VmFsdWUgPSAndHJ1ZSc7XG4gICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gJ251bGwnKSB7XG4gICAgICBuZXdWYWx1ZSA9IG51bGw7XG4gICAgfVxuXG4gICAgZXhwZWN0ZWRWYWx1ZUNvbnRyb2wuY2xlYXJWYWxpZGF0b3JzKCk7XG4gICAgZXhwZWN0ZWRWYWx1ZUNvbnRyb2wuc2V0VmFsdWUobmV3VmFsdWUsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcblxuICAgIGlmICh2YWx1ZSA9PT0gJ251bGwnKSB7XG4gICAgICBleHBlY3RlZFZhbHVlQ29udHJvbC5zZXRWYWxpZGF0b3JzKFt0aGlzLmV4cGVjdGVkVmFsdWVWYWxpZGF0b3JdKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAnb2JqZWN0JyB8fCB2YWx1ZSA9PT0gJ2FycmF5Jykge1xuICAgICAgZXhwZWN0ZWRWYWx1ZUNvbnRyb2wuc2V0VmFsaWRhdG9ycyhbVmFsaWRhdG9ycy5yZXF1aXJlZF0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBleHBlY3RlZFZhbHVlQ29udHJvbC5zZXRWYWxpZGF0b3JzKFtWYWxpZGF0b3JzLnJlcXVpcmVkLCB0aGlzLmV4cGVjdGVkVmFsdWVWYWxpZGF0b3JdKTtcbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGV4cGVjdGVkVmFsdWVDb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH0sIDEwMCk7XG4gIH1cblxuICAvKipcbiAgICogRXhwZWN0ZWQgdmFsdWUgdmFsaWRhdG9yXG4gICAqL1xuICBleHBlY3RlZFZhbHVlVmFsaWRhdG9yID0gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCk6IHsgW2tleTogc3RyaW5nXTogYW55IH0gfCBudWxsID0+IHtcbiAgICBjb25zdCBleHBlY3RlZFR5cGUgPSBjb250cm9sLnBhcmVudD8uZ2V0KCdleHBlY3RlZFR5cGUnKT8udmFsdWU7XG4gICAgaWYgKCFleHBlY3RlZFR5cGUgfHwgZXhwZWN0ZWRUeXBlID09PSAnbnVsbCcpIHJldHVybiBudWxsO1xuXG4gICAgY29uc3QgdmFsdWUgPSBjb250cm9sLnZhbHVlO1xuICAgIGlmICghdmFsdWUgJiYgdmFsdWUgIT09IDAgJiYgdmFsdWUgIT09IGZhbHNlKSByZXR1cm4gbnVsbDtcblxuICAgIGlmIChleHBlY3RlZFR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICBpZiAoaXNOYU4oTnVtYmVyKHZhbHVlKSkpIHtcbiAgICAgICAgcmV0dXJuIHsgaW52YWxpZFR5cGU6IHRydWUsIG1lc3NhZ2U6ICdJbnZhbGlkIG51bWJlciB2YWx1ZScgfTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGV4cGVjdGVkVHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICBpZiAodmFsdWUgIT09ICd0cnVlJyAmJiB2YWx1ZSAhPT0gJ2ZhbHNlJyAmJiB2YWx1ZSAhPT0gdHJ1ZSAmJiB2YWx1ZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgcmV0dXJuIHsgaW52YWxpZFR5cGU6IHRydWUsIG1lc3NhZ2U6ICdJbnZhbGlkIGJvb2xlYW4gdmFsdWUnIH07XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChleHBlY3RlZFR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnICYmIHZhbHVlLnRyaW0oKSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShwYXJzZWQpKSB7XG4gICAgICAgICAgICByZXR1cm4geyBpbnZhbGlkVHlwZTogdHJ1ZSwgbWVzc2FnZTogJ1ZhbHVlIG11c3QgYmUgYSB2YWxpZCBKU09OIGFycmF5JyB9O1xuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHJldHVybiB7IGludmFsaWRUeXBlOiB0cnVlLCBtZXNzYWdlOiAnSW52YWxpZCBBcnJheSB2YWx1ZSAtIG11c3QgYmUgdmFsaWQgSlNPTicgfTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZXhwZWN0ZWRUeXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUudHJpbSgpICYmIHZhbHVlLnRyaW0oKSAhPT0gJ3t9Jykge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgICAgIGlmIChwYXJzZWQgPT09IG51bGwgfHwgdHlwZW9mIHBhcnNlZCAhPT0gJ29iamVjdCcgfHwgQXJyYXkuaXNBcnJheShwYXJzZWQpKSB7XG4gICAgICAgICAgICByZXR1cm4geyBpbnZhbGlkVHlwZTogdHJ1ZSwgbWVzc2FnZTogJ1ZhbHVlIG11c3QgYmUgYSB2YWxpZCBKU09OIG9iamVjdCcgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICByZXR1cm4geyBpbnZhbGlkVHlwZTogdHJ1ZSwgbWVzc2FnZTogJ0ludmFsaWQgT2JqZWN0IHZhbHVlIC0gbXVzdCBiZSB2YWxpZCBKU09OJyB9O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldCBhc3NlcnRpb25zIGRhdGEgc291cmNlIGZvciB0YWJsZVxuICAgKi9cbiAgZ2V0IGFzc2VydGlvbnNEYXRhU291cmNlKCkge1xuICAgIHJldHVybiB0aGlzLmdldEFzc2VydGlvbnNGb3JtQXJyYXkoKS5jb250cm9scztcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFjayBieSBmdW5jdGlvbiBmb3IgdGFibGUgcm93c1xuICAgKi9cbiAgdHJhY2tCeUluZGV4KGluZGV4OiBudW1iZXIpOiBhbnkge1xuICAgIHJldHVybiBpbmRleDtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIC8vIENsZWFuIHVwIHN1YnNjcmlwdGlvbnNcbiAgICB0aGlzLmZvcm1TdWJzY3JpcHRpb25zLmZvckVhY2goc3ViID0+IHN1Yi51bnN1YnNjcmliZSgpKTtcbiAgICB0aGlzLmZvcm1TdWJzY3JpcHRpb25zLmNsZWFyKCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWgtZnVsbCBjcWEtYmctd2hpdGUgY3FhLXB4LTQgY3FhLXB5LTJcIj5cbiAgPCEtLSBIZWFkZXIgLS0+XG4gIDxoMiBjbGFzcz1cImNxYS10ZXh0LVsxMnB4XSBjcWEtZm9udC1zZW1pYm9sZCBjcWEtdGV4dC1ibGFjay0xMDAgY3FhLW1iLTRcIj5cbiAgICB7eyBlZGl0TW9kZSA/ICdVcGRhdGUgRGF0YWJhc2UgVGVzdCBTdGVwJyA6ICdDcmVhdGUgRGF0YWJhc2UgVGVzdCBTdGVwJyB9fVxuICA8L2gyPlxuXG4gIDwhLS0gREIgRW52aXJvbm1lbnQgU2VjdGlvbiAoc2VwYXJhdG9yIGxpbmUgb25seSBvbiBib3R0b20pIC0tPlxuICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1nYXAtMS41IGNxYS1wYi1bMC41cmVtXSBjcWEtbWItNCBjcWEtYm9yZGVyLTAgY3FhLWJvcmRlci1iIGNxYS1ib3JkZXItc29saWQgY3FhLWJvcmRlci1ncmF5LTIwMFwiPlxuICAgIDxsYWJlbCBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTcwMCBjcWEtYmxvY2tcIj5cbiAgICAgIERCIEVudmlyb25tZW50IDxzcGFuIGNsYXNzPVwiY3FhLXRleHQtcmVkLTUwMFwiPio8L3NwYW4+XG4gICAgPC9sYWJlbD5cbiAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLXctZnVsbCBjcWEtZmxleC1ub3dyYXAgY3FhLWl0ZW1zLWNlbnRlciBjcWEtanVzdGlmeS1iZXR3ZWVuIGNxYS1nYXAtM1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImNxYS1taW4tdy0wXCIgc3R5bGU9XCJ3aWR0aDogMjgwcHg7XCI+XG4gICAgICAgIDxjcWEtZHluYW1pYy1zZWxlY3QgW2Zvcm1dPVwiZGF0YWJhc2VGb3JtXCIgW2NvbmZpZ109XCJnZXREYkVudmlyb25tZW50Q29uZmlnKClcIj5cbiAgICAgICAgPC9jcWEtZHluYW1pYy1zZWxlY3Q+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxjcWEtYnV0dG9uIHZhcmlhbnQ9XCJmaWxsZWRcIiB0ZXh0PVwiUnVuIFF1ZXJ5XCIgKGNsaWNrZWQpPVwib25SdW5RdWVyeSgpXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cIiFkYXRhYmFzZUZvcm0uZ2V0KCdkYkVudmlyb25tZW50Jyk/LnZhbHVlIHx8IGlzTG9hZGluZ1wiXG4gICAgICAgIFtjdXN0b21DbGFzc109XCInIWNxYS1iZy1bIzNGNDNFRV0gY3FhLXRleHQtWyNGQkZDRkZdIGNxYS10ZXh0LXNtIGNxYS1mb250LXNlbWlib2xkIGNxYS13aGl0ZXNwYWNlLW5vd3JhcCAhY3FhLXB0LVsxMHB4XSAhY3FhLXBiLVsxMHB4XSAhY3FhLXBsLVsyNHB4XSAhY3FhLXByLVsyNHB4XSAhY3FhLWdhcC1bOHB4XSBjcWEtcm91bmRlZC1sZyBjcWEtbWluLWgtWzM3cHhdIGhvdmVyOiFjcWEtYmctWyMxQjFGRUJdIGNxYS1mbGV4LXNocmluay0wJ1wiPlxuICAgICAgPC9jcWEtYnV0dG9uPlxuICAgIDwvZGl2PlxuICAgIDxwIGNsYXNzPVwiY3FhLXRleHQteHMgY3FhLXRleHQtZ3JheS01MDBcIj5cbiAgICAgIFVzZXMgRGF0YWJhc2UgZW52aXJvbm1lbnRzIGZyb20gRW52aXJvbm1lbnRzLlxuICAgIDwvcD5cbiAgPC9kaXY+XG5cbiAgPCEtLSBNYWluIENvbnRlbnQ6IFR3byBDb2x1bW4gTGF5b3V0IC0tPlxuICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWdhcC1bMTJweF0gY3FhLWZsZXgtMSBjcWEtb3ZlcmZsb3ctaGlkZGVuIGNxYS1tYi02XCI+XG4gICAgPCEtLSBMZWZ0IFBhbmVsOiBRdWVyeSBMaXN0IC0tPlxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwiY3FhLXctWzE3NXB4XSBjcWEtbWluLXctWzE3NXB4XSBjcWEtZmxleC1zaHJpbmstMCBjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWJvcmRlci0wIGNxYS1ib3JkZXItciBjcWEtYm9yZGVyLXItWzFweF0gY3FhLWJvcmRlci1zb2xpZCBjcWEtYm9yZGVyLVsjRTBFMEUwXSBjcWEtYmctWyNGQUZBRkFdIGNxYS1vdmVyZmxvdy1oaWRkZW5cIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleC0xIGNxYS1vdmVyZmxvdy15LWF1dG8gY3FhLXAtMlwiPlxuICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBxdWVyeSBvZiBxdWVyaWVzOyBsZXQgaSA9IGluZGV4XCJcbiAgICAgICAgICBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWp1c3RpZnktYmV0d2VlbiBjcWEtZ2FwLVsxMHB4XSBjcWEtdy1mdWxsIGNxYS1wdC1bMTRweF0gY3FhLXBiLVsxNHB4XSBjcWEtcGwtWzE2cHhdIGNxYS1wci1bMTZweF0gY3FhLXJvdW5kZWQtWzhweF0gY3FhLWN1cnNvci1wb2ludGVyIGNxYS1tYi0xXCJcbiAgICAgICAgICBbY2xhc3MuY3FhLWJnLWJsdWUtNTBdPVwic2VsZWN0ZWRRdWVyeUluZGV4ID09PSBpXCJcbiAgICAgICAgICBbY2xhc3MuY3FhLWJvcmRlcl09XCJzZWxlY3RlZFF1ZXJ5SW5kZXggPT09IGlcIlxuICAgICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLWJsdWUtNTAwXT1cInNlbGVjdGVkUXVlcnlJbmRleCA9PT0gaVwiXG4gICAgICAgICAgW2NsYXNzLmNxYS1iZy1ncmV5LTQwMF09XCJzZWxlY3RlZFF1ZXJ5SW5kZXggIT09IGlcIlxuICAgICAgICAgIChjbGljayk9XCJvblNlbGVjdFF1ZXJ5KGkpXCJcbiAgICAgICAgICBzdHlsZT1cImhlaWdodDogNDlweDsgbWluLWhlaWdodDogNDlweDtcIj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTkwMFwiPlF1ZXJ5IHt7IGkgKyAxIH19PC9zcGFuPlxuICAgICAgICAgIDxjcWEtYmFkZ2UgKm5nSWY9XCJxdWVyeS5zdGF0dXNcIlxuICAgICAgICAgICAgW2xhYmVsXT1cInF1ZXJ5LnN0YXR1cyA9PT0gJ3Bhc3NlZCcgPyAnUGFzc2VkJyA6IHF1ZXJ5LnN0YXR1cyA9PT0gJ2ZhaWxlZCcgPyAnRmFpbGVkJyA6ICdQZW5kaW5nJ1wiXG4gICAgICAgICAgICBbdmFyaWFudF09XCJxdWVyeS5zdGF0dXMgPT09ICdwYXNzZWQnID8gJ3N1Y2Nlc3MnIDogcXVlcnkuc3RhdHVzID09PSAnZmFpbGVkJyA/ICdlcnJvcicgOiAnZGVmYXVsdCdcIlxuICAgICAgICAgICAgc2l6ZT1cInNtYWxsXCI+XG4gICAgICAgICAgPC9jcWEtYmFkZ2U+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIFJpZ2h0IFBhbmVsOiBRdWVyeSBFZGl0b3IgLS0+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTEgY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1vdmVyZmxvdy1hdXRvXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXgtMSBjcWEtZmxleCBjcWEtYm9yZGVyIGNxYS1ib3JkZXItZ3JheS0yMDAgY3FhLXJvdW5kZWQtbGcgY3FhLWdhcC1bMTBweF0gY3FhLW1iLTRcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtZ2FwLVs2cHhdXCIgc3R5bGU9XCJ3aWR0aDogNTAlO1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJcIj5cbiAgICAgICAgICAgIDxoMyBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktOTAwIGNxYS10ZXh0LVsxNHB4XVwiPlF1ZXJ5ICYgU3RvcmUgUmVzcG9uc2U8L2gzPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1qdXN0aWZ5LWJldHdlZW5cIj5cbiAgICAgICAgICAgIDwhLS0gU1FMIFF1ZXJ5IFRleHRhcmVhIC0tPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTEgY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1taW4tdy0wIGNxYS13LWZ1bGwgY3FhLXJvdW5kZWQtbWQgY3FhLWJnLWdyYXktNTAvNTBcIj5cbiAgICAgICAgICAgICAgPGNxYS1jdXN0b20tdGV4dGFyZWEgW3BsYWNlaG9sZGVyXT1cIidFbnRlciB5b3VyIFNRTCBxdWVyeSBoZXJlLi4uJ1wiXG4gICAgICAgICAgICAgICAgW3ZhbHVlXT1cImdldEN1cnJlbnRRdWVyeUZvcm1Hcm91cCgpPy5nZXQoJ3F1ZXJ5Jyk/LnZhbHVlIHx8ICcnXCIgW2Z1bGxXaWR0aF09XCJ0cnVlXCIgW3Jvd3NdPVwiOFwiXG4gICAgICAgICAgICAgICAgW3RleHRhcmVhSW5saW5lU3R5bGVdPVwiJ3BhZGRpbmc6IDFyZW07J1wiXG4gICAgICAgICAgICAgICAgKHZhbHVlQ2hhbmdlKT1cImdldEN1cnJlbnRRdWVyeUZvcm1Hcm91cCgpPy5nZXQoJ3F1ZXJ5Jyk/LnNldFZhbHVlKCRldmVudClcIj5cbiAgICAgICAgICAgICAgPC9jcWEtY3VzdG9tLXRleHRhcmVhPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleC0xIGNxYS1vdmVyZmxvdy15LWF1dG8gY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1nYXAtWzEwcHhdIGNxYS1tYi1bOHB4XVwiPlxuXG5cbiAgICAgICAgICA8IS0tIFZhcmlhYmxlIElucHV0IC0tPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZ2FwLTRcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleC0xXCI+XG4gICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTcwMCBjcWEtbWItMS41IGNxYS1ibG9jayBjcWEtdGV4dC1bMTRweF0gY3FhLWZvbnQtc2VtaWJvbGRcIj5cbiAgICAgICAgICAgICAgICBWYXJpYWJsZVxuICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICA8Y3FhLWN1c3RvbS1pbnB1dCBbcGxhY2Vob2xkZXJdPVwiJ1ZhcmlhYmxlIG5hbWUnXCJcbiAgICAgICAgICAgICAgICBbdmFsdWVdPVwiZ2V0Q3VycmVudFF1ZXJ5Rm9ybUdyb3VwKCk/LmdldCgndmFyaWFibGUnKT8udmFsdWUgfHwgJydcIiBbZnVsbFdpZHRoXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICh2YWx1ZUNoYW5nZSk9XCJnZXRDdXJyZW50UXVlcnlGb3JtR3JvdXAoKT8uZ2V0KCd2YXJpYWJsZScpPy5zZXRWYWx1ZSgkZXZlbnQpXCI+XG4gICAgICAgICAgICAgIDwvY3FhLWN1c3RvbS1pbnB1dD5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJjcWEtdGV4dC14cyBjcWEtdGV4dC1ncmF5LTUwMCBjcWEtbXQtMVwiPlxuICAgICAgICAgICAgICAgIFVzZSBsZXR0ZXJzLCBudW1iZXJzLCB1bmRlcnNjb3JlLiBObyBzcGFjZXMuIFVuaXF1ZSBwZXIgc3RlcC4gQ2FzZSBzZW5zaXRpdmUuXG4gICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwhLS0gQWN0aW9uIEJ1dHRvbnMgKHBpbm5lZCB0byBib3R0b20pIC0tPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1nYXAtMiBjcWEtbXQtYXV0b1wiPlxuICAgICAgICAgICAgPGNxYS1idXR0b24gdmFyaWFudD1cIm91dGxpbmVkXCIgdGV4dD1cIkFkZCBRdWVyeVwiIGljb249XCJhZGRcIiAoY2xpY2tlZCk9XCJhZGROZXdRdWVyeSgpXCJcbiAgICAgICAgICAgICAgW2N1c3RvbUNsYXNzXT1cIidjcWEtYmctd2hpdGUgIWNxYS1ib3JkZXItWyM0MTQxNDZdIGNxYS10ZXh0LXNtIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LVsjNDE0MTQ2XSBjcWEtd2hpdGVzcGFjZS1ub3dyYXAgIWNxYS1weS1bMTBweF0gIWNxYS1weC1bMTBweF0gIWNxYS1nYXAtWzhweF0gY3FhLXJvdW5kZWQtbGcgaG92ZXI6IWNxYS1ib3JkZXItWyM0MTQxNDZdIGhvdmVyOmNxYS1iZy1ncmF5LTUwJ1wiXG4gICAgICAgICAgICAgIFtpY29uQ29sb3JdPVwiJyM0MTQxNDYnXCI+XG4gICAgICAgICAgICA8L2NxYS1idXR0b24+XG4gICAgICAgICAgICA8Y3FhLWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgdmFyaWFudD1cInRleHRcIlxuICAgICAgICAgICAgICBbY3VzdG9tQ2xhc3NdPVwiJ2NxYS1taW4tdy1bNDBweF0gY3FhLXctMTAgY3FhLWgtOSBjcWEtcm91bmRlZCBjcWEtYmctZ3JheS0xMDAgY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtanVzdGlmeS1jZW50ZXIgaG92ZXI6Y3FhLWJnLWdyYXktMjAwIGNxYS1wLTAnXCJcbiAgICAgICAgICAgICAgW3Rvb2x0aXBdPVwiJ0RlbGV0ZSBxdWVyeSdcIiAoY2xpY2tlZCk9XCJkZWxldGVRdWVyeUJ5SWQoZ2V0Q3VycmVudFF1ZXJ5KCk/LmlkIHx8ICcnKVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJxdWVyaWVzLmxlbmd0aCA8PSAxXCIgW2F0dHIuYXJpYS1sYWJlbF09XCInRGVsZXRlIHF1ZXJ5J1wiPlxuICAgICAgICAgICAgICA8c3ZnIGNsYXNzPVwiY3FhLWZsZXgtc2hyaW5rLTBcIiB3aWR0aD1cIjE2XCIgaGVpZ2h0PVwiMTZcIiB2aWV3Qm94PVwiMCAwIDE2IDE2XCJcbiAgICAgICAgICAgICAgICBmaWxsPVwibm9uZVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiBhcmlhLWhpZGRlbj1cInRydWVcIj5cbiAgICAgICAgICAgICAgICA8cGF0aFxuICAgICAgICAgICAgICAgICAgZD1cIk0xMC42NjYzIDZWMTIuNjY2N0g1LjMzMzAxVjZIMTAuNjY2M1pNOS42NjYzNCAySDYuMzMzMDFMNS42NjYzNCAyLjY2NjY3SDMuMzMzMDFWNEgxMi42NjYzVjIuNjY2NjdIMTAuMzMzTDkuNjY2MzQgMlpNMTEuOTk5NyA0LjY2NjY3SDMuOTk5NjdWMTIuNjY2N0MzLjk5OTY3IDEzLjQgNC41OTk2NyAxNCA1LjMzMzAxIDE0SDEwLjY2NjNDMTEuMzk5NyAxNCAxMS45OTk3IDEzLjQgMTEuOTk5NyAxMi42NjY3VjQuNjY2NjdaXCJcbiAgICAgICAgICAgICAgICAgIGZpbGw9XCIjNkI3MjgwXCIgLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICA8L2NxYS1idXR0b24+XG4gICAgICAgICAgICA8Y3FhLWJ1dHRvbiB2YXJpYW50PVwiZmlsbGVkXCIgdGV4dD1cIlJ1blwiIGljb249XCJwbGF5X2Fycm93XCIgKGNsaWNrZWQpPVwib25SdW5RdWVyeSgpXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFnZXRDdXJyZW50UXVlcnlGb3JtR3JvdXAoKT8uZ2V0KCdxdWVyeScpPy52YWx1ZSB8fCAhZGF0YWJhc2VGb3JtLmdldCgnZGJFbnZpcm9ubWVudCcpPy52YWx1ZSB8fCBpc0xvYWRpbmdcIlxuICAgICAgICAgICAgICBbY3VzdG9tQ2xhc3NdPVwiJyFjcWEtYmctWyMzRjQzRUVdIGNxYS10ZXh0LVsjRkJGQ0ZGXSBjcWEtdGV4dC1zbSBjcWEtZm9udC1zZW1pYm9sZCBjcWEtd2hpdGVzcGFjZS1ub3dyYXAgIWNxYS1wdC1bMTBweF0gIWNxYS1wYi1bMTBweF0gIWNxYS1wbC1bMTZweF0gIWNxYS1wci1bMjRweF0gIWNxYS1nYXAtWzhweF0gY3FhLXJvdW5kZWQtbGcgY3FhLW1pbi1oLVszOHB4XSBob3ZlcjohY3FhLWJnLVsjMUIxRkVCXSAhY3FhLWJvcmRlci1ub25lJ1wiXG4gICAgICAgICAgICAgIFtpY29uQ29sb3JdPVwiJyNGQkZDRkYnXCI+XG4gICAgICAgICAgICA8L2NxYS1idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8IS0tIFJlc3VsdHMgU2VjdGlvbiAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWJvcmRlciBjcWEtYm9yZGVyLWdyYXktMjAwIGNxYS1yb3VuZGVkLWxnIGNxYS1tYi02XCI+XG4gICAgICAgIDwhLS0gVGFicyAtLT5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWJvcmRlci1iIGNxYS1ib3JkZXItZ3JheS0yMDAgY3FhLWJnLWdyYXktNTBcIj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJjcWEtcHgtNCBjcWEtcHktMiBjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRyYW5zaXRpb24tY29sb3JzIGNxYS1ib3JkZXItYi0yXCJcbiAgICAgICAgICAgIFtjbGFzcy5jcWEtdGV4dC1ibHVlLTYwMF09XCJzZWxlY3RlZFRhYiA9PT0gJ291dHB1dCdcIiBbY2xhc3MuY3FhLWJvcmRlci1ibHVlLTYwMF09XCJzZWxlY3RlZFRhYiA9PT0gJ291dHB1dCdcIlxuICAgICAgICAgICAgW2NsYXNzLmNxYS10ZXh0LWdyYXktNjAwXT1cInNlbGVjdGVkVGFiICE9PSAnb3V0cHV0J1wiXG4gICAgICAgICAgICBbY2xhc3MuY3FhLWJvcmRlci10cmFuc3BhcmVudF09XCJzZWxlY3RlZFRhYiAhPT0gJ291dHB1dCdcIiAoY2xpY2spPVwib25UYWJDaGFuZ2UoJ291dHB1dCcpXCI+XG4gICAgICAgICAgICBPdXRwdXRcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJjcWEtcHgtNCBjcWEtcHktMiBjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRyYW5zaXRpb24tY29sb3JzIGNxYS1ib3JkZXItYi0yXCJcbiAgICAgICAgICAgIFtjbGFzcy5jcWEtdGV4dC1ibHVlLTYwMF09XCJzZWxlY3RlZFRhYiA9PT0gJ3ZlcmlmaWNhdGlvbidcIlxuICAgICAgICAgICAgW2NsYXNzLmNxYS1ib3JkZXItYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICd2ZXJpZmljYXRpb24nXCJcbiAgICAgICAgICAgIFtjbGFzcy5jcWEtdGV4dC1ncmF5LTYwMF09XCJzZWxlY3RlZFRhYiAhPT0gJ3ZlcmlmaWNhdGlvbidcIlxuICAgICAgICAgICAgW2NsYXNzLmNxYS1ib3JkZXItdHJhbnNwYXJlbnRdPVwic2VsZWN0ZWRUYWIgIT09ICd2ZXJpZmljYXRpb24nXCIgKGNsaWNrKT1cIm9uVGFiQ2hhbmdlKCd2ZXJpZmljYXRpb24nKVwiPlxuICAgICAgICAgICAgVmVyaWZpY2F0aW9uXG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDwhLS0gVGFiIENvbnRlbnQgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtcC00XCI+XG4gICAgICAgICAgPCEtLSBPdXRwdXQgVGFiIC0tPlxuICAgICAgICAgIDxkaXYgKm5nSWY9XCJzZWxlY3RlZFRhYiA9PT0gJ291dHB1dCdcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1qdXN0aWZ5LWJldHdlZW4gY3FhLW1iLTNcIj5cbiAgICAgICAgICAgICAgPGg0IGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtZ3JheS05MDBcIj5RdWVyeSBSZXN1bHRzPC9oND5cbiAgICAgICAgICAgICAgPGNxYS1idXR0b24gdmFyaWFudD1cInRleHRcIiB0ZXh0PVwiQ29weVwiIGljb249XCJjb250ZW50X2NvcHlcIiBbY3VzdG9tQ2xhc3NdPVwiJ2NxYS10ZXh0LWJsdWUtNjAwJ1wiXG4gICAgICAgICAgICAgICAgKGNsaWNrZWQpPVwib25Db3B5UmVzdWx0cygpXCI+XG4gICAgICAgICAgICAgIDwvY3FhLWJ1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICA8IS0tIFJlc3VsdHMgVGFibGUgLS0+XG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwicXVlcnlSZXN1bHRzICYmIHF1ZXJ5UmVzdWx0cy5sZW5ndGggPiAwXCIgY2xhc3M9XCJjcWEtb3ZlcmZsb3cteC1hdXRvXCI+XG4gICAgICAgICAgICAgIDx0YWJsZSBjbGFzcz1cImNxYS13LWZ1bGwgY3FhLWJvcmRlci1jb2xsYXBzZVwiPlxuICAgICAgICAgICAgICAgIDx0aGVhZD5cbiAgICAgICAgICAgICAgICAgIDx0ciBjbGFzcz1cImNxYS1iZy1ncmF5LTUwIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLWdyYXktMjAwXCI+XG4gICAgICAgICAgICAgICAgICAgIDx0aCAqbmdGb3I9XCJsZXQga2V5IG9mIGdldFRhYmxlQ29sdW1ucygpXCJcbiAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNxYS1weC00IGNxYS1weS0yIGNxYS10ZXh0LWxlZnQgY3FhLXRleHQteHMgY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtZ3JheS03MDAgY3FhLXVwcGVyY2FzZVwiPlxuICAgICAgICAgICAgICAgICAgICAgIHt7IGtleSB9fVxuICAgICAgICAgICAgICAgICAgICA8L3RoPlxuICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgICAgICAgIDx0Ym9keT5cbiAgICAgICAgICAgICAgICAgIDx0ciAqbmdGb3I9XCJsZXQgcm93IG9mIHF1ZXJ5UmVzdWx0c1wiIGNsYXNzPVwiY3FhLWJvcmRlci1iIGNxYS1ib3JkZXItZ3JheS0yMDAgaG92ZXI6Y3FhLWJnLWdyYXktNTBcIj5cbiAgICAgICAgICAgICAgICAgICAgPHRkICpuZ0Zvcj1cImxldCBrZXkgb2YgZ2V0VGFibGVDb2x1bW5zKClcIiBjbGFzcz1cImNxYS1weC00IGNxYS1weS0yIGNxYS10ZXh0LXNtIGNxYS10ZXh0LWdyYXktOTAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAge3sgcm93W2tleV0gfX1cbiAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgPC90Ym9keT5cbiAgICAgICAgICAgICAgPC90YWJsZT5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIXF1ZXJ5UmVzdWx0cyB8fCBxdWVyeVJlc3VsdHMubGVuZ3RoID09PSAwXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJjcWEtdGV4dC1jZW50ZXIgY3FhLXB5LTggY3FhLXRleHQtZ3JheS00MDAgY3FhLXRleHQtc21cIj5cbiAgICAgICAgICAgICAgTm8gcmVzdWx0cyB5ZXQuIFJ1biBhIHF1ZXJ5IHRvIHNlZSByZXN1bHRzLlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8IS0tIFZlcmlmaWNhdGlvbiBUYWIgLS0+XG4gICAgICAgICAgPGRpdiAqbmdJZj1cInNlbGVjdGVkVGFiID09PSAndmVyaWZpY2F0aW9uJ1wiIGNsYXNzPVwiYXNzZXJ0aW9ucy1jb250YWluZXJcIj5cbiAgICAgICAgICAgIDwhLS0gSGVhZGVyIFNlY3Rpb24gLS0+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYXNzZXJ0aW9ucy1oZWFkZXJcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhlYWRlci1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgPGgzIGNsYXNzPVwiaGVhZGVyLXRpdGxlXCI+QXNzZXJ0aW9uczwvaDM+XG4gICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJoZWFkZXItc3VidGl0bGVcIj5Vc2UgSlNPTlBhdGggdG8gdGFyZ2V0IHZhbHVlcyBpbiB0aGUgcXVlcnkgb3V0cHV0LjwvcD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDxidXR0b24gXG4gICAgICAgICAgICAgICAgbWF0LXN0cm9rZWQtYnV0dG9uIFxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiIFxuICAgICAgICAgICAgICAgIGNsYXNzPVwiYWRkLWFzc2VydGlvbi1idXR0b25cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJhZGRBc3NlcnRpb24oKVwiPlxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5hZGQ8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgIEFkZCBBc3NlcnRpb25cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPCEtLSBUYWJsZSBTZWN0aW9uIC0tPlxuICAgICAgICAgICAgPGZvcm0gKm5nSWY9XCJnZXRDdXJyZW50QXNzZXJ0aW9uc0Zvcm0oKVwiIFtmb3JtR3JvdXBdPVwiZ2V0Q3VycmVudEFzc2VydGlvbnNGb3JtKCkhXCIgY2xhc3M9XCJhc3NlcnRpb25zLWZvcm1cIj5cbiAgICAgICAgICAgICAgPGRpdiBmb3JtQXJyYXlOYW1lPVwiYXNzZXJ0aW9uc1wiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1zY3JvbGwtY29udGFpbmVyXCI+XG4gICAgICAgICAgICAgICAgICA8dGFibGUgbWF0LXRhYmxlIFtkYXRhU291cmNlXT1cImFzc2VydGlvbnNEYXRhU291cmNlXCIgY2xhc3M9XCJhc3NlcnRpb25zLXRhYmxlXCIgI2Fzc2VydGlvbnNUYWJsZT5cbiAgICAgICAgICAgICAgICAgICAgPCEtLSBKU09OUGF0aCBDb2x1bW4gLS0+XG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwianNvblBhdGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPmpzb25QYXRoPC90aD5cbiAgICAgICAgICAgICAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgYXNzZXJ0aW9uOyBsZXQgaSA9IGluZGV4XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyIFtmb3JtR3JvdXBOYW1lXT1cImlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgY2xhc3M9XCJmdWxsLXdpZHRoLWZpZWxkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXQgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJqc29uUGF0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cInVzZXJuYW1lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJnZXRGb3JtQ29udHJvbEF0KGksICdqc29uUGF0aCcpPy5oYXNFcnJvcigncmVxdWlyZWQnKSAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRGb3JtQ29udHJvbEF0KGksICdqc29uUGF0aCcpPy50b3VjaGVkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBKU09OUGF0aCBpcyByZXF1aXJlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgICAgICAgICAgICAgPCEtLSBWZXJpZmljYXRpb24gVHlwZSBDb2x1bW4gLS0+XG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwidmVyaWZpY2F0aW9uVHlwZVwiPlxuICAgICAgICAgICAgICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+dmVyaWZpY2F0aW9uVHlwZTwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGFzc2VydGlvbjsgbGV0IGkgPSBpbmRleFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBbZm9ybUdyb3VwTmFtZV09XCJpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwib3V0bGluZVwiIGNsYXNzPVwiZnVsbC13aWR0aC1maWVsZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0IGZvcm1Db250cm9sTmFtZT1cInZlcmlmaWNhdGlvblR5cGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwiZXF1YWxzXCI+RXF1YWxzPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJub3RfZXF1YWxzXCI+Tm90IEVxdWFsczwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwiY29udGFpbnNcIj5Db250YWluczwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwibm90X2NvbnRhaW5zXCI+Tm90IENvbnRhaW5zPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJncmVhdGVyX3RoYW5cIj5HcmVhdGVyIFRoYW48L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cImxlc3NfdGhhblwiPkxlc3MgVGhhbjwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwiZ3JlYXRlcl90aGFuX29yX2VxdWFsc1wiPkdyZWF0ZXIgVGhhbiBPciBFcXVhbHM8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cImxlc3NfdGhhbl9vcl9lcXVhbHNcIj5MZXNzIFRoYW4gT3IgRXF1YWxzPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJleGlzdHNcIj5FeGlzdHM8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cIm5vdF9leGlzdHNcIj5Ob3QgRXhpc3RzPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgICAgICAgICAgICAgIDwhLS0gRXhwZWN0ZWQgVHlwZSBDb2x1bW4gLS0+XG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiZXhwZWN0ZWRUeXBlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZj5leHBlY3RlZFR5cGU8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBhc3NlcnRpb247IGxldCBpID0gaW5kZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgW2Zvcm1Hcm91cE5hbWVdPVwiaVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBjbGFzcz1cImZ1bGwtd2lkdGgtZmllbGRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImV4cGVjdGVkVHlwZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cIm9uRXhwZWN0ZWRUeXBlQ2hhbmdlKGksICRldmVudC52YWx1ZSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwic3RyaW5nXCI+U3RyaW5nPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJudW1iZXJcIj5OdW1iZXI8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cImJvb2xlYW5cIj5Cb29sZWFuPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJvYmplY3RcIj5PYmplY3Q8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cImFycmF5XCI+QXJyYXk8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cIm51bGxcIj5OdWxsPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgICAgICAgICAgICAgIDwhLS0gRXhwZWN0ZWQgVmFsdWUgQ29sdW1uIC0tPlxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImV4cGVjdGVkVmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPmV4cGVjdGVkVmFsdWU8L3RoPlxuICAgICAgICAgICAgICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBhc3NlcnRpb247IGxldCBpID0gaW5kZXhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgW2Zvcm1Hcm91cE5hbWVdPVwiaVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFN0cmluZywgQXJyYXksIE9iamVjdCBJbnB1dCAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiZ2V0RXhwZWN0ZWRUeXBlKGkpID09PSAnc3RyaW5nJyB8fCBnZXRFeHBlY3RlZFR5cGUoaSkgPT09ICdhcnJheScgfHwgZ2V0RXhwZWN0ZWRUeXBlKGkpID09PSAnb2JqZWN0J1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZ1bGwtd2lkdGgtZmllbGRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGV4dGFyZWEgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImdldEV4cGVjdGVkVHlwZShpKSA9PT0gJ2FycmF5JyB8fCBnZXRFeHBlY3RlZFR5cGUoaSkgPT09ICdvYmplY3QnXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZXhwZWN0ZWRWYWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiZ2V0RXhwZWN0ZWRWYWx1ZVBsYWNlaG9sZGVyKGkpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd3M9XCIzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkPjwvdGV4dGFyZWE+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJnZXRFeHBlY3RlZFR5cGUoaSkgPT09ICdzdHJpbmcnXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZXhwZWN0ZWRWYWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiZ2V0RXhwZWN0ZWRWYWx1ZVBsYWNlaG9sZGVyKGkpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJnZXRGb3JtQ29udHJvbEF0KGksICdleHBlY3RlZFZhbHVlJyk/Lmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEZvcm1Db250cm9sQXQoaSwgJ2V4cGVjdGVkVmFsdWUnKT8udG91Y2hlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXhwZWN0ZWQgdmFsdWUgaXMgcmVxdWlyZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZ2V0Rm9ybUNvbnRyb2xBdChpLCAnZXhwZWN0ZWRWYWx1ZScpPy5oYXNFcnJvcignaW52YWxpZFR5cGUnKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgZ2V0Rm9ybUNvbnRyb2xBdChpLCAnZXhwZWN0ZWRWYWx1ZScpPy5lcnJvcnM/Lm1lc3NhZ2UgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIE51bGwgVHlwZSBEaXNwbGF5IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJnZXRFeHBlY3RlZFR5cGUoaSkgPT09ICdudWxsJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZ1bGwtd2lkdGgtZmllbGRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImV4cGVjdGVkVmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cImdldEV4cGVjdGVkVmFsdWVQbGFjZWhvbGRlcihpKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gTnVtYmVyIElucHV0IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJnZXRFeHBlY3RlZFR5cGUoaSkgPT09ICdudW1iZXInXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBlYXJhbmNlPVwib3V0bGluZVwiIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZnVsbC13aWR0aC1maWVsZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdElucHV0IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJleHBlY3RlZFZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRXhwZWN0ZWQgVmFsdWUgaW4gTnVtYmVyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3IgKm5nSWY9XCJnZXRGb3JtQ29udHJvbEF0KGksICdleHBlY3RlZFZhbHVlJyk/Lmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdldEZvcm1Db250cm9sQXQoaSwgJ2V4cGVjdGVkVmFsdWUnKT8udG91Y2hlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXhwZWN0ZWQgdmFsdWUgaXMgcmVxdWlyZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIEJvb2xlYW4gU2VsZWN0IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJnZXRFeHBlY3RlZFR5cGUoaSkgPT09ICdib29sZWFuJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZ1bGwtd2lkdGgtZmllbGRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBmb3JtQ29udHJvbE5hbWU9XCJleHBlY3RlZFZhbHVlXCIgcmVxdWlyZWQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cInRydWVcIj50cnVlPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJmYWxzZVwiPmZhbHNlPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZ2V0Rm9ybUNvbnRyb2xBdChpLCAnZXhwZWN0ZWRWYWx1ZScpPy5oYXNFcnJvcigncmVxdWlyZWQnKSAmJiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRGb3JtQ29udHJvbEF0KGksICdleHBlY3RlZFZhbHVlJyk/LnRvdWNoZWRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEV4cGVjdGVkIHZhbHVlIGlzIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgICA8L3RkPlxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICAgICAgICAgICAgICA8IS0tIEFjdGlvbnMgQ29sdW1uIC0tPlxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyIG1hdENvbHVtbkRlZj1cImFjdGlvbnNcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPjwvdGg+XG4gICAgICAgICAgICAgICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGFzc2VydGlvbjsgbGV0IGkgPSBpbmRleFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uIFxuICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1cIndhcm5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImRlbGV0ZS1idXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwicmVtb3ZlQXNzZXJ0aW9uKGkpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW21hdFRvb2x0aXBdPVwiJ0RlbGV0ZSBhc3NlcnRpb24nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgICAgICAgICAgICAgPHRyIG1hdC1oZWFkZXItcm93ICptYXRIZWFkZXJSb3dEZWY9XCJkaXNwbGF5ZWRDb2x1bW5zXCI+PC90cj5cbiAgICAgICAgICAgICAgICAgICAgPHRyIG1hdC1yb3cgKm1hdFJvd0RlZj1cImxldCByb3c7IGNvbHVtbnM6IGRpc3BsYXllZENvbHVtbnM7XCI+PC90cj5cbiAgICAgICAgICAgICAgICAgIDwvdGFibGU+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICA8IS0tIEVtcHR5IFN0YXRlIC0tPlxuICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJnZXRBc3NlcnRpb25zRm9ybUFycmF5KCkubGVuZ3RoID09PSAwXCIgY2xhc3M9XCJlbXB0eS1zdGF0ZVwiPlxuICAgICAgICAgICAgICAgICAgPHA+Tm8gYXNzZXJ0aW9ucyBhZGRlZC4gQ2xpY2sgXCJBZGQgQXNzZXJ0aW9uXCIgdG8gY3JlYXRlIG9uZS48L3A+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9mb3JtPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cblxuXG5cbiAgPCEtLSBBY3Rpb24gQnV0dG9ucyAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS13LWZ1bGwgY3FhLWdhcC0yIGNxYS1tdC1hdXRvIGNxYS1wdC00IGNxYS1ib3JkZXItdCBjcWEtYm9yZGVyLWdyYXktMjAwXCI+XG4gICAgPGNxYS1idXR0b24gY2xhc3M9XCJjcWEtdy0xLzJcIiB2YXJpYW50PVwib3V0bGluZWRcIiB0ZXh0PVwiQ2FuY2VsXCIgW2N1c3RvbUNsYXNzXT1cIidjcWEtZmxleC0xIGNxYS13LWZ1bGwnXCJcbiAgICAgIChjbGlja2VkKT1cIm9uQ2FuY2VsKClcIj5cbiAgICA8L2NxYS1idXR0b24+XG4gICAgPGNxYS1idXR0b24gY2xhc3M9XCJjcWEtdy0xLzJcIiB2YXJpYW50PVwiZmlsbGVkXCIgW3RleHRdPVwiZWRpdE1vZGUgPyAnVXBkYXRlIFN0ZXAnIDogJ0NyZWF0ZSBTdGVwJ1wiIFtjdXN0b21DbGFzc109XCInY3FhLWZsZXgtMSBjcWEtdy1mdWxsJ1wiXG4gICAgICAoY2xpY2tlZCk9XCJvbkNyZWF0ZVN0ZXAoKVwiPlxuICAgIDwvY3FhLWJ1dHRvbj5cbiAgPC9kaXY+XG48L2Rpdj4iXX0=
|