@cqa-lib/cqa-ui 1.1.184 → 1.1.185

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.
@@ -0,0 +1,510 @@
1
+ import { Component, Input, Output, EventEmitter } from '@angular/core';
2
+ import { Validators } from '@angular/forms';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/forms";
5
+ import * as i2 from "../../dynamic-select/dynamic-select-field.component";
6
+ import * as i3 from "../../custom-input/custom-input.component";
7
+ import * as i4 from "../../button/button.component";
8
+ import * as i5 from "@angular/material/icon";
9
+ import * as i6 from "../../custom-textarea/custom-textarea.component";
10
+ import * as i7 from "@angular/material/checkbox";
11
+ import * as i8 from "@angular/common";
12
+ export class StepBuilderApiComponent {
13
+ constructor(fb) {
14
+ this.fb = fb;
15
+ /** Options for HTTP method dropdown */
16
+ this.httpMethodOptions = [
17
+ { id: 'GET', value: 'GET', name: 'GET', label: 'GET' },
18
+ { id: 'POST', value: 'POST', name: 'POST', label: 'POST' },
19
+ { id: 'PUT', value: 'PUT', name: 'PUT', label: 'PUT' },
20
+ { id: 'PATCH', value: 'PATCH', name: 'PATCH', label: 'PATCH' },
21
+ { id: 'DELETE', value: 'DELETE', name: 'DELETE', label: 'DELETE' },
22
+ { id: 'HEAD', value: 'HEAD', name: 'HEAD', label: 'HEAD' },
23
+ { id: 'OPTIONS', value: 'OPTIONS', name: 'OPTIONS', label: 'OPTIONS' }
24
+ ];
25
+ /** Options for header name dropdown */
26
+ this.headerNameOptions = [];
27
+ /** Current progress step */
28
+ this.currentStep = 'request-details';
29
+ /** Response preview data */
30
+ this.responsePreview = null;
31
+ /** Loading state */
32
+ this.isLoading = false;
33
+ /** Emit when step is created */
34
+ this.createStep = new EventEmitter();
35
+ /** Emit when cancelled */
36
+ this.cancelled = new EventEmitter();
37
+ /** Emit when request is sent */
38
+ this.sendRequest = new EventEmitter();
39
+ /** Emit when cURL is imported */
40
+ this.importCurl = new EventEmitter();
41
+ this.selectedTab = 'headers';
42
+ this.selectedProgressStep = 'request-details';
43
+ // progressSteps: ProgressStep[] = ['request-details', 'store-response', 'validation'];
44
+ // Cache config objects to prevent infinite change detection loops
45
+ this.verificationTypeConfigCache = null;
46
+ this.expectedTypeConfigCache = null;
47
+ this.httpMethodConfigCache = null;
48
+ this.headerNameConfigCache = null;
49
+ this.paramNameConfigCache = null;
50
+ this.hasLoadedInitialData = false;
51
+ this.apiForm = this.fb.group({
52
+ method: ['GET', Validators.required],
53
+ url: ['', Validators.required],
54
+ headers: this.fb.array([]),
55
+ body: [''],
56
+ params: this.fb.array([]),
57
+ scripts: [''],
58
+ variableName: [''],
59
+ validation: this.fb.array([])
60
+ });
61
+ }
62
+ ngOnInit() {
63
+ // Sync currentStep input with selectedProgressStep
64
+ if (this.currentStep) {
65
+ this.selectedProgressStep = this.currentStep;
66
+ }
67
+ // Load initial data if provided (edit mode)
68
+ if (this.initialData) {
69
+ this.loadInitialData(this.initialData);
70
+ this.hasLoadedInitialData = true;
71
+ }
72
+ else {
73
+ // Add initial header row for new step
74
+ this.addHeader();
75
+ }
76
+ // Initialize validation form array if starting on validation step
77
+ if (this.selectedProgressStep === 'validation' && this.validationFormArray.length === 0) {
78
+ this.addValidationRule();
79
+ }
80
+ }
81
+ loadInitialData(data) {
82
+ console.log('loadInitialData: Loading data', data);
83
+ console.log('loadInitialData: Headers count', data.headers?.length || 0);
84
+ console.log('loadInitialData: Headers data', data.headers);
85
+ // Set basic fields
86
+ this.apiForm.patchValue({
87
+ method: data.method || 'GET',
88
+ url: data.url || '',
89
+ body: data.body || '',
90
+ scripts: data.scripts || '',
91
+ variableName: data.variableName || ''
92
+ });
93
+ // Load headers
94
+ // Clear existing headers first
95
+ while (this.headersFormArray.length !== 0) {
96
+ this.headersFormArray.removeAt(0);
97
+ }
98
+ if (data.headers && data.headers.length > 0) {
99
+ // Add headers from initial data (include all headers, even if empty)
100
+ data.headers.forEach(header => {
101
+ const headerGroup = this.fb.group({
102
+ name: [header.name || '', Validators.required],
103
+ value: [header.value || '', Validators.required]
104
+ });
105
+ this.headersFormArray.push(headerGroup);
106
+ });
107
+ console.log('loadInitialData: Loaded headers into form array, count:', this.headersFormArray.length);
108
+ }
109
+ // Ensure at least one header row exists
110
+ if (this.headersFormArray.length === 0) {
111
+ console.log('loadInitialData: No headers found, adding empty header row');
112
+ this.addHeader();
113
+ }
114
+ // Load params
115
+ // Clear existing params first
116
+ while (this.paramsFormArray.length !== 0) {
117
+ this.paramsFormArray.removeAt(0);
118
+ }
119
+ if (data.params && data.params.length > 0) {
120
+ // Add params from initial data (include all params, even if empty)
121
+ data.params.forEach(param => {
122
+ const paramGroup = this.fb.group({
123
+ name: [param.name || '', Validators.required],
124
+ value: [param.value || '', Validators.required]
125
+ });
126
+ this.paramsFormArray.push(paramGroup);
127
+ });
128
+ }
129
+ // Load validation rules
130
+ if (data.validation && data.validation.length > 0) {
131
+ // Clear existing validation rules
132
+ while (this.validationFormArray.length !== 0) {
133
+ this.validationFormArray.removeAt(0);
134
+ }
135
+ // Add validation rules from initial data
136
+ data.validation.forEach(rule => {
137
+ const validationGroup = this.fb.group({
138
+ jsonPath: [rule.jsonPath || '', Validators.required],
139
+ verificationType: [rule.verificationType || 'equals', Validators.required],
140
+ expectedType: [rule.expectedType || 'string', Validators.required],
141
+ expectedValue: [rule.expectedValue !== undefined ? rule.expectedValue : '', Validators.required],
142
+ result: [rule.result || 'Not run'],
143
+ checked: [rule.checked || false]
144
+ });
145
+ // Ensure all controls are enabled
146
+ validationGroup.enable({ emitEvent: false });
147
+ this.validationFormArray.push(validationGroup);
148
+ });
149
+ }
150
+ }
151
+ get headersFormArray() {
152
+ return this.apiForm.get('headers');
153
+ }
154
+ get paramsFormArray() {
155
+ return this.apiForm.get('params');
156
+ }
157
+ get validationFormArray() {
158
+ return this.apiForm.get('validation');
159
+ }
160
+ addHeader() {
161
+ const headerGroup = this.fb.group({
162
+ name: ['', Validators.required],
163
+ value: ['', Validators.required]
164
+ });
165
+ this.headersFormArray.push(headerGroup);
166
+ }
167
+ removeHeader(index) {
168
+ this.headersFormArray.removeAt(index);
169
+ }
170
+ addParam() {
171
+ const paramGroup = this.fb.group({
172
+ name: ['', Validators.required],
173
+ value: ['', Validators.required]
174
+ });
175
+ this.paramsFormArray.push(paramGroup);
176
+ }
177
+ removeParam(index) {
178
+ this.paramsFormArray.removeAt(index);
179
+ }
180
+ ngOnChanges(changes) {
181
+ // Reset config caches when inputs change
182
+ if (changes['httpMethodOptions']) {
183
+ this.httpMethodConfigCache = null;
184
+ }
185
+ if (changes['headerNameOptions']) {
186
+ this.headerNameConfigCache = null;
187
+ }
188
+ // Load initial data if it's set after component initialization
189
+ if (changes['initialData'] && !changes['initialData'].firstChange && this.initialData && !this.hasLoadedInitialData) {
190
+ this.loadInitialData(this.initialData);
191
+ this.hasLoadedInitialData = true;
192
+ }
193
+ }
194
+ getHttpMethodConfig() {
195
+ if (!this.httpMethodConfigCache) {
196
+ this.httpMethodConfigCache = {
197
+ key: 'method',
198
+ placeholder: 'Select method',
199
+ multiple: false,
200
+ searchable: false,
201
+ options: this.httpMethodOptions
202
+ };
203
+ }
204
+ return this.httpMethodConfigCache;
205
+ }
206
+ getHeaderNameConfig(index) {
207
+ if (!this.headerNameConfigCache) {
208
+ const defaultOptions = [
209
+ { id: 'string', value: 'string', name: 'string', label: 'string' },
210
+ { id: 'Content-Type', value: 'Content-Type', name: 'Content-Type', label: 'Content-Type' },
211
+ { id: 'Authorization', value: 'Authorization', name: 'Authorization', label: 'Authorization' },
212
+ { id: 'Accept', value: 'Accept', name: 'Accept', label: 'Accept' }
213
+ ];
214
+ this.headerNameConfigCache = {
215
+ key: 'name',
216
+ placeholder: 'Select header',
217
+ multiple: false,
218
+ searchable: true,
219
+ options: this.headerNameOptions.length > 0 ? this.headerNameOptions : defaultOptions
220
+ };
221
+ }
222
+ return this.headerNameConfigCache;
223
+ }
224
+ getParamNameConfig(index) {
225
+ if (!this.paramNameConfigCache) {
226
+ this.paramNameConfigCache = {
227
+ key: 'name',
228
+ placeholder: 'Parameter name',
229
+ multiple: false,
230
+ searchable: false,
231
+ options: []
232
+ };
233
+ }
234
+ return this.paramNameConfigCache;
235
+ }
236
+ getHeaderFormGroup(index) {
237
+ return this.headersFormArray.at(index);
238
+ }
239
+ getParamFormGroup(index) {
240
+ return this.paramsFormArray.at(index);
241
+ }
242
+ onTabChange(tab) {
243
+ this.selectedTab = tab;
244
+ }
245
+ onSendRequest() {
246
+ if (this.apiForm.valid) {
247
+ const formValue = this.apiForm.value;
248
+ const headers = formValue.headers.map((h) => ({
249
+ name: h.name,
250
+ value: h.value
251
+ }));
252
+ const params = formValue.params ? formValue.params.map((p) => ({
253
+ name: p.name,
254
+ value: p.value
255
+ })) : [];
256
+ this.sendRequest.emit({
257
+ method: formValue.method,
258
+ url: formValue.url,
259
+ headers,
260
+ body: formValue.body,
261
+ params
262
+ });
263
+ }
264
+ }
265
+ onImportCurl() {
266
+ this.importCurl.emit();
267
+ }
268
+ onCancel() {
269
+ this.cancelled.emit();
270
+ }
271
+ onCreateStep() {
272
+ if (this.apiForm.valid) {
273
+ const formValue = this.apiForm.value;
274
+ const stepData = {
275
+ method: formValue.method,
276
+ url: formValue.url,
277
+ headers: formValue.headers.map((h) => ({
278
+ name: h.name,
279
+ value: h.value
280
+ })),
281
+ body: formValue.body,
282
+ params: formValue.params ? formValue.params.map((p) => ({
283
+ name: p.name,
284
+ value: p.value
285
+ })) : [],
286
+ scripts: formValue.scripts,
287
+ variableName: formValue.variableName || '',
288
+ validation: formValue.validation ? formValue.validation.map((v) => ({
289
+ jsonPath: v.jsonPath,
290
+ verificationType: v.verificationType,
291
+ expectedType: v.expectedType,
292
+ expectedValue: v.expectedValue,
293
+ result: v.result || 'Not run'
294
+ })) : []
295
+ };
296
+ this.createStep.emit(stepData);
297
+ }
298
+ }
299
+ onNext() {
300
+ // Move to next step or create step if on last step
301
+ const stepOrder = ['request-details', 'store-response', 'validation'];
302
+ const currentIndex = stepOrder.indexOf(this.selectedProgressStep);
303
+ if (currentIndex < stepOrder.length - 1) {
304
+ this.onProgressStepChange(stepOrder[currentIndex + 1]);
305
+ }
306
+ else {
307
+ this.onCreateStep();
308
+ }
309
+ }
310
+ onBack() {
311
+ // Move to previous step
312
+ const stepOrder = ['request-details', 'store-response', 'validation'];
313
+ const currentIndex = stepOrder.indexOf(this.selectedProgressStep);
314
+ if (currentIndex > 0) {
315
+ this.onProgressStepChange(stepOrder[currentIndex - 1]);
316
+ }
317
+ }
318
+ canGoBack() {
319
+ const stepOrder = ['request-details', 'store-response', 'validation'];
320
+ const currentIndex = stepOrder.indexOf(this.selectedProgressStep);
321
+ return currentIndex > 0;
322
+ }
323
+ isLastStep() {
324
+ const stepOrder = ['request-details', 'store-response', 'validation'];
325
+ const currentIndex = stepOrder.indexOf(this.selectedProgressStep);
326
+ return currentIndex === stepOrder.length - 1;
327
+ }
328
+ getProgressStepClass(step) {
329
+ const stepOrder = ['request-details', 'store-response', 'validation'];
330
+ const currentIndex = stepOrder.indexOf(this.currentStep);
331
+ const stepIndex = stepOrder.indexOf(step);
332
+ if (stepIndex < currentIndex) {
333
+ return 'cqa-text-gray-400'; // Completed
334
+ }
335
+ else if (stepIndex === currentIndex) {
336
+ return 'cqa-text-purple-600 cqa-font-semibold'; // Active
337
+ }
338
+ else {
339
+ return 'cqa-text-gray-400'; // Pending
340
+ }
341
+ }
342
+ getProgressStepNumber(step) {
343
+ const stepOrder = ['request-details', 'store-response', 'validation'];
344
+ return stepOrder.indexOf(step) + 1;
345
+ }
346
+ getProgressStepLabel(step) {
347
+ const labels = {
348
+ 'request-details': 'Request Details',
349
+ 'store-response': 'Store Response',
350
+ 'validation': 'Validation'
351
+ };
352
+ return labels[step];
353
+ }
354
+ formatJsonResponse(data) {
355
+ if (!data)
356
+ return '';
357
+ try {
358
+ return JSON.stringify(data, null, 2);
359
+ }
360
+ catch {
361
+ return String(data);
362
+ }
363
+ }
364
+ onProgressStepChange(step) {
365
+ this.selectedProgressStep = step;
366
+ // Initialize validation form array if switching to validation step
367
+ if (step === 'validation' && this.validationFormArray.length === 0) {
368
+ this.addValidationRule();
369
+ }
370
+ }
371
+ addValidationRule() {
372
+ const validationGroup = this.fb.group({
373
+ checked: [false],
374
+ jsonPath: ['', Validators.required],
375
+ verificationType: ['equals'],
376
+ expectedType: ['string'],
377
+ expectedValue: ['', Validators.required],
378
+ result: ['Not run']
379
+ });
380
+ // Ensure all controls are enabled to avoid disabled attribute warnings
381
+ validationGroup.enable({ emitEvent: false });
382
+ this.validationFormArray.push(validationGroup);
383
+ }
384
+ removeValidationRule(index) {
385
+ this.validationFormArray.removeAt(index);
386
+ }
387
+ getValidationFormGroup(index) {
388
+ return this.validationFormArray.at(index);
389
+ }
390
+ trackByValidationRuleIndex(index) {
391
+ return index;
392
+ }
393
+ trackByHeaderIndex(index) {
394
+ return index;
395
+ }
396
+ trackByParamIndex(index) {
397
+ return index;
398
+ }
399
+ getVerificationTypeOptions() {
400
+ return [
401
+ { id: 'equals', value: 'equals', name: 'Equals', label: 'Equals' },
402
+ { id: 'not_equals', value: 'not_equals', name: 'Not Equals', label: 'Not Equals' },
403
+ { id: 'contains', value: 'contains', name: 'Contains', label: 'Contains' },
404
+ { id: 'not_contains', value: 'not_contains', name: 'Not Contains', label: 'Not Contains' },
405
+ { id: 'greater_than', value: 'greater_than', name: 'Greater Than', label: 'Greater Than' },
406
+ { id: 'less_than', value: 'less_than', name: 'Less Than', label: 'Less Than' },
407
+ { id: 'greater_than_or_equals', value: 'greater_than_or_equals', name: 'Greater Than Or Equals', label: 'Greater Than Or Equals' },
408
+ { id: 'less_than_or_equals', value: 'less_than_or_equals', name: 'Less Than Or Equals', label: 'Less Than Or Equals' },
409
+ { id: 'exists', value: 'exists', name: 'Exists', label: 'Exists' },
410
+ { id: 'not_exists', value: 'not_exists', name: 'Not Exists', label: 'Not Exists' }
411
+ ];
412
+ }
413
+ getExpectedTypeOptions() {
414
+ return [
415
+ { id: 'string', value: 'string', name: 'String', label: 'String' },
416
+ { id: 'number', value: 'number', name: 'Number', label: 'Number' },
417
+ { id: 'boolean', value: 'boolean', name: 'Boolean', label: 'Boolean' },
418
+ { id: 'object', value: 'object', name: 'Object', label: 'Object' },
419
+ { id: 'array', value: 'array', name: 'Array', label: 'Array' },
420
+ { id: 'null', value: 'null', name: 'Null', label: 'Null' }
421
+ ];
422
+ }
423
+ getVerificationTypeConfig(index) {
424
+ // Cache the config to prevent infinite change detection loops
425
+ if (!this.verificationTypeConfigCache) {
426
+ this.verificationTypeConfigCache = {
427
+ key: 'verificationType',
428
+ placeholder: 'Select verification type',
429
+ multiple: false,
430
+ searchable: false,
431
+ options: this.getVerificationTypeOptions()
432
+ };
433
+ }
434
+ return this.verificationTypeConfigCache;
435
+ }
436
+ getExpectedTypeConfig(index) {
437
+ // Cache the config to prevent infinite change detection loops
438
+ if (!this.expectedTypeConfigCache) {
439
+ this.expectedTypeConfigCache = {
440
+ key: 'expectedType',
441
+ placeholder: 'Select expected type',
442
+ multiple: false,
443
+ searchable: false,
444
+ options: this.getExpectedTypeOptions()
445
+ };
446
+ }
447
+ return this.expectedTypeConfigCache;
448
+ }
449
+ getResultClass(result) {
450
+ if (result === 'Pass') {
451
+ return 'cqa-bg-green-500 cqa-text-white';
452
+ }
453
+ else if (result === 'Fail') {
454
+ return 'cqa-bg-red-500 cqa-text-white';
455
+ }
456
+ return 'cqa-bg-gray-300 cqa-text-gray-700';
457
+ }
458
+ get allValidationRulesSelected() {
459
+ return this.validationFormArray.length > 0 &&
460
+ this.validationFormArray.controls.every(control => control.get('checked')?.value);
461
+ }
462
+ get someValidationRulesSelected() {
463
+ return this.validationFormArray.controls.some(control => control.get('checked')?.value) &&
464
+ !this.allValidationRulesSelected;
465
+ }
466
+ onSelectAllValidationRules(checked) {
467
+ this.validationFormArray.controls.forEach(control => {
468
+ control.get('checked')?.setValue(checked);
469
+ });
470
+ }
471
+ onDeleteSelectedValidationRules() {
472
+ const indicesToRemove = [];
473
+ this.validationFormArray.controls.forEach((control, index) => {
474
+ if (control.get('checked')?.value) {
475
+ indicesToRemove.push(index);
476
+ }
477
+ });
478
+ // Remove in reverse order to maintain correct indices
479
+ indicesToRemove.reverse().forEach(index => {
480
+ this.removeValidationRule(index);
481
+ });
482
+ }
483
+ }
484
+ StepBuilderApiComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderApiComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
485
+ StepBuilderApiComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderApiComponent, selector: "cqa-step-builder-api", inputs: { httpMethodOptions: "httpMethodOptions", headerNameOptions: "headerNameOptions", currentStep: "currentStep", responsePreview: "responsePreview", isLoading: "isLoading", initialData: "initialData" }, outputs: { createStep: "createStep", cancelled: "cancelled", sendRequest: "sendRequest", importCurl: "importCurl" }, 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 Create API Test Step\n </h2>\n\n <!-- Progress Tracker -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-4 cqa-mb-6 cqa-pb-4 cqa-border-b cqa-border-gray-200\">\n <!-- <div *ngFor=\"let step of progressSteps\"\n class=\"cqa-flex cqa-items-center cqa-gap-2\"\n [ngClass]=\"getProgressStepClass(step)\">\n <span class=\"cqa-text-sm cqa-font-medium\">{{ getProgressStepNumber(step) }} {{ getProgressStepLabel(step) }}</span>\n <span *ngIf=\"step !== 'validation'\" class=\"cqa-text-gray-300\">\u2022</span>\n </div> -->\n <div\n class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'request-details'}\" (click)=\"onProgressStepChange('request-details')\">\n <div>1</div>\n <div>Request Details</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'store-response'}\" (click)=\"onProgressStepChange('store-response')\">\n <div>2</div>\n <div>Store Response</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'validation'}\" (click)=\"onProgressStepChange('validation')\">\n <div>3</div>\n <div>Validation</div>\n <div></div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"selectedProgressStep === 'request-details'\">\n <!-- API Request Configuration -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-mb-6\">\n <div class=\"cqa-w-32 cqa-flex-shrink-0\">\n <cqa-dynamic-select\n [form]=\"apiForm\"\n [config]=\"getHttpMethodConfig()\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Enter API endpoint URL'\"\n [value]=\"apiForm.get('url')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('url')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <cqa-button\n variant=\"outlined\"\n text=\"Import API cURL\"\n (clicked)=\"onImportCurl()\">\n </cqa-button>\n <cqa-button\n variant=\"filled\"\n text=\"Send Request\"\n (clicked)=\"onSendRequest()\"\n [disabled]=\"!apiForm.get('url')?.value || isLoading\">\n </cqa-button>\n </div>\n\n <!-- Request Details Tabs -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Tab Navigation -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n 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 === 'headers'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'headers'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'headers'\"\n (click)=\"onTabChange('headers')\">\n Headers\n </button>\n <button\n 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 === 'body'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'body'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'body'\"\n (click)=\"onTabChange('body')\">\n Body\n </button>\n <button\n 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 === 'params'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'params'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'params'\"\n (click)=\"onTabChange('params')\">\n Params\n </button>\n <button\n 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 === 'scripts'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'scripts'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'scripts'\"\n (click)=\"onTabChange('scripts')\">\n Scripts\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-border cqa-border-gray-200 cqa-border-t-0 cqa-rounded-b-lg\">\n <!-- Headers Tab -->\n <div *ngIf=\"selectedTab === 'headers'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Value</div>\n </div>\n <div *ngFor=\"let header of headersFormArray.controls; let i = index; trackBy: trackByHeaderIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-dynamic-select\n [form]=\"getHeaderFormGroup(i)\"\n [config]=\"getHeaderNameConfig(i)\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Header value'\"\n [value]=\"getHeaderFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getHeaderFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeHeader(i)\"\n [attr.aria-label]=\"'Remove header'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addHeader()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Header</span>\n </button>\n </div>\n\n <!-- Body Tab -->\n <div *ngIf=\"selectedTab === 'body'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter request body (JSON, XML, etc.)'\"\n [value]=\"apiForm.get('body')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('body')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Params Tab -->\n <div *ngIf=\"selectedTab === 'params'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Value</div>\n </div>\n <div *ngFor=\"let param of paramsFormArray.controls; let i = index; trackBy: trackByParamIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-custom-input\n [placeholder]=\"'Parameter name'\"\n [value]=\"getParamFormGroup(i).get('name')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('name')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Parameter value'\"\n [value]=\"getParamFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeParam(i)\"\n [attr.aria-label]=\"'Remove parameter'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addParam()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Parameter</span>\n </button>\n </div>\n\n <!-- Scripts Tab -->\n <div *ngIf=\"selectedTab === 'scripts'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter scripts (JavaScript, etc.)'\"\n [value]=\"apiForm.get('scripts')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('scripts')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'store-response'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Store Response Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Store Response\n </h3>\n\n <!-- Variable Name Input -->\n <div class=\"cqa-mb-6\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-gray-700 cqa-mb-1 cqa-block\">\n Variable Name\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable Name'\"\n [value]=\"apiForm.get('variableName')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('variableName')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </div>\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'validation'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Validation Rules Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Validation Rules\n </h3>\n\n <!-- Validation Rules Table -->\n <div class=\"cqa-bg-white cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-4\">\n <!-- Table Header -->\n <div class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200 cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox\n [checked]=\"allValidationRulesSelected\"\n [indeterminate]=\"someValidationRulesSelected\"\n (change)=\"onSelectAllValidationRules($event.checked)\">\n </mat-checkbox>\n </div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">jsonPath</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">verificationType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedValue</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Result</div>\n </div>\n\n <!-- Table Body -->\n <div class=\"cqa-flex cqa-flex-col\">\n <div *ngFor=\"let validationRule of validationFormArray.controls; let i = index; trackBy: trackByValidationRuleIndex\" \n [formGroup]=\"getValidationFormGroup(i)\"\n class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-border-b cqa-border-gray-200 cqa-items-center cqa-last:border-b-0\">\n <!-- Checkbox -->\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox formControlName=\"checked\">\n </mat-checkbox>\n </div>\n\n <!-- jsonPath -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'jsonPath'\"\n [value]=\"getValidationFormGroup(i).get('jsonPath')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('jsonPath')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- verificationType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getVerificationTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getExpectedTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedValue -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'expectedValue'\"\n [value]=\"getValidationFormGroup(i).get('expectedValue')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('expectedValue')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Result and Delete -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button\n type=\"button\"\n class=\"cqa-px-3 cqa-py-1 cqa-rounded cqa-text-[10px] cqa-font-medium\"\n [ngClass]=\"getResultClass(getValidationFormGroup(i).get('result')?.value || 'Not run')\">\n {{ getValidationFormGroup(i).get('result')?.value || 'Not run' }}\n </button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-6 cqa-h-6 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeValidationRule(i)\"\n [attr.aria-label]=\"'Delete validation rule'\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Add Another Rule and Delete Selected -->\n <div class=\"cqa-flex cqa-justify-between cqa-items-center cqa-mb-4\">\n <button\n *ngIf=\"someValidationRulesSelected || allValidationRulesSelected\"\n type=\"button\"\n class=\"cqa-text-red-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-red-700 cqa-transition-colors\"\n (click)=\"onDeleteSelectedValidationRules()\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n <span>Delete Selected</span>\n </button>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addValidationRule()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Another</span>\n </button>\n </div>\n </div>\n</ng-container>\n\n\n <!-- Response Preview Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Response Preview</h3>\n </div>\n <div class=\"cqa-p-4 cqa-bg-gray-50 cqa-overflow-auto\" style=\"max-height: 300px;\">\n <pre *ngIf=\"responsePreview\" class=\"cqa-text-xs cqa-font-mono cqa-text-gray-800 cqa-whitespace-pre-wrap\">{{ formatJsonResponse(responsePreview) }}</pre>\n <p *ngIf=\"!responsePreview\" class=\"cqa-text-sm cqa-text-gray-400 cqa-text-center cqa-py-8\">\n No response yet. Send a request to see the response preview.\n </p>\n </div>\n </div>\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 <!-- Cancel button (only on first step) -->\n <cqa-button\n *ngIf=\"selectedProgressStep === 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <!-- Back button (on all steps except first) -->\n <cqa-button\n *ngIf=\"selectedProgressStep !== 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Back\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onBack()\">\n </cqa-button>\n <!-- Next/Create Step button -->\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n [text]=\"isLastStep() ? 'Create Step' : 'Next'\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"isLastStep() ? onCreateStep() : onNext()\">\n </cqa-button>\n </div>\n</div>\n\n", components: [{ type: i2.DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: i3.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: i4.ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { type: i6.CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle", "customClass"], outputs: ["valueChange", "blurred", "focused"] }, { type: i7.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }], directives: [{ type: i8.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i8.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
486
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderApiComponent, decorators: [{
487
+ type: Component,
488
+ args: [{ selector: 'cqa-step-builder-api', 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 Create API Test Step\n </h2>\n\n <!-- Progress Tracker -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-4 cqa-mb-6 cqa-pb-4 cqa-border-b cqa-border-gray-200\">\n <!-- <div *ngFor=\"let step of progressSteps\"\n class=\"cqa-flex cqa-items-center cqa-gap-2\"\n [ngClass]=\"getProgressStepClass(step)\">\n <span class=\"cqa-text-sm cqa-font-medium\">{{ getProgressStepNumber(step) }} {{ getProgressStepLabel(step) }}</span>\n <span *ngIf=\"step !== 'validation'\" class=\"cqa-text-gray-300\">\u2022</span>\n </div> -->\n <div\n class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'request-details'}\" (click)=\"onProgressStepChange('request-details')\">\n <div>1</div>\n <div>Request Details</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'store-response'}\" (click)=\"onProgressStepChange('store-response')\">\n <div>2</div>\n <div>Store Response</div>\n <div></div>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\" [ngClass]=\"{'cqa-text-purple-600 cqa-font-semibold': selectedProgressStep === 'validation'}\" (click)=\"onProgressStepChange('validation')\">\n <div>3</div>\n <div>Validation</div>\n <div></div>\n </div>\n </div>\n </div>\n <ng-container *ngIf=\"selectedProgressStep === 'request-details'\">\n <!-- API Request Configuration -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-mb-6\">\n <div class=\"cqa-w-32 cqa-flex-shrink-0\">\n <cqa-dynamic-select\n [form]=\"apiForm\"\n [config]=\"getHttpMethodConfig()\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Enter API endpoint URL'\"\n [value]=\"apiForm.get('url')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('url')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <cqa-button\n variant=\"outlined\"\n text=\"Import API cURL\"\n (clicked)=\"onImportCurl()\">\n </cqa-button>\n <cqa-button\n variant=\"filled\"\n text=\"Send Request\"\n (clicked)=\"onSendRequest()\"\n [disabled]=\"!apiForm.get('url')?.value || isLoading\">\n </cqa-button>\n </div>\n\n <!-- Request Details Tabs -->\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Tab Navigation -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n 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 === 'headers'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'headers'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'headers'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'headers'\"\n (click)=\"onTabChange('headers')\">\n Headers\n </button>\n <button\n 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 === 'body'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'body'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'body'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'body'\"\n (click)=\"onTabChange('body')\">\n Body\n </button>\n <button\n 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 === 'params'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'params'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'params'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'params'\"\n (click)=\"onTabChange('params')\">\n Params\n </button>\n <button\n 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 === 'scripts'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'scripts'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'scripts'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'scripts'\"\n (click)=\"onTabChange('scripts')\">\n Scripts\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-border cqa-border-gray-200 cqa-border-t-0 cqa-rounded-b-lg\">\n <!-- Headers Tab -->\n <div *ngIf=\"selectedTab === 'headers'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Header Value</div>\n </div>\n <div *ngFor=\"let header of headersFormArray.controls; let i = index; trackBy: trackByHeaderIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-dynamic-select\n [form]=\"getHeaderFormGroup(i)\"\n [config]=\"getHeaderNameConfig(i)\">\n </cqa-dynamic-select>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Header value'\"\n [value]=\"getHeaderFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getHeaderFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeHeader(i)\"\n [attr.aria-label]=\"'Remove header'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addHeader()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Header</span>\n </button>\n </div>\n\n <!-- Body Tab -->\n <div *ngIf=\"selectedTab === 'body'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter request body (JSON, XML, etc.)'\"\n [value]=\"apiForm.get('body')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('body')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Params Tab -->\n <div *ngIf=\"selectedTab === 'params'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <div class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-start\">\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Name</div>\n <div class=\"cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Parameter Value</div>\n </div>\n <div *ngFor=\"let param of paramsFormArray.controls; let i = index; trackBy: trackByParamIndex\" \n class=\"cqa-grid cqa-grid-cols-2 cqa-gap-4 cqa-items-center\">\n <div>\n <cqa-custom-input\n [placeholder]=\"'Parameter name'\"\n [value]=\"getParamFormGroup(i).get('name')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('name')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <div class=\"cqa-flex-1\">\n <cqa-custom-input\n [placeholder]=\"'Parameter value'\"\n [value]=\"getParamFormGroup(i).get('value')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getParamFormGroup(i).get('value')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-8 cqa-h-8 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeParam(i)\"\n [attr.aria-label]=\"'Remove parameter'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n </div>\n </div>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-self-start cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addParam()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Parameter</span>\n </button>\n </div>\n\n <!-- Scripts Tab -->\n <div *ngIf=\"selectedTab === 'scripts'\" class=\"cqa-flex cqa-flex-col cqa-gap-3\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter scripts (JavaScript, etc.)'\"\n [value]=\"apiForm.get('scripts')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"10\"\n (valueChange)=\"apiForm.get('scripts')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n </div>\n </div>\n\n\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'store-response'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Store Response Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Store Response\n </h3>\n\n <!-- Variable Name Input -->\n <div class=\"cqa-mb-6\">\n <label class=\"cqa-text-[12px] cqa-font-medium cqa-text-gray-700 cqa-mb-1 cqa-block\">\n Variable Name\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable Name'\"\n [value]=\"apiForm.get('variableName')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"apiForm.get('variableName')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n </div>\n</ng-container>\n<ng-container *ngIf=\"selectedProgressStep === 'validation'\">\n <div class=\"cqa-flex cqa-flex-col cqa-flex-1 cqa-max-h-[500px] cqa-overflow-y-auto\">\n <!-- Validation Rules Title -->\n <h3 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Validation Rules\n </h3>\n\n <!-- Validation Rules Table -->\n <div class=\"cqa-bg-white cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-4\">\n <!-- Table Header -->\n <div class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200 cqa-items-center\">\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox\n [checked]=\"allValidationRulesSelected\"\n [indeterminate]=\"someValidationRulesSelected\"\n (change)=\"onSelectAllValidationRules($event.checked)\">\n </mat-checkbox>\n </div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">jsonPath</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">verificationType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedType</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">expectedValue</div>\n <div class=\"cqa-text-[10px] cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">Result</div>\n </div>\n\n <!-- Table Body -->\n <div class=\"cqa-flex cqa-flex-col\">\n <div *ngFor=\"let validationRule of validationFormArray.controls; let i = index; trackBy: trackByValidationRuleIndex\" \n [formGroup]=\"getValidationFormGroup(i)\"\n class=\"cqa-grid cqa-grid-cols-6 cqa-gap-2 cqa-p-3 cqa-border-b cqa-border-gray-200 cqa-items-center cqa-last:border-b-0\">\n <!-- Checkbox -->\n <div class=\"cqa-flex cqa-items-center\">\n <mat-checkbox formControlName=\"checked\">\n </mat-checkbox>\n </div>\n\n <!-- jsonPath -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'jsonPath'\"\n [value]=\"getValidationFormGroup(i).get('jsonPath')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('jsonPath')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- verificationType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getVerificationTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedType -->\n <div>\n <cqa-dynamic-select\n [form]=\"getValidationFormGroup(i)\"\n [config]=\"getExpectedTypeConfig(i)\">\n </cqa-dynamic-select>\n </div>\n\n <!-- expectedValue -->\n <div>\n <cqa-custom-input\n [placeholder]=\"'expectedValue'\"\n [value]=\"getValidationFormGroup(i).get('expectedValue')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getValidationFormGroup(i).get('expectedValue')?.setValue($event)\">\n </cqa-custom-input>\n </div>\n\n <!-- Result and Delete -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <button\n type=\"button\"\n class=\"cqa-px-3 cqa-py-1 cqa-rounded cqa-text-[10px] cqa-font-medium\"\n [ngClass]=\"getResultClass(getValidationFormGroup(i).get('result')?.value || 'Not run')\">\n {{ getValidationFormGroup(i).get('result')?.value || 'Not run' }}\n </button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-6 cqa-h-6 cqa-rounded cqa-text-red-500 hover:cqa-text-red-700 hover:cqa-bg-red-50 cqa-transition-colors\"\n (click)=\"removeValidationRule(i)\"\n [attr.aria-label]=\"'Delete validation rule'\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n </button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Add Another Rule and Delete Selected -->\n <div class=\"cqa-flex cqa-justify-between cqa-items-center cqa-mb-4\">\n <button\n *ngIf=\"someValidationRulesSelected || allValidationRulesSelected\"\n type=\"button\"\n class=\"cqa-text-red-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-red-700 cqa-transition-colors\"\n (click)=\"onDeleteSelectedValidationRules()\">\n <mat-icon class=\"cqa-text-base\">delete</mat-icon>\n <span>Delete Selected</span>\n </button>\n <button\n type=\"button\"\n class=\"cqa-text-blue-600 cqa-text-sm cqa-font-medium cqa-flex cqa-items-center cqa-gap-1 hover:cqa-text-blue-700 cqa-transition-colors\"\n (click)=\"addValidationRule()\">\n <mat-icon class=\"cqa-text-base\">add</mat-icon>\n <span>Add Another</span>\n </button>\n </div>\n </div>\n</ng-container>\n\n\n <!-- Response Preview Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Response Preview</h3>\n </div>\n <div class=\"cqa-p-4 cqa-bg-gray-50 cqa-overflow-auto\" style=\"max-height: 300px;\">\n <pre *ngIf=\"responsePreview\" class=\"cqa-text-xs cqa-font-mono cqa-text-gray-800 cqa-whitespace-pre-wrap\">{{ formatJsonResponse(responsePreview) }}</pre>\n <p *ngIf=\"!responsePreview\" class=\"cqa-text-sm cqa-text-gray-400 cqa-text-center cqa-py-8\">\n No response yet. Send a request to see the response preview.\n </p>\n </div>\n </div>\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 <!-- Cancel button (only on first step) -->\n <cqa-button\n *ngIf=\"selectedProgressStep === 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <!-- Back button (on all steps except first) -->\n <cqa-button\n *ngIf=\"selectedProgressStep !== 'request-details'\"\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Back\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onBack()\">\n </cqa-button>\n <!-- Next/Create Step button -->\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n [text]=\"isLastStep() ? 'Create Step' : 'Next'\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"isLastStep() ? onCreateStep() : onNext()\">\n </cqa-button>\n </div>\n</div>\n\n", styles: [] }]
489
+ }], ctorParameters: function () { return [{ type: i1.FormBuilder }]; }, propDecorators: { httpMethodOptions: [{
490
+ type: Input
491
+ }], headerNameOptions: [{
492
+ type: Input
493
+ }], currentStep: [{
494
+ type: Input
495
+ }], responsePreview: [{
496
+ type: Input
497
+ }], isLoading: [{
498
+ type: Input
499
+ }], initialData: [{
500
+ type: Input
501
+ }], createStep: [{
502
+ type: Output
503
+ }], cancelled: [{
504
+ type: Output
505
+ }], sendRequest: [{
506
+ type: Output
507
+ }], importCurl: [{
508
+ type: Output
509
+ }] } });
510
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1idWlsZGVyLWFwaS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3N0ZXAtYnVpbGRlci9zdGVwLWJ1aWxkZXItYXBpL3N0ZXAtYnVpbGRlci1hcGkuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zdGVwLWJ1aWxkZXIvc3RlcC1idWlsZGVyLWFwaS9zdGVwLWJ1aWxkZXItYXBpLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQW1ELE1BQU0sZUFBZSxDQUFDO0FBQ3hILE9BQU8sRUFBa0QsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7Ozs7Ozs7QUF1QzVGLE1BQU0sT0FBTyx1QkFBdUI7SUFvRGxDLFlBQW9CLEVBQWU7UUFBZixPQUFFLEdBQUYsRUFBRSxDQUFhO1FBbkRuQyx1Q0FBdUM7UUFDOUIsc0JBQWlCLEdBQW1CO1lBQzNDLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRTtZQUN0RCxFQUFFLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUU7WUFDMUQsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFO1lBQ3RELEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRTtZQUM5RCxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUs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QixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25DLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7b0hBdGhCVSx1QkFBdUI7d0dBQXZCLHVCQUF1QiwrYkN4Q3BDLDZ5akJBK1lBOzJGRHZXYSx1QkFBdUI7a0JBTm5DLFNBQVM7K0JBQ0Usc0JBQXNCLFFBRzFCLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRTtrR0FJckIsaUJBQWlCO3NCQUF6QixLQUFLO2dCQVdHLGlCQUFpQjtzQkFBekIsS0FBSztnQkFHRyxXQUFXO3NCQUFuQixLQUFLO2dCQUdHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBR0csU0FBUztzQkFBakIsS0FBSztnQkFHRyxXQUFXO3NCQUFuQixLQUFLO2dCQUdJLFVBQVU7c0JBQW5CLE1BQU07Z0JBR0csU0FBUztzQkFBbEIsTUFBTTtnQkFHRyxXQUFXO3NCQUFwQixNQUFNO2dCQUdHLFVBQVU7c0JBQW5CLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgT25Jbml0LCBPbkNoYW5nZXMsIFNpbXBsZUNoYW5nZXMsIEFmdGVyVmlld0luaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1BcnJheSwgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEeW5hbWljU2VsZWN0RmllbGRDb25maWcsIFNlbGVjdE9wdGlvbiB9IGZyb20gJy4uLy4uL2R5bmFtaWMtc2VsZWN0L2R5bmFtaWMtc2VsZWN0LWZpZWxkLmNvbXBvbmVudCc7XG5cbmV4cG9ydCB0eXBlIEh0dHBNZXRob2QgPSAnR0VUJyB8ICdQT1NUJyB8ICdQVVQnIHwgJ1BBVENIJyB8ICdERUxFVEUnIHwgJ0hFQUQnIHwgJ09QVElPTlMnO1xuZXhwb3J0IHR5cGUgUmVxdWVzdFRhYiA9ICdoZWFkZXJzJyB8ICdib2R5JyB8ICdwYXJhbXMnIHwgJ3NjcmlwdHMnO1xuZXhwb3J0IHR5cGUgUHJvZ3Jlc3NTdGVwID0gJ3JlcXVlc3QtZGV0YWlscycgfCAnc3RvcmUtcmVzcG9uc2UnIHwgJ3ZhbGlkYXRpb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEhlYWRlclJvdyB7XG4gIG5hbWU6IHN0cmluZztcbiAgdmFsdWU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0aW9uUnVsZSB7XG4gIGpzb25QYXRoOiBzdHJpbmc7XG4gIHZlcmlmaWNhdGlvblR5cGU6IHN0cmluZztcbiAgZXhwZWN0ZWRUeXBlOiBzdHJpbmc7XG4gIGV4cGVjdGVkVmFsdWU6IGFueTtcbiAgcmVzdWx0PzogJ1Bhc3MnIHwgJ0ZhaWwnIHwgJ05vdCBydW4nO1xuICBjaGVja2VkPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBcGlGb3JtRGF0YSB7XG4gIG1ldGhvZDogSHR0cE1ldGhvZDtcbiAgdXJsOiBzdHJpbmc7XG4gIGhlYWRlcnM6IEhlYWRlclJvd1tdO1xuICBib2R5Pzogc3RyaW5nO1xuICBwYXJhbXM/OiBIZWFkZXJSb3dbXTtcbiAgc2NyaXB0cz86IHN0cmluZztcbiAgdmFyaWFibGVOYW1lPzogc3RyaW5nO1xuICBzdG9yZVJlc3BvbnNlPzogYW55O1xuICB2YWxpZGF0aW9uPzogVmFsaWRhdGlvblJ1bGVbXTtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY3FhLXN0ZXAtYnVpbGRlci1hcGknLFxuICB0ZW1wbGF0ZVVybDogJy4vc3RlcC1idWlsZGVyLWFwaS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogW10sXG4gIGhvc3Q6IHsgY2xhc3M6ICdjcWEtdWktcm9vdCcgfVxufSlcbmV4cG9ydCBjbGFzcyBTdGVwQnVpbGRlckFwaUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgLyoqIE9wdGlvbnMgZm9yIEhUVFAgbWV0aG9kIGRyb3Bkb3duICovXG4gIEBJbnB1dCgpIGh0dHBNZXRob2RPcHRpb25zOiBTZWxlY3RPcHRpb25bXSA9IFtcbiAgICB7IGlkOiAnR0VUJywgdmFsdWU6ICdHRVQnLCBuYW1lOiAnR0VUJywgbGFiZWw6ICdHRVQnIH0sXG4gICAgeyBpZDogJ1BPU1QnLCB2YWx1ZTogJ1BPU1QnLCBuYW1lOiAnUE9TVCcsIGxhYmVsOiAnUE9TVCcgfSxcbiAgICB7IGlkOiAnUFVUJywgdmFsdWU6ICdQVVQnLCBuYW1lOiAnUFVUJywgbGFiZWw6ICdQVVQnIH0sXG4gICAgeyBpZDogJ1BBVENIJywgdmFsdWU6ICdQQVRDSCcsIG5hbWU6ICdQQVRDSCcsIGxhYmVsOiAnUEFUQ0gnIH0sXG4gICAgeyBpZDogJ0RFTEVURScsIHZhbHVlOiAnREVMRVRFJywgbmFtZTogJ0RFTEVURScsIGxhYmVsOiAnREVMRVRFJyB9LFxuICAgIHsgaWQ6ICdIRUFEJywgdmFsdWU6ICdIRUFEJywgbmFtZTogJ0hFQUQnLCBsYWJlbDogJ0hFQUQnIH0sXG4gICAgeyBpZDogJ09QVElPTlMnLCB2YWx1ZTogJ09QVElPTlMnLCBuYW1lOiAnT1BUSU9OUycsIGxhYmVsOiAnT1BUSU9OUycgfVxuICBdO1xuXG4gIC8qKiBPcHRpb25zIGZvciBoZWFkZXIgbmFtZSBkcm9wZG93biAqL1xuICBASW5wdXQoKSBoZWFkZXJOYW1lT3B0aW9uczogU2VsZWN0T3B0aW9uW10gPSBbXTtcblxuICAvKiogQ3VycmVudCBwcm9ncmVzcyBzdGVwICovXG4gIEBJbnB1dCgpIGN1cnJlbnRTdGVwOiBQcm9ncmVzc1N0ZXAgPSAncmVxdWVzdC1kZXRhaWxzJztcblxuICAvKiogUmVzcG9uc2UgcHJldmlldyBkYXRhICovXG4gIEBJbnB1dCgpIHJlc3BvbnNlUHJldmlldzogYW55ID0gbnVsbDtcblxuICAvKiogTG9hZGluZyBzdGF0ZSAqL1xuICBASW5wdXQoKSBpc0xvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogSW5pdGlhbCBmb3JtIGRhdGEgZm9yIGVkaXQgbW9kZSAqL1xuICBASW5wdXQoKSBpbml0aWFsRGF0YT86IEFwaUZvcm1EYXRhO1xuXG4gIC8qKiBFbWl0IHdoZW4gc3RlcCBpcyBjcmVhdGVkICovXG4gIEBPdXRwdXQoKSBjcmVhdGVTdGVwID0gbmV3IEV2ZW50RW1pdHRlcjxBcGlGb3JtRGF0YT4oKTtcblxuICAvKiogRW1pdCB3aGVuIGNhbmNlbGxlZCAqL1xuICBAT3V0cHV0KCkgY2FuY2VsbGVkID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIC8qKiBFbWl0IHdoZW4gcmVxdWVzdCBpcyBzZW50ICovXG4gIEBPdXRwdXQoKSBzZW5kUmVxdWVzdCA9IG5ldyBFdmVudEVtaXR0ZXI8eyBtZXRob2Q6IEh0dHBNZXRob2Q7IHVybDogc3RyaW5nOyBoZWFkZXJzOiBIZWFkZXJSb3dbXTsgYm9keT86IHN0cmluZzsgcGFyYW1zPzogSGVhZGVyUm93W10gfT4oKTtcblxuICAvKiogRW1pdCB3aGVuIGNVUkwgaXMgaW1wb3J0ZWQgKi9cbiAgQE91dHB1dCgpIGltcG9ydEN1cmwgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgYXBpRm9ybTogRm9ybUdyb3VwO1xuICBzZWxlY3RlZFRhYjogUmVxdWVzdFRhYiA9ICdoZWFkZXJzJztcbiAgc2VsZWN0ZWRQcm9ncmVzc1N0ZXA6IFByb2dyZXNzU3RlcCA9ICdyZXF1ZXN0LWRldGFpbHMnO1xuICAvLyBwcm9ncmVzc1N0ZXBzOiBQcm9ncmVzc1N0ZXBbXSA9IFsncmVxdWVzdC1kZXRhaWxzJywgJ3N0b3JlLXJlc3BvbnNlJywgJ3ZhbGlkYXRpb24nXTtcbiAgXG4gIC8vIENhY2hlIGNvbmZpZyBvYmplY3RzIHRvIHByZXZlbnQgaW5maW5pdGUgY2hhbmdlIGRldGVjdGlvbiBsb29wc1xuICBwcml2YXRlIHZlcmlmaWNhdGlvblR5cGVDb25maWdDYWNoZTogRHluYW1pY1NlbGVjdEZpZWxkQ29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgZXhwZWN0ZWRUeXBlQ29uZmlnQ2FjaGU6IER5bmFtaWNTZWxlY3RGaWVsZENvbmZpZyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGh0dHBNZXRob2RDb25maWdDYWNoZTogRHluYW1pY1NlbGVjdEZpZWxkQ29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgaGVhZGVyTmFtZUNvbmZpZ0NhY2hlOiBEeW5hbWljU2VsZWN0RmllbGRDb25maWcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBwYXJhbU5hbWVDb25maWdDYWNoZTogRHluYW1pY1NlbGVjdEZpZWxkQ29uZmlnIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgaGFzTG9hZGVkSW5pdGlhbERhdGE6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZiOiBGb3JtQnVpbGRlcikge1xuICAgIHRoaXMuYXBpRm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgbWV0aG9kOiBbJ0dFVCcsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgdXJsOiBbJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgaGVhZGVyczogdGhpcy5mYi5hcnJheShbXSksXG4gICAgICBib2R5OiBbJyddLFxuICAgICAgcGFyYW1zOiB0aGlzLmZiLmFycmF5KFtdKSxcbiAgICAgIHNjcmlwdHM6IFsnJ10sXG4gICAgICB2YXJpYWJsZU5hbWU6IFsnJ10sXG4gICAgICB2YWxpZGF0aW9uOiB0aGlzLmZiLmFycmF5KFtdKVxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgLy8gU3luYyBjdXJyZW50U3RlcCBpbnB1dCB3aXRoIHNlbGVjdGVkUHJvZ3Jlc3NTdGVwXG4gICAgaWYgKHRoaXMuY3VycmVudFN0ZXApIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRQcm9ncmVzc1N0ZXAgPSB0aGlzLmN1cnJlbnRTdGVwO1xuICAgIH1cbiAgICBcbiAgICAvLyBMb2FkIGluaXRpYWwgZGF0YSBpZiBwcm92aWRlZCAoZWRpdCBtb2RlKVxuICAgIGlmICh0aGlzLmluaXRpYWxEYXRhKSB7XG4gICAgICB0aGlzLmxvYWRJbml0aWFsRGF0YSh0aGlzLmluaXRpYWxEYXRhKTtcbiAgICAgIHRoaXMuaGFzTG9hZGVkSW5pdGlhbERhdGEgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBBZGQgaW5pdGlhbCBoZWFkZXIgcm93IGZvciBuZXcgc3RlcFxuICAgICAgdGhpcy5hZGRIZWFkZXIoKTtcbiAgICB9XG4gICAgXG4gICAgLy8gSW5pdGlhbGl6ZSB2YWxpZGF0aW9uIGZvcm0gYXJyYXkgaWYgc3RhcnRpbmcgb24gdmFsaWRhdGlvbiBzdGVwXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRQcm9ncmVzc1N0ZXAgPT09ICd2YWxpZGF0aW9uJyAmJiB0aGlzLnZhbGlkYXRpb25Gb3JtQXJyYXkubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLmFkZFZhbGlkYXRpb25SdWxlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBsb2FkSW5pdGlhbERhdGEoZGF0YTogQXBpRm9ybURhdGEpOiB2b2lkIHtcbiAgICBjb25zb2xlLmxvZygnbG9hZEluaXRpYWxEYXRhOiBMb2FkaW5nIGRhdGEnLCBkYXRhKTtcbiAgICBjb25zb2xlLmxvZygnbG9hZEluaXRpYWxEYXRhOiBIZWFkZXJzIGNvdW50JywgZGF0YS5oZWFkZXJzPy5sZW5ndGggfHwgMCk7XG4gICAgY29uc29sZS5sb2coJ2xvYWRJbml0aWFsRGF0YTogSGVhZGVycyBkYXRhJywgZGF0YS5oZWFkZXJzKTtcbiAgICBcbiAgICAvLyBTZXQgYmFzaWMgZmllbGRzXG4gICAgdGhpcy5hcGlGb3JtLnBhdGNoVmFsdWUoe1xuICAgICAgbWV0aG9kOiBkYXRhLm1ldGhvZCB8fCAnR0VUJyxcbiAgICAgIHVybDogZGF0YS51cmwgfHwgJycsXG4gICAgICBib2R5OiBkYXRhLmJvZHkgfHwgJycsXG4gICAgICBzY3JpcHRzOiBkYXRhLnNjcmlwdHMgfHwgJycsXG4gICAgICB2YXJpYWJsZU5hbWU6IGRhdGEudmFyaWFibGVOYW1lIHx8ICcnXG4gICAgfSk7XG5cbiAgICAvLyBMb2FkIGhlYWRlcnNcbiAgICAvLyBDbGVhciBleGlzdGluZyBoZWFkZXJzIGZpcnN0XG4gICAgd2hpbGUgKHRoaXMuaGVhZGVyc0Zvcm1BcnJheS5sZW5ndGggIT09IDApIHtcbiAgICAgIHRoaXMuaGVhZGVyc0Zvcm1BcnJheS5yZW1vdmVBdCgwKTtcbiAgICB9XG4gICAgXG4gICAgaWYgKGRhdGEuaGVhZGVycyAmJiBkYXRhLmhlYWRlcnMubGVuZ3RoID4gMCkge1xuICAgICAgLy8gQWRkIGhlYWRlcnMgZnJvbSBpbml0aWFsIGRhdGEgKGluY2x1ZGUgYWxsIGhlYWRlcnMsIGV2ZW4gaWYgZW1wdHkpXG4gICAgICBkYXRhLmhlYWRlcnMuZm9yRWFjaChoZWFkZXIgPT4ge1xuICAgICAgICBjb25zdCBoZWFkZXJHcm91cCA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgICAgIG5hbWU6IFtoZWFkZXIubmFtZSB8fCAnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICAgICAgdmFsdWU6IFtoZWFkZXIudmFsdWUgfHwgJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmhlYWRlcnNGb3JtQXJyYXkucHVzaChoZWFkZXJHcm91cCk7XG4gICAgICB9KTtcbiAgICAgIGNvbnNvbGUubG9nKCdsb2FkSW5pdGlhbERhdGE6IExvYWRlZCBoZWFkZXJzIGludG8gZm9ybSBhcnJheSwgY291bnQ6JywgdGhpcy5oZWFkZXJzRm9ybUFycmF5Lmxlbmd0aCk7XG4gICAgfVxuICAgIFxuICAgIC8vIEVuc3VyZSBhdCBsZWFzdCBvbmUgaGVhZGVyIHJvdyBleGlzdHNcbiAgICBpZiAodGhpcy5oZWFkZXJzRm9ybUFycmF5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgY29uc29sZS5sb2coJ2xvYWRJbml0aWFsRGF0YTogTm8gaGVhZGVycyBmb3VuZCwgYWRkaW5nIGVtcHR5IGhlYWRlciByb3cnKTtcbiAgICAgIHRoaXMuYWRkSGVhZGVyKCk7XG4gICAgfVxuXG4gICAgLy8gTG9hZCBwYXJhbXNcbiAgICAvLyBDbGVhciBleGlzdGluZyBwYXJhbXMgZmlyc3RcbiAgICB3aGlsZSAodGhpcy5wYXJhbXNGb3JtQXJyYXkubGVuZ3RoICE9PSAwKSB7XG4gICAgICB0aGlzLnBhcmFtc0Zvcm1BcnJheS5yZW1vdmVBdCgwKTtcbiAgICB9XG4gICAgXG4gICAgaWYgKGRhdGEucGFyYW1zICYmIGRhdGEucGFyYW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIEFkZCBwYXJhbXMgZnJvbSBpbml0aWFsIGRhdGEgKGluY2x1ZGUgYWxsIHBhcmFtcywgZXZlbiBpZiBlbXB0eSlcbiAgICAgIGRhdGEucGFyYW1zLmZvckVhY2gocGFyYW0gPT4ge1xuICAgICAgICBjb25zdCBwYXJhbUdyb3VwID0gdGhpcy5mYi5ncm91cCh7XG4gICAgICAgICAgbmFtZTogW3BhcmFtLm5hbWUgfHwgJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgICAgIHZhbHVlOiBbcGFyYW0udmFsdWUgfHwgJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnBhcmFtc0Zvcm1BcnJheS5wdXNoKHBhcmFtR3JvdXApO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gTG9hZCB2YWxpZGF0aW9uIHJ1bGVzXG4gICAgaWYgKGRhdGEudmFsaWRhdGlvbiAmJiBkYXRhLnZhbGlkYXRpb24ubGVuZ3RoID4gMCkge1xuICAgICAgLy8gQ2xlYXIgZXhpc3RpbmcgdmFsaWRhdGlvbiBydWxlc1xuICAgICAgd2hpbGUgKHRoaXMudmFsaWRhdGlvbkZvcm1BcnJheS5sZW5ndGggIT09IDApIHtcbiAgICAgICAgdGhpcy52YWxpZGF0aW9uRm9ybUFycmF5LnJlbW92ZUF0KDApO1xuICAgICAgfVxuICAgICAgLy8gQWRkIHZhbGlkYXRpb24gcnVsZXMgZnJvbSBpbml0aWFsIGRhdGFcbiAgICAgIGRhdGEudmFsaWRhdGlvbi5mb3JFYWNoKHJ1bGUgPT4ge1xuICAgICAgICBjb25zdCB2YWxpZGF0aW9uR3JvdXAgPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgICAgICBqc29uUGF0aDogW3J1bGUuanNvblBhdGggfHwgJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgICAgIHZlcmlmaWNhdGlvblR5cGU6IFtydWxlLnZlcmlmaWNhdGlvblR5cGUgfHwgJ2VxdWFscycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgICAgIGV4cGVjdGVkVHlwZTogW3J1bGUuZXhwZWN0ZWRUeXBlIHx8ICdzdHJpbmcnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgICAgICBleHBlY3RlZFZhbHVlOiBbcnVsZS5leHBlY3RlZFZhbHVlICE9PSB1bmRlZmluZWQgPyBydWxlLmV4cGVjdGVkVmFsdWUgOiAnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICAgICAgcmVzdWx0OiBbcnVsZS5yZXN1bHQgfHwgJ05vdCBydW4nXSxcbiAgICAgICAgICBjaGVja2VkOiBbcnVsZS5jaGVja2VkIHx8IGZhbHNlXVxuICAgICAgICB9KTtcbiAgICAgICAgLy8gRW5zdXJlIGFsbCBjb250cm9scyBhcmUgZW5hYmxlZFxuICAgICAgICB2YWxpZGF0aW9uR3JvdXAuZW5hYmxlKHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgdGhpcy52YWxpZGF0aW9uRm9ybUFycmF5LnB1c2godmFsaWRhdGlvbkdyb3VwKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGdldCBoZWFkZXJzRm9ybUFycmF5KCk6IEZvcm1BcnJheSB7XG4gICAgcmV0dXJuIHRoaXMuYXBpRm9ybS5nZXQoJ2hlYWRlcnMnKSBhcyBGb3JtQXJyYXk7XG4gIH1cblxuICBnZXQgcGFyYW1zRm9ybUFycmF5KCk6IEZvcm1BcnJheSB7XG4gICAgcmV0dXJuIHRoaXMuYXBpRm9ybS5nZXQoJ3BhcmFtcycpIGFzIEZvcm1BcnJheTtcbiAgfVxuXG4gIGdldCB2YWxpZGF0aW9uRm9ybUFycmF5KCk6IEZvcm1BcnJheSB7XG4gICAgcmV0dXJuIHRoaXMuYXBpRm9ybS5nZXQoJ3ZhbGlkYXRpb24nKSBhcyBGb3JtQXJyYXk7XG4gIH1cblxuICBhZGRIZWFkZXIoKTogdm9pZCB7XG4gICAgY29uc3QgaGVhZGVyR3JvdXAgPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIG5hbWU6IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICB2YWx1ZTogWycnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXVxuICAgIH0pO1xuICAgIHRoaXMuaGVhZGVyc0Zvcm1BcnJheS5wdXNoKGhlYWRlckdyb3VwKTtcbiAgfVxuXG4gIHJlbW92ZUhlYWRlcihpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5oZWFkZXJzRm9ybUFycmF5LnJlbW92ZUF0KGluZGV4KTtcbiAgfVxuXG4gIGFkZFBhcmFtKCk6IHZvaWQge1xuICAgIGNvbnN0IHBhcmFtR3JvdXAgPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIG5hbWU6IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICB2YWx1ZTogWycnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXVxuICAgIH0pO1xuICAgIHRoaXMucGFyYW1zRm9ybUFycmF5LnB1c2gocGFyYW1Hcm91cCk7XG4gIH1cblxuICByZW1vdmVQYXJhbShpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5wYXJhbXNGb3JtQXJyYXkucmVtb3ZlQXQoaW5kZXgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIC8vIFJlc2V0IGNvbmZpZyBjYWNoZXMgd2hlbiBpbnB1dHMgY2hhbmdlXG4gICAgaWYgKGNoYW5nZXNbJ2h0dHBNZXRob2RPcHRpb25zJ10pIHtcbiAgICAgIHRoaXMuaHR0cE1ldGhvZENvbmZpZ0NhY2hlID0gbnVsbDtcbiAgICB9XG4gICAgaWYgKGNoYW5nZXNbJ2hlYWRlck5hbWVPcHRpb25zJ10pIHtcbiAgICAgIHRoaXMuaGVhZGVyTmFtZUNvbmZpZ0NhY2hlID0gbnVsbDtcbiAgICB9XG4gICAgXG4gICAgLy8gTG9hZCBpbml0aWFsIGRhdGEgaWYgaXQncyBzZXQgYWZ0ZXIgY29tcG9uZW50IGluaXRpYWxpemF0aW9uXG4gICAgaWYgKGNoYW5nZXNbJ2luaXRpYWxEYXRhJ10gJiYgIWNoYW5nZXNbJ2luaXRpYWxEYXRhJ10uZmlyc3RDaGFuZ2UgJiYgdGhpcy5pbml0aWFsRGF0YSAmJiAhdGhpcy5oYXNMb2FkZWRJbml0aWFsRGF0YSkge1xuICAgICAgdGhpcy5sb2FkSW5pdGlhbERhdGEodGhpcy5pbml0aWFsRGF0YSk7XG4gICAgICB0aGlzLmhhc0xvYWRlZEluaXRpYWxEYXRhID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBnZXRIdHRwTWV0aG9kQ29uZmlnKCk6IER5bmFtaWNTZWxlY3RGaWVsZENvbmZpZyB7XG4gICAgaWYgKCF0aGlzLmh0dHBNZXRob2RDb25maWdDYWNoZSkge1xuICAgICAgdGhpcy5odHRwTWV0aG9kQ29uZmlnQ2FjaGUgPSB7XG4gICAgICAgIGtleTogJ21ldGhvZCcsXG4gICAgICAgIHBsYWNlaG9sZGVyOiAnU2VsZWN0IG1ldGhvZCcsXG4gICAgICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICAgICAgc2VhcmNoYWJsZTogZmFsc2UsXG4gICAgICAgIG9wdGlvbnM6IHRoaXMuaHR0cE1ldGhvZE9wdGlvbnNcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmh0dHBNZXRob2RDb25maWdDYWNoZTtcbiAgfVxuXG4gIGdldEhlYWRlck5hbWVDb25maWcoaW5kZXg6IG51bWJlcik6IER5bmFtaWNTZWxlY3RGaWVsZENvbmZpZyB7XG4gICAgaWYgKCF0aGlzLmhlYWRlck5hbWVDb25maWdDYWNoZSkge1xuICAgICAgY29uc3QgZGVmYXVsdE9wdGlvbnMgPSBbXG4gICAgICAgIHsgaWQ6ICdzdHJpbmcnLCB2YWx1ZTogJ3N0cmluZycsIG5hbWU6ICdzdHJpbmcnLCBsYWJlbDogJ3N0cmluZycgfSxcbiAgICAgICAgeyBpZDogJ0NvbnRlbnQtVHlwZScsIHZhbHVlOiAnQ29udGVudC1UeXBlJywgbmFtZTogJ0NvbnRlbnQtVHlwZScsIGxhYmVsOiAnQ29udGVudC1UeXBlJyB9LFxuICAgICAgICB7IGlkOiAnQXV0aG9yaXphdGlvbicsIHZhbHVlOiAnQXV0aG9yaXphdGlvbicsIG5hbWU6ICdBdXRob3JpemF0aW9uJywgbGFiZWw6ICdBdXRob3JpemF0aW9uJyB9LFxuICAgICAgICB7IGlkOiAnQWNjZXB0JywgdmFsdWU6ICdBY2NlcHQnLCBuYW1lOiAnQWNjZXB0JywgbGFiZWw6ICdBY2NlcHQnIH1cbiAgICAgIF07XG4gICAgICBcbiAgICAgIHRoaXMuaGVhZGVyTmFtZUNvbmZpZ0NhY2hlID0ge1xuICAgICAgICBrZXk6ICduYW1lJyxcbiAgICAgICAgcGxhY2Vob2xkZXI6ICdTZWxlY3QgaGVhZGVyJyxcbiAgICAgICAgbXVsdGlwbGU6IGZhbHNlLFxuICAgICAgICBzZWFyY2hhYmxlOiB0cnVlLFxuICAgICAgICBvcHRpb25zOiB0aGlzLmhlYWRlck5hbWVPcHRpb25zLmxlbmd0aCA+IDAgPyB0aGlzLmhlYWRlck5hbWVPcHRpb25zIDogZGVmYXVsdE9wdGlvbnNcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmhlYWRlck5hbWVDb25maWdDYWNoZTtcbiAgfVxuXG4gIGdldFBhcmFtTmFtZUNvbmZpZyhpbmRleDogbnVtYmVyKTogRHluYW1pY1NlbGVjdEZpZWxkQ29uZmlnIHtcbiAgICBpZiAoIXRoaXMucGFyYW1OYW1lQ29uZmlnQ2FjaGUpIHtcbiAgICAgIHRoaXMucGFyYW1OYW1lQ29uZmlnQ2FjaGUgPSB7XG4gICAgICAgIGtleTogJ25hbWUnLFxuICAgICAgICBwbGFjZWhvbGRlcjogJ1BhcmFtZXRlciBuYW1lJyxcbiAgICAgICAgbXVsdGlwbGU6IGZhbHNlLFxuICAgICAgICBzZWFyY2hhYmxlOiBmYWxzZSxcbiAgICAgICAgb3B0aW9uczogW11cbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnBhcmFtTmFtZUNvbmZpZ0NhY2hlO1xuICB9XG5cbiAgZ2V0SGVhZGVyRm9ybUdyb3VwKGluZGV4OiBudW1iZXIpOiBGb3JtR3JvdXAge1xuICAgIHJldHVybiB0aGlzLmhlYWRlcnNGb3JtQXJyYXkuYXQoaW5kZXgpIGFzIEZvcm1Hcm91cDtcbiAgfVxuXG4gIGdldFBhcmFtRm9ybUdyb3VwKGluZGV4OiBudW1iZXIpOiBGb3JtR3JvdXAge1xuICAgIHJldHVybiB0aGlzLnBhcmFtc0Zvcm1BcnJheS5hdChpbmRleCkgYXMgRm9ybUdyb3VwO1xuICB9XG5cbiAgb25UYWJDaGFuZ2UodGFiOiBSZXF1ZXN0VGFiKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZFRhYiA9IHRhYjtcbiAgfVxuXG4gIG9uU2VuZFJlcXVlc3QoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuYXBpRm9ybS52YWxpZCkge1xuICAgICAgY29uc3QgZm9ybVZhbHVlID0gdGhpcy5hcGlGb3JtLnZhbHVlO1xuICAgICAgY29uc3QgaGVhZGVycyA9IGZvcm1WYWx1ZS5oZWFkZXJzLm1hcCgoaDogYW55KSA9PiAoe1xuICAgICAgICBuYW1lOiBoLm5hbWUsXG4gICAgICAgIHZhbHVlOiBoLnZhbHVlXG4gICAgICB9KSk7XG4gICAgICBjb25zdCBwYXJhbXMgPSBmb3JtVmFsdWUucGFyYW1zID8gZm9ybVZhbHVlLnBhcmFtcy5tYXAoKHA6IGFueSkgPT4gKHtcbiAgICAgICAgbmFtZTogcC5uYW1lLFxuICAgICAgICB2YWx1ZTogcC52YWx1ZVxuICAgICAgfSkpIDogW107XG5cbiAgICAgIHRoaXMuc2VuZFJlcXVlc3QuZW1pdCh7XG4gICAgICAgIG1ldGhvZDogZm9ybVZhbHVlLm1ldGhvZCxcbiAgICAgICAgdXJsOiBmb3JtVmFsdWUudXJsLFxuICAgICAgICBoZWFkZXJzLFxuICAgICAgICBib2R5OiBmb3JtVmFsdWUuYm9keSxcbiAgICAgICAgcGFyYW1zXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBvbkltcG9ydEN1cmwoKTogdm9pZCB7XG4gICAgdGhpcy5pbXBvcnRDdXJsLmVtaXQoKTtcbiAgfVxuXG4gIG9uQ2FuY2VsKCk6IHZvaWQge1xuICAgIHRoaXMuY2FuY2VsbGVkLmVtaXQoKTtcbiAgfVxuXG4gIG9uQ3JlYXRlU3RlcCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5hcGlGb3JtLnZhbGlkKSB7XG4gICAgICBjb25zdCBmb3JtVmFsdWUgPSB0aGlzLmFwaUZvcm0udmFsdWU7XG4gICAgICBjb25zdCBzdGVwRGF0YTogQXBpRm9ybURhdGEgPSB7XG4gICAgICAgIG1ldGhvZDogZm9ybVZhbHVlLm1ldGhvZCxcbiAgICAgICAgdXJsOiBmb3JtVmFsdWUudXJsLFxuICAgICAgICBoZWFkZXJzOiBmb3JtVmFsdWUuaGVhZGVycy5tYXAoKGg6IGFueSkgPT4gKHtcbiAgICAgICAgICBuYW1lOiBoLm5hbWUsXG4gICAgICAgICAgdmFsdWU6IGgudmFsdWVcbiAgICAgICAgfSkpLFxuICAgICAgICBib2R5OiBmb3JtVmFsdWUuYm9keSxcbiAgICAgICAgcGFyYW1zOiBmb3JtVmFsdWUucGFyYW1zID8gZm9ybVZhbHVlLnBhcmFtcy5tYXAoKHA6IGFueSkgPT4gKHtcbiAgICAgICAgICBuYW1lOiBwLm5hbWUsXG4gICAgICAgICAgdmFsdWU6IHAudmFsdWVcbiAgICAgICAgfSkpIDogW10sXG4gICAgICAgIHNjcmlwdHM6IGZvcm1WYWx1ZS5zY3JpcHRzLFxuICAgICAgICB2YXJpYWJsZU5hbWU6IGZvcm1WYWx1ZS52YXJpYWJsZU5hbWUgfHwgJycsXG4gICAgICAgIHZhbGlkYXRpb246IGZvcm1WYWx1ZS52YWxpZGF0aW9uID8gZm9ybVZhbHVlLnZhbGlkYXRpb24ubWFwKCh2OiBhbnkpID0+ICh7XG4gICAgICAgICAganNvblBhdGg6IHYuanNvblBhdGgsXG4gICAgICAgICAgdmVyaWZpY2F0aW9uVHlwZTogdi52ZXJpZmljYXRpb25UeXBlLFxuICAgICAgICAgIGV4cGVjdGVkVHlwZTogdi5leHBlY3RlZFR5cGUsXG4gICAgICAgICAgZXhwZWN0ZWRWYWx1ZTogdi5leHBlY3RlZFZhbHVlLFxuICAgICAgICAgIHJlc3VsdDogdi5yZXN1bHQgfHwgJ05vdCBydW4nXG4gICAgICAgIH0pKSA6IFtdXG4gICAgICB9O1xuICAgICAgdGhpcy5jcmVhdGVTdGVwLmVtaXQoc3RlcERhdGEpO1xuICAgIH1cbiAgfVxuXG4gIG9uTmV4dCgpOiB2b2lkIHtcbiAgICAvLyBNb3ZlIHRvIG5leHQgc3RlcCBvciBjcmVhdGUgc3RlcCBpZiBvbiBsYXN0IHN0ZXBcbiAgICBjb25zdCBzdGVwT3JkZXI6IFByb2dyZXNzU3RlcFtdID0gWydyZXF1ZXN0LWRldGFpbHMnLCAnc3RvcmUtcmVzcG9uc2UnLCAndmFsaWRhdGlvbiddO1xuICAgIGNvbnN0IGN1cnJlbnRJbmRleCA9IHN0ZXBPcmRlci5pbmRleE9mKHRoaXMuc2VsZWN0ZWRQcm9ncmVzc1N0ZXApO1xuICAgIGlmIChjdXJyZW50SW5kZXggPCBzdGVwT3JkZXIubGVuZ3RoIC0gMSkge1xuICAgICAgdGhpcy5vblByb2dyZXNzU3RlcENoYW5nZShzdGVwT3JkZXJbY3VycmVudEluZGV4ICsgMV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm9uQ3JlYXRlU3RlcCgpO1xuICAgIH1cbiAgfVxuXG4gIG9uQmFjaygpOiB2b2lkIHtcbiAgICAvLyBNb3ZlIHRvIHByZXZpb3VzIHN0ZXBcbiAgICBjb25zdCBzdGVwT3JkZXI6IFByb2dyZXNzU3RlcFtdID0gWydyZXF1ZXN0LWRldGFpbHMnLCAnc3RvcmUtcmVzcG9uc2UnLCAndmFsaWRhdGlvbiddO1xuICAgIGNvbnN0IGN1cnJlbnRJbmRleCA9IHN0ZXBPcmRlci5pbmRleE9mKHRoaXMuc2VsZWN0ZWRQcm9ncmVzc1N0ZXApO1xuICAgIGlmIChjdXJyZW50SW5kZXggPiAwKSB7XG4gICAgICB0aGlzLm9uUHJvZ3Jlc3NTdGVwQ2hhbmdlKHN0ZXBPcmRlcltjdXJyZW50SW5kZXggLSAxXSk7XG4gICAgfVxuICB9XG5cbiAgY2FuR29CYWNrKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHN0ZXBPcmRlcjogUHJvZ3Jlc3NTdGVwW10gPSBbJ3JlcXVlc3QtZGV0YWlscycsICdzdG9yZS1yZXNwb25zZScsICd2YWxpZGF0aW9uJ107XG4gICAgY29uc3QgY3VycmVudEluZGV4ID0gc3RlcE9yZGVyLmluZGV4T2YodGhpcy5zZWxlY3RlZFByb2dyZXNzU3RlcCk7XG4gICAgcmV0dXJuIGN1cnJlbnRJbmRleCA+IDA7XG4gIH1cblxuICBpc0xhc3RTdGVwKCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHN0ZXBPcmRlcjogUHJvZ3Jlc3NTdGVwW10gPSBbJ3JlcXVlc3QtZGV0YWlscycsICdzdG9yZS1yZXNwb25zZScsICd2YWxpZGF0aW9uJ107XG4gICAgY29uc3QgY3VycmVudEluZGV4ID0gc3RlcE9yZGVyLmluZGV4T2YodGhpcy5zZWxlY3RlZFByb2dyZXNzU3RlcCk7XG4gICAgcmV0dXJuIGN1cnJlbnRJbmRleCA9PT0gc3RlcE9yZGVyLmxlbmd0aCAtIDE7XG4gIH1cblxuICBnZXRQcm9ncmVzc1N0ZXBDbGFzcyhzdGVwOiBQcm9ncmVzc1N0ZXApOiBzdHJpbmcge1xuICAgIGNvbnN0IHN0ZXBPcmRlcjogUHJvZ3Jlc3NTdGVwW10gPSBbJ3JlcXVlc3QtZGV0YWlscycsICdzdG9yZS1yZXNwb25zZScsICd2YWxpZGF0aW9uJ107XG4gICAgY29uc3QgY3VycmVudEluZGV4ID0gc3RlcE9yZGVyLmluZGV4T2YodGhpcy5jdXJyZW50U3RlcCk7XG4gICAgY29uc3Qgc3RlcEluZGV4ID0gc3RlcE9yZGVyLmluZGV4T2Yoc3RlcCk7XG5cbiAgICBpZiAoc3RlcEluZGV4IDwgY3VycmVudEluZGV4KSB7XG4gICAgICByZXR1cm4gJ2NxYS10ZXh0LWdyYXktNDAwJzsgLy8gQ29tcGxldGVkXG4gICAgfSBlbHNlIGlmIChzdGVwSW5kZXggPT09IGN1cnJlbnRJbmRleCkge1xuICAgICAgcmV0dXJuICdjcWEtdGV4dC1wdXJwbGUtNjAwIGNxYS1mb250LXNlbWlib2xkJzsgLy8gQWN0aXZlXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnY3FhLXRleHQtZ3JheS00MDAnOyAvLyBQZW5kaW5nXG4gICAgfVxuICB9XG5cbiAgZ2V0UHJvZ3Jlc3NTdGVwTnVtYmVyKHN0ZXA6IFByb2dyZXNzU3RlcCk6IG51bWJlciB7XG4gICAgY29uc3Qgc3RlcE9yZGVyOiBQcm9ncmVzc1N0ZXBbXSA9IFsncmVxdWVzdC1kZXRhaWxzJywgJ3N0b3JlLXJlc3BvbnNlJywgJ3ZhbGlkYXRpb24nXTtcbiAgICByZXR1cm4gc3RlcE9yZGVyLmluZGV4T2Yoc3RlcCkgKyAxO1xuICB9XG5cbiAgZ2V0UHJvZ3Jlc3NTdGVwTGFiZWwoc3RlcDogUHJvZ3Jlc3NTdGVwKTogc3RyaW5nIHtcbiAgICBjb25zdCBsYWJlbHM6IFJlY29yZDxQcm9ncmVzc1N0ZXAsIHN0cmluZz4gPSB7XG4gICAgICAncmVxdWVzdC1kZXRhaWxzJzogJ1JlcXVlc3QgRGV0YWlscycsXG4gICAgICAnc3RvcmUtcmVzcG9uc2UnOiAnU3RvcmUgUmVzcG9uc2UnLFxuICAgICAgJ3ZhbGlkYXRpb24nOiAnVmFsaWRhdGlvbidcbiAgICB9O1xuICAgIHJldHVybiBsYWJlbHNbc3RlcF07XG4gIH1cblxuICBmb3JtYXRKc29uUmVzcG9uc2UoZGF0YTogYW55KTogc3RyaW5nIHtcbiAgICBpZiAoIWRhdGEpIHJldHVybiAnJztcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGRhdGEsIG51bGwsIDIpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIFN0cmluZyhkYXRhKTtcbiAgICB9XG4gIH1cbiAgXG4gIG9uUHJvZ3Jlc3NTdGVwQ2hhbmdlKHN0ZXA6IFByb2dyZXNzU3RlcCk6IHZvaWQge1xuICAgIHRoaXMuc2VsZWN0ZWRQcm9ncmVzc1N0ZXAgPSBzdGVwO1xuICAgIC8vIEluaXRpYWxpemUgdmFsaWRhdGlvbiBmb3JtIGFycmF5IGlmIHN3aXRjaGluZyB0byB2YWxpZGF0aW9uIHN0ZXBcbiAgICBpZiAoc3RlcCA9PT0gJ3ZhbGlkYXRpb24nICYmIHRoaXMudmFsaWRhdGlvbkZvcm1BcnJheS5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMuYWRkVmFsaWRhdGlvblJ1bGUoKTtcbiAgICB9XG4gIH1cblxuICBhZGRWYWxpZGF0aW9uUnVsZSgpOiB2b2lkIHtcbiAgICBjb25zdCB2YWxpZGF0aW9uR3JvdXAgPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIGNoZWNrZWQ6IFtmYWxzZV0sXG4gICAgICBqc29uUGF0aDogWycnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgIHZlcmlmaWNhdGlvblR5cGU6IFsnZXF1YWxzJ10sXG4gICAgICBleHBlY3RlZFR5cGU6IFsnc3RyaW5nJ10sXG4gICAgICBleHBlY3RlZFZhbHVlOiBbJycsIFZhbGlkYXRvcnMucmVxdWlyZWRdLFxuICAgICAgcmVzdWx0OiBbJ05vdCBydW4nXVxuICAgIH0pO1xuICAgIC8vIEVuc3VyZSBhbGwgY29udHJvbHMgYXJlIGVuYWJsZWQgdG8gYXZvaWQgZGlzYWJsZWQgYXR0cmlidXRlIHdhcm5pbmdzXG4gICAgdmFsaWRhdGlvbkdyb3VwLmVuYWJsZSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgdGhpcy52YWxpZGF0aW9uRm9ybUFycmF5LnB1c2godmFsaWRhdGlvbkdyb3VwKTtcbiAgfVxuXG4gIHJlbW92ZVZhbGlkYXRpb25SdWxlKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnZhbGlkYXRpb25Gb3JtQXJyYXkucmVtb3ZlQXQoaW5kZXgpO1xuICB9XG5cbiAgZ2V0VmFsaWRhdGlvbkZvcm1Hcm91cChpbmRleDogbnVtYmVyKTogRm9ybUdyb3VwIHtcbiAgICByZXR1cm4gdGhpcy52YWxpZGF0aW9uRm9ybUFycmF5LmF0KGluZGV4KSBhcyBGb3JtR3JvdXA7XG4gIH1cblxuICB0cmFja0J5VmFsaWRhdGlvblJ1bGVJbmRleChpbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICB0cmFja0J5SGVhZGVySW5kZXgoaW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgdHJhY2tCeVBhcmFtSW5kZXgoaW5kZXg6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG5cbiAgZ2V0VmVyaWZpY2F0aW9uVHlwZU9wdGlvbnMoKTogU2VsZWN0T3B0aW9uW10ge1xuICAgIHJldHVybiBbXG4gICAgICB7IGlkOiAnZXF1YWxzJywgdmFsdWU6ICdlcXVhbHMnLCBuYW1lOiAnRXF1YWxzJywgbGFiZWw6ICdFcXVhbHMnIH0sXG4gICAgICB7IGlkOiAnbm90X2VxdWFscycsIHZhbHVlOiAnbm90X2VxdWFscycsIG5hbWU6ICdOb3QgRXF1YWxzJywgbGFiZWw6ICdOb3QgRXF1YWxzJyB9LFxuICAgICAgeyBpZDogJ2NvbnRhaW5zJywgdmFsdWU6ICdjb250YWlucycsIG5hbWU6ICdDb250YWlucycsIGxhYmVsOiAnQ29udGFpbnMnIH0sXG4gICAgICB7IGlkOiAnbm90X2NvbnRhaW5zJywgdmFsdWU6ICdub3RfY29udGFpbnMnLCBuYW1lOiAnTm90IENvbnRhaW5zJywgbGFiZWw6ICdOb3QgQ29udGFpbnMnIH0sXG4gICAgICB7IGlkOiAnZ3JlYXRlcl90aGFuJywgdmFsdWU6ICdncmVhdGVyX3RoYW4nLCBuYW1lOiAnR3JlYXRlciBUaGFuJywgbGFiZWw6ICdHcmVhdGVyIFRoYW4nIH0sXG4gICAgICB7IGlkOiAnbGVzc190aGFuJywgdmFsdWU6ICdsZXNzX3RoYW4nLCBuYW1lOiAnTGVzcyBUaGFuJywgbGFiZWw6ICdMZXNzIFRoYW4nIH0sXG4gICAgICB7IGlkOiAnZ3JlYXRlcl90aGFuX29yX2VxdWFscycsIHZhbHVlOiAnZ3JlYXRlcl90aGFuX29yX2VxdWFscycsIG5hbWU6ICdHcmVhdGVyIFRoYW4gT3IgRXF1YWxzJywgbGFiZWw6ICdHcmVhdGVyIFRoYW4gT3IgRXF1YWxzJyB9LFxuICAgICAgeyBpZDogJ2xlc3NfdGhhbl9vcl9lcXVhbHMnLCB2YWx1ZTogJ2xlc3NfdGhhbl9vcl9lcXVhbHMnLCBuYW1lOiAnTGVzcyBUaGFuIE9yIEVxdWFscycsIGxhYmVsOiAnTGVzcyBUaGFuIE9yIEVxdWFscycgfSxcbiAgICAgIHsgaWQ6ICdleGlzdHMnLCB2YWx1ZTogJ2V4aXN0cycsIG5hbWU6ICdFeGlzdHMnLCBsYWJlbDogJ0V4aXN0cycgfSxcbiAgICAgIHsgaWQ6ICdub3RfZXhpc3RzJywgdmFsdWU6ICdub3RfZXhpc3RzJywgbmFtZTogJ05vdCBFeGlzdHMnLCBsYWJlbDogJ05vdCBFeGlzdHMnIH1cbiAgICBdO1xuICB9XG5cbiAgZ2V0RXhwZWN0ZWRUeXBlT3B0aW9ucygpOiBTZWxlY3RPcHRpb25bXSB7XG4gICAgcmV0dXJuIFtcbiAgICAgIHsgaWQ6ICdzdHJpbmcnLCB2YWx1ZTogJ3N0cmluZycsIG5hbWU6ICdTdHJpbmcnLCBsYWJlbDogJ1N0cmluZycgfSxcbiAgICAgIHsgaWQ6ICdudW1iZXInLCB2YWx1ZTogJ251bWJlcicsIG5hbWU6ICdOdW1iZXInLCBsYWJlbDogJ051bWJlcicgfSxcbiAgICAgIHsgaWQ6ICdib29sZWFuJywgdmFsdWU6ICdib29sZWFuJywgbmFtZTogJ0Jvb2xlYW4nLCBsYWJlbDogJ0Jvb2xlYW4nIH0sXG4gICAgICB7IGlkOiAnb2JqZWN0JywgdmFsdWU6ICdvYmplY3QnLCBuYW1lOiAnT2JqZWN0JywgbGFiZWw6ICdPYmplY3QnIH0sXG4gICAgICB7IGlkOiAnYXJyYXknLCB2YWx1ZTogJ2FycmF5JywgbmFtZTogJ0FycmF5JywgbGFiZWw6ICdBcnJheScgfSxcbiAgICAgIHsgaWQ6ICdudWxsJywgdmFsdWU6ICdudWxsJywgbmFtZTogJ051bGwnLCBsYWJlbDogJ051bGwnIH1cbiAgICBdO1xuICB9XG5cbiAgZ2V0VmVyaWZpY2F0aW9uVHlwZUNvbmZpZyhpbmRleDogbnVtYmVyKTogRHluYW1pY1NlbGVjdEZpZWxkQ29uZmlnIHtcbiAgICAvLyBDYWNoZSB0aGUgY29uZmlnIHRvIHByZXZlbnQgaW5maW5pdGUgY2hhbmdlIGRldGVjdGlvbiBsb29wc1xuICAgIGlmICghdGhpcy52ZXJpZmljYXRpb25UeXBlQ29uZmlnQ2FjaGUpIHtcbiAgICAgIHRoaXMudmVyaWZpY2F0aW9uVHlwZUNvbmZpZ0NhY2hlID0ge1xuICAgICAgICBrZXk6ICd2ZXJpZmljYXRpb25UeXBlJyxcbiAgICAgICAgcGxhY2Vob2xkZXI6ICdTZWxlY3QgdmVyaWZpY2F0aW9uIHR5cGUnLFxuICAgICAgICBtdWx0aXBsZTogZmFsc2UsXG4gICAgICAgIHNlYXJjaGFibGU6IGZhbHNlLFxuICAgICAgICBvcHRpb25zOiB0aGlzLmdldFZlcmlmaWNhdGlvblR5cGVPcHRpb25zKClcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnZlcmlmaWNhdGlvblR5cGVDb25maWdDYWNoZTtcbiAgfVxuXG4gIGdldEV4cGVjdGVkVHlwZUNvbmZpZyhpbmRleDogbnVtYmVyKTogRHluYW1pY1NlbGVjdEZpZWxkQ29uZmlnIHtcbiAgICAvLyBDYWNoZSB0aGUgY29uZmlnIHRvIHByZXZlbnQgaW5maW5pdGUgY2hhbmdlIGRldGVjdGlvbiBsb29wc1xuICAgIGlmICghdGhpcy5leHBlY3RlZFR5cGVDb25maWdDYWNoZSkge1xuICAgICAgdGhpcy5leHBlY3RlZFR5cGVDb25maWdDYWNoZSA9IHtcbiAgICAgICAga2V5OiAnZXhwZWN0ZWRUeXBlJyxcbiAgICAgICAgcGxhY2Vob2xkZXI6ICdTZWxlY3QgZXhwZWN0ZWQgdHlwZScsXG4gICAgICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICAgICAgc2VhcmNoYWJsZTogZmFsc2UsXG4gICAgICAgIG9wdGlvbnM6IHRoaXMuZ2V0RXhwZWN0ZWRUeXBlT3B0aW9ucygpXG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5leHBlY3RlZFR5cGVDb25maWdDYWNoZTtcbiAgfVxuXG4gIGdldFJlc3VsdENsYXNzKHJlc3VsdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAocmVzdWx0ID09PSAnUGFzcycpIHtcbiAgICAgIHJldHVybiAnY3FhLWJnLWdyZWVuLTUwMCBjcWEtdGV4dC13aGl0ZSc7XG4gICAgfSBlbHNlIGlmIChyZXN1bHQgPT09ICdGYWlsJykge1xuICAgICAgcmV0dXJuICdjcWEtYmctcmVkLTUwMCBjcWEtdGV4dC13aGl0ZSc7XG4gICAgfVxuICAgIHJldHVybiAnY3FhLWJnLWdyYXktMzAwIGNxYS10ZXh0LWdyYXktNzAwJztcbiAgfVxuXG4gIGdldCBhbGxWYWxpZGF0aW9uUnVsZXNTZWxlY3RlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy52YWxpZGF0aW9uRm9ybUFycmF5Lmxlbmd0aCA+IDAgJiYgXG4gICAgICAgICAgIHRoaXMudmFsaWRhdGlvbkZvcm1BcnJheS5jb250cm9scy5ldmVyeShjb250cm9sID0+IGNvbnRyb2wuZ2V0KCdjaGVja2VkJyk/LnZhbHVlKTtcbiAgfVxuXG4gIGdldCBzb21lVmFsaWRhdGlvblJ1bGVzU2VsZWN0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGlvbkZvcm1BcnJheS5jb250cm9scy5zb21lKGNvbnRyb2wgPT4gY29udHJvbC5nZXQoJ2NoZWNrZWQnKT8udmFsdWUpICYmIFxuICAgICAgICAgICAhdGhpcy5hbGxWYWxpZGF0aW9uUnVsZXNTZWxlY3RlZDtcbiAgfVxuXG4gIG9uU2VsZWN0QWxsVmFsaWRhdGlvblJ1bGVzKGNoZWNrZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnZhbGlkYXRpb25Gb3JtQXJyYXkuY29udHJvbHMuZm9yRWFjaChjb250cm9sID0+IHtcbiAgICAgIGNvbnRyb2wuZ2V0KCdjaGVja2VkJyk/LnNldFZhbHVlKGNoZWNrZWQpO1xuICAgIH0pO1xuICB9XG5cbiAgb25EZWxldGVTZWxlY3RlZFZhbGlkYXRpb25SdWxlcygpOiB2b2lkIHtcbiAgICBjb25zdCBpbmRpY2VzVG9SZW1vdmU6IG51bWJlcltdID0gW107XG4gICAgdGhpcy52YWxpZGF0aW9uRm9ybUFycmF5LmNvbnRyb2xzLmZvckVhY2goKGNvbnRyb2wsIGluZGV4KSA9PiB7XG4gICAgICBpZiAoY29udHJvbC5nZXQoJ2NoZWNrZWQnKT8udmFsdWUpIHtcbiAgICAgICAgaW5kaWNlc1RvUmVtb3ZlLnB1c2goaW5kZXgpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIC8vIFJlbW92ZSBpbiByZXZlcnNlIG9yZGVyIHRvIG1haW50YWluIGNvcnJlY3QgaW5kaWNlc1xuICAgIGluZGljZXNUb1JlbW92ZS5yZXZlcnNlKCkuZm9yRWFjaChpbmRleCA9PiB7XG4gICAgICB0aGlzLnJlbW92ZVZhbGlkYXRpb25SdWxlKGluZGV4KTtcbiAgICB9KTtcbiAgfVxufVxuXG4iLCI8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1oLWZ1bGwgY3FhLWJnLXdoaXRlIGNxYS1weC00IGNxYS1weS0yXCI+XG4gIDwhLS0gSGVhZGVyIC0tPlxuICA8aDIgY2xhc3M9XCJjcWEtdGV4dC1bMTJweF0gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtYmxhY2stMTAwIGNxYS1tYi00XCI+XG4gICAgQ3JlYXRlIEFQSSBUZXN0IFN0ZXBcbiAgPC9oMj5cblxuICA8IS0tIFByb2dyZXNzIFRyYWNrZXIgLS0+XG4gIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1nYXAtNCBjcWEtbWItNiBjcWEtcGItNCBjcWEtYm9yZGVyLWIgY3FhLWJvcmRlci1ncmF5LTIwMFwiPlxuICAgIDwhLS0gPGRpdiAqbmdGb3I9XCJsZXQgc3RlcCBvZiBwcm9ncmVzc1N0ZXBzXCJcbiAgICAgICAgIGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtZ2FwLTJcIlxuICAgICAgICAgW25nQ2xhc3NdPVwiZ2V0UHJvZ3Jlc3NTdGVwQ2xhc3Moc3RlcClcIj5cbiAgICAgIDxzcGFuIGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLWZvbnQtbWVkaXVtXCI+e3sgZ2V0UHJvZ3Jlc3NTdGVwTnVtYmVyKHN0ZXApIH19IHt7IGdldFByb2dyZXNzU3RlcExhYmVsKHN0ZXApIH19PC9zcGFuPlxuICAgICAgPHNwYW4gKm5nSWY9XCJzdGVwICE9PSAndmFsaWRhdGlvbidcIiBjbGFzcz1cImNxYS10ZXh0LWdyYXktMzAwXCI+4oCiPC9zcGFuPlxuICAgIDwvZGl2PiAtLT5cbiAgICA8ZGl2XG4gICAgICAgICBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWdhcC0yXCI+XG4gICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtZ2FwLTJcIiBbbmdDbGFzc109XCJ7J2NxYS10ZXh0LXB1cnBsZS02MDAgY3FhLWZvbnQtc2VtaWJvbGQnOiBzZWxlY3RlZFByb2dyZXNzU3RlcCA9PT0gJ3JlcXVlc3QtZGV0YWlscyd9XCIgKGNsaWNrKT1cIm9uUHJvZ3Jlc3NTdGVwQ2hhbmdlKCdyZXF1ZXN0LWRldGFpbHMnKVwiPlxuICAgICAgICAgIDxkaXY+MTwvZGl2PlxuICAgICAgICAgIDxkaXY+UmVxdWVzdCBEZXRhaWxzPC9kaXY+XG4gICAgICAgICAgPGRpdj48L2Rpdj5cbiAgICAgICAgIDwvZGl2PlxuICAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWdhcC0yXCIgW25nQ2xhc3NdPVwieydjcWEtdGV4dC1wdXJwbGUtNjAwIGNxYS1mb250LXNlbWlib2xkJzogc2VsZWN0ZWRQcm9ncmVzc1N0ZXAgPT09ICdzdG9yZS1yZXNwb25zZSd9XCIgKGNsaWNrKT1cIm9uUHJvZ3Jlc3NTdGVwQ2hhbmdlKCdzdG9yZS1yZXNwb25zZScpXCI+XG4gICAgICAgICAgPGRpdj4yPC9kaXY+XG4gICAgICAgICAgPGRpdj5TdG9yZSBSZXNwb25zZTwvZGl2PlxuICAgICAgICAgIDxkaXY+PC9kaXY+XG4gICAgICAgICA8L2Rpdj5cbiAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1nYXAtMlwiIFtuZ0NsYXNzXT1cInsnY3FhLXRleHQtcHVycGxlLTYwMCBjcWEtZm9udC1zZW1pYm9sZCc6IHNlbGVjdGVkUHJvZ3Jlc3NTdGVwID09PSAndmFsaWRhdGlvbid9XCIgKGNsaWNrKT1cIm9uUHJvZ3Jlc3NTdGVwQ2hhbmdlKCd2YWxpZGF0aW9uJylcIj5cbiAgICAgICAgICA8ZGl2PjM8L2Rpdj5cbiAgICAgICAgICA8ZGl2PlZhbGlkYXRpb248L2Rpdj5cbiAgICAgICAgICA8ZGl2PjwvZGl2PlxuICAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwic2VsZWN0ZWRQcm9ncmVzc1N0ZXAgPT09ICdyZXF1ZXN0LWRldGFpbHMnXCI+XG4gIDwhLS0gQVBJIFJlcXVlc3QgQ29uZmlndXJhdGlvbiAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWdhcC0yIGNxYS1tYi02XCI+XG4gICAgPGRpdiBjbGFzcz1cImNxYS13LTMyIGNxYS1mbGV4LXNocmluay0wXCI+XG4gICAgICA8Y3FhLWR5bmFtaWMtc2VsZWN0XG4gICAgICAgIFtmb3JtXT1cImFwaUZvcm1cIlxuICAgICAgICBbY29uZmlnXT1cImdldEh0dHBNZXRob2RDb25maWcoKVwiPlxuICAgICAgPC9jcWEtZHluYW1pYy1zZWxlY3Q+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTFcIj5cbiAgICAgIDxjcWEtY3VzdG9tLWlucHV0XG4gICAgICAgIFtwbGFjZWhvbGRlcl09XCInRW50ZXIgQVBJIGVuZHBvaW50IFVSTCdcIlxuICAgICAgICBbdmFsdWVdPVwiYXBpRm9ybS5nZXQoJ3VybCcpPy52YWx1ZSB8fCAnJ1wiXG4gICAgICAgIFtmdWxsV2lkdGhdPVwidHJ1ZVwiXG4gICAgICAgICh2YWx1ZUNoYW5nZSk9XCJhcGlGb3JtLmdldCgndXJsJyk/LnNldFZhbHVlKCRldmVudClcIj5cbiAgICAgIDwvY3FhLWN1c3RvbS1pbnB1dD5cbiAgICA8L2Rpdj5cbiAgICA8Y3FhLWJ1dHRvblxuICAgICAgdmFyaWFudD1cIm91dGxpbmVkXCJcbiAgICAgIHRleHQ9XCJJbXBvcnQgQVBJIGNVUkxcIlxuICAgICAgKGNsaWNrZWQpPVwib25JbXBvcnRDdXJsKClcIj5cbiAgICA8L2NxYS1idXR0b24+XG4gICAgPGNxYS1idXR0b25cbiAgICAgIHZhcmlhbnQ9XCJmaWxsZWRcIlxuICAgICAgdGV4dD1cIlNlbmQgUmVxdWVzdFwiXG4gICAgICAoY2xpY2tlZCk9XCJvblNlbmRSZXF1ZXN0KClcIlxuICAgICAgW2Rpc2FibGVkXT1cIiFhcGlGb3JtLmdldCgndXJsJyk/LnZhbHVlIHx8IGlzTG9hZGluZ1wiPlxuICAgIDwvY3FhLWJ1dHRvbj5cbiAgPC9kaXY+XG5cbiAgPCEtLSBSZXF1ZXN0IERldGFpbHMgVGFicyAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtZmxleC0xIGNxYS1vdmVyZmxvdy1oaWRkZW4gY3FhLW1iLTZcIj5cbiAgICA8IS0tIFRhYiBOYXZpZ2F0aW9uIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLWdyYXktMjAwIGNxYS1iZy1ncmF5LTUwXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImNxYS1weC00IGNxYS1weS0yIGNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdHJhbnNpdGlvbi1jb2xvcnMgY3FhLWJvcmRlci1iLTJcIlxuICAgICAgICBbY2xhc3MuY3FhLXRleHQtYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICdoZWFkZXJzJ1wiXG4gICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLWJsdWUtNjAwXT1cInNlbGVjdGVkVGFiID09PSAnaGVhZGVycydcIlxuICAgICAgICBbY2xhc3MuY3FhLXRleHQtZ3JheS02MDBdPVwic2VsZWN0ZWRUYWIgIT09ICdoZWFkZXJzJ1wiXG4gICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLXRyYW5zcGFyZW50XT1cInNlbGVjdGVkVGFiICE9PSAnaGVhZGVycydcIlxuICAgICAgICAoY2xpY2spPVwib25UYWJDaGFuZ2UoJ2hlYWRlcnMnKVwiPlxuICAgICAgICBIZWFkZXJzXG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwiY3FhLXB4LTQgY3FhLXB5LTIgY3FhLXRleHQtc20gY3FhLWZvbnQtbWVkaXVtIGNxYS10cmFuc2l0aW9uLWNvbG9ycyBjcWEtYm9yZGVyLWItMlwiXG4gICAgICAgIFtjbGFzcy5jcWEtdGV4dC1ibHVlLTYwMF09XCJzZWxlY3RlZFRhYiA9PT0gJ2JvZHknXCJcbiAgICAgICAgW2NsYXNzLmNxYS1ib3JkZXItYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICdib2R5J1wiXG4gICAgICAgIFtjbGFzcy5jcWEtdGV4dC1ncmF5LTYwMF09XCJzZWxlY3RlZFRhYiAhPT0gJ2JvZHknXCJcbiAgICAgICAgW2NsYXNzLmNxYS1ib3JkZXItdHJhbnNwYXJlbnRdPVwic2VsZWN0ZWRUYWIgIT09ICdib2R5J1wiXG4gICAgICAgIChjbGljayk9XCJvblRhYkNoYW5nZSgnYm9keScpXCI+XG4gICAgICAgIEJvZHlcbiAgICAgIDwvYnV0dG9uPlxuICAgICAgPGJ1dHRvblxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgY2xhc3M9XCJjcWEtcHgtNCBjcWEtcHktMiBjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRyYW5zaXRpb24tY29sb3JzIGNxYS1ib3JkZXItYi0yXCJcbiAgICAgICAgW2NsYXNzLmNxYS10ZXh0LWJsdWUtNjAwXT1cInNlbGVjdGVkVGFiID09PSAncGFyYW1zJ1wiXG4gICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLWJsdWUtNjAwXT1cInNlbGVjdGVkVGFiID09PSAncGFyYW1zJ1wiXG4gICAgICAgIFtjbGFzcy5jcWEtdGV4dC1ncmF5LTYwMF09XCJzZWxlY3RlZFRhYiAhPT0gJ3BhcmFtcydcIlxuICAgICAgICBbY2xhc3MuY3FhLWJvcmRlci10cmFuc3BhcmVudF09XCJzZWxlY3RlZFRhYiAhPT0gJ3BhcmFtcydcIlxuICAgICAgICAoY2xpY2spPVwib25UYWJDaGFuZ2UoJ3BhcmFtcycpXCI+XG4gICAgICAgIFBhcmFtc1xuICAgICAgPC9idXR0b24+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImNxYS1weC00IGNxYS1weS0yIGNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdHJhbnNpdGlvbi1jb2xvcnMgY3FhLWJvcmRlci1iLTJcIlxuICAgICAgICBbY2xhc3MuY3FhLXRleHQtYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICdzY3JpcHRzJ1wiXG4gICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLWJsdWUtNjAwXT1cInNlbGVjdGVkVGFiID09PSAnc2NyaXB0cydcIlxuICAgICAgICBbY2xhc3MuY3FhLXRleHQtZ3JheS02MDBdPVwic2VsZWN0ZWRUYWIgIT09ICdzY3JpcHRzJ1wiXG4gICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLXRyYW5zcGFyZW50XT1cInNlbGVjdGVkVGFiICE9PSAnc2NyaXB0cydcIlxuICAgICAgICAoY2xpY2spPVwib25UYWJDaGFuZ2UoJ3NjcmlwdHMnKVwiPlxuICAgICAgICBTY3JpcHRzXG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cblxuICAgIDwhLS0gVGFiIENvbnRlbnQgLS0+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTEgY3FhLW92ZXJmbG93LXktYXV0byBjcWEtcC00IGNxYS1ib3JkZXIgY3FhLWJvcmRlci1ncmF5LTIwMCBjcWEtYm9yZGVyLXQtMCBjcWEtcm91bmRlZC1iLWxnXCI+XG4gICAgICA8IS0tIEhlYWRlcnMgVGFiIC0tPlxuICAgICAgPGRpdiAqbmdJZj1cInNlbGVjdGVkVGFiID09PSAnaGVhZGVycydcIiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtZ2FwLTNcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1ncmlkIGNxYS1ncmlkLWNvbHMtMiBjcWEtZ2FwLTQgY3FhLWl0ZW1zLXN0YXJ0XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNxYS10ZXh0LXhzIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktNzAwIGNxYS11cHBlcmNhc2VcIj5IZWFkZXIgTmFtZTwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtdGV4dC14cyBjcWEtZm9udC1zZW1pYm9sZCBjcWEtdGV4dC1ncmF5LTcwMCBjcWEtdXBwZXJjYXNlXCI+SGVhZGVyIFZhbHVlPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBoZWFkZXIgb2YgaGVhZGVyc0Zvcm1BcnJheS5jb250cm9sczsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogdHJhY2tCeUhlYWRlckluZGV4XCIgXG4gICAgICAgICAgICAgY2xhc3M9XCJjcWEtZ3JpZCBjcWEtZ3JpZC1jb2xzLTIgY3FhLWdhcC00IGNxYS1pdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPGNxYS1keW5hbWljLXNlbGVjdFxuICAgICAgICAgICAgICBbZm9ybV09XCJnZXRIZWFkZXJGb3JtR3JvdXAoaSlcIlxuICAgICAgICAgICAgICBbY29uZmlnXT1cImdldEhlYWRlck5hbWVDb25maWcoaSlcIj5cbiAgICAgICAgICAgIDwvY3FhLWR5bmFtaWMtc2VsZWN0PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1nYXAtMlwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTFcIj5cbiAgICAgICAgICAgICAgPGNxYS1jdXN0b20taW5wdXRcbiAgICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ0hlYWRlciB2YWx1ZSdcIlxuICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJnZXRIZWFkZXJGb3JtR3JvdXAoaSkuZ2V0KCd2YWx1ZScpPy52YWx1ZSB8fCAnJ1wiXG4gICAgICAgICAgICAgICAgW2Z1bGxXaWR0aF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiZ2V0SGVhZGVyRm9ybUdyb3VwKGkpLmdldCgndmFsdWUnKT8uc2V0VmFsdWUoJGV2ZW50KVwiPlxuICAgICAgICAgICAgICA8L2NxYS1jdXN0b20taW5wdXQ+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtanVzdGlmeS1jZW50ZXIgY3FhLXctOCBjcWEtaC04IGNxYS1yb3VuZGVkIGNxYS10ZXh0LXJlZC01MDAgaG92ZXI6Y3FhLXRleHQtcmVkLTcwMCBob3ZlcjpjcWEtYmctcmVkLTUwIGNxYS10cmFuc2l0aW9uLWNvbG9yc1wiXG4gICAgICAgICAgICAgIChjbGljayk9XCJyZW1vdmVIZWFkZXIoaSlcIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidSZW1vdmUgaGVhZGVyJ1wiPlxuICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJjcWEtdGV4dC1sZ1wiPmRlbGV0ZTwvbWF0LWljb24+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICBjbGFzcz1cImNxYS10ZXh0LWJsdWUtNjAwIGNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtc2VsZi1zdGFydCBjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1nYXAtMSBob3ZlcjpjcWEtdGV4dC1ibHVlLTcwMCBjcWEtdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICAgIChjbGljayk9XCJhZGRIZWFkZXIoKVwiPlxuICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cImNxYS10ZXh0LWJhc2VcIj5hZGQ8L21hdC1pY29uPlxuICAgICAgICAgIDxzcGFuPkFkZCBIZWFkZXI8L3NwYW4+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gQm9keSBUYWIgLS0+XG4gICAgICA8ZGl2ICpuZ0lmPVwic2VsZWN0ZWRUYWIgPT09ICdib2R5J1wiIGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1nYXAtM1wiPlxuICAgICAgICA8Y3FhLWN1c3RvbS10ZXh0YXJlYVxuICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInRW50ZXIgcmVxdWVzdCBib2R5IChKU09OLCBYTUwsIGV0Yy4pJ1wiXG4gICAgICAgICAgW3ZhbHVlXT1cImFwaUZvcm0uZ2V0KCdib2R5Jyk/LnZhbHVlIHx8ICcnXCJcbiAgICAgICAgICBbZnVsbFdpZHRoXT1cInRydWVcIlxuICAgICAgICAgIFtyb3dzXT1cIjEwXCJcbiAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiYXBpRm9ybS5nZXQoJ2JvZHknKT8uc2V0VmFsdWUoJGV2ZW50KVwiPlxuICAgICAgICA8L2NxYS1jdXN0b20tdGV4dGFyZWE+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPCEtLSBQYXJhbXMgVGFiIC0tPlxuICAgICAgPGRpdiAqbmdJZj1cInNlbGVjdGVkVGFiID09PSAncGFyYW1zJ1wiIGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1nYXAtM1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWdyaWQgY3FhLWdyaWQtY29scy0yIGNxYS1nYXAtNCBjcWEtaXRlbXMtc3RhcnRcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLXRleHQteHMgY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtZ3JheS03MDAgY3FhLXVwcGVyY2FzZVwiPlBhcmFtZXRlciBOYW1lPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNxYS10ZXh0LXhzIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktNzAwIGNxYS11cHBlcmNhc2VcIj5QYXJhbWV0ZXIgVmFsdWU8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IHBhcmFtIG9mIHBhcmFtc0Zvcm1BcnJheS5jb250cm9sczsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogdHJhY2tCeVBhcmFtSW5kZXhcIiBcbiAgICAgICAgICAgICBjbGFzcz1cImNxYS1ncmlkIGNxYS1ncmlkLWNvbHMtMiBjcWEtZ2FwLTQgY3FhLWl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8Y3FhLWN1c3RvbS1pbnB1dFxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1BhcmFtZXRlciBuYW1lJ1wiXG4gICAgICAgICAgICAgIFt2YWx1ZV09XCJnZXRQYXJhbUZvcm1Hcm91cChpKS5nZXQoJ25hbWUnKT8udmFsdWUgfHwgJydcIlxuICAgICAgICAgICAgICBbZnVsbFdpZHRoXT1cInRydWVcIlxuICAgICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiZ2V0UGFyYW1Gb3JtR3JvdXAoaSkuZ2V0KCduYW1lJyk/LnNldFZhbHVlKCRldmVudClcIj5cbiAgICAgICAgICAgIDwvY3FhLWN1c3RvbS1pbnB1dD5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtZ2FwLTJcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleC0xXCI+XG4gICAgICAgICAgICAgIDxjcWEtY3VzdG9tLWlucHV0XG4gICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cIidQYXJhbWV0ZXIgdmFsdWUnXCJcbiAgICAgICAgICAgICAgICBbdmFsdWVdPVwiZ2V0UGFyYW1Gb3JtR3JvdXAoaSkuZ2V0KCd2YWx1ZScpPy52YWx1ZSB8fCAnJ1wiXG4gICAgICAgICAgICAgICAgW2Z1bGxXaWR0aF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiZ2V0UGFyYW1Gb3JtR3JvdXAoaSkuZ2V0KCd2YWx1ZScpPy5zZXRWYWx1ZSgkZXZlbnQpXCI+XG4gICAgICAgICAgICAgIDwvY3FhLWN1c3RvbS1pbnB1dD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1qdXN0aWZ5LWNlbnRlciBjcWEtdy04IGNxYS1oLTggY3FhLXJvdW5kZWQgY3FhLXRleHQtcmVkLTUwMCBob3ZlcjpjcWEtdGV4dC1yZWQtNzAwIGhvdmVyOmNxYS1iZy1yZWQtNTAgY3FhLXRyYW5zaXRpb24tY29sb3JzXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZVBhcmFtKGkpXCJcbiAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInUmVtb3ZlIHBhcmFtZXRlcidcIj5cbiAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwiY3FhLXRleHQtbGdcIj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgY2xhc3M9XCJjcWEtdGV4dC1ibHVlLTYwMCBjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXNlbGYtc3RhcnQgY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtZ2FwLTEgaG92ZXI6Y3FhLXRleHQtYmx1ZS03MDAgY3FhLXRyYW5zaXRpb24tY29sb3JzXCJcbiAgICAgICAgICAoY2xpY2spPVwiYWRkUGFyYW0oKVwiPlxuICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cImNxYS10ZXh0LWJhc2VcIj5hZGQ8L21hdC1pY29uPlxuICAgICAgICAgIDxzcGFuPkFkZCBQYXJhbWV0ZXI8L3NwYW4+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gU2NyaXB0cyBUYWIgLS0+XG4gICAgICA8ZGl2ICpuZ0lmPVwic2VsZWN0ZWRUYWIgPT09ICdzY3JpcHRzJ1wiIGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1nYXAtM1wiPlxuICAgICAgICA8Y3FhLWN1c3RvbS10ZXh0YXJlYVxuICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInRW50ZXIgc2NyaXB0cyAoSmF2YVNjcmlwdCwgZXRjLiknXCJcbiAgICAgICAgICBbdmFsdWVdPVwiYXBpRm9ybS5nZXQoJ3NjcmlwdHMnKT8udmFsdWUgfHwgJydcIlxuICAgICAgICAgIFtmdWxsV2lkdGhdPVwidHJ1ZVwiXG4gICAgICAgICAgW3Jvd3NdPVwiMTBcIlxuICAgICAgICAgICh2YWx1ZUNoYW5nZSk9XCJhcGlGb3JtLmdldCgnc2NyaXB0cycpPy5zZXRWYWx1ZSgkZXZlbnQpXCI+XG4gICAgICAgIDwvY3FhLWN1c3RvbS10ZXh0YXJlYT5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cblxuXG48L25nLWNvbnRhaW5lcj5cbjxuZy1jb250YWluZXIgKm5nSWY9XCJzZWxlY3RlZFByb2dyZXNzU3RlcCA9PT0gJ3N0b3JlLXJlc3BvbnNlJ1wiPlxuICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1mbGV4LTEgY3FhLW1heC1oLVs1MDBweF0gY3FhLW92ZXJmbG93LXktYXV0b1wiPlxuICAgIDwhLS0gU3RvcmUgUmVzcG9uc2UgVGl0bGUgLS0+XG4gICAgPGgzIGNsYXNzPVwiY3FhLXRleHQtWzEycHhdIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWJsYWNrLTEwMCBjcWEtbWItNFwiPlxuICAgICAgU3RvcmUgUmVzcG9uc2VcbiAgICA8L2gzPlxuXG4gICAgPCEtLSBWYXJpYWJsZSBOYW1lIElucHV0IC0tPlxuICAgIDxkaXYgY2xhc3M9XCJjcWEtbWItNlwiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwiY3FhLXRleHQtWzEycHhdIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTcwMCBjcWEtbWItMSBjcWEtYmxvY2tcIj5cbiAgICAgICAgVmFyaWFibGUgTmFtZVxuICAgICAgPC9sYWJlbD5cbiAgICAgIDxjcWEtY3VzdG9tLWlucHV0XG4gICAgICAgIFtwbGFjZWhvbGRlcl09XCInVmFyaWFibGUgTmFtZSdcIlxuICAgICAgICBbdmFsdWVdPVwiYXBpRm9ybS5nZXQoJ3ZhcmlhYmxlTmFtZScpPy52YWx1ZSB8fCAnJ1wiXG4gICAgICAgIFtmdWxsV2lkdGhdPVwidHJ1ZVwiXG4gICAgICAgICh2YWx1ZUNoYW5nZSk9XCJhcGlGb3JtLmdldCgndmFyaWFibGVOYW1lJyk/LnNldFZhbHVlKCRldmVudClcIj5cbiAgICAgIDwvY3FhLWN1c3RvbS1pbnB1dD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLWNvbnRhaW5lcj5cbjxuZy1jb250YWluZXIgKm5nSWY9XCJzZWxlY3RlZFByb2dyZXNzU3RlcCA9PT0gJ3ZhbGlkYXRpb24nXCI+XG4gIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2wgY3FhLWZsZXgtMSBjcWEtbWF4LWgtWzUwMHB4XSBjcWEtb3ZlcmZsb3cteS1hdXRvXCI+XG4gICAgPCEtLSBWYWxpZGF0aW9uIFJ1bGVzIFRpdGxlIC0tPlxuICAgIDxoMyBjbGFzcz1cImNxYS10ZXh0LVsxMnB4XSBjcWEtZm9udC1zZW1pYm9sZCBjcWEtdGV4dC1ibGFjay0xMDAgY3FhLW1iLTRcIj5cbiAgICAgIFZhbGlkYXRpb24gUnVsZXNcbiAgICA8L2gzPlxuXG4gICAgPCEtLSBWYWxpZGF0aW9uIFJ1bGVzIFRhYmxlIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJjcWEtYmctd2hpdGUgY3FhLWJvcmRlciBjcWEtYm9yZGVyLWdyYXktMjAwIGNxYS1yb3VuZGVkLWxnIGNxYS1vdmVyZmxvdy1oaWRkZW4gY3FhLW1iLTRcIj5cbiAgICAgIDwhLS0gVGFibGUgSGVhZGVyIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cImNxYS1ncmlkIGNxYS1ncmlkLWNvbHMtNiBjcWEtZ2FwLTIgY3FhLXAtMyBjcWEtYmctZ3JheS01MCBjcWEtYm9yZGVyLWIgY3FhLWJvcmRlci1ncmF5LTIwMCBjcWEtaXRlbXMtY2VudGVyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgPG1hdC1jaGVja2JveFxuICAgICAgICAgICAgW2NoZWNrZWRdPVwiYWxsVmFsaWRhdGlvblJ1bGVzU2VsZWN0ZWRcIlxuICAgICAgICAgICAgW2luZGV0ZXJtaW5hdGVdPVwic29tZVZhbGlkYXRpb25SdWxlc1NlbGVjdGVkXCJcbiAgICAgICAgICAgIChjaGFuZ2UpPVwib25TZWxlY3RBbGxWYWxpZGF0aW9uUnVsZXMoJGV2ZW50LmNoZWNrZWQpXCI+XG4gICAgICAgICAgPC9tYXQtY2hlY2tib3g+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLXRleHQtWzEwcHhdIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktNzAwIGNxYS11cHBlcmNhc2VcIj5qc29uUGF0aDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLXRleHQtWzEwcHhdIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktNzAwIGNxYS11cHBlcmNhc2VcIj52ZXJpZmljYXRpb25UeXBlPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtdGV4dC1bMTBweF0gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtZ3JheS03MDAgY3FhLXVwcGVyY2FzZVwiPmV4cGVjdGVkVHlwZTwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLXRleHQtWzEwcHhdIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktNzAwIGNxYS11cHBlcmNhc2VcIj5leHBlY3RlZFZhbHVlPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtdGV4dC1bMTBweF0gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtZ3JheS03MDAgY3FhLXVwcGVyY2FzZVwiPlJlc3VsdDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDwhLS0gVGFibGUgQm9keSAtLT5cbiAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtZmxleC1jb2xcIj5cbiAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgdmFsaWRhdGlvblJ1bGUgb2YgdmFsaWRhdGlvbkZvcm1BcnJheS5jb250cm9sczsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogdHJhY2tCeVZhbGlkYXRpb25SdWxlSW5kZXhcIiBcbiAgICAgICAgICAgICBbZm9ybUdyb3VwXT1cImdldFZhbGlkYXRpb25Gb3JtR3JvdXAoaSlcIlxuICAgICAgICAgICAgIGNsYXNzPVwiY3FhLWdyaWQgY3FhLWdyaWQtY29scy02IGNxYS1nYXAtMiBjcWEtcC0zIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLWdyYXktMjAwIGNxYS1pdGVtcy1jZW50ZXIgY3FhLWxhc3Q6Ym9yZGVyLWItMFwiPlxuICAgICAgICAgIDwhLS0gQ2hlY2tib3ggLS0+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgIDxtYXQtY2hlY2tib3ggZm9ybUNvbnRyb2xOYW1lPVwiY2hlY2tlZFwiPlxuICAgICAgICAgICAgPC9tYXQtY2hlY2tib3g+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8IS0tIGpzb25QYXRoIC0tPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8Y3FhLWN1c3RvbS1pbnB1dFxuICAgICAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ2pzb25QYXRoJ1wiXG4gICAgICAgICAgICAgIFt2YWx1ZV09XCJnZXRWYWxpZGF0aW9uRm9ybUdyb3VwKGkpLmdldCgnanNvblBhdGgnKT8udmFsdWUgfHwgJydcIlxuICAgICAgICAgICAgICBbZnVsbFdpZHRoXT1cInRydWVcIlxuICAgICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiZ2V0VmFsaWRhdGlvbkZvcm1Hcm91cChpKS5nZXQoJ2pzb25QYXRoJyk/LnNldFZhbHVlKCRldmVudClcIj5cbiAgICAgICAgICAgIDwvY3FhLWN1c3RvbS1pbnB1dD5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDwhLS0gdmVyaWZpY2F0aW9uVHlwZSAtLT5cbiAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgPGNxYS1keW5hbWljLXNlbGVjdFxuICAgICAgICAgICAgICBbZm9ybV09XCJnZXRWYWxpZGF0aW9uRm9ybUdyb3VwKGkpXCJcbiAgICAgICAgICAgICAgW2NvbmZpZ109XCJnZXRWZXJpZmljYXRpb25UeXBlQ29uZmlnKGkpXCI+XG4gICAgICAgICAgICA8L2NxYS1keW5hbWljLXNlbGVjdD5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDwhLS0gZXhwZWN0ZWRUeXBlIC0tPlxuICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8Y3FhLWR5bmFtaWMtc2VsZWN0XG4gICAgICAgICAgICAgIFtmb3JtXT1cImdldFZhbGlkYXRpb25Gb3JtR3JvdXAoaSlcIlxuICAgICAgICAgICAgICBbY29uZmlnXT1cImdldEV4cGVjdGVkVHlwZUNvbmZpZyhpKVwiPlxuICAgICAgICAgICAgPC9jcWEtZHluYW1pYy1zZWxlY3Q+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8IS0tIGV4cGVjdGVkVmFsdWUgLS0+XG4gICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgIDxjcWEtY3VzdG9tLWlucHV0XG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInZXhwZWN0ZWRWYWx1ZSdcIlxuICAgICAgICAgICAgICBbdmFsdWVdPVwiZ2V0VmFsaWRhdGlvbkZvcm1Hcm91cChpKS5nZXQoJ2V4cGVjdGVkVmFsdWUnKT8udmFsdWUgfHwgJydcIlxuICAgICAgICAgICAgICBbZnVsbFdpZHRoXT1cInRydWVcIlxuICAgICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiZ2V0VmFsaWRhdGlvbkZvcm1Hcm91cChpKS5nZXQoJ2V4cGVjdGVkVmFsdWUnKT8uc2V0VmFsdWUoJGV2ZW50KVwiPlxuICAgICAgICAgICAgPC9jcWEtY3VzdG9tLWlucHV0PlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPCEtLSBSZXN1bHQgYW5kIERlbGV0ZSAtLT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtZ2FwLTJcIj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiY3FhLXB4LTMgY3FhLXB5LTEgY3FhLXJvdW5kZWQgY3FhLXRleHQtWzEwcHhdIGNxYS1mb250LW1lZGl1bVwiXG4gICAgICAgICAgICAgIFtuZ0NsYXNzXT1cImdldFJlc3VsdENsYXNzKGdldFZhbGlkYXRpb25Gb3JtR3JvdXAoaSkuZ2V0KCdyZXN1bHQnKT8udmFsdWUgfHwgJ05vdCBydW4nKVwiPlxuICAgICAgICAgICAgICB7eyBnZXRWYWxpZGF0aW9uRm9ybUdyb3VwKGkpLmdldCgncmVzdWx0Jyk/LnZhbHVlIHx8ICdOb3QgcnVuJyB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICBjbGFzcz1cImNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWp1c3RpZnktY2VudGVyIGNxYS13LTYgY3FhLWgtNiBjcWEtcm91bmRlZCBjcWEtdGV4dC1yZWQtNTAwIGhvdmVyOmNxYS10ZXh0LXJlZC03MDAgaG92ZXI6Y3FhLWJnLXJlZC01MCBjcWEtdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwicmVtb3ZlVmFsaWRhdGlvblJ1bGUoaSlcIlxuICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidEZWxldGUgdmFsaWRhdGlvbiBydWxlJ1wiPlxuICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJjcWEtdGV4dC1iYXNlXCI+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBBZGQgQW5vdGhlciBSdWxlIGFuZCBEZWxldGUgU2VsZWN0ZWQgLS0+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1qdXN0aWZ5LWJldHdlZW4gY3FhLWl0ZW1zLWNlbnRlciBjcWEtbWItNFwiPlxuICAgICAgPGJ1dHRvblxuICAgICAgICAqbmdJZj1cInNvbWVWYWxpZGF0aW9uUnVsZXNTZWxlY3RlZCB8fCBhbGxWYWxpZGF0aW9uUnVsZXNTZWxlY3RlZFwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImNxYS10ZXh0LXJlZC02MDAgY3FhLXRleHQtc20gY3FhLWZvbnQtbWVkaXVtIGNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWdhcC0xIGhvdmVyOmNxYS10ZXh0LXJlZC03MDAgY3FhLXRyYW5zaXRpb24tY29sb3JzXCJcbiAgICAgICAgKGNsaWNrKT1cIm9uRGVsZXRlU2VsZWN0ZWRWYWxpZGF0aW9uUnVsZXMoKVwiPlxuICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJjcWEtdGV4dC1iYXNlXCI+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgICAgPHNwYW4+RGVsZXRlIFNlbGVjdGVkPC9zcGFuPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImNxYS10ZXh0LWJsdWUtNjAwIGNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1nYXAtMSBob3ZlcjpjcWEtdGV4dC1ibHVlLTcwMCBjcWEtdHJhbnNpdGlvbi1jb2xvcnNcIlxuICAgICAgICAoY2xpY2spPVwiYWRkVmFsaWRhdGlvblJ1bGUoKVwiPlxuICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJjcWEtdGV4dC1iYXNlXCI+YWRkPC9tYXQtaWNvbj5cbiAgICAgICAgPHNwYW4+QWRkIEFub3RoZXI8L3NwYW4+XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLWNvbnRhaW5lcj5cblxuXG4gIDwhLS0gUmVzcG9uc2UgUHJldmlldyBTZWN0aW9uIC0tPlxuICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1ib3JkZXIgY3FhLWJvcmRlci1ncmF5LTIwMCBjcWEtcm91bmRlZC1sZyBjcWEtb3ZlcmZsb3ctaGlkZGVuIGNxYS1tYi02XCI+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1wLTMgY3FhLWJnLWdyYXktNTAgY3FhLWJvcmRlci1iIGNxYS1ib3JkZXItZ3JheS0yMDBcIj5cbiAgICAgIDxoMyBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktOTAwXCI+UmVzcG9uc2UgUHJldmlldzwvaDM+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1wLTQgY3FhLWJnLWdyYXktNTAgY3FhLW92ZXJmbG93LWF1dG9cIiBzdHlsZT1cIm1heC1oZWlnaHQ6IDMwMHB4O1wiPlxuICAgICAgPHByZSAqbmdJZj1cInJlc3BvbnNlUHJldmlld1wiIGNsYXNzPVwiY3FhLXRleHQteHMgY3FhLWZvbnQtbW9ubyBjcWEtdGV4dC1ncmF5LTgwMCBjcWEtd2hpdGVzcGFjZS1wcmUtd3JhcFwiPnt7IGZvcm1hdEpzb25SZXNwb25zZShyZXNwb25zZVByZXZpZXcpIH19PC9wcmU+XG4gICAgICA8cCAqbmdJZj1cIiFyZXNwb25zZVByZXZpZXdcIiBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS10ZXh0LWdyYXktNDAwIGNxYS10ZXh0LWNlbnRlciBjcWEtcHktOFwiPlxuICAgICAgICBObyByZXNwb25zZSB5ZXQuIFNlbmQgYSByZXF1ZXN0IHRvIHNlZSB0aGUgcmVzcG9uc2UgcHJldmlldy5cbiAgICAgIDwvcD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDwhLS0gQWN0aW9uIEJ1dHRvbnMgLS0+XG4gIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtdy1mdWxsIGNxYS1nYXAtMiBjcWEtbXQtYXV0byBjcWEtcHQtNCBjcWEtYm9yZGVyLXQgY3FhLWJvcmRlci1ncmF5LTIwMFwiPlxuICAgIDwhLS0gQ2FuY2VsIGJ1dHRvbiAob25seSBvbiBmaXJzdCBzdGVwKSAtLT5cbiAgICA8Y3FhLWJ1dHRvblxuICAgICAgKm5nSWY9XCJzZWxlY3RlZFByb2dyZXNzU3RlcCA9PT0gJ3JlcXVlc3QtZGV0YWlscydcIlxuICAgICAgY2xhc3M9XCJjcWEtdy0xLzJcIlxuICAgICAgdmFyaWFudD1cIm91dGxpbmVkXCJcbiAgICAgIHRleHQ9XCJDYW5jZWxcIlxuICAgICAgW2N1c3RvbUNsYXNzXT1cIidjcWEtZmxleC0xIGNxYS13LWZ1bGwnXCJcbiAgICAgIChjbGlja2VkKT1cIm9uQ2FuY2VsKClcIj5cbiAgICA8L2NxYS1idXR0b24+XG4gICAgPCEtLSBCYWNrIGJ1dHRvbiAob24gYWxsIHN0ZXBzIGV4Y2VwdCBmaXJzdCkgLS0+XG4gICAgPGNxYS1idXR0b25cbiAgICAgICpuZ0lmPVwic2VsZWN0ZWRQcm9ncmVzc1N0ZXAgIT09ICdyZXF1ZXN0LWRldGFpbHMnXCJcbiAgICAgIGNsYXNzPVwiY3FhLXctMS8yXCJcbiAgICAgIHZhcmlhbnQ9XCJvdXRsaW5lZFwiXG4gICAgICB0ZXh0PVwiQmFja1wiXG4gICAgICBbY3VzdG9tQ2xhc3NdPVwiJ2NxYS1mbGV4LTEgY3FhLXctZnVsbCdcIlxuICAgICAgKGNsaWNrZWQpPVwib25CYWNrKClcIj5cbiAgICA8L2NxYS1idXR0b24+XG4gICAgPCEtLSBOZXh0L0NyZWF0ZSBTdGVwIGJ1dHRvbiAtLT5cbiAgICA8Y3FhLWJ1dHRvblxuICAgICAgY2xhc3M9XCJjcWEtdy0xLzJcIlxuICAgICAgdmFyaWFudD1cImZpbGxlZFwiXG4gICAgICBbdGV4dF09XCJpc0xhc3RTdGVwKCkgPyAnQ3JlYXRlIFN0ZXAnIDogJ05leHQnXCJcbiAgICAgIFtjdXN0b21DbGFzc109XCInY3FhLWZsZXgtMSBjcWEtdy1mdWxsJ1wiXG4gICAgICAoY2xpY2tlZCk9XCJpc0xhc3RTdGVwKCkgPyBvbkNyZWF0ZVN0ZXAoKSA6IG9uTmV4dCgpXCI+XG4gICAgPC9jcWEtYnV0dG9uPlxuICA8L2Rpdj5cbjwvZGl2PlxuXG4iXX0=