@nowzoo/ngx-firebase-auth
Version:
Angular components for Firebase email-first sign in and out-of-band (oob) actions (reset password, etc).
251 lines (250 loc) • 33.2 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
*/
import { Component, Input, Output, EventEmitter, NgZone, ViewChild, ElementRef } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { AngularFireAuth } from 'angularfire2/auth';
import { debounceTime } from 'rxjs/operators';
import { getOAuthProviderIcon, getOAuthProviderName } from '../../shared';
import { NgxFirebaseAuthFormHelper } from '../../form-helper';
import { NgxFirebaseAuthService } from '../../ngx-firebase-auth.service';
import { fadeInOutAnimation, screenAnimation } from '../../shared';
var SignInMethodsFormComponent = /** @class */ (function () {
function SignInMethodsFormComponent(_afAuth, _authService, _ngZone) {
this._afAuth = _afAuth;
this._authService = _authService;
this._ngZone = _ngZone;
this.oAuthProviderIds = [];
this.emailChange = new EventEmitter();
this.rememberChange = new EventEmitter();
this.success = new EventEmitter();
this.error = new EventEmitter();
this.formId = 'ngx-firebase-auth-sign-in-methods-form-';
this.submitting = false;
this.getOAuthProviderIcon = getOAuthProviderIcon;
this.getOAuthProviderName = getOAuthProviderName;
this.methodsForEmail = { status: 'unfetched', methods: [], email: null };
}
Object.defineProperty(SignInMethodsFormComponent.prototype, "auth", {
get: /**
* @return {?}
*/
function () {
return this._afAuth.auth;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SignInMethodsFormComponent.prototype, "authService", {
get: /**
* @return {?}
*/
function () {
return this._authService;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SignInMethodsFormComponent.prototype, "methods", {
get: /**
* @return {?}
*/
function () {
return this.methodsForEmail.methods;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SignInMethodsFormComponent.prototype, "fetchStatus", {
get: /**
* @return {?}
*/
function () {
return this.methodsForEmail.status;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SignInMethodsFormComponent.prototype, "methodsFetched", {
get: /**
* @return {?}
*/
function () {
return this.methodsForEmail.status === 'fetched';
},
enumerable: true,
configurable: true
});
Object.defineProperty(SignInMethodsFormComponent.prototype, "accountIsNew", {
get: /**
* @return {?}
*/
function () {
return this.methodsFetched && this.methods.length === 0;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SignInMethodsFormComponent.prototype, "accountExists", {
get: /**
* @return {?}
*/
function () {
return this.methodsFetched && this.methods.length > 0;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SignInMethodsFormComponent.prototype, "accountHasPassword", {
get: /**
* @return {?}
*/
function () {
return this.accountExists && this.methods.indexOf('password') !== -1;
},
enumerable: true,
configurable: true
});
Object.defineProperty(SignInMethodsFormComponent.prototype, "accountOAuthMethods", {
get: /**
* @return {?}
*/
function () {
if (!this.accountExists) {
return [];
}
return this.methods.filter(function (id) { return id !== 'password'; });
},
enumerable: true,
configurable: true
});
/**
* @return {?}
*/
SignInMethodsFormComponent.prototype.ngOnInit = /**
* @return {?}
*/
function () {
var _this = this;
this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
this.rememberFc = new FormControl(this.remember);
this.rememberFc.valueChanges.subscribe(function () { return _this.rememberChange.emit(_this.rememberFc.value); });
this.fg = new FormGroup({ email: this.emailFc, remember: this.rememberFc });
this.emailFc.valueChanges.subscribe(function () { return _this.emailChange.emit(_this.emailFc.value.trim()); });
this.emailFc.valueChanges.pipe(debounceTime(500)).subscribe(function () { return _this.fetch(); });
this.fetch();
};
/**
* @return {?}
*/
SignInMethodsFormComponent.prototype.ngAfterViewInit = /**
* @return {?}
*/
function () {
this.emailInput.nativeElement.focus();
};
/**
* @return {?}
*/
SignInMethodsFormComponent.prototype.fetch = /**
* @return {?}
*/
function () {
var _this = this;
/** @type {?} */
var email = this.emailFc.value.trim();
if (email === this.methodsForEmail.email) {
return;
}
if ('fetching' === this.methodsForEmail.status) {
return;
}
this.methodsForEmail = { status: 'fetching', methods: [], email: email };
if (this.emailFc.invalid) {
this.methodsForEmail = { status: 'unfetched', methods: [], email: email };
return;
}
this.auth.fetchSignInMethodsForEmail(email)
.then(function (results) {
_this.methodsForEmail = { status: 'fetched', methods: results, email: email };
})
.catch(function (error) {
_this.emailFc.markAsDirty();
_this.emailFc.markAsTouched();
switch (error.code) {
case 'auth/invalid-email':
NgxFirebaseAuthFormHelper.setErrorUntilChanged(_this.emailFc, error.code);
break;
}
_this.methodsForEmail = { email: _this.email, status: 'unfetched', methods: [] };
});
};
SignInMethodsFormComponent.decorators = [
{ type: Component, args: [{
selector: 'ngx-firebase-auth-sign-in-methods-form',
template: "<form [formGroup]=\"fg\">\n <div class=\"form-group\">\n <label [attr.for]=\"formId + 'email'\">Email Address</label>\n <input\n #emailInput\n [attr.id]=\"formId + 'email'\"\n [attr.aria-describedby]=\"formId + 'email'\"\n type=\"email\"\n autocomplete=\"email\"\n placeholder=\"Email Address\"\n formControlName=\"email\"\n (blur)=\"fetch()\"\n (keyup.enter)=\"emailInput.blur()\"\n class=\"form-control\"\n [class.is-invalid]=\"emailFc.touched && emailFc.invalid\">\n <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n *ngIf=\"emailFc.touched && emailFc.hasError('required')\">\n Required.\n </div>\n <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n *ngIf=\"emailFc.touched && emailFc.hasError('email')\">\n Invalid email.\n </div>\n <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n *ngIf=\"emailFc.touched && emailFc.hasError('auth/invalid-email')\">\n Invalid email.\n </div>\n <small class=\"text-muted form-text\" [attr.id]=\"formId + 'email'\" [ngSwitch]=\"fetchStatus\">\n <span *ngSwitchCase=\"'unfetched'\" [@fadeInOut]=\"'in'\">\n To get started, enter your email address.\n If you don\u2019t yet have an account we\u2019ll create one for you.\n </span>\n <span *ngSwitchCase=\"'fetching'\" [@fadeInOut]=\"'in'\">\n <i class=\"fas fa-spin fa-spinner fa-fw\" aria-hidden=\"true\"></i>\n Looking up account...\n </span>\n <span *ngSwitchCase=\"'fetched'\" [@fadeInOut]=\"'in'\">\n <i class=\"fas fa-check fa-fw text-success\" aria-hidden=\"true\"></i>\n <span *ngIf=\"accountExists\">Account found.</span>\n <span *ngIf=\"accountIsNew\">We'll create an account.</span>\n </span>\n </small>\n </div>\n <div class=\"form-group\">\n <div class=\"form-check\">\n <input\n class=\"form-check-input\"\n type=\"checkbox\"\n [value]=\"true\"\n formControlName=\"remember\"\n [attr.id]=\"formId + 'remember'\">\n <label class=\"form-check-label\" [attr.for]=\"formId + 'remember'\">\n Remember me on this device.\n </label>\n </div>\n </div>\n</form>\n<div *ngIf=\"methodsFetched && accountExists\" [@screen]=\"'in'\">\n <small class=\"text-muted mb-1 form-text\">\n <span *ngIf=\"accountHasPassword\">\n <span *ngIf=\"accountOAuthMethods.length === 0\">\n Please sign in with your password...\n </span>\n <span *ngIf=\"accountOAuthMethods.length === 1\">\n Please sign in with your password or your\n linked {{getOAuthProviderName(accountOAuthMethods[0])}} account...\n </span>\n <span *ngIf=\"accountOAuthMethods.length > 1\">\n Please sign in with your password or one of your linked accounts...\n </span>\n </span>\n <span *ngIf=\"!accountHasPassword\">\n <span *ngIf=\"accountOAuthMethods.length === 1\">\n Please sign in with your\n linked {{getOAuthProviderName(accountOAuthMethods[0])}} account...\n </span>\n <span *ngIf=\"accountOAuthMethods.length > 1\">\n Please sign in with one of your linked accounts...\n </span>\n </span>\n\n </small>\n\n <div class=\"list-group\">\n <a\n *ngIf=\"accountHasPassword\"\n routerLink=\".\"\n [queryParams]=\"{action: 'signInPassword'}\"\n class=\"list-group-item list-group-item-action\">\n <i class=\"fas fa-lock fa-fw\" aria-hidden=\"true\"></i>\n <span class=\"ml-2\">\n Sign In with Your Password\n </span>\n </a>\n <a\n *ngFor=\"let id of accountOAuthMethods\"\n routerLink=\".\"\n [queryParams]=\"{action: 'signInOAuth', providerId: id}\"\n class=\"list-group-item list-group-item-action\">\n <i [attr.class]=\"getOAuthProviderIcon(id)\" aria-hidden=\"true\"></i>\n <span class=\"ml-2\">\n Sign In with {{getOAuthProviderName(id)}}\n </span>\n </a>\n </div>\n</div>\n\n<div *ngIf=\"methodsFetched && accountIsNew\" [@screen]=\"'in'\">\n <small class=\"text-muted mb-1 form-text\">\n <span *ngIf=\"oAuthProviderIds.length === 0\">\n Please create an account...\n </span>\n <span *ngIf=\"oAuthProviderIds.length === 1\">\n Please sign up with your\n {{getOAuthProviderName(oAuthProviderIds[0])}} account,\n or create a separate account with a password....\n </span>\n <span *ngIf=\"oAuthProviderIds.length >1\">\n Please sign up with one of the services listed below,\n or create a separate account with a password....\n </span>\n </small>\n <div class=\"list-group\">\n\n <a\n *ngFor=\"let id of oAuthProviderIds\"\n routerLink=\".\"\n [queryParams]=\"{action: 'signInOAuth', providerId: id}\"\n class=\"list-group-item list-group-item-action\">\n <i [attr.class]=\"getOAuthProviderIcon(id)\" aria-hidden=\"true\"></i>\n <span class=\"ml-2\">\n Sign Up with {{getOAuthProviderName(id)}}\n </span>\n </a>\n <a\n routerLink=\".\"\n [queryParams]=\"{action: 'signUpPassword'}\"\n class=\"list-group-item list-group-item-action\">\n <i class=\"fas fa-lock fa-fw\" aria-hidden=\"true\"></i>\n <span class=\"ml-2\">\n Create\n <span *ngIf=\"oAuthProviderIds.length > 0\">\n a Separate\n </span>\n Account\n </span>\n </a>\n </div>\n</div>\n",
styles: [""],
animations: [fadeInOutAnimation, screenAnimation]
},] },
];
/** @nocollapse */
SignInMethodsFormComponent.ctorParameters = function () { return [
{ type: AngularFireAuth },
{ type: NgxFirebaseAuthService },
{ type: NgZone }
]; };
SignInMethodsFormComponent.propDecorators = {
emailInput: [{ type: ViewChild, args: ['emailInput',] }],
email: [{ type: Input }],
remember: [{ type: Input }],
oAuthProviderIds: [{ type: Input }],
emailChange: [{ type: Output }],
rememberChange: [{ type: Output }],
success: [{ type: Output }],
error: [{ type: Output }]
};
return SignInMethodsFormComponent;
}());
export { SignInMethodsFormComponent };
if (false) {
/** @type {?} */
SignInMethodsFormComponent.prototype.emailInput;
/** @type {?} */
SignInMethodsFormComponent.prototype.email;
/** @type {?} */
SignInMethodsFormComponent.prototype.remember;
/** @type {?} */
SignInMethodsFormComponent.prototype.oAuthProviderIds;
/** @type {?} */
SignInMethodsFormComponent.prototype.emailChange;
/** @type {?} */
SignInMethodsFormComponent.prototype.rememberChange;
/** @type {?} */
SignInMethodsFormComponent.prototype.success;
/** @type {?} */
SignInMethodsFormComponent.prototype.error;
/** @type {?} */
SignInMethodsFormComponent.prototype.formId;
/** @type {?} */
SignInMethodsFormComponent.prototype.submitting;
/** @type {?} */
SignInMethodsFormComponent.prototype.fg;
/** @type {?} */
SignInMethodsFormComponent.prototype.emailFc;
/** @type {?} */
SignInMethodsFormComponent.prototype.rememberFc;
/** @type {?} */
SignInMethodsFormComponent.prototype.getOAuthProviderIcon;
/** @type {?} */
SignInMethodsFormComponent.prototype.getOAuthProviderName;
/** @type {?} */
SignInMethodsFormComponent.prototype.methodsForEmail;
/** @type {?} */
SignInMethodsFormComponent.prototype._afAuth;
/** @type {?} */
SignInMethodsFormComponent.prototype._authService;
/** @type {?} */
SignInMethodsFormComponent.prototype._ngZone;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lnbi1pbi1tZXRob2RzLWZvcm0uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC8iLCJzb3VyY2VzIjpbImxpYi9zaWduLWluL3NpZ24taW4tbWV0aG9kcy1mb3JtL3NpZ24taW4tbWV0aG9kcy1mb3JtLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUFFLFNBQVMsRUFBeUIsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0gsT0FBTyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRXBELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5QyxPQUFPLEVBQWdDLG9CQUFvQixFQUFFLG9CQUFvQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3hHLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQzlELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsTUFBTSxjQUFjLENBQUM7O0lBbUxqRSxvQ0FDVSxTQUNBLGNBQ0E7UUFGQSxZQUFPLEdBQVAsT0FBTztRQUNQLGlCQUFZLEdBQVosWUFBWTtRQUNaLFlBQU8sR0FBUCxPQUFPO2dDQW5CcUIsRUFBRTsyQkFDTSxJQUFJLFlBQVksRUFBRTs4QkFDZCxJQUFJLFlBQVksRUFBRTt1QkFDYixJQUFJLFlBQVksRUFBRTtxQkFDN0IsSUFBSSxZQUFZLEVBQUU7c0JBR3JELHlDQUF5QzswQkFDckMsS0FBSztvQ0FJSyxvQkFBb0I7b0NBQ3BCLG9CQUFvQjsrQkFDSyxFQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFDO0tBTTFGO0lBRUwsc0JBQUksNENBQUk7Ozs7UUFBUjtZQUNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztTQUMxQjs7O09BQUE7SUFDRCxzQkFBSSxtREFBVzs7OztRQUFmO1lBQ0UsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUM7U0FDMUI7OztPQUFBO0lBR0Qsc0JBQUksK0NBQU87Ozs7UUFBWDtZQUNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQztTQUNyQzs7O09BQUE7SUFFRCxzQkFBSSxtREFBVzs7OztRQUFmO1lBQ0UsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDO1NBQ3BDOzs7T0FBQTtJQUVELHNCQUFJLHNEQUFjOzs7O1FBQWxCO1lBQ0UsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQztTQUNsRDs7O09BQUE7SUFFRCxzQkFBSSxvREFBWTs7OztRQUFoQjtZQUNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztTQUN6RDs7O09BQUE7SUFFRCxzQkFBSSxxREFBYTs7OztRQUFqQjtZQUNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztTQUN2RDs7O09BQUE7SUFFRCxzQkFBSSwwREFBa0I7Ozs7UUFBdEI7WUFDRSxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztTQUN0RTs7O09BQUE7SUFFRCxzQkFBSSwyREFBbUI7Ozs7UUFBdkI7WUFDRSxFQUFFLENBQUMsQ0FBQyxDQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO2dCQUN6QixNQUFNLENBQUMsRUFBRSxDQUFDO2FBQ1g7WUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBQSxFQUFFLElBQUksT0FBQSxFQUFFLEtBQUssVUFBVSxFQUFqQixDQUFpQixDQUFDLENBQUM7U0FDckQ7OztPQUFBOzs7O0lBS0QsNkNBQVE7OztJQUFSO1FBQUEsaUJBV0M7UUFWQyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksV0FBVyxDQUM1QixJQUFJLENBQUMsS0FBSyxFQUNWLEVBQUMsVUFBVSxFQUFFLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUMsQ0FDdEQsQ0FBQztRQUNGLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2pELElBQUksQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxjQUFNLE9BQUEsS0FBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBL0MsQ0FBK0MsQ0FBQyxDQUFDO1FBQzlGLElBQUksQ0FBQyxFQUFFLEdBQUcsSUFBSSxTQUFTLENBQUMsRUFBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBQyxDQUFDLENBQUM7UUFDMUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLGNBQU0sT0FBQSxLQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFoRCxDQUFnRCxDQUFDLENBQUM7UUFDNUYsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxjQUFNLE9BQUEsS0FBSSxDQUFDLEtBQUssRUFBRSxFQUFaLENBQVksQ0FBQyxDQUFDO1FBQ2hGLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztLQUNkOzs7O0lBRUQsb0RBQWU7OztJQUFmO1FBQ0UsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7S0FFdkM7Ozs7SUFHRCwwQ0FBSzs7O0lBQUw7UUFBQSxpQkEyQkM7O1FBMUJDLElBQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hDLEVBQUUsQ0FBQyxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDekMsTUFBTSxDQUFDO1NBQ1I7UUFDRCxFQUFFLENBQUMsQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQy9DLE1BQU0sQ0FBQztTQUNSO1FBQ0QsSUFBSSxDQUFDLGVBQWUsR0FBRyxFQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFDLENBQUM7UUFDdkUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBQyxNQUFNLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBQyxDQUFDO1lBQ3hFLE1BQU0sQ0FBQztTQUNSO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxLQUFLLENBQUM7YUFDeEMsSUFBSSxDQUFDLFVBQUEsT0FBTztZQUNYLEtBQUksQ0FBQyxlQUFlLEdBQUcsRUFBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBQyxDQUFDO1NBQzVFLENBQUM7YUFDRCxLQUFLLENBQUMsVUFBQyxLQUFpQjtZQUN2QixLQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzNCLEtBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDN0IsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Z0JBQ25CLEtBQUssb0JBQW9CO29CQUN2Qix5QkFBeUIsQ0FBQyxvQkFBb0IsQ0FBQyxLQUFJLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDekUsS0FBSyxDQUFDO2FBQ1Q7WUFDRCxLQUFJLENBQUMsZUFBZSxHQUFHLEVBQUMsS0FBSyxFQUFFLEtBQUksQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFDLENBQUM7U0FDOUUsQ0FBQyxDQUFDO0tBQ047O2dCQS9RRixTQUFTLFNBQUM7b0JBQ1QsUUFBUSxFQUFFLHdDQUF3QztvQkFDbEQsUUFBUSxFQUFFLDYwS0FxSlg7b0JBQ0MsTUFBTSxFQUFFLENBQUMsRUFBRSxDQUFDO29CQUNaLFVBQVUsRUFBRSxDQUFDLGtCQUFrQixFQUFFLGVBQWUsQ0FBQztpQkFDbEQ7Ozs7Z0JBbEtRLGVBQWU7Z0JBS2Ysc0JBQXNCO2dCQVB5QyxNQUFNOzs7NkJBd0szRSxTQUFTLFNBQUMsWUFBWTt3QkFDdEIsS0FBSzsyQkFDTCxLQUFLO21DQUNMLEtBQUs7OEJBQ0wsTUFBTTtpQ0FDTixNQUFNOzBCQUNOLE1BQU07d0JBQ04sTUFBTTs7cUNBL0tUOztTQXFLYSwwQkFBMEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBOZ1pvbmUsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSVNpZ25Jbk1ldGhvZHNGb3JFbWFpbFJlc3VsdCwgZ2V0T0F1dGhQcm92aWRlckljb24sIGdldE9BdXRoUHJvdmlkZXJOYW1lIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIgfSBmcm9tICcuLi8uLi9mb3JtLWhlbHBlcic7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbmd4LWZpcmViYXNlLWF1dGguc2VydmljZSc7XG5pbXBvcnQgeyBmYWRlSW5PdXRBbmltYXRpb24sIHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tbWV0aG9kcy1mb3JtJyxcbiAgdGVtcGxhdGU6IGA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCI+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICAjZW1haWxJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cImVtYWlsXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiRW1haWwgQWRkcmVzc1wiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICAoYmx1cik9XCJmZXRjaCgpXCJcbiAgICAgIChrZXl1cC5lbnRlcik9XCJlbWFpbElucHV0LmJsdXIoKVwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5pbnZhbGlkXCI+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdhdXRoL2ludmFsaWQtZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIGZvcm0tdGV4dFwiIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIiBbbmdTd2l0Y2hdPVwiZmV0Y2hTdGF0dXNcIj5cbiAgICAgIDxzcGFuICpuZ1N3aXRjaENhc2U9XCIndW5mZXRjaGVkJ1wiIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgICAgVG8gZ2V0IHN0YXJ0ZWQsIGVudGVyIHlvdXIgZW1haWwgYWRkcmVzcy5cbiAgICAgICAgSWYgeW91IGRvbuKAmXQgeWV0IGhhdmUgYW4gYWNjb3VudCB3ZeKAmWxsIGNyZWF0ZSBvbmUgZm9yIHlvdS5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ1N3aXRjaENhc2U9XCInZmV0Y2hpbmcnXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1zcGluIGZhLXNwaW5uZXIgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgIExvb2tpbmcgdXAgYWNjb3VudC4uLlxuICAgICAgPC9zcGFuPlxuICAgICAgPHNwYW4gKm5nU3dpdGNoQ2FzZT1cIidmZXRjaGVkJ1wiIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZncgdGV4dC1zdWNjZXNzXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRFeGlzdHNcIj5BY2NvdW50IGZvdW5kLjwvc3Bhbj5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50SXNOZXdcIj5XZSdsbCBjcmVhdGUgYW4gYWNjb3VudC48L3NwYW4+XG4gICAgICA8L3NwYW4+XG4gICAgPC9zbWFsbD5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgIDxpbnB1dFxuICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxuICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICBbdmFsdWVdPVwidHJ1ZVwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJlbWVtYmVyXCJcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgIFJlbWVtYmVyIG1lIG9uIHRoaXMgZGV2aWNlLlxuICAgICAgPC9sYWJlbD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Zvcm0+XG48ZGl2ICpuZ0lmPVwibWV0aG9kc0ZldGNoZWQgJiYgYWNjb3VudEV4aXN0c1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0xIGZvcm0tdGV4dFwiPlxuICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudEhhc1Bhc3N3b3JkXCI+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID09PSAwXCI+XG4gICAgICAgIFBsZWFzZSBzaWduIGluIHdpdGggeW91ciBwYXNzd29yZC4uLlxuICAgICAgPC9zcGFuPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA9PT0gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXIgcGFzc3dvcmQgb3IgeW91clxuICAgICAgICBsaW5rZWQge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShhY2NvdW50T0F1dGhNZXRob2RzWzBdKX19IGFjY291bnQuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudE9BdXRoTWV0aG9kcy5sZW5ndGggPiAxXCI+XG4gICAgICAgIFBsZWFzZSBzaWduIGluIHdpdGggeW91ciBwYXNzd29yZCBvciBvbmUgb2YgeW91ciBsaW5rZWQgYWNjb3VudHMuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICA8L3NwYW4+XG4gICAgPHNwYW4gKm5nSWY9XCIhYWNjb3VudEhhc1Bhc3N3b3JkXCI+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID09PSAxXCI+XG4gICAgICAgIFBsZWFzZSBzaWduIGluIHdpdGggeW91clxuICAgICAgICBsaW5rZWQge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShhY2NvdW50T0F1dGhNZXRob2RzWzBdKX19IGFjY291bnQuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudE9BdXRoTWV0aG9kcy5sZW5ndGggPiAxXCI+XG4gICAgICAgIFBsZWFzZSBzaWduIGluIHdpdGggb25lIG9mIHlvdXIgbGlua2VkIGFjY291bnRzLi4uXG4gICAgICA8L3NwYW4+XG4gICAgPC9zcGFuPlxuXG4gIDwvc21hbGw+XG5cbiAgPGRpdiBjbGFzcz1cImxpc3QtZ3JvdXBcIj5cbiAgICA8YVxuICAgICAgKm5nSWY9XCJhY2NvdW50SGFzUGFzc3dvcmRcIlxuICAgICAgcm91dGVyTGluaz1cIi5cIlxuICAgICAgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW5QYXNzd29yZCd9XCJcbiAgICAgIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIj5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWxvY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5cbiAgICAgICAgU2lnbiBJbiB3aXRoIFlvdXIgUGFzc3dvcmRcbiAgICAgIDwvc3Bhbj5cbiAgICA8L2E+XG4gICAgPGFcbiAgICAgICpuZ0Zvcj1cImxldCBpZCBvZiBhY2NvdW50T0F1dGhNZXRob2RzXCJcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluT0F1dGgnLCBwcm92aWRlcklkOiBpZH1cIlxuICAgICAgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiPlxuICAgICAgPGkgW2F0dHIuY2xhc3NdPVwiZ2V0T0F1dGhQcm92aWRlckljb24oaWQpXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+XG4gICAgICAgIFNpZ24gSW4gd2l0aCB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKGlkKX19XG4gICAgICA8L3NwYW4+XG4gICAgPC9hPlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwibWV0aG9kc0ZldGNoZWQgJiYgYWNjb3VudElzTmV3XCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIG1iLTEgZm9ybS10ZXh0XCI+XG4gICAgPHNwYW4gKm5nSWY9XCJvQXV0aFByb3ZpZGVySWRzLmxlbmd0aCA9PT0gMFwiPlxuICAgICAgUGxlYXNlIGNyZWF0ZSBhbiBhY2NvdW50Li4uXG4gICAgPC9zcGFuPlxuICAgIDxzcGFuICpuZ0lmPVwib0F1dGhQcm92aWRlcklkcy5sZW5ndGggPT09IDFcIj5cbiAgICAgIFBsZWFzZSBzaWduIHVwIHdpdGggeW91clxuICAgICAge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShvQXV0aFByb3ZpZGVySWRzWzBdKX19IGFjY291bnQsXG4gICAgICBvciBjcmVhdGUgYSBzZXBhcmF0ZSBhY2NvdW50IHdpdGggYSBwYXNzd29yZC4uLi5cbiAgICA8L3NwYW4+XG4gICAgPHNwYW4gKm5nSWY9XCJvQXV0aFByb3ZpZGVySWRzLmxlbmd0aCA+MVwiPlxuICAgICAgUGxlYXNlIHNpZ24gdXAgd2l0aCBvbmUgb2YgdGhlIHNlcnZpY2VzIGxpc3RlZCBiZWxvdyxcbiAgICAgIG9yIGNyZWF0ZSBhIHNlcGFyYXRlIGFjY291bnQgd2l0aCBhIHBhc3N3b3JkLi4uLlxuICAgIDwvc3Bhbj5cbiAgPC9zbWFsbD5cbiAgPGRpdiBjbGFzcz1cImxpc3QtZ3JvdXBcIj5cblxuICAgIDxhXG4gICAgICAqbmdGb3I9XCJsZXQgaWQgb2Ygb0F1dGhQcm92aWRlcklkc1wiXG4gICAgICByb3V0ZXJMaW5rPVwiLlwiXG4gICAgICBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbk9BdXRoJywgcHJvdmlkZXJJZDogaWR9XCJcbiAgICAgIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIj5cbiAgICAgIDxpIFthdHRyLmNsYXNzXT1cImdldE9BdXRoUHJvdmlkZXJJY29uKGlkKVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlxuICAgICAgICBTaWduIFVwIHdpdGgge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fVxuICAgICAgPC9zcGFuPlxuICAgIDwvYT5cbiAgICA8YVxuICAgICAgcm91dGVyTGluaz1cIi5cIlxuICAgICAgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduVXBQYXNzd29yZCd9XCJcbiAgICAgIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIj5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWxvY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5cbiAgICAgICAgQ3JlYXRlXG4gICAgICAgIDxzcGFuICpuZ0lmPVwib0F1dGhQcm92aWRlcklkcy5sZW5ndGggPiAwXCI+XG4gICAgICAgICAgYSBTZXBhcmF0ZVxuICAgICAgICA8L3NwYW4+XG4gICAgICAgIEFjY291bnRcbiAgICAgIDwvc3Bhbj5cbiAgICA8L2E+XG4gIDwvZGl2PlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtmYWRlSW5PdXRBbmltYXRpb24sIHNjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgU2lnbkluTWV0aG9kc0Zvcm1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG5cbiAgQFZpZXdDaGlsZCgnZW1haWxJbnB1dCcpIGVtYWlsSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpIGVtYWlsOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHJlbWVtYmVyOiBib29sZWFuO1xuICBASW5wdXQoKSBvQXV0aFByb3ZpZGVySWRzOiBzdHJpbmdbXSA9IFtdO1xuICBAT3V0cHV0KCkgZW1haWxDaGFuZ2U6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgcmVtZW1iZXJDaGFuZ2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVycm9yOiBFdmVudEVtaXR0ZXI8YXV0aC5FcnJvcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cblxuICBmb3JtSWQgPSAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1tZXRob2RzLWZvcm0tJztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICBmZzogRm9ybUdyb3VwO1xuICBlbWFpbEZjOiBGb3JtQ29udHJvbDtcbiAgcmVtZW1iZXJGYzogRm9ybUNvbnRyb2w7XG4gIGdldE9BdXRoUHJvdmlkZXJJY29uID0gZ2V0T0F1dGhQcm92aWRlckljb247XG4gIGdldE9BdXRoUHJvdmlkZXJOYW1lID0gZ2V0T0F1dGhQcm92aWRlck5hbWU7XG4gIG1ldGhvZHNGb3JFbWFpbDogSVNpZ25Jbk1ldGhvZHNGb3JFbWFpbFJlc3VsdCA9IHtzdGF0dXM6ICd1bmZldGNoZWQnLCBtZXRob2RzOiBbXSwgZW1haWw6IG51bGx9O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2FmQXV0aDogQW5ndWxhckZpcmVBdXRoLFxuICAgIHByaXZhdGUgX2F1dGhTZXJ2aWNlOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgX25nWm9uZTogTmdab25lXG4gICkgeyB9XG5cbiAgZ2V0IGF1dGgoKTogYXV0aC5BdXRoIHtcbiAgICByZXR1cm4gdGhpcy5fYWZBdXRoLmF1dGg7XG4gIH1cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9hdXRoU2VydmljZTtcbiAgfVxuXG5cbiAgZ2V0IG1ldGhvZHMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLm1ldGhvZHNGb3JFbWFpbC5tZXRob2RzO1xuICB9XG5cbiAgZ2V0IGZldGNoU3RhdHVzKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZvckVtYWlsLnN0YXR1cztcbiAgfVxuXG4gIGdldCBtZXRob2RzRmV0Y2hlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRm9yRW1haWwuc3RhdHVzID09PSAnZmV0Y2hlZCc7XG4gIH1cblxuICBnZXQgYWNjb3VudElzTmV3KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1ldGhvZHNGZXRjaGVkICYmIHRoaXMubWV0aG9kcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICBnZXQgYWNjb3VudEV4aXN0cygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRmV0Y2hlZCAmJiB0aGlzLm1ldGhvZHMubGVuZ3RoID4gMDtcbiAgfVxuXG4gIGdldCBhY2NvdW50SGFzUGFzc3dvcmQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuYWNjb3VudEV4aXN0cyAmJiB0aGlzLm1ldGhvZHMuaW5kZXhPZigncGFzc3dvcmQnKSAhPT0gLTE7XG4gIH1cblxuICBnZXQgYWNjb3VudE9BdXRoTWV0aG9kcygpOiBzdHJpbmdbXSB7XG4gICAgaWYgKCEgdGhpcy5hY2NvdW50RXhpc3RzKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm1ldGhvZHMuZmlsdGVyKGlkID0+IGlkICE9PSAncGFzc3dvcmQnKTtcbiAgfVxuXG5cblxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbChcbiAgICAgIHRoaXMuZW1haWwsXG4gICAgICB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMuZW1haWxdfVxuICAgICk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKCgpID0+IHRoaXMucmVtZW1iZXJDaGFuZ2UuZW1pdCh0aGlzLnJlbWVtYmVyRmMudmFsdWUpKTtcbiAgICB0aGlzLmZnID0gbmV3IEZvcm1Hcm91cCh7ZW1haWw6IHRoaXMuZW1haWxGYywgcmVtZW1iZXI6IHRoaXMucmVtZW1iZXJGY30pO1xuICAgIHRoaXMuZW1haWxGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKCgpID0+IHRoaXMuZW1haWxDaGFuZ2UuZW1pdCh0aGlzLmVtYWlsRmMudmFsdWUudHJpbSgpKSk7XG4gICAgdGhpcy5lbWFpbEZjLnZhbHVlQ2hhbmdlcy5waXBlKGRlYm91bmNlVGltZSg1MDApKS5zdWJzY3JpYmUoKCkgPT4gdGhpcy5mZXRjaCgpKTtcbiAgICB0aGlzLmZldGNoKCk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5lbWFpbElucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcblxuICB9XG5cblxuICBmZXRjaCgpIHtcbiAgICBjb25zdCBlbWFpbCA9IHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCk7XG4gICAgaWYgKGVtYWlsID09PSB0aGlzLm1ldGhvZHNGb3JFbWFpbC5lbWFpbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoJ2ZldGNoaW5nJyA9PT0gdGhpcy5tZXRob2RzRm9yRW1haWwuc3RhdHVzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0ge3N0YXR1czogJ2ZldGNoaW5nJywgbWV0aG9kczogW10sIGVtYWlsOiBlbWFpbH07XG4gICAgaWYgKHRoaXMuZW1haWxGYy5pbnZhbGlkKSB7XG4gICAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHtzdGF0dXM6ICd1bmZldGNoZWQnLCBtZXRob2RzOiBbXSwgZW1haWw6IGVtYWlsfTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5hdXRoLmZldGNoU2lnbkluTWV0aG9kc0ZvckVtYWlsKGVtYWlsKVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0ge3N0YXR1czogJ2ZldGNoZWQnLCBtZXRob2RzOiByZXN1bHRzLCBlbWFpbDogZW1haWx9O1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1lbWFpbCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMuZW1haWxGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHtlbWFpbDogdGhpcy5lbWFpbCwgc3RhdHVzOiAndW5mZXRjaGVkJywgbWV0aG9kczogW119O1xuICAgICAgfSk7XG4gIH1cblxufVxuIl19