@davebaol/angular-formio-editor
Version:
Angular component integrating Form.io builder and renderer with a json editor
241 lines • 43.4 kB
JavaScript
import { __decorate } from "tslib";
import { Component, ViewChild, Input } from '@angular/core';
import { BsModalService, BsModalRef } from 'ngx-bootstrap/modal';
import { merge, clone } from './clone-utils';
import { generateFormJsonSchema } from './resource-json-schema/json-schema-generator';
import { loose as formioJsonSchema } from './formio-json-schema';
var defaultJsonEditorOptions = {
enableSort: true,
enableTransform: true,
escapeUnicode: false,
expandAll: false,
history: true,
indentation: 2,
limitDragging: false,
mode: 'view',
modes: ['code', 'tree', 'view'],
schema: formioJsonSchema.schema,
schemaRefs: formioJsonSchema.schemaRefs,
search: true,
sortObjectKeys: false
};
var defaultRendererResourceJsonEditorOptions = merge(defaultJsonEditorOptions, {
mode: 'tree',
modes: ['code', 'tree'],
schema: undefined,
schemaRefs: undefined
});
var defaultRendererSchemaJsonEditorOptions = clone(defaultRendererResourceJsonEditorOptions);
var FormioEditorComponent = /** @class */ (function () {
function FormioEditorComponent(modalService) {
this.modalService = modalService;
this.builderDisplayChanged = false;
this.jsonEditorChanged = false;
// tslint:disable-next-line:variable-name
this._jsonEditorErrors = [];
this.jsonEditorWarningCounter = 0;
}
Object.defineProperty(FormioEditorComponent.prototype, "options", {
get: function () { return this._options; },
set: function (options) { this.setOptions(options); },
enumerable: true,
configurable: true
});
Object.defineProperty(FormioEditorComponent.prototype, "activeTab", {
get: function () { return this._activeTab; },
set: function (tab) {
this._activeTab = tab;
if (tab === 'renderer') {
this.submissionPanel = false; // Disable submission panel when the renderer tab becomes active
}
},
enumerable: true,
configurable: true
});
Object.defineProperty(FormioEditorComponent.prototype, "jsonEditorErrors", {
get: function () {
return this._jsonEditorErrors;
},
set: function (errors) {
var _this = this;
this._jsonEditorErrors = errors;
this.jsonEditorWarningCounter = 0;
errors.forEach(function (error) {
if (error.type === 'validation') {
_this.jsonEditorWarningCounter++;
}
});
},
enumerable: true,
configurable: true
});
FormioEditorComponent.prototype.ngOnInit = function () {
var _this = this;
if (!this.options) {
this.setOptions(); // Set default options
}
this.activeTab = ['builder', 'json', 'renderer']
.find(function (t) { var _a; return _this.options && ((_a = _this.options[t]) === null || _a === void 0 ? void 0 : _a.defaultTab) ? t : undefined; }) || 'builder';
if (this.reset) {
this.resetSubscription = this.reset.subscribe(function () { return _this.resetFormBuilder(); });
}
};
FormioEditorComponent.prototype.ngAfterViewInit = function () {
this.refreshJsonEditor();
};
FormioEditorComponent.prototype.ngOnDestroy = function () {
if (this.resetSubscription) {
this.resetSubscription.unsubscribe();
}
};
FormioEditorComponent.prototype.setOptions = function (options) {
if (options === void 0) { options = {}; }
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
this._options = options;
this.jsonEditorOptions = merge(defaultJsonEditorOptions, (_b = (_a = options === null || options === void 0 ? void 0 : options.json) === null || _a === void 0 ? void 0 : _a.input) === null || _b === void 0 ? void 0 : _b.options);
this.rendererResourceJsonEditorOptions = merge(defaultRendererResourceJsonEditorOptions, (_f = (_e = (_d = (_c = options === null || options === void 0 ? void 0 : options.renderer) === null || _c === void 0 ? void 0 : _c.submissionPanel) === null || _d === void 0 ? void 0 : _d.resourceJsonEditor) === null || _e === void 0 ? void 0 : _e.input) === null || _f === void 0 ? void 0 : _f.options);
this.rendererSchemaJsonEditorOptions = merge(defaultRendererSchemaJsonEditorOptions, (_k = (_j = (_h = (_g = options === null || options === void 0 ? void 0 : options.renderer) === null || _g === void 0 ? void 0 : _g.submissionPanel) === null || _h === void 0 ? void 0 : _h.schemaJsonEditor) === null || _j === void 0 ? void 0 : _j.input) === null || _k === void 0 ? void 0 : _k.options);
this.fullSubmission = (_m = (_l = options === null || options === void 0 ? void 0 : options.renderer) === null || _l === void 0 ? void 0 : _l.submissionPanel) === null || _m === void 0 ? void 0 : _m.fullSubmission;
};
//
// Form Builder Tab
//
FormioEditorComponent.prototype.resetFormBuilder = function (fromJsonEditor) {
var _this = this;
if (fromJsonEditor === void 0) { fromJsonEditor = false; }
console.log('resetFormBuilder');
// Here we have to reset builder component through *ngIf="!builderDisplayChanged"
// See https://github.com/formio/angular-formio/issues/172#issuecomment-401876490
this.builderDisplayChanged = true;
setTimeout(function () {
_this.builderDisplayChanged = false;
if (!fromJsonEditor) {
_this.refreshJsonEditor(true);
}
_this.resetFormRendererIfActive();
});
};
FormioEditorComponent.prototype.onBuilderDiplayChange = function (event) {
console.log('onBuilderDiplayChange');
this.resetFormBuilder();
};
FormioEditorComponent.prototype.onBuilderChange = function (event) {
console.log('onBuilderChange: event', event);
this.refreshJsonEditor(true);
};
//
// JSON Tab
//
FormioEditorComponent.prototype.onJsonEditorError = function (errors) {
console.log('onJsonEditorError: found', errors.length, 'validation errors:');
this.jsonEditorErrors = errors;
};
FormioEditorComponent.prototype.onJsonEditorChange = function (event) {
console.log('onJsonEditorChange');
this.jsonEditorChanged = true;
};
FormioEditorComponent.prototype.onJsonEditorApply = function (template) {
console.log('Errors: ', this.jsonEditorErrors.length - this.jsonEditorWarningCounter, 'Warnings: ', this.jsonEditorWarningCounter);
if (this.jsonEditorWarningCounter === 0) {
this.jsonEditorApplyChanges();
}
else {
this.modalRef = this.modalService.show(template);
}
};
FormioEditorComponent.prototype.jsonEditorApplyChanges = function () {
var _this = this;
console.log('jsonEditorApplyChanges');
this.jsonEditorChanged = false;
// Remove all properties from this form
// then copy the properties of the edited json to this form
// and reset the builder
Object.getOwnPropertyNames(this.form).forEach(function (p) { return delete _this.form[p]; });
Object.assign(this.form, this.jsonEditor.get());
this.resetFormBuilder(true);
};
FormioEditorComponent.prototype.jsonEditorDiscardChanges = function () {
console.log('jsonEditorDiscardChanges');
this.refreshJsonEditor();
};
FormioEditorComponent.prototype.refreshJsonEditor = function (forceReset) {
if (forceReset === void 0) { forceReset = false; }
console.log('refreshJsonEditor');
if (forceReset) {
this.jsonEditor.reset(true);
}
// Here we use update instead of set to preserve the editor status
this.jsonEditor.update(this.form);
this.jsonEditorChanged = false;
};
//
// Form Renderer Tab
//
FormioEditorComponent.prototype.resetFormRendererIfActive = function () {
var _this = this;
console.log('resetFormRenderer');
// Here we recreate the renderer component through *ngIf="activeTab='renderer'"
// by changing the active tab and then restoring it.
// Although this is a rather dirty hack it is hardly noticeable to the eye :)
if (this.activeTab === 'renderer') {
this.activeTab = 'builder';
setTimeout(function () { _this.activeTab = 'renderer'; });
}
};
FormioEditorComponent.prototype.showSubmissionPanel = function (submission) {
var _this = this;
var _a, _b;
this.submissionPanel = !((_b = (_a = this.options.renderer) === null || _a === void 0 ? void 0 : _a.submissionPanel) === null || _b === void 0 ? void 0 : _b.disabled);
if (this.submissionPanel) {
if (submission) {
this.submission = submission;
}
setTimeout(function () {
var schema = generateFormJsonSchema(_this.form);
if (_this.fullSubmission) {
schema = { type: 'object', properties: { data: schema } };
}
_this.rendererResourceJsonEditor.setSchema(undefined);
_this.rendererResourceJsonEditor.set(_this.fullSubmission ? _this.submission : _this.submission.data);
_this.rendererSchemaJsonEditor.set(schema);
_this.rendererResourceJsonEditor.setSchema(schema);
});
}
};
FormioEditorComponent.prototype.applyResourceJsonSchema = function () {
var schema = this.rendererSchemaJsonEditor.get();
this.rendererResourceJsonEditor.setSchema(schema);
};
FormioEditorComponent.ctorParameters = function () { return [
{ type: BsModalService }
]; };
__decorate([
Input()
], FormioEditorComponent.prototype, "form", void 0);
__decorate([
Input()
], FormioEditorComponent.prototype, "reset", void 0);
__decorate([
Input()
], FormioEditorComponent.prototype, "options", null);
__decorate([
ViewChild('jsoneditor', { static: true })
], FormioEditorComponent.prototype, "jsonEditor", void 0);
__decorate([
ViewChild('renderer_resource_jsoneditor', { static: false })
], FormioEditorComponent.prototype, "rendererResourceJsonEditor", void 0);
__decorate([
ViewChild('renderer_schema_jsoneditor', { static: false })
], FormioEditorComponent.prototype, "rendererSchemaJsonEditor", void 0);
FormioEditorComponent = __decorate([
Component({
// tslint:disable-next-line:component-selector
selector: 'formio-editor',
template: "<!-- Modal -->\r\n<ng-template #saveModal class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"saveModalLabel\" aria-hidden=\"true\">\r\n\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title\" id=\"exampleModalLabel\">Validation warning</h5>\r\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"modalRef.hide()\">\r\n <span aria-hidden=\"true\">×</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n Looks like the json is not a valid form.\r\n Do you want to apply changes anyways?\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\" (click)=\"modalRef.hide();\">NO</button>\r\n <button type=\"button\" class=\"btn btn-primary\" data-dismiss=\"modal\" (click)=\"modalRef.hide(); jsonEditorApplyChanges()\">YES</button>\r\n </div>\r\n</ng-template>\r\n<ul class=\"nav nav-tabs\" id=\"myTab\" role=\"tablist\">\r\n <li class=\"nav-item\" *ngIf=\"options?.builder?.hideTab !== true\">\r\n <span class=\"nav-link\" [ngClass]=\"{'active':activeTab=='builder'}\" (click)=\"activeTab='builder'\"\r\n id=\"builder-tab\" data-toggle=\"tab\" data-target=\"#builder\" role=\"tab\" aria-controls=\"builder\" aria-selected=\"true\">\r\n Builder\r\n </span>\r\n </li>\r\n <li class=\"nav-item\" *ngIf=\"options?.json?.hideTab !== true\">\r\n <span class=\"nav-link\" [ngClass]=\"{'active':activeTab=='json'}\" (click)=\"activeTab='json'\"\r\n id=\"json-editor-tab\" data-toggle=\"tab\" data-target=\"#json-editor\" role=\"tab\" aria-controls=\"json-editor\"\r\n aria-selected=\"false\">\r\n Json\r\n </span>\r\n </li>\r\n <li class=\"nav-item\" *ngIf=\"options?.renderer?.hideTab !== true\">\r\n <span class=\"nav-link\" [ngClass]=\"{'active':activeTab=='renderer'}\" (click)=\"activeTab='renderer'\"\r\n id=\"renderer-tab\" data-toggle=\"tab\" data-target=\"#renderer\" role=\"tab\" aria-controls=\"renderer\" aria-selected=\"false\">\r\n Renderer\r\n </span>\r\n </li>\r\n</ul>\r\n<div class=\"tab-content\" id=\"myTabContent\">\r\n <div class=\"tab-pane fade\" [ngClass]=\"{'show active':activeTab=='builder'}\" id=\"builder\" role=\"tabpanel\" aria-labelledby=\"builder-tab\">\r\n <div class=\"m-2\">\r\n <div *ngIf=\"options?.builder?.hideDisplaySelect !== true\">\r\n <label for=\"form-display-select\" class=\"mx-2\">Display as: </label>\r\n <select id=\"form-display-select\" class=\"form-control my-2\" style=\"display: inline-block; width: 150px;\"\r\n [(ngModel)]=\"form.display\" (ngModelChange)=\"onBuilderDiplayChange($event)\">\r\n <option value=\"form\">Form</option>\r\n <option value=\"wizard\">Wizard</option>\r\n </select>\r\n </div>\r\n <form-builder *ngIf=\"!builderDisplayChanged\" [form]=\"form\"\r\n [options]=\"options?.builder?.input?.options\"\r\n [formbuilder]=\"options?.builder?.input?.formbuilder\"\r\n [noeval]=\"options?.builder?.input?.noeval\"\r\n [refresh]=\"options?.builder?.input?.refresh\"\r\n (change)=\"onBuilderChange($event); options?.builder?.output?.change ? options.builder.output.change($event) : undefined\"\r\n ></form-builder>\r\n </div>\r\n </div>\r\n <div class=\"tab-pane fade\" [ngClass]=\"{'show active':activeTab=='json'}\" id=\"json-editor\" role=\"tabpanel\" aria-labelledby=\"json-editor-tab\">\r\n <div class=\"m-2 well\">\r\n <div class=\"row mx-0\" *ngIf=\"!options?.json?.changePanelLocations || options.json.changePanelLocations?.includes('top')\">\r\n <div class=\"m-2 p-0\">\r\n <button type=\"button\" class=\"btn btn-success mr-4\" (click)=\"onJsonEditorApply(saveModal)\"\r\n [disabled]=\"!jsonEditorChanged || jsonEditorErrors.length !== jsonEditorWarningCounter\">\r\n Apply\r\n </button>\r\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"jsonEditorDiscardChanges()\">Discard</button>\r\n </div>\r\n <alert class=\"col-6 mx-4 m-2 p-0\" type=\"danger\" [isOpen]=\"jsonEditorErrors.length !== jsonEditorWarningCounter\" >\r\n Cannot apply changes. Json is not well-formed.\r\n </alert>\r\n </div>\r\n <json-editor #jsoneditor \r\n [options]=\"jsonEditorOptions\"\r\n (dataChange)=\"onJsonEditorChange($event); options?.json?.output?.dataChange ? options.json.output.dataChange($event) : undefined\"\r\n (dataError)=\"onJsonEditorError($event); options?.json?.output?.dataError ? options.json.output.dataError($event) : undefined\"\r\n ></json-editor>\r\n <div class=\"row mx-0\" *ngIf=\"!options?.json?.changePanelLocations || options.json.changePanelLocations?.includes('bottom')\">\r\n <div class=\"m-2 p-0\">\r\n <button type=\"button\" class=\"btn btn-success mr-4\" (click)=\"onJsonEditorApply(saveModal)\"\r\n [disabled]=\"!jsonEditorChanged || jsonEditorErrors.length !== jsonEditorWarningCounter\">\r\n Apply\r\n </button>\r\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"jsonEditorDiscardChanges()\">Discard</button>\r\n </div>\r\n <alert class=\"col-6 mx-4 my-2 p-1 align-middle\" type=\"danger\" [isOpen]=\"jsonEditorErrors.length !== jsonEditorWarningCounter\" >\r\n Json is not well-formed. You won't be able to apply changes!\r\n </alert>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"tab-pane fade\" [ngClass]=\"{'show active':activeTab=='renderer'}\" id=\"renderer\" role=\"tabpanel\" aria-labelledby=\"renderer-tab\">\r\n <div class=\"m-2\">\r\n <formio *ngIf=\"activeTab=='renderer'\" [form]=\"form\"\r\n [submission]=\"options?.renderer?.input?.submission\"\r\n [src]=\"options?.renderer?.input?.src\"\r\n [url]=\"options?.renderer?.input?.url\"\r\n [service]=\"options?.renderer?.input?.service\"\r\n [options]=\"options?.renderer?.input?.options\"\r\n [noeval]=\"options?.renderer?.input?.noeval\"\r\n [formioOptions]=\"options?.renderer?.input?.formioOptions\"\r\n [renderOptions]=\"options?.renderer?.input?.renderOptions\"\r\n [readOnly]=\"options?.renderer?.input?.readOnly\"\r\n [viewOnly]=\"options?.renderer?.input?.viewOnly\"\r\n [hideComponents]=\"options?.renderer?.input?.hideComponents\"\r\n [refresh]=\"options?.renderer?.input?.refresh\"\r\n [success]=\"options?.renderer?.input?.success\"\r\n [language]=\"options?.renderer?.input?.language\"\r\n [hooks]=\"options?.renderer?.input?.hooks\"\r\n [renderer]=\"options?.renderer?.input?.renderer\"\r\n (render)=\"options?.renderer?.output?.render ? options.renderer.output.render($event) : undefined\"\r\n (customEvent)=\"options?.renderer?.output?.customEvent ? options.renderer.output.customEvent($event) : undefined\"\r\n (submit)=\"options?.renderer?.output?.submit ? options.renderer.output.submit($event) : undefined\"\r\n (prevPage)=\"options?.renderer?.output?.prevPage ? options.renderer.output.prevPage($event) : undefined\"\r\n (nextPage)=\"options?.renderer?.output?.nextPage ? options.renderer.output.nextPage($event) : undefined\"\r\n (beforeSubmit)=\"showSubmissionPanel($event); options?.renderer?.output?.beforeSubmit ? options.renderer.output.beforeSubmit($event) : undefined\"\r\n (change)=\"options?.renderer?.output?.change ? options.renderer.output.change($event) : undefined\"\r\n (invalid)=\"options?.renderer?.output?.invalid ? options.renderer.output.invalid($event) : undefined\"\r\n (errorChange)=\"options?.renderer?.output?.errorChange ? options.renderer.output.errorChange($event) : undefined\"\r\n (formLoad)=\"options?.renderer?.output?.formLoad ? options.renderer.output.formLoad($event) : undefined\"\r\n (submissionLoad)=\"options?.renderer?.output?.submissionLoad ? options.renderer.output.submissionLoad($event) : undefined\"\r\n (ready)=\"options?.renderer?.output?.ready ? options.renderer.output.ready($event) : undefined\"\r\n ></formio>\r\n </div>\r\n <div *ngIf=\"submissionPanel\" class=\"m-2 border-top border-primary\">\r\n <div class=\"row mx-0\">\r\n <div class=\"p-2\" [ngClass]=\"{'col-6':showResourceSchema,'col-12':!showResourceSchema}\">\r\n <p class=\"font-weight-bold text-center mb-1\">\r\n Summission (\r\n <label for=\"fullSubmitCheckbox\" class=\"my-0\">full</label>\r\n <input id=\"fullSubmitCheckbox\" class=\"mx-1\" type=\"checkbox\" [(ngModel)]=\"fullSubmission\" (change)=\"showSubmissionPanel(submission)\">\r\n )\r\n </p>\r\n <json-editor #renderer_resource_jsoneditor\r\n [options]=\"rendererResourceJsonEditorOptions\"\r\n (dataChange)=\"options?.renderer?.submissionPanel?.resourceJsonEditor?.output?.dataChange ? options.renderer.submissionPanel.resourceJsonEditor.output.dataChange($event) : undefined\"\r\n (dataError)=\"options?.renderer?.submissionPanel?.resourceJsonEditor?.output?.dataError ? options.renderer.submissionPanel.resourceJsonEditor.output.dataError($event) : undefined\"\r\n ></json-editor>\r\n </div>\r\n <div class=\"p-2 col-6\" [hidden]=!showResourceSchema>\r\n <p class=\"font-weight-bold text-center mb-1\">Json Schema Validator</p>\r\n <json-editor #renderer_schema_jsoneditor\r\n [options]=\"rendererSchemaJsonEditorOptions\"\r\n (dataChange)=\"options?.renderer?.submissionPanel?.schemaJsonEditor?.output?.dataChange ? options.renderer.submissionPanel.schemaJsonEditor.output.dataChange($event) : undefined\"\r\n (dataError)=\"options?.renderer?.submissionPanel?.schemaJsonEditor?.output?.dataError ? options.renderer.submissionPanel.schemaJsonEditor.output.dataError($event) : undefined\"\r\n ></json-editor>\r\n </div>\r\n </div>\r\n <button class=\"mx-3 btn btn-primary\" *ngIf=\"options?.renderer?.submissionPanel?.schemaJsonEditor?.enabled\" (click)=\"showResourceSchema = !showResourceSchema\">{{showResourceSchema? 'Hide Schema' : 'Show Schema'}}</button>\r\n <button class=\"mx-2 btn btn-primary\" *ngIf=\"options?.renderer?.submissionPanel?.schemaJsonEditor?.enabled && showResourceSchema\" (click)=\"applyResourceJsonSchema()\">Apply Schema</button>\r\n <button class=\"mx-2 btn btn-primary\" *ngIf=\"options?.renderer?.submissionPanel?.schemaJsonEditor?.enabled && showResourceSchema\" (click)=\"showSubmissionPanel(submission)\">Regenerate Schema</button>\r\n </div>\r\n </div>\r\n</div>\r\n",
styles: [""]
})
], FormioEditorComponent);
return FormioEditorComponent;
}());
export { FormioEditorComponent };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWlvLWVkaXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AZGF2ZWJhb2wvYW5ndWxhci1mb3JtaW8tZWRpdG9yLyIsInNvdXJjZXMiOlsibGliL2Zvcm1pby1lZGl0b3IuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQWlCLFNBQVMsRUFBVSxTQUFTLEVBQUUsS0FBSyxFQUF5QixNQUFNLGVBQWUsQ0FBQztBQUUxRyxPQUFPLEVBQUUsY0FBYyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBSWpFLE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQ3RGLE9BQU8sRUFBRSxLQUFLLElBQUksZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVqRSxJQUFNLHdCQUF3QixHQUFzQjtJQUNsRCxVQUFVLEVBQUUsSUFBSTtJQUNoQixlQUFlLEVBQUUsSUFBSTtJQUNyQixhQUFhLEVBQUUsS0FBSztJQUNwQixTQUFTLEVBQUUsS0FBSztJQUNoQixPQUFPLEVBQUUsSUFBSTtJQUNiLFdBQVcsRUFBRSxDQUFDO0lBQ2QsYUFBYSxFQUFFLEtBQUs7SUFDcEIsSUFBSSxFQUFFLE1BQU07SUFDWixLQUFLLEVBQUUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQztJQUMvQixNQUFNLEVBQUUsZ0JBQWdCLENBQUMsTUFBTTtJQUMvQixVQUFVLEVBQUUsZ0JBQWdCLENBQUMsVUFBVTtJQUN2QyxNQUFNLEVBQUUsSUFBSTtJQUNaLGNBQWMsRUFBRSxLQUFLO0NBQ3RCLENBQUM7QUFFRixJQUFNLHdDQUF3QyxHQUFzQixLQUFLLENBQUMsd0JBQXdCLEVBQUU7SUFDbEcsSUFBSSxFQUFFLE1BQU07SUFDWixLQUFLLEVBQUUsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFD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Q0FBQyxDQUFDLENBQUM7U0FDSjtJQUNILENBQUM7SUFDRCx1REFBdUIsR0FBdkI7UUFDRSxJQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDbkQsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwRCxDQUFDOztnQkE1SmlDLGNBQWM7O0lBcER2QztRQUFSLEtBQUssRUFBRTt1REFBVztJQUdWO1FBQVIsS0FBSyxFQUFFO3dEQUEwQjtJQU16QjtRQUFSLEtBQUssRUFBRTt3REFBd0U7SUFHdkM7UUFBeEMsU0FBUyxDQUFDLFlBQVksRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUMsQ0FBQzs2REFBaUM7SUFFYjtRQUEzRCxTQUFTLENBQUMsOEJBQThCLEVBQUUsRUFBQyxNQUFNLEVBQUUsS0FBSyxFQUFDLENBQUM7NkVBQWlEO0lBQ2xEO1FBQXpELFNBQVMsQ0FBQyw0QkFBNEIsRUFBRSxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUMsQ0FBQzsyRUFBK0M7SUFoQjdGLHFCQUFxQjtRQU5qQyxTQUFTLENBQUM7WUFDVCw4Q0FBOEM7WUFDOUMsUUFBUSxFQUFFLGVBQWU7WUFDekIsK2xWQUE2Qzs7U0FFOUMsQ0FBQztPQUNXLHFCQUFxQixDQWtOakM7SUFBRCw0QkFBQztDQUFBLEFBbE5ELElBa05DO1NBbE5ZLHFCQUFxQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENvbXBvbmVudCwgT25Jbml0LCBWaWV3Q2hpbGQsIElucHV0LCBUZW1wbGF0ZVJlZiwgT25EZXN0cm95fSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IEJzTW9kYWxTZXJ2aWNlLCBCc01vZGFsUmVmIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9tb2RhbCc7XHJcbmltcG9ydCB7IEZvcm1pb0VkaXRvck9wdGlvbnMsIEZvcm1pb0VkaXRvclRhYiB9IGZyb20gJy4vZm9ybWlvLWVkaXRvci1vcHRpb25zJztcclxuaW1wb3J0IHsgSnNvbkVkaXRvckNvbXBvbmVudCB9IGZyb20gJy4vanNvbi1lZGl0b3IvanNvbi1lZGl0b3IuY29tcG9uZW50JztcclxuaW1wb3J0IHsgSnNvbkVkaXRvclZhbGlkYXRpb25FcnJvciwgSnNvbkVkaXRvck9wdGlvbnMgfSBmcm9tICcuL2pzb24tZWRpdG9yL2pzb24tZWRpdG9yLXNoYXBlcyc7XHJcbmltcG9ydCB7IG1lcmdlLCBjbG9uZSB9IGZyb20gJy4vY2xvbmUtdXRpbHMnO1xyXG5pbXBvcnQgeyBnZW5lcmF0ZUZvcm1Kc29uU2NoZW1hIH0gZnJvbSAnLi9yZXNvdXJjZS1qc29uLXNjaGVtYS9qc29uLXNjaGVtYS1nZW5lcmF0b3InO1xyXG5pbXBvcnQgeyBsb29zZSBhcyBmb3JtaW9Kc29uU2NoZW1hIH0gZnJvbSAnLi9mb3JtaW8tanNvbi1zY2hlbWEnO1xyXG5cclxuY29uc3QgZGVmYXVsdEpzb25FZGl0b3JPcHRpb25zOiBKc29uRWRpdG9yT3B0aW9ucyA9IHtcclxuICBlbmFibGVTb3J0OiB0cnVlLFxyXG4gIGVuYWJsZVRyYW5zZm9ybTogdHJ1ZSxcclxuICBlc2NhcGVVbmljb2RlOiBmYWxzZSxcclxuICBleHBhbmRBbGw6IGZhbHNlLFxyXG4gIGhpc3Rvcnk6IHRydWUsXHJcbiAgaW5kZW50YXRpb246IDIsXHJcbiAgbGltaXREcmFnZ2luZzogZmFsc2UsXHJcbiAgbW9kZTogJ3ZpZXcnLCAvLyBzZXQgZGVmYXVsdCBtb2RlXHJcbiAgbW9kZXM6IFsnY29kZScsICd0cmVlJywgJ3ZpZXcnXSwgLy8gc2V0IGFsbG93ZWQgbW9kZXNcclxuICBzY2hlbWE6IGZvcm1pb0pzb25TY2hlbWEuc2NoZW1hLFxyXG4gIHNjaGVtYVJlZnM6IGZvcm1pb0pzb25TY2hlbWEuc2NoZW1hUmVmcyxcclxuICBzZWFyY2g6IHRydWUsXHJcbiAgc29ydE9iamVjdEtleXM6IGZhbHNlXHJcbn07XHJcblxyXG5jb25zdCBkZWZhdWx0UmVuZGVyZXJSZXNvdXJjZUpzb25FZGl0b3JPcHRpb25zOiBKc29uRWRpdG9yT3B0aW9ucyA9IG1lcmdlKGRlZmF1bHRKc29uRWRpdG9yT3B0aW9ucywge1xyXG4gIG1vZGU6ICd0cmVlJywgLy8gc2V0IGRlZmF1bHQgbW9kZVxyXG4gIG1vZGVzOiBbJ2NvZGUnLCAndHJlZSddLCAvLyBzZXQgYWxsb3dlZCBtb2Rlc1xyXG4gIHNjaGVtYTogdW5kZWZpbmVkLFxyXG4gIHNjaGVtYVJlZnM6IHVuZGVmaW5lZFxyXG59KTtcclxuXHJcbmNvbnN0IGRlZmF1bHRSZW5kZXJlclNjaGVtYUpzb25FZGl0b3JPcHRpb25zOiBKc29uRWRpdG9yT3B0aW9ucyA9IGNsb25lKGRlZmF1bHRSZW5kZXJlclJlc291cmNlSnNvbkVkaXRvck9wdGlvbnMpO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOmNvbXBvbmVudC1zZWxlY3RvclxyXG4gIHNlbGVjdG9yOiAnZm9ybWlvLWVkaXRvcicsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2Zvcm1pby1lZGl0b3IuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2Zvcm1pby1lZGl0b3IuY29tcG9uZW50LmNzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBGb3JtaW9FZGl0b3JDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSAge1xyXG4gIEBJbnB1dCgpIGZvcm06IGFueTtcclxuICBidWlsZGVyRGlzcGxheUNoYW5nZWQgPSBmYWxzZTtcclxuXHJcbiAgQElucHV0KCkgcmVzZXQ/OiBPYnNlcnZhYmxlPHZvaWQ+O1xyXG4gIHByaXZhdGUgcmVzZXRTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnZhcmlhYmxlLW5hbWVcclxuICBwcml2YXRlIF9vcHRpb25zOiBGb3JtaW9FZGl0b3JPcHRpb25zO1xyXG4gIGdldCBvcHRpb25zKCkgeyByZXR1cm4gdGhpcy5fb3B0aW9uczsgfVxyXG4gIEBJbnB1dCgpIHNldCBvcHRpb25zKG9wdGlvbnM6IEZvcm1pb0VkaXRvck9wdGlvbnMpIHsgdGhpcy5zZXRPcHRpb25zKG9wdGlvbnMpOyB9XHJcbiAganNvbkVkaXRvck9wdGlvbnM6IEpzb25FZGl0b3JPcHRpb25zO1xyXG4gIGpzb25FZGl0b3JDaGFuZ2VkID0gZmFsc2U7XHJcbiAgQFZpZXdDaGlsZCgnanNvbmVkaXRvcicsIHtzdGF0aWM6IHRydWV9KSBqc29uRWRpdG9yOiBKc29uRWRpdG9yQ29tcG9uZW50O1xyXG5cclxuICBAVmlld0NoaWxkKCdyZW5kZXJlcl9yZXNvdXJjZV9qc29uZWRpdG9yJywge3N0YXRpYzogZmFsc2V9KSByZW5kZXJlclJlc291cmNlSnNvbkVkaXRvcjogSnNvbkVkaXRvckNvbXBvbmVudDtcclxuICBAVmlld0NoaWxkKCdyZW5kZXJlcl9zY2hlbWFfanNvbmVkaXRvcicsIHtzdGF0aWM6IGZhbHNlfSkgcmVuZGVyZXJTY2hlbWFKc29uRWRpdG9yOiBKc29uRWRpdG9yQ29tcG9uZW50O1xyXG4gIHJlbmRlcmVyUmVzb3VyY2VKc29uRWRpdG9yT3B0aW9uczogSnNvbkVkaXRvck9wdGlvbnM7XHJcbiAgcmVuZGVyZXJTY2hlbWFKc29uRWRpdG9yT3B0aW9uczogSnNvbkVkaXRvck9wdGlvbnM7XHJcbiAgc3VibWlzc2lvblBhbmVsOiBib29sZWFuO1xyXG4gIHNob3dSZXNvdXJjZVNjaGVtYTogYm9vbGVhbjtcclxuICBzdWJtaXNzaW9uOiBhbnk7XHJcbiAgZnVsbFN1Ym1pc3Npb246IGJvb2xlYW47XHJcblxyXG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTp2YXJpYWJsZS1uYW1lXHJcbiAgcHJpdmF0ZSBfYWN0aXZlVGFiOiBGb3JtaW9FZGl0b3JUYWI7XHJcbiAgZ2V0IGFjdGl2ZVRhYigpIHsgcmV0dXJuIHRoaXMuX2FjdGl2ZVRhYjsgfVxyXG4gIHNldCBhY3RpdmVUYWIodGFiOiBGb3JtaW9FZGl0b3JUYWIpIHtcclxuICAgIHRoaXMuX2FjdGl2ZVRhYiA9IHRhYjtcclxuICAgIGlmICh0YWIgPT09ICdyZW5kZXJlcicpIHtcclxuICAgICAgdGhpcy5zdWJtaXNzaW9uUGFuZWwgPSBmYWxzZTsgLy8gRGlzYWJsZSBzdWJtaXNzaW9uIHBhbmVsIHdoZW4gdGhlIHJlbmRlcmVyIHRhYiBiZWNvbWVzIGFjdGl2ZVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbW9kYWxSZWY6IEJzTW9kYWxSZWY7XHJcblxyXG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTp2YXJpYWJsZS1uYW1lXHJcbiAgcHJpdmF0ZSBfanNvbkVkaXRvckVycm9yczogSnNvbkVkaXRvclZhbGlkYXRpb25FcnJvcltdID0gW107XHJcbiAgZ2V0IGpzb25FZGl0b3JFcnJvcnMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5fanNvbkVkaXRvckVycm9ycztcclxuICB9XHJcbiAgc2V0IGpzb25FZGl0b3JFcnJvcnMoZXJyb3JzOiBKc29uRWRpdG9yVmFsaWRhdGlvbkVycm9yW10pIHtcclxuICAgIHRoaXMuX2pzb25FZGl0b3JFcnJvcnMgPSBlcnJvcnM7XHJcbiAgICB0aGlzLmpzb25FZGl0b3JXYXJuaW5nQ291bnRlciA9IDA7XHJcbiAgICBlcnJvcnMuZm9yRWFjaCgoZXJyb3IpID0+IHtcclxuICAgICAgaWYgKGVycm9yLnR5cGUgPT09ICd2YWxpZGF0aW9uJykge1xyXG4gICAgICAgIHRoaXMuanNvbkVkaXRvcldhcm5pbmdDb3VudGVyKys7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAganNvbkVkaXRvcldhcm5pbmdDb3VudGVyID0gMDtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBtb2RhbFNlcnZpY2U6IEJzTW9kYWxTZXJ2aWNlKSB7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5vcHRpb25zKSB7XHJcbiAgICAgIHRoaXMuc2V0T3B0aW9ucygpOyAvLyBTZXQgZGVmYXVsdCBvcHRpb25zXHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5hY3RpdmVUYWIgPSAoWydidWlsZGVyJywgJ2pzb24nLCAncmVuZGVyZXInXSBhcyBGb3JtaW9FZGl0b3JUYWJbXSlcclxuICAgICAgICAgIC5maW5kKHQgPT4gdGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9uc1t0XT8uZGVmYXVsdFRhYiA/IHQgOiB1bmRlZmluZWQpIHx8ICdidWlsZGVyJztcclxuXHJcbiAgICBpZiAodGhpcy5yZXNldCkge1xyXG4gICAgICB0aGlzLnJlc2V0U3Vic2NyaXB0aW9uID0gdGhpcy5yZXNldC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5yZXNldEZvcm1CdWlsZGVyKCkpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgdGhpcy5yZWZyZXNoSnNvbkVkaXRvcigpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKSB7XHJcbiAgICBpZiAodGhpcy5yZXNldFN1YnNjcmlwdGlvbikge1xyXG4gICAgICB0aGlzLnJlc2V0U3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldE9wdGlvbnMob3B0aW9uczogRm9ybWlvRWRpdG9yT3B0aW9ucyA9IHt9KSB7XHJcbiAgICB0aGlzLl9vcHRpb25zID0gb3B0aW9ucztcclxuICAgIHRoaXMuanNvbkVkaXRvck9wdGlvbnMgPSBtZXJnZShcclxuICAgICAgZGVmYXVsdEpzb25FZGl0b3JPcHRpb25zLFxyXG4gICAgICBvcHRpb25zPy5qc29uPy5pbnB1dD8ub3B0aW9uc1xyXG4gICAgKTtcclxuICAgIHRoaXMucmVuZGVyZXJSZXNvdXJjZUpzb25FZGl0b3JPcHRpb25zID0gbWVyZ2UoXHJcbiAgICAgIGRlZmF1bHRSZW5kZXJlclJlc291cmNlSnNvbkVkaXRvck9wdGlvbnMsXHJcbiAgICAgIG9wdGlvbnM/LnJlbmRlcmVyPy5zdWJtaXNzaW9uUGFuZWw/LnJlc291cmNlSnNvbkVkaXRvcj8uaW5wdXQ/Lm9wdGlvbnNcclxuICAgICk7XHJcbiAgICB0aGlzLnJlbmRlcmVyU2NoZW1hSnNvbkVkaXRvck9wdGlvbnMgPSBtZXJnZShcclxuICAgICAgZGVmYXVsdFJlbmRlcmVyU2NoZW1hSnNvbkVkaXRvck9wdGlvbnMsXHJcbiAgICAgIG9wdGlvbnM/LnJlbmRlcmVyPy5zdWJtaXNzaW9uUGFuZWw/LnNjaGVtYUpzb25FZGl0b3I/LmlucHV0Py5vcHRpb25zXHJcbiAgICApO1xyXG4gICAgdGhpcy5mdWxsU3VibWlzc2lvbiA9IG9wdGlvbnM/LnJlbmRlcmVyPy5zdWJtaXNzaW9uUGFuZWw/LmZ1bGxTdWJtaXNzaW9uO1xyXG4gIH1cclxuXHJcbiAgLy9cclxuICAvLyBGb3JtIEJ1aWxkZXIgVGFiXHJcbiAgLy9cclxuXHJcbiAgcmVzZXRGb3JtQnVpbGRlcihmcm9tSnNvbkVkaXRvcjogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICBjb25zb2xlLmxvZygncmVzZXRGb3JtQnVpbGRlcicpO1xyXG4gICAgLy8gSGVyZSB3ZSBoYXZlIHRvIHJlc2V0IGJ1aWxkZXIgY29tcG9uZW50IHRocm91Z2ggKm5nSWY9XCIhYnVpbGRlckRpc3BsYXlDaGFuZ2VkXCJcclxuICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZm9ybWlvL2FuZ3VsYXItZm9ybWlvL2lzc3Vlcy8xNzIjaXNzdWVjb21tZW50LTQwMTg3NjQ5MFxyXG4gICAgdGhpcy5idWlsZGVyRGlzcGxheUNoYW5nZWQgPSB0cnVlO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHRoaXMuYnVpbGRlckRpc3BsYXlDaGFuZ2VkID0gZmFsc2U7XHJcbiAgICAgIGlmICghZnJvbUpzb25FZGl0b3IpIHtcclxuICAgICAgICB0aGlzLnJlZnJlc2hKc29uRWRpdG9yKHRydWUpO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMucmVzZXRGb3JtUmVuZGVyZXJJZkFjdGl2ZSgpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBvbkJ1aWxkZXJEaXBsYXlDaGFuZ2UoZXZlbnQpIHtcclxuICAgIGNvbnNvbGUubG9nKCdvbkJ1aWxkZXJEaXBsYXlDaGFuZ2UnKTtcclxuICAgIHRoaXMucmVzZXRGb3JtQnVpbGRlcigpO1xyXG4gIH1cclxuXHJcbiAgb25CdWlsZGVyQ2hhbmdlKGV2ZW50KSB7XHJcbiAgICBjb25zb2xlLmxvZygnb25CdWlsZGVyQ2hhbmdlOiBldmVudCcsIGV2ZW50KTtcclxuICAgIHRoaXMucmVmcmVzaEpzb25FZGl0b3IodHJ1ZSk7XHJcbiAgfVxyXG5cclxuICAvL1xyXG4gIC8vIEpTT04gVGFiXHJcbiAgLy9cclxuXHJcbiAgb25Kc29uRWRpdG9yRXJyb3IoZXJyb3JzOiBhbnlbXSkge1xyXG4gICAgY29uc29sZS5sb2coJ29uSnNvbkVkaXRvckVycm9yOiBmb3VuZCcsIGVycm9ycy5sZW5ndGgsICd2YWxpZGF0aW9uIGVycm9yczonKTtcclxuICAgIHRoaXMuanNvbkVkaXRvckVycm9ycyA9IGVycm9ycztcclxuICB9XHJcblxyXG4gIG9uSnNvbkVkaXRvckNoYW5nZShldmVudCkge1xyXG4gICAgY29uc29sZS5sb2coJ29uSnNvbkVkaXRvckNoYW5nZScpO1xyXG4gICAgdGhpcy5qc29uRWRpdG9yQ2hhbmdlZCA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBvbkpzb25FZGl0b3JBcHBseSh0ZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55Pikge1xyXG4gICAgY29uc29sZS5sb2coJ0Vycm9yczogJywgdGhpcy5qc29uRWRpdG9yRXJyb3JzLmxlbmd0aCAtIHRoaXMuanNvbkVkaXRvcldhcm5pbmdDb3VudGVyLCAnV2FybmluZ3M6ICcsIHRoaXMuanNvbkVkaXRvcldhcm5pbmdDb3VudGVyKTtcclxuICAgIGlmICh0aGlzLmpzb25FZGl0b3JXYXJuaW5nQ291bnRlciA9PT0gMCkge1xyXG4gICAgICB0aGlzLmpzb25FZGl0b3JBcHBseUNoYW5nZXMoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMubW9kYWxSZWYgPSB0aGlzLm1vZGFsU2VydmljZS5zaG93KHRlbXBsYXRlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGpzb25FZGl0b3JBcHBseUNoYW5nZXMoKSB7XHJcbiAgICBjb25zb2xlLmxvZygnanNvbkVkaXRvckFwcGx5Q2hhbmdlcycpO1xyXG4gICAgdGhpcy5qc29uRWRpdG9yQ2hhbmdlZCA9IGZhbHNlO1xyXG4gICAgLy8gUmVtb3ZlIGFsbCBwcm9wZXJ0aWVzIGZyb20gdGhpcyBmb3JtXHJcbiAgICAvLyB0aGVuIGNvcHkgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGVkaXRlZCBqc29uIHRvIHRoaXMgZm9ybVxyXG4gICAgLy8gYW5kIHJlc2V0IHRoZSBidWlsZGVyXHJcbiAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzLmZvcm0pLmZvckVhY2gocCA9PiBkZWxldGUgdGhpcy5mb3JtW3BdKTtcclxuICAgIE9iamVjdC5hc3NpZ24odGhpcy5mb3JtLCB0aGlzLmpzb25FZGl0b3IuZ2V0KCkpO1xyXG4gICAgdGhpcy5yZXNldEZvcm1CdWlsZGVyKHRydWUpO1xyXG4gIH1cclxuXHJcbiAganNvbkVkaXRvckRpc2NhcmRDaGFuZ2VzKCkge1xyXG4gICAgY29uc29sZS5sb2coJ2pzb25FZGl0b3JEaXNjYXJkQ2hhbmdlcycpO1xyXG4gICAgdGhpcy5yZWZyZXNoSnNvbkVkaXRvcigpO1xyXG4gIH1cclxuXHJcbiAgcmVmcmVzaEpzb25FZGl0b3IoZm9yY2VSZXNldDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICBjb25zb2xlLmxvZygncmVmcmVzaEpzb25FZGl0b3InKTtcclxuICAgIGlmIChmb3JjZVJlc2V0KSB7XHJcbiAgICAgIHRoaXMuanNvbkVkaXRvci5yZXNldCh0cnVlKTtcclxuICAgIH1cclxuICAgIC8vIEhlcmUgd2UgdXNlIHVwZGF0ZSBpbnN0ZWFkIG9mIHNldCB0byBwcmVzZXJ2ZSB0aGUgZWRpdG9yIHN0YXR1c1xyXG4gICAgdGhpcy5qc29uRWRpdG9yLnVwZGF0ZSh0aGlzLmZvcm0pO1xyXG4gICAgdGhpcy5qc29uRWRpdG9yQ2hhbmdlZCA9IGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLy9cclxuICAvLyBGb3JtIFJlbmRlcmVyIFRhYlxyXG4gIC8vXHJcblxyXG4gIHJlc2V0Rm9ybVJlbmRlcmVySWZBY3RpdmUoKSB7XHJcbiAgICBjb25zb2xlLmxvZygncmVzZXRGb3JtUmVuZGVyZXInKTtcclxuICAgIC8vIEhlcmUgd2UgcmVjcmVhdGUgdGhlIHJlbmRlcmVyIGNvbXBvbmVudCB0aHJvdWdoICpuZ0lmPVwiYWN0aXZlVGFiPSdyZW5kZXJlcidcIlxyXG4gICAgLy8gYnkgY2hhbmdpbmcgdGhlIGFjdGl2ZSB0YWIgYW5kIHRoZW4gcmVzdG9yaW5nIGl0LlxyXG4gICAgLy8gQWx0aG91Z2ggdGhpcyBpcyBhIHJhdGhlciBkaXJ0eSBoYWNrIGl0IGlzIGhhcmRseSBub3RpY2VhYmxlIHRvIHRoZSBleWUgOilcclxuICAgIGlmICh0aGlzLmFjdGl2ZVRhYiA9PT0gJ3JlbmRlcmVyJykge1xyXG4gICAgICB0aGlzLmFjdGl2ZVRhYiA9ICdidWlsZGVyJztcclxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7IHRoaXMuYWN0aXZlVGFiID0gJ3JlbmRlcmVyJzsgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBzaG93U3VibWlzc2lvblBhbmVsKHN1Ym1pc3Npb246IGFueSkge1xyXG4gICAgdGhpcy5zdWJtaXNzaW9uUGFuZWwgPSAhdGhpcy5vcHRpb25zLnJlbmRlcmVyPy5zdWJtaXNzaW9uUGFuZWw/LmRpc2FibGVkO1xyXG4gICAgaWYgKHRoaXMuc3VibWlzc2lvblBhbmVsKSB7XHJcbiAgICAgIGlmIChzdWJtaXNzaW9uKSB7XHJcbiAgICAgICAgdGhpcy5zdWJtaXNzaW9uID0gc3VibWlzc2lvbjtcclxuICAgICAgfVxyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICBsZXQgc2NoZW1hID0gZ2VuZXJhdGVGb3JtSnNvblNjaGVtYSh0aGlzLmZvcm0pO1xyXG4gICAgICAgIGlmICh0aGlzLmZ1bGxTdWJtaXNzaW9uKSB7XHJcbiAgICAgICAgICBzY2hlbWEgPSB7IHR5cGU6ICdvYmplY3QnLCBwcm9wZXJ0aWVzOiB7IGRhdGE6IHNjaGVtYSB9IH07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMucmVuZGVyZXJSZXNvdXJjZUpzb25FZGl0b3Iuc2V0U2NoZW1hKHVuZGVmaW5lZCk7XHJcbiAgICAgICAgdGhpcy5yZW5kZXJlclJlc291cmNlSnNvbkVkaXRvci5zZXQodGhpcy5mdWxsU3VibWlzc2lvbiA/IHRoaXMuc3VibWlzc2lvbiA6IHRoaXMuc3VibWlzc2lvbi5kYXRhKTtcclxuICAgICAgICB0aGlzLnJlbmRlcmVyU2NoZW1hSnNvbkVkaXRvci5zZXQoc2NoZW1hIGFzIEpTT04pO1xyXG4gICAgICAgIHRoaXMucmVuZGVyZXJSZXNvdXJjZUpzb25FZGl0b3Iuc2V0U2NoZW1hKHNjaGVtYSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuICBhcHBseVJlc291cmNlSnNvblNjaGVtYSgpIHtcclxuICAgIGNvbnN0IHNjaGVtYSA9IHRoaXMucmVuZGVyZXJTY2hlbWFKc29uRWRpdG9yLmdldCgpO1xyXG4gICAgdGhpcy5yZW5kZXJlclJlc291cmNlSnNvbkVkaXRvci5zZXRTY2hlbWEoc2NoZW1hKTtcclxuICB9XHJcbn1cclxuIl19