UNPKG

@nowzoo/ngx-firebase-auth

Version:

Angular components for Firebase email-first sign in and out-of-band (oob) actions (reset password, etc).

1,790 lines 233 kB
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/animations'), require('@angular/core'), require('angularfire2/auth'), require('firebase/app'), require('@angular/router'), require('rxjs'), require('rxjs/operators'), require('@angular/forms'), require('@angular/common')) :
    typeof define === 'function' && define.amd ? define('@nowzoo/ngx-firebase-auth', ['exports', '@angular/animations', '@angular/core', 'angularfire2/auth', 'firebase/app', '@angular/router', 'rxjs', 'rxjs/operators', '@angular/forms', '@angular/common'], factory) :
    (factory((global.nowzoo = global.nowzoo || {}, global.nowzoo['ngx-firebase-auth'] = {}),global.ng.animations,global.ng.core,null,null,global.ng.router,global.rxjs,global.rxjs.operators,global.ng.forms,global.ng.common));
}(this, (function (exports,animations,i0,i1,app,router,rxjs,operators,forms,common) { 'use strict';

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    /** @type {?} */
    var fadeInOutAnimation = animations.trigger('fadeInOut', [
        animations.state('in', animations.style({ opacity: 1, display: 'block' })),
        animations.transition('void => *', [
            animations.style({ opacity: 0 }),
            animations.animate(300)
        ]),
        animations.transition('* => void', [
            animations.animate(300, animations.style({ opacity: 0 }))
        ])
    ]);
    /** @type {?} */
    var screenAnimation = animations.trigger('screen', [
        animations.state('in', animations.style({ opacity: 1 })),
        animations.transition('void => *', [
            animations.style({ opacity: 0 }),
            animations.animate(300)
        ]),
        animations.transition('* => void', [
            animations.animate(0, animations.style({ opacity: 0 }))
        ])
    ]);
    /** @type {?} */
    var getOAuthProviderName = function (id) {
        switch (id) {
            case 'twitter.com': return 'Twitter';
            case 'facebook.com': return 'Facebook';
            case 'google.com': return 'Google';
            case 'github.com': return 'GitHub';
            default: return id;
        }
    };
    /** @type {?} */
    var getOAuthProviderIcon = function (id) {
        switch (id) {
            case 'twitter.com':
            case 'facebook.com':
            case 'google.com':
            case 'github.com':
                return 'fab fa-fw fa-' + id.replace('.com', '');
            default: return 'fas fa-fw fa-sign-in-alt';
        }
    };

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var NgxFirebaseAuthService = (function () {
        function NgxFirebaseAuthService(_afAuth) {
            this._afAuth = _afAuth;
        }
        Object.defineProperty(NgxFirebaseAuthService.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(NgxFirebaseAuthService.prototype, "storage", {
            get: /**
             * @return {?}
             */ function () {
                return window.localStorage;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        NgxFirebaseAuthService.prototype.getRemembered = /**
         * @return {?}
         */
            function () {
                /** @type {?} */
                var str = this.storage.getItem(NgxFirebaseAuthService.rememberKey);
                if (str) {
                    try {
                        return JSON.parse(str);
                    }
                    catch (e) {
                        return { email: '', remember: true };
                    }
                }
                return { email: '', remember: true };
            };
        /**
         * @param {?} remember
         * @param {?} email
         * @return {?}
         */
        NgxFirebaseAuthService.prototype.setRemembered = /**
         * @param {?} remember
         * @param {?} email
         * @return {?}
         */
            function (remember, email) {
                var _this = this;
                /** @type {?} */
                var persistence = remember ?
                    app.auth.Auth.Persistence.LOCAL : app.auth.Auth.Persistence.SESSION;
                return this.auth.setPersistence(persistence)
                    .then(function () {
                    /** @type {?} */
                    var o = {
                        email: remember ? email : '',
                        remember: remember
                    };
                    /** @type {?} */
                    var str = JSON.stringify(o);
                    _this.storage.setItem(NgxFirebaseAuthService.rememberKey, str);
                    return o;
                });
            };
        NgxFirebaseAuthService.rememberKey = 'ngx-firebase-auth-remember';
        NgxFirebaseAuthService.decorators = [
            { type: i0.Injectable, args: [{
                        providedIn: 'root'
                    },] },
        ];
        /** @nocollapse */
        NgxFirebaseAuthService.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth }
            ];
        };
        /** @nocollapse */ NgxFirebaseAuthService.ngInjectableDef = i0.defineInjectable({ factory: function NgxFirebaseAuthService_Factory() { return new NgxFirebaseAuthService(i0.inject(i1.AngularFireAuth)); }, token: NgxFirebaseAuthService, providedIn: "root" });
        return NgxFirebaseAuthService;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var SignInComponent = (function () {
        function SignInComponent(_afAuth, _svc, _route, _router) {
            this._afAuth = _afAuth;
            this._svc = _svc;
            this._route = _route;
            this._router = _router;
            this.ngUnsubscribe = new rxjs.Subject();
            this.tosTemplate = null;
            this.success = new i0.EventEmitter();
            this.mode = new i0.EventEmitter();
            this.initialOAuthError = null;
            this.signedOut = false;
            this.oAuthProviderId = null;
            this.cred = null;
            this.unhandledError = null;
            this.screen = 'wait';
        }
        Object.defineProperty(SignInComponent.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInComponent.prototype, "authService", {
            get: /**
             * @return {?}
             */ function () {
                return this._svc;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInComponent.prototype, "router", {
            get: /**
             * @return {?}
             */ function () {
                return this._router;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInComponent.prototype, "route", {
            get: /**
             * @return {?}
             */ function () {
                return this._route;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInComponent.prototype, "queryParams", {
            get: /**
             * @return {?}
             */ function () {
                return this.route.queryParams;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInComponent.prototype, "snapshotQueryParams", {
            get: /**
             * @return {?}
             */ function () {
                return this.route.snapshot.queryParams;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        SignInComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                this.init();
            };
        /**
         * @return {?}
         */
        SignInComponent.prototype.ngOnDestroy = /**
         * @return {?}
         */
            function () {
                this.ngUnsubscribe.next();
                this.ngUnsubscribe.complete();
            };
        /**
         * @return {?}
         */
        SignInComponent.prototype.init = /**
         * @return {?}
         */
            function () {
                var _this = this;
                /** @type {?} */
                var rememberRecord = this.authService.getRemembered();
                this.remember = rememberRecord.remember;
                this.email = rememberRecord.email;
                return this.onInitHandleSignOut()
                    .then(function (handled) {
                    if (handled) {
                        return handled;
                    }
                    return _this.onInitHandleOAuthRedirect();
                })
                    .then(function (handled) {
                    if (!handled) {
                        _this.showSignIn();
                    }
                    _this.queryParams.pipe(operators.takeUntil(_this.ngUnsubscribe)).subscribe(function (params) {
                        /** @type {?} */
                        var action = params["action"] || null;
                        switch (action) {
                            case 'signOut':
                                _this.showSignOut();
                                break;
                            case 'resetPassword':
                                _this.showResetPassword();
                                break;
                            case 'signIn':
                                _this.showSignIn();
                                break;
                            case 'signInPassword':
                                _this.showSignInPassword();
                                break;
                            case 'signUpPassword':
                                _this.showSignUpPassword();
                                break;
                            case 'signInOAuth':
                                _this.showSignInOAuth(params["providerId"], null);
                                break;
                        }
                    });
                });
            };
        /**
         * @return {?}
         */
        SignInComponent.prototype.onInitHandleSignOut = /**
         * @return {?}
         */
            function () {
                if (this.snapshotQueryParams["action"] !== 'signOut') {
                    return Promise.resolve(false);
                }
                return this.showSignOut().then(function () { return true; });
            };
        /**
         * @return {?}
         */
        SignInComponent.prototype.onInitHandleOAuthRedirect = /**
         * @return {?}
         */
            function () {
                var _this = this;
                return new Promise(function (resolve) {
                    /** @type {?} */
                    var remember = _this.route.snapshot.queryParams["remember"] === 'true';
                    return _this.auth.getRedirectResult()
                        .then(function (cred) {
                        if (_this.auth.currentUser && cred.user) {
                            _this.authService.setRemembered(remember, cred.user.email)
                                .then(function () {
                                _this.showSignInSuccess(cred);
                                resolve(true);
                            });
                        }
                        else {
                            resolve(false);
                        }
                    })
                        .catch(function (error) {
                        _this.showSignInOAuth(null, error);
                        resolve(true);
                    });
                });
            };
        /**
         * @return {?}
         */
        SignInComponent.prototype.showSignOut = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.signedOut = false;
                this.screen = 'wait';
                return this.auth.signOut()
                    .then(function () {
                    _this.showSignIn(true);
                });
            };
        /**
         * @param {?=} signedOut
         * @return {?}
         */
        SignInComponent.prototype.showSignIn = /**
         * @param {?=} signedOut
         * @return {?}
         */
            function (signedOut) {
                this.mode.emit('signIn');
                this.signedOut = signedOut === true;
                this.screen = 'signIn';
            };
        /**
         * @return {?}
         */
        SignInComponent.prototype.showSignInPassword = /**
         * @return {?}
         */
            function () {
                this.mode.emit('signIn');
                this.signedOut = false;
                this.screen = 'signInPassword';
            };
        /**
         * @return {?}
         */
        SignInComponent.prototype.showSignUpPassword = /**
         * @return {?}
         */
            function () {
                this.mode.emit('signIn');
                this.signedOut = false;
                this.screen = 'signUpPassword';
            };
        /**
         * @param {?} oAuthProviderId
         * @param {?} error
         * @return {?}
         */
        SignInComponent.prototype.showSignInOAuth = /**
         * @param {?} oAuthProviderId
         * @param {?} error
         * @return {?}
         */
            function (oAuthProviderId, error) {
                this.mode.emit('signIn');
                this.signedOut = false;
                this.oAuthProviderId = oAuthProviderId;
                this.initialOAuthError = error;
                this.screen = 'signInOAuth';
            };
        /**
         * @param {?} cred
         * @return {?}
         */
        SignInComponent.prototype.showSignInSuccess = /**
         * @param {?} cred
         * @return {?}
         */
            function (cred) {
                this.mode.emit('signIn');
                this.signedOut = false;
                this.cred = cred;
                this.screen = 'signInSuccess';
                this.success.emit(cred);
            };
        /**
         * @return {?}
         */
        SignInComponent.prototype.showResetPassword = /**
         * @return {?}
         */
            function () {
                this.mode.emit('resetPassword');
                this.signedOut = false;
                this.screen = 'resetPassword';
            };
        /**
         * @param {?} error
         * @return {?}
         */
        SignInComponent.prototype.showUnhandledError = /**
         * @param {?} error
         * @return {?}
         */
            function (error) {
                this.signedOut = false;
                this.unhandledError = error;
                this.screen = 'unhandledError';
            };
        SignInComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-sign-in',
                        template: "<div *ngIf=\"'wait' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-secondary\">\n    <i class=\"fas fa-spin fa-spinner fa-fw\" aria-hidden=\"true\"></i>\n    Please wait...\n  </div>\n</div>\n\n<div *ngIf=\"'unhandledError' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-danger\">\n    <i class=\"fas fa-exclamation-triangle fa-fw text-danger\" aria-hidden=\"true\"></i>\n    <strong>Woops!</strong> An unexpected error occurred.\n  </div>\n  <p class=\"text-muted\">\n    Code: {{unhandledError.code}}. Message: {{unhandledError.message}}\n  </p>\n  <p>\n    <a routerLink=\".\" [queryParams]=\"{action: 'signIn'}\">Start Over</a>\n  </p>\n</div>\n\n\n<div *ngIf=\"'signInSuccess' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-success\">\n    <i class=\"fas fa-check fa-fw\" aria-hidden=\"true\"></i>\n    Welcome, {{cred.user.displayName}}!\n  </div>\n</div>\n\n\n\n\n<div *ngIf=\"'signIn' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-success\" *ngIf=\"signedOut\">\n    <i class=\"fas fa-check fa-fw\" aria-hidden=\"true\"></i>\n    You\u2019re signed out.\n  </div>\n  <ngx-firebase-auth-sign-in-methods-form\n    [(email)]=\"email\"\n    [(remember)]=\"remember\"\n    [oAuthProviderIds]=\"oAuthProviderIds\"\n    (error)=\"showUnhandledError($event)\"\n    (success)=\"showSignInSuccess($event)\"></ngx-firebase-auth-sign-in-methods-form>\n  <small class=\"text-center text-muted my-2 form-text\">\n    <ng-container *ngTemplateOutlet=\"tosTemplate\"></ng-container>\n  </small>\n</div>\n\n<div *ngIf=\"'signInPassword' === screen\" [@screen]=\"'in'\">\n  <ngx-firebase-auth-sign-in-form\n    [email]=\"email\"\n    [(remember)]=\"remember\"\n    (error)=\"showUnhandledError($event)\"\n    (success)=\"showSignInSuccess($event)\"></ngx-firebase-auth-sign-in-form>\n  <small class=\"text-center text-muted my-2 form-text\">\n    <ng-container *ngTemplateOutlet=\"tosTemplate\"></ng-container>\n  </small>\n</div>\n\n<div *ngIf=\"'signUpPassword' === screen\" [@screen]=\"'in'\">\n  <ngx-firebase-auth-sign-up-form\n    [email]=\"email\"\n    [(remember)]=\"remember\"\n    (error)=\"showUnhandledError($event)\"\n    (success)=\"showSignInSuccess($event)\"></ngx-firebase-auth-sign-up-form>\n  <small class=\"text-center text-muted my-2 form-text\">\n    <ng-container *ngTemplateOutlet=\"tosTemplate\"></ng-container>\n  </small>\n</div>\n\n<div *ngIf=\"'signInOAuth' === screen\" [@screen]=\"'in'\">\n  <ngx-firebase-auth-sign-in-oauth\n    [providerId]=\"oAuthProviderId\"\n    [initialError]=\"initialOAuthError\"\n    [useOAuthPopup]=\"useOAuthPopup\"\n    [oAuthProviderFactory]=\"oAuthProviderFactory\"\n    [(email)]=\"email\"\n    [(remember)]=\"remember\"\n    (error)=\"showUnhandledError($event)\"\n    (success)=\"showSignInSuccess($event)\"></ngx-firebase-auth-sign-in-oauth>\n  <small class=\"text-center text-muted my-2 form-text\">\n    <ng-container *ngTemplateOutlet=\"tosTemplate\"></ng-container>\n  </small>\n</div>\n\n\n\n<div *ngIf=\"'resetPassword' === screen\" [@screen]=\"'in'\">\n  <h6>Reset Password</h6>\n  <ngx-firebase-auth-reset-password-send-form\n    [(email)]=\"email\"\n    (error)=\"showUnhandledError($event)\"></ngx-firebase-auth-reset-password-send-form>\n</div>\n",
                        styles: [""],
                        animations: [screenAnimation]
                    },] },
        ];
        /** @nocollapse */
        SignInComponent.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth },
                { type: NgxFirebaseAuthService },
                { type: router.ActivatedRoute },
                { type: router.Router }
            ];
        };
        SignInComponent.propDecorators = {
            oAuthProviderIds: [{ type: i0.Input }],
            useOAuthPopup: [{ type: i0.Input }],
            oAuthProviderFactory: [{ type: i0.Input }],
            tosTemplate: [{ type: i0.Input }],
            success: [{ type: i0.Output }],
            mode: [{ type: i0.Output }]
        };
        return SignInComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var OobComponent = (function () {
        function OobComponent(_route) {
            this._route = _route;
            this.screen = null;
            this.mode = new i0.EventEmitter();
            this.navigationError = new i0.EventEmitter();
            this.success = new i0.EventEmitter();
        }
        Object.defineProperty(OobComponent.prototype, "queryParams", {
            get: /**
             * @return {?}
             */ function () {
                return this._route.snapshot.queryParams;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        OobComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                this.oobCode = this.queryParams["oobCode"] || null;
                if (!this.oobCode) {
                    this.navigationError.emit();
                    return;
                }
                switch (this.queryParams["mode"]) {
                    case 'resetPassword':
                    case 'verifyEmail':
                    case 'recoverEmail':
                        this.screen = this.queryParams["mode"];
                        this.mode.emit(this.queryParams["mode"]);
                        break;
                    default:
                        this.navigationError.emit();
                        break;
                }
            };
        OobComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-oob',
                        template: "<div *ngIf=\"'resetPassword' === screen\" [@screen]=\"'in'\">\n  <ngx-firebase-auth-oob-reset-password\n    [oobCode]=\"oobCode\"\n    (success)=\"success.emit($event)\"></ngx-firebase-auth-oob-reset-password>\n</div>\n\n<div *ngIf=\"'verifyEmail' === screen\" [@screen]=\"'in'\">\n  <ngx-firebase-auth-oob-verify-email\n    [oobCode]=\"oobCode\"\n    (success)=\"success.emit($event)\"></ngx-firebase-auth-oob-verify-email>\n</div>\n\n<div *ngIf=\"'recoverEmail' === screen\" [@screen]=\"'in'\">\n  <ngx-firebase-auth-oob-recover-email\n    [oobCode]=\"oobCode\"\n    (success)=\"success.emit($event)\"></ngx-firebase-auth-oob-recover-email>\n</div>\n",
                        styles: [""],
                        animations: [screenAnimation]
                    },] },
        ];
        /** @nocollapse */
        OobComponent.ctorParameters = function () {
            return [
                { type: router.ActivatedRoute }
            ];
        };
        OobComponent.propDecorators = {
            mode: [{ type: i0.Output }],
            navigationError: [{ type: i0.Output }],
            success: [{ type: i0.Output }]
        };
        return OobComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var NgxFirebaseAuthFormHelper = (function () {
        function NgxFirebaseAuthFormHelper() {
        }
        /**
         * @param {?} fc
         * @param {?} key
         * @param {?=} value
         * @return {?}
         */
        NgxFirebaseAuthFormHelper.setErrorUntilChanged = /**
         * @param {?} fc
         * @param {?} key
         * @param {?=} value
         * @return {?}
         */
            function (fc, key, value) {
                if (value === void 0) {
                    value = true;
                }
                /** @type {?} */
                var error = {};
                error[key] = value;
                fc.setErrors(error);
                fc.valueChanges.pipe(operators.take(1)).subscribe(function () {
                    NgxFirebaseAuthFormHelper.clearError(fc, key);
                });
            };
        /**
         * @param {?} fc
         * @param {?} key
         * @return {?}
         */
        NgxFirebaseAuthFormHelper.clearError = /**
         * @param {?} fc
         * @param {?} key
         * @return {?}
         */
            function (fc, key) {
                /** @type {?} */
                var errors = {};
                if (!fc.errors) {
                    return;
                }
                Object.keys(fc.errors).forEach(function (k) {
                    if (k !== key) {
                        errors[k] = fc.errors[k];
                    }
                });
                if (Object.keys(errors).length === 0) {
                    fc.setErrors(null);
                }
                else {
                    fc.setErrors(errors);
                }
            };
        /**
         * @param {?} fc
         * @return {?}
         */
        NgxFirebaseAuthFormHelper.requiredNonEmpty = /**
         * @param {?} fc
         * @return {?}
         */
            function (fc) {
                /** @type {?} */
                var value = fc.value;
                if (typeof value !== 'string') {
                    return null;
                }
                return value.trim().length === 0 ? { required: true } : null;
            };
        return NgxFirebaseAuthFormHelper;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var SignInMethodsFormComponent = (function () {
        function SignInMethodsFormComponent(_afAuth, _authService, _ngZone) {
            this._afAuth = _afAuth;
            this._authService = _authService;
            this._ngZone = _ngZone;
            this.oAuthProviderIds = [];
            this.emailChange = new i0.EventEmitter();
            this.rememberChange = new i0.EventEmitter();
            this.success = new i0.EventEmitter();
            this.error = new i0.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 forms.FormControl(this.email, { validators: [forms.Validators.required, forms.Validators.email] });
                this.rememberFc = new forms.FormControl(this.remember);
                this.rememberFc.valueChanges.subscribe(function () { return _this.rememberChange.emit(_this.rememberFc.value); });
                this.fg = new forms.FormGroup({ email: this.emailFc, remember: this.rememberFc });
                this.emailFc.valueChanges.subscribe(function () { return _this.emailChange.emit(_this.emailFc.value.trim()); });
                this.emailFc.valueChanges.pipe(operators.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: i0.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: i1.AngularFireAuth },
                { type: NgxFirebaseAuthService },
                { type: i0.NgZone }
            ];
        };
        SignInMethodsFormComponent.propDecorators = {
            emailInput: [{ type: i0.ViewChild, args: ['emailInput',] }],
            email: [{ type: i0.Input }],
            remember: [{ type: i0.Input }],
            oAuthProviderIds: [{ type: i0.Input }],
            emailChange: [{ type: i0.Output }],
            rememberChange: [{ type: i0.Output }],
            success: [{ type: i0.Output }],
            error: [{ type: i0.Output }]
        };
        return SignInMethodsFormComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var SignInFormComponent = (function () {
        function SignInFormComponent(_afAuth, _authService) {
            this._afAuth = _afAuth;
            this._authService = _authService;
            this.rememberChange = new i0.EventEmitter();
            this.success = new i0.EventEmitter();
            this.error = new i0.EventEmitter();
            this.formId = 'ngx-firebase-auth-sign-in-form-';
            this.submitting = false;
            this.methodsForEmail = [];
            this.getOAuthProviderIcon = getOAuthProviderIcon;
            this.getOAuthProviderName = getOAuthProviderName;
        }
        Object.defineProperty(SignInFormComponent.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInFormComponent.prototype, "authService", {
            get: /**
             * @return {?}
             */ function () {
                return this._authService;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        SignInFormComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.emailFc = new forms.FormControl(this.email, { validators: [forms.Validators.required, forms.Validators.email] });
                this.passwordFc = new forms.FormControl('', { validators: [forms.Validators.required] });
                this.rememberFc = new forms.FormControl(this.remember);
                this.rememberFc.valueChanges.subscribe(function (val) { return _this.rememberChange.emit(val); });
                this.fg = new forms.FormGroup({
                    email: this.emailFc,
                    password: this.passwordFc,
                    remember: this.rememberFc
                });
            };
        /**
         * @return {?}
         */
        SignInFormComponent.prototype.ngAfterViewInit = /**
         * @return {?}
         */
            function () {
                this.passwordInput.nativeElement.focus();
            };
        /**
         * @return {?}
         */
        SignInFormComponent.prototype.submit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                /** @type {?} */
                var email = this.emailFc.value.trim();
                this.submitting = true;
                this.methodsForEmail = [];
                /** @type {?} */
                var cred;
                this.auth.fetchSignInMethodsForEmail(email)
                    .then(function (results) {
                    _this.methodsForEmail = results;
                    if (results.length === 0) {
                        return Promise.reject({
                            code: 'auth/user-not-found'
                        });
                    }
                    if (results.indexOf('password') === -1) {
                        return Promise.reject({
                            code: 'ngx-firebase-auth/no-password',
                        });
                    }
                    return _this.auth.signInWithEmailAndPassword(email, _this.passwordFc.value);
                })
                    .then(function (result) {
                    cred = result;
                    return _this.authService.setRemembered(_this.rememberFc.value === true, email);
                })
                    .then(function () {
                    _this.success.emit(cred);
                })
                    .catch(function (error) {
                    _this.submitting = false;
                    _this.emailFc.markAsDirty();
                    _this.emailFc.markAsTouched();
                    _this.passwordFc.markAsDirty();
                    _this.passwordFc.markAsTouched();
                    switch (error.code) {
                        case 'auth/invalid-email':
                        case 'auth/user-not-found':
                        case 'auth/user-disabled':
                        case 'ngx-firebase-auth/no-password':
                            NgxFirebaseAuthFormHelper.setErrorUntilChanged(_this.emailFc, error.code);
                            break;
                        case 'auth/wrong-password':
                            NgxFirebaseAuthFormHelper.setErrorUntilChanged(_this.passwordFc, error.code);
                            break;
                        default:
                            _this.error.emit(error);
                            break;
                    }
                });
            };
        SignInFormComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-sign-in-form',
                        template: "<form [formGroup]=\"fg\" (ngSubmit)=\"submit()\">\n\n  <div class=\"form-group\">\n    <label [attr.for]=\"formId + 'email'\">Email Address</label>\n\n    <input\n      readonly\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      class=\"form-control\">\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('required')\">\n      Required.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('email')\">\n      Invalid email.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('auth/invalid-email')\">\n      Invalid email.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('auth/user-not-found')\">\n      We could not find an account with that email address.\n      <a routerLink=\".\" [queryParams]=\"{action: 'signIn'}\">Create Account</a>\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('auth/user-disabled')\">\n      The account with that email address has been disabled.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('ngx-firebase-auth/no-password')\">\n      The account with that email address does not have a password.\n      Please sign in using:\n      <span *ngFor=\"let id of methodsForEmail; let isLast = last\">\n        <a routerLink=\".\" [queryParams]=\"{action: 'signInOAuth', providerId: id}\">{{getOAuthProviderName(id)}}</a>\n        <span *ngIf=\"!isLast\">\n          |\n        </span>\n      </span>\n    </div>\n\n    <small class=\"text-muted form-text\" [attr.id]=\"formId + 'email'\" >\n      Not your email address?\n      <a routerLink=\".\" [queryParams]=\"{action: 'signIn'}\">Start Over</a>\n    </small>\n  </div>\n\n\n  <div class=\"form-group\">\n    <div class=\"d-flex justify-content-between align-items-end\">\n      <label [attr.for]=\"formId + 'password'\">Password</label>\n      <small>\n        <a (click)=\"$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type  ? 'text' : 'password'\"\n          href=\"#\" tabindex=\"-1\" class=\"d-inline-block\">\n          <span *ngIf=\"'password' === passwordInput.type\">Show</span>\n          <span *ngIf=\"'text' === passwordInput.type\">Hide</span>\n        </a>\n      </small>\n    </div>\n    <input\n      #passwordInput\n      [attr.id]=\"formId + 'password'\"\n      [attr.aria-describedby]=\"formId + 'password-help'\"\n      type=\"password\"\n      formControlName=\"password\"\n      placeholder=\"Password\"\n      autocomplete=\"password\"\n      class=\"form-control\"\n      [class.is-invalid]=\"passwordFc.touched && passwordFc.invalid\">\n    <div class=\"invalid-feedback\"\n      *ngIf=\"passwordFc.touched && passwordFc.hasError('required')\"\n      [@fadeInOut]=\"'in'\">\n      Required.\n    </div>\n    <div class=\"invalid-feedback\"\n      *ngIf=\"passwordFc.touched && passwordFc.hasError('auth/wrong-password')\"\n      [@fadeInOut]=\"'in'\">\n      Wrong password.\n    </div>\n    <small [attr.id]=\"formId + 'password-help'\" class=\"form-text text-muted\">\n      Forgot? <a routerLink=\".\" [queryParams]=\"{action: 'resetPassword'}\">Reset Password</a>\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  <div class=\"form-group\">\n    <button type=\"submit\"\n      class=\"btn btn-success btn-block\"\n      [disabled]=\"fg.invalid || submitting\">\n      <i class=\"fas fa-lock fa-fw\" aria-hidden=\"true\"></i>\n      Sign In\n    </button>\n  </div>\n</form>\n",
                        styles: [""],
                        animations: [fadeInOutAnimation]
                    },] },
        ];
        /** @nocollapse */
        SignInFormComponent.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth },
                { type: NgxFirebaseAuthService }
            ];
        };
        SignInFormComponent.propDecorators = {
            passwordInput: [{ type: i0.ViewChild, args: ['passwordInput',] }],
            email: [{ type: i0.Input }],
            remember: [{ type: i0.Input }],
            rememberChange: [{ type: i0.Output }],
            success: [{ type: i0.Output }],
            error: [{ type: i0.Output }]
        };
        return SignInFormComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var SignUpFormComponent = (function () {
        function SignUpFormComponent(_afAuth, _authService) {
            this._afAuth = _afAuth;
            this._authService = _authService;
            this.rememberChange = new i0.EventEmitter();
            this.success = new i0.EventEmitter();
            this.error = new i0.EventEmitter();
            this.formId = 'ngx-firebase-auth-sign-up-form-';
            this.submitting = false;
        }
        Object.defineProperty(SignUpFormComponent.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignUpFormComponent.prototype, "authService", {
            get: /**
             * @return {?}
             */ function () {
                return this._authService;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        SignUpFormComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.emailFc = new forms.FormControl(this.email, { validators: [forms.Validators.required, forms.Validators.email] });
                this.passwordFc = new forms.FormControl('', { validators: [forms.Validators.required] });
                this.nameFc = new forms.FormControl('', { validators: [forms.Validators.required, NgxFirebaseAuthFormHelper.requiredNonEmpty] });
                this.rememberFc = new forms.FormControl(this.remember);
                this.rememberFc.valueChanges.subscribe(function (val) { return _this.rememberChange.emit(val); });
                this.fg = new forms.FormGroup({
                    email: this.emailFc,
                    password: this.passwordFc,
                    name: this.nameFc,
                    remember: this.rememberFc
                });
            };
        /**
         * @return {?}
         */
        SignUpFormComponent.prototype.ngAfterViewInit = /**
         * @return {?}
         */
            function () {
                this.passwordInput.nativeElement.focus();
            };
        /**
         * @return {?}
         */
        SignUpFormComponent.prototype.submit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.submitting = true;
                /** @type {?} */
                var cred;
                this.auth.fetchSignInMethodsForEmail(this.email)
                    .then(function (results) {
                    if (results.length > 0) {
                        return Promise.reject({
                            code: 'ngx-firebase-auth/account-exists'
                        });
                    }
                    return _this.auth.createUserWithEmailAndPassword(_this.email, _this.passwordFc.value);
                })
                    .then(function (result) {
                    cred = result;
                    return cred.user.updateProfile({ displayName: _this.nameFc.value.trim(), photoURL: null });
                })
                    .then(function () {
                    return _this.authService.setRemembered(_this.rememberFc.value === true, _this.email);
                })
                    .then(function () {
                    _this.success.emit(cred);
                })
                    .catch(function (error) {
                    _this.submitting = false;
                    _this.emailFc.markAsDirty();
                    _this.emailFc.markAsTouched();
                    _this.passwordFc.markAsDirty();
                    _this.passwordFc.markAsTouched();
                    switch (error.code) {
                        case 'auth/invalid-email':
                        case 'ngx-firebase-auth/account-exists':
                            NgxFirebaseAuthFormHelper.setErrorUntilChanged(_this.emailFc, error.code);
                            break;
                        case 'auth/weak-password':
                            NgxFirebaseAuthFormHelper.setErrorUntilChanged(_this.passwordFc, error.code);
                            break;
                        default:
                            _this.error.emit(error);
                            break;
                    }
                });
            };
        SignUpFormComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-sign-up-form',
                        template: "<form [formGroup]=\"fg\" (ngSubmit)=\"submit()\">\n  <div class=\"form-group\">\n    <label [attr.for]=\"formId + 'email'\">Email Address</label>\n    <input\n      readonly\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      class=\"form-control\">\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('required')\">\n      Required.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('email')\">\n      Invalid email.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('auth/invalid-email')\">\n      Invalid email.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.hasError('ngx-firebase-auth/account-exists')\">\n      We found an account with that email address.\n      <a routerLink=\".\" [queryParams]=\"{action: 'signIn'}\">Sign In</a>\n    </div>\n    <small class=\"text-muted form-text\" [attr.id]=\"formId + 'email'\" >\n      Not your email address?\n      <a routerLink=\".\" [queryParams]=\"{action: 'signIn'}\">Go Back</a>\n    </small>\n  </div>\n\n  <div class=\"form-group\">\n    <div class=\"d-flex justify-content-between align-items-end\">\n      <label [attr.for]=\"formId + 'password'\">Choose Password</label>\n      <small>\n        <a (click)=\"$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type  ? 'text' : 'password'\"\n          href=\"#\" tabindex=\"-1\" class=\"d-inline-block\">\n          <span *ngIf=\"'password' === passwordInput.type\">Show</span>\n          <span *ngIf=\"'text' === passwordInput.type\">Hide</span>\n        </a>\n      </small>\n    </div>\n    <input\n      #passwordInput\n      [attr.id]=\"formId + 'password'\"\n      [attr.aria-describedby]=\"formId + 'password-help'\"\n      type=\"password\"\n      formControlName=\"password\"\n      placeholder=\"Choose Password\"\n      autocomplete=\"password\"\n      class=\"form-control\"\n      [class.is-invalid]=\"passwordFc.touched && passwordFc.invalid\">\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"passwordFc.touched && passwordFc.hasError('required')\">\n      Required.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"passwordFc.touched && passwordFc.hasError('auth/wrong-password')\">\n      Wrong password.\n    </div>\n    <small [attr.id]=\"formId + 'password-help'\" class=\"form-text text-muted\">\n      Please choose a strong password.\n    </small>\n  </div>\n  <div class=\"form-group\">\n    <label [attr.for]=\"formId + 'name'\">Your Name</label>\n    <input\n      [attr.id]=\"formId + 'name'\"\n      type=\"text\"\n      formControlName=\"name\"\n      placeholder=\"Your Name\"\n      class=\"form-control\"\n      [class.is-invalid]=\"nameFc.touched && nameFc.invalid\">\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"nameFc.touched && nameFc.hasError('required')\">\n      Required.\n    </div>\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  <div class=\"form-group\">\n    <button type=\"submit\"\n      class=\"btn btn-success btn-block\"\n      [disabled]=\"fg.invalid || submitting\">\n      <i class=\"fas fa-lock fa-fw\" aria-hidden=\"true\"></i>\n      Create Account\n    </button>\n  </div>\n</form>\n",
                        styles: [""],
                        animations: [fadeInOutAnimation]
                    },] },
        ];
        /** @nocollapse */
        SignUpFormComponent.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth },
                { type: NgxFirebaseAuthService }
            ];
        };
        SignUpFormComponent.propDecorators = {
            passwordInput: [{ type: i0.ViewChild, args: ['passwordInput',] }],
            email: [{ type: i0.Input }],
            remember: [{ type: i0.Input }],
            rememberChange: [{ type: i0.Output }],
            success: [{ type: i0.Output }],
            error: [{ type: i0.Output }]
        };
        return SignUpFormComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var ResetPasswordSendFormComponent = (function () {
        function ResetPasswordSendFormComponent(_afAuth) {
            this._afAuth = _afAuth;
            this.emailChange = new i0.EventEmitter();
            this.error = new i0.EventEmitter();
            this.formId = 'ngx-firebase-auth-reset-password-send-form-';
            this.submitting = false;
            this.sent = null;
        }
        Object.defineProperty(ResetPasswordSendFormComponent.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        ResetPasswordSendFormComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.emailFc = new forms.FormControl(this.email, { validators: [forms.Validators.required, forms.Validators.email] });
                this.emailFc.valueChanges.subscribe(function () { return _this.emailChange.emit(_this.emailFc.value.trim()); });
                this.fg = new forms.FormGroup({ email: this.emailFc });
            };
        /**
         * @return {?}
         */
        ResetPasswordSendFormComponent.prototype.ngAfterViewInit = /**
         * @return {?}
         */
            function () {
                this.emailInput.nativeElement.focus();
            };
        /**
         * @return {?}
         */
        ResetPasswordSendFormComponent.prototype.submit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                /** @type {?} */
                var email = this.emailFc.value.trim();
                this.submitting = true;
                this.sent = null;
                this.auth.sendPasswordResetEmail(email)
                    .then(function () {
                    _this.submitting = false;
                    _this.sent = email;
                })
                    .catch(function (error) {
                    _this.submitting = false;
                    _this.emailFc.markAsTouched();
                    _this.emailFc.markAsDirty();
                    switch (error.code) {
                        case 'auth/invalid-email':
                        case 'auth/user-not-found':
                            NgxFirebaseAuthFormHelper.setErrorUntilChanged(_this.emailFc, error.code);
                            break;
                        default:
                            _this.error.emit(error);
                            break;
                    }
                });
            };
        ResetPasswordSendFormComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-reset-password-send-form',
                        template: "<form [formGroup]=\"fg\" (ngSubmit)=\"submit()\">\n  <div *ngIf=\"sent\" [@fadeInOut]=\"'in'\">\n    <div class=\"alert alert-success\">\n      <i class=\"fas fa-check fa-fw\" aria-hidden=\"true\"></i>\n      We\u2019ve sent a reset password link to {{sent}}.\n      Please allow a few moments for the email to arrive.\n    </div>\n  </div>\n\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-help'\"\n      type=\"email\"\n      formControlName=\"email\"\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('auth/user-not-found')\">\n      We could not find an account with that email address.\n      Please <a routerLink=\".\" [queryParams]=\"{action: 'signIUpPassword'}\">sign up</a>.\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 [attr.id]=\"formId + 'email-help'\" class=\"form-text text-muted\">\n      Enter the email address you used to sign up. We\u2019ll\n      send a reset password link to that address.\n    </small>\n  </div>\n  <div class=\"form-group\">\n    <button type=\"submit\"\n      class=\"btn btn-block btn-success\"\n      [disabled]=\"fg.invalid || submitting\">\n      <i class=\"fas fa-fw fa-envelope\" aria-hidden=\"true\"></i>\n      Send Link\n    </button>\n  </div>\n</form>\n",
                        styles: [""],
                        animations: [fadeInOutAnimation]
                    },] },
        ];
        /** @nocollapse */
        ResetPasswordSendFormComponent.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth }
            ];
        };
        ResetPasswordSendFormComponent.propDecorators = {
            emailInput: [{ type: i0.ViewChild, args: ['emailInput',] }],
            email: [{ type: i0.Input }],
            emailChange: [{ type: i0.Output }],
            error: [{ type: i0.Output }]
        };
        return ResetPasswordSendFormComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var SignInOauthComponent = (function () {
        function SignInOauthComponent(_afAuth, _svc, _route, _router) {
            this._afAuth = _afAuth;
            this._svc = _svc;
            this._route = _route;
            this._router = _router;
            this.success = new i0.EventEmitter();
            this.emailChange = new i0.EventEmitter();
            this.rememberChange = new i0.EventEmitter();
            this.error = new i0.EventEmitter();
            this.screen = 'wait';
            this.methodError = null;
            this.getOAuthProviderIcon = getOAuthProviderIcon;
            this.getOAuthProviderName = getOAuthProviderName;
            this.formId = 'ngx-firebase-auth-sign-in-oauth-';
        }
        Object.defineProperty(SignInOauthComponent.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInOauthComponent.prototype, "authService", {
            get: /**
             * @return {?}
             */ function () {
                return this._svc;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInOauthComponent.prototype, "route", {
            get: /**
             * @return {?}
             */ function () {
                return this._route;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(SignInOauthComponent.prototype, "router", {
            get: /**
             * @return {?}
             */ function () {
                return this._router;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        SignInOauthComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.rememberFc = new forms.FormControl(this.remember);
                this.rememberFc.valueChanges.subscribe(function (val) { return _this.rememberChange.emit(val); });
                this.fg = new forms.FormGroup({
                    remember: this.rememberFc
                });
                if (this.initialError) {
                    this.handleOAuthError(this.initialError);
                }
                else {
                    this.oAuthSignIn(this.providerId);
                }
            };
        /**
         * @param {?} id
         * @param {?=} forceRedirect
         * @return {?}
         */
        SignInOauthComponent.prototype.oAuthSignIn = /**
         * @param {?} id
         * @param {?=} forceRedirect
         * @return {?}
         */
            function (id, forceRedirect) {
                var _this = this;
                this.methodError = null;
                /** @type {?} */
                var cred;
                if (this.useOAuthPopup && forceRedirect !== true) {
                    this.getOAuthProvider(id)
                        .then(function (provider) {
                        return _this.auth.signInWithPopup(provider);
                    })
                        .then(function (result) {
                        cred = result;
                        return _this.authService.setRemembered(_this.rememberFc.value === true, result.user.email);
                    })
                        .then(function () {
                        _this.success.emit(cred);
                    })
                        .catch(function (error) { return _this.handleOAuthError(error, id); });
                }
                else {
                    this.router.navigate(['.'], { relativeTo: this.route, queryParams: { remember: this.rememberFc.value === true } })
                        .then(function () {
                        return _this.getOAuthProvider(id);
                    })
                        .then(function (provider) {
                        return _this.auth.signInWithRedirect(provider);
                    })
                        .catch(function (error) { return _this.handleOAuthError(error, id); });
                }
            };
        /**
         * @param {?} error
         * @param {?=} providerId
         * @return {?}
         */
        SignInOauthComponent.prototype.handleOAuthError = /**
         * @param {?} error
         * @param {?=} providerId
         * @return {?}
         */
            function (error, providerId) {
                var _this = this;
                if (error['email'] && error['credential']) {
                    this.emailChange.emit(error['email']);
                    this.auth.fetchSignInMethodsForEmail(error['email'])
                        .then(function (results) {
                        error['methods'] = results;
                        error['accountHasPassword'] = results.indexOf('password') !== -1;
                        error['accountOAuthMethods'] = results.filter(function (id) { return id !== 'password'; });
                        _this.methodError = error;
                        _this.screen = 'methodError';
                    });
                    return;
                }
                switch (error.code) {
                    case 'auth/cancelled-popup-request':
                    case 'auth/popup-closed-by-user':
                        this.screen = 'retry';
                        break;
                    case 'auth/popup-blocked':
                        this.oAuthSignIn(providerId, true);
                        break;
                    default:
                        this.error.emit(error);
                        break;
                }
            };
        /**
         * @param {?} id
         * @return {?}
         */
        SignInOauthComponent.prototype.getOAuthProvider = /**
         * @param {?} id
         * @return {?}
         */
            function (id) {
                /** @type {?} */
                var provider = null;
                if (this.oAuthProviderFactory) {
                    provider = this.oAuthProviderFactory(id);
                }
                if (!provider) {
                    switch (id) {
                        case 'twitter.com':
                            provider = new app.auth.TwitterAuthProvider();
                            break;
                        case 'facebook.com':
                            provider = new app.auth.FacebookAuthProvider();
                            break;
                        case 'google.com':
                            provider = new app.auth.GoogleAuthProvider();
                            break;
                        case 'github.com':
                            provider = new app.auth.GithubAuthProvider();
                            break;
                    }
                }
                if (provider) {
                    return Promise.resolve(provider);
                }
                else {
                    return Promise.reject({
                        code: 'ngx-firebase-auth/no-provider-found',
                        message: "We could not create an OAuth provider for provider id \"" + id + "\"."
                    });
                }
            };
        SignInOauthComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-sign-in-oauth',
                        template: "<div *ngIf=\"'wait' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-secondary\">\n    <i class=\"fas fa-spin fa-spinner fa-fw\" aria-hidden=\"true\"></i>\n    Please wait...\n  </div>\n</div>\n\n<div *ngIf=\"'methodError' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-danger\">\n    <i class=\"fas fa-exclamation-triangle fa-fw\" aria-hidden=\"true\"></i>\n    We could not sign you in with {{methodError.credential.providerId}}.\n  </div>\n\n  <p class=\"text-muted\">\n    Please sign in with one of the methods associated with\n    {{methodError.email}}:\n  </p>\n\n  <div class=\"list-group\">\n    <a\n      *ngIf=\"methodError.accountHasPassword\"\n      routerLink=\".\"\n      [queryParams]=\"{action: 'signInPassword'}\"\n      class=\"list-group-item list-group-item-action\">\n      <i class=\"fas fa-unlock\" aria-hidden=\"true\"></i>\n      <span class=\"ml-2\">Sign In with Your Password</span>\n    </a>\n    <button\n      *ngFor=\"let id of methodError.accountOAuthMethods\"\n      (click)=\"oAuthSignIn(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\">Sign In with {{getOAuthProviderName(id)}}</span>\n    </button>\n  </div>\n\n  <form [formGroup]=\"fg\">\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\n  <p class=\"text-muted\">\n    Is {{methodError.email}} not your email address?\n    <a routerLink=\".\" [queryParams]=\"{action: 'signIn'}\">Start Over</a>\n  </p>\n\n</div>\n\n<div *ngIf=\"'retry' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-danger\">\n    <i class=\"fas fa-exclamation-triangle fa-fw\" aria-hidden=\"true\"></i>\n    It looks like you cancelled signing in with\n    {{getOAuthProviderName(providerId)}}. Try again:\n  </div>\n\n  <div class=\"list-group\">\n    <button\n      (click)=\"oAuthSignIn(providerId)\"\n      class=\"list-group-item list-group-item-action\">\n      <i [attr.class]=\"getOAuthProviderIcon(providerId)\" aria-hidden=\"true\"></i>\n      <span class=\"ml-2\">Sign In with {{getOAuthProviderName(providerId)}}</span>\n    </button>\n  </div>\n\n  <form [formGroup]=\"fg\">\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\n\n  <p class=\"text-muted\">\n    <a routerLink=\".\" [queryParams]=\"{action: 'signIn'}\">Start Over</a>\n  </p>\n\n</div>\n",
                        styles: [""],
                        animations: [screenAnimation]
                    },] },
        ];
        /** @nocollapse */
        SignInOauthComponent.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth },
                { type: NgxFirebaseAuthService },
                { type: router.ActivatedRoute },
                { type: router.Router }
            ];
        };
        SignInOauthComponent.propDecorators = {
            providerId: [{ type: i0.Input }],
            initialError: [{ type: i0.Input }],
            useOAuthPopup: [{ type: i0.Input }],
            oAuthProviderFactory: [{ type: i0.Input }],
            email: [{ type: i0.Input }],
            remember: [{ type: i0.Input }],
            success: [{ type: i0.Output }],
            emailChange: [{ type: i0.Output }],
            rememberChange: [{ type: i0.Output }],
            error: [{ type: i0.Output }]
        };
        return SignInOauthComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var NgxFirebaseAuthModule = (function () {
        function NgxFirebaseAuthModule() {
        }
        NgxFirebaseAuthModule.decorators = [
            { type: i0.NgModule, args: [{
                        imports: [
                            common.CommonModule
                        ],
                        providers: [
                            NgxFirebaseAuthService
                        ]
                    },] },
        ];
        return NgxFirebaseAuthModule;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var NgxFirebaseAuthSignInModule = (function () {
        function NgxFirebaseAuthSignInModule() {
        }
        NgxFirebaseAuthSignInModule.decorators = [
            { type: i0.NgModule, args: [{
                        imports: [
                            common.CommonModule,
                            forms.ReactiveFormsModule,
                            router.RouterModule,
                            NgxFirebaseAuthModule
                        ],
                        declarations: [
                            SignInComponent,
                            SignInMethodsFormComponent,
                            SignInFormComponent,
                            SignUpFormComponent,
                            ResetPasswordSendFormComponent,
                            SignInOauthComponent,
                        ],
                        exports: [
                            SignInComponent,
                        ]
                    },] },
        ];
        return NgxFirebaseAuthSignInModule;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var OobResetPasswordComponent = (function () {
        function OobResetPasswordComponent(_afAuth, _authService) {
            this._afAuth = _afAuth;
            this._authService = _authService;
            this.success = new i0.EventEmitter();
            this.screen = 'wait';
            this.submitting = false;
            this.formId = 'ngx-firebase-auth-oob-reset-password-';
            this.unhandledError = null;
            this.cred = null;
        }
        Object.defineProperty(OobResetPasswordComponent.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        Object.defineProperty(OobResetPasswordComponent.prototype, "authService", {
            get: /**
             * @return {?}
             */ function () {
                return this._authService;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        OobResetPasswordComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                /** @type {?} */
                var remembered = this.authService.getRemembered();
                this.emailFc = new forms.FormControl('');
                this.passwordFc = new forms.FormControl('', { validators: [forms.Validators.required] });
                this.rememberFc = new forms.FormControl(remembered.remember);
                this.fg = new forms.FormGroup({ email: this.emailFc, password: this.passwordFc, remember: this.rememberFc });
                this.auth.checkActionCode(this.oobCode)
                    .then(function (result) {
                    _this.info = result;
                    _this.emailFc.setValue(result.data.email);
                    _this.screen = 'form';
                })
                    .catch(function (error) {
                    _this.unhandledError = error;
                    _this.screen = 'error';
                });
            };
        /**
         * @return {?}
         */
        OobResetPasswordComponent.prototype.submit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.submitting = true;
                this.auth.confirmPasswordReset(this.oobCode, this.passwordFc.value)
                    .then(function () {
                    return _this.auth.signInWithEmailAndPassword(_this.info.data.email, _this.passwordFc.value);
                })
                    .then(function (cred) {
                    _this.cred = cred;
                    return _this.authService.setRemembered(_this.rememberFc.value === true, _this.info.data.email);
                })
                    .then(function () {
                    _this.screen = 'success';
                    _this.success.emit({
                        mode: 'resetPassword',
                        info: _this.info,
                        cred: _this.cred,
                        user: _this.cred.user
                    });
                })
                    .catch(function (error) {
                    _this.submitting = false;
                    _this.passwordFc.markAsDirty();
                    _this.passwordFc.markAsTouched();
                    switch (error.code) {
                        case 'auth/weak-password':
                            NgxFirebaseAuthFormHelper.setErrorUntilChanged(_this.passwordFc, error.code);
                            break;
                        default:
                            _this.unhandledError = error;
                            _this.screen = 'error';
                            break;
                    }
                });
            };
        OobResetPasswordComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-oob-reset-password',
                        template: "<div *ngIf=\"'wait' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-secondary\">\n    <i class=\"fas fa-spin fa-spinner fa-fw\" aria-hidden=\"true\"></i>\n    Please wait...\n  </div>\n</div>\n\n<div *ngIf=\"'success' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-success\">\n    <i class=\"fas fa-check fa-fw\" aria-hidden=\"true\"></i>\n    Welcome, {{cred.user.displayName}}!\n    Your new password has been saved and you are signed in.\n  </div>\n</div>\n\n<div *ngIf=\"screen === 'error'\" [@screen]=\"'in'\">\n  <div class=\"alert alert-danger\">\n    <p>\n      <i class=\"fas fa-exclamation-triangle fa-fw\" aria-hidden=\"true\"></i>\n      Woops! An error occurred.\n    </p>\n    <div [ngSwitch]=\"unhandledError.code\">\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/expired-action-code'\">\n        The reset password link you used has expired.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/invalid-action-code'\">\n        The reset password link you used is not valid. This may be because it\n        has already been used.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/user-disabled'\">\n        The account associated with the reset password link you used has been disabled.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/user-not-found'\">\n        The account associated with the reset password link you used has been removed.\n      </p>\n      <div *ngSwitchDefault>\n        <p>Code: {{unhandledError.code}}</p>\n        <p class=\"mb-0\">\n          Message: {{unhandledError.message}}\n        </p>\n      </div>\n    </div>\n  </div>\n</div>\n\n\n<div *ngIf=\"'form' === screen\" [@screen]=\"'in'\">\n  <form [formGroup]=\"fg\" (ngSubmit)=\"submit()\">\n    <div class=\"form-group\">\n      <label [attr.for]=\"formId + 'email'\">Email Address</label>\n\n      <input\n        readonly\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        class=\"form-control\">\n      <small class=\"text-muted form-text\" [attr.id]=\"formId + 'email'\" >\n        You are resetting the password for {{emailFc.value}}.\n      </small>\n    </div>\n\n    <div class=\"form-group\">\n      <div class=\"d-flex justify-content-between align-items-end\">\n        <label [attr.for]=\"formId + 'password'\">Password</label>\n        <small>\n          <a (click)=\"$event.preventDefault(); passwordInput.type = 'password' === passwordInput.type  ? 'text' : 'password'\"\n            href=\"#\" tabindex=\"-1\" class=\"d-inline-block\">\n            <span *ngIf=\"'password' === passwordInput.type\">Show</span>\n            <span *ngIf=\"'text' === passwordInput.type\">Hide</span>\n          </a>\n        </small>\n      </div>\n      <input\n        #passwordInput\n        [attr.id]=\"formId + 'password'\"\n        [attr.aria-describedby]=\"formId + 'password-help'\"\n        type=\"password\"\n        formControlName=\"password\"\n        placeholder=\"Password\"\n        autocomplete=\"password\"\n        class=\"form-control\"\n        [class.is-invalid]=\"passwordFc.touched && passwordFc.invalid\">\n      <div class=\"invalid-feedback\" *ngIf=\"passwordFc.touched && passwordFc.hasError('required')\">\n        Required.\n      </div>\n      <div class=\"invalid-feedback\" *ngIf=\"passwordFc.touched && passwordFc.hasError('auth/weak-password')\">\n        That password is too weak.\n      </div>\n      <small [attr.id]=\"formId + 'password-help'\" class=\"form-text text-muted\">\n        Please choose a strong password.\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    <div class=\"form-group\">\n      <button type=\"submit\"\n        class=\"btn btn-success btn-block\"\n        [disabled]=\"fg.invalid || submitting\">\n        <i class=\"fas fa-save fa-fw\" aria-hidden=\"true\"></i>\n        Save Password and Sign In\n      </button>\n    </div>\n  </form>\n</div>\n",
                        styles: [""],
                        animations: [screenAnimation]
                    },] },
        ];
        /** @nocollapse */
        OobResetPasswordComponent.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth },
                { type: NgxFirebaseAuthService }
            ];
        };
        OobResetPasswordComponent.propDecorators = {
            oobCode: [{ type: i0.Input }],
            success: [{ type: i0.Output }]
        };
        return OobResetPasswordComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var OobRecoverEmailComponent = (function () {
        function OobRecoverEmailComponent(_afAuth) {
            this._afAuth = _afAuth;
            this.success = new i0.EventEmitter();
            this.screen = 'wait';
            this.submitting = false;
        }
        Object.defineProperty(OobRecoverEmailComponent.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        OobRecoverEmailComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.auth.checkActionCode(this.oobCode)
                    .then(function (result) {
                    _this.info = result;
                    _this.screen = 'form';
                })
                    .catch(function (error) {
                    _this.unhandledError = error;
                    _this.screen = 'error';
                });
            };
        /**
         * @return {?}
         */
        OobRecoverEmailComponent.prototype.submit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.auth.applyActionCode(this.oobCode)
                    .then(function () {
                    _this.screen = 'success';
                    _this.success.emit({
                        mode: 'recoverEmail',
                        info: _this.info,
                        user: _this.auth.currentUser
                    });
                })
                    .catch(function (error) {
                    _this.unhandledError = error;
                    _this.screen = 'error';
                });
            };
        OobRecoverEmailComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-oob-recover-email',
                        template: "\n\n<div *ngIf=\"'wait' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-secondary\">\n    <i class=\"fas fa-spin fa-spinner fa-fw\" aria-hidden=\"true\"></i>\n    Please wait...\n  </div>\n</div>\n\n\n<div *ngIf=\"'success' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-success\">\n    <i class=\"fas fa-check fa-fw\" aria-hidden=\"true\"></i>\n    Your email has been changed back to {{info.data.email}};\n  </div>\n</div>\n\n<div *ngIf=\"screen === 'form'\" [@screen]=\"'in'\">\n  <div class=\"form-group\">\n    <p>\n      Are you sure you want to change your email back to\n      {{info.data.email}} from {{info.data.fromEmail}}?\n    </p>\n    <button\n      type=\"button\"\n      [disabled]=\"submitting\"\n      (click)=\"submit()\"\n      class=\"btn btn-block btn-success\">\n      <i class=\"fas fa-save fa-fw\" aria-hidden=\"true\"></i>\n      Yes, Continue\n    </button>\n  </div>\n</div>\n\n\n\n<div *ngIf=\"screen === 'error'\" [@screen]=\"'in'\">\n  <div class=\"alert alert-danger\">\n    <p>\n      <i class=\"fas fa-exclamation-triangle fa-fw\" aria-hidden=\"true\"></i>\n      Woops! An error occurred.\n    </p>\n    <div [ngSwitch]=\"unhandledError.code\">\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/expired-action-code'\">\n        The recover email link you used has expired.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/invalid-action-code'\">\n        The recover email link you used is not valid. This may be because it\n        has already been used.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/user-disabled'\">\n        The account associated with the recover email link you used has been disabled.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/user-not-found'\">\n        The account associated with the recover email link you used has been removed.\n      </p>\n      <div *ngSwitchDefault>\n        <p>Code: {{unhandledError.code}}</p>\n        <p class=\"mb-0\">\n          Message: {{unhandledError.message}}\n        </p>\n      </div>\n    </div>\n  </div>\n</div>\n",
                        styles: [""],
                        animations: [screenAnimation]
                    },] },
        ];
        /** @nocollapse */
        OobRecoverEmailComponent.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth }
            ];
        };
        OobRecoverEmailComponent.propDecorators = {
            oobCode: [{ type: i0.Input }],
            success: [{ type: i0.Output }]
        };
        return OobRecoverEmailComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var OobVerifyEmailComponent = (function () {
        function OobVerifyEmailComponent(_afAuth) {
            this._afAuth = _afAuth;
            this.success = new i0.EventEmitter();
            this.screen = 'wait';
            this.submitting = false;
        }
        Object.defineProperty(OobVerifyEmailComponent.prototype, "auth", {
            get: /**
             * @return {?}
             */ function () {
                return this._afAuth.auth;
            },
            enumerable: true,
            configurable: true
        });
        /**
         * @return {?}
         */
        OobVerifyEmailComponent.prototype.ngOnInit = /**
         * @return {?}
         */
            function () {
                var _this = this;
                this.auth.checkActionCode(this.oobCode)
                    .then(function (result) {
                    _this.info = result;
                    return _this.auth.applyActionCode(_this.oobCode);
                })
                    .then(function () {
                    _this.screen = 'success';
                    _this.success.emit({
                        mode: 'verifyEmail',
                        info: _this.info,
                        user: _this.auth.currentUser
                    });
                })
                    .catch(function (error) {
                    _this.unhandledError = error;
                    _this.screen = 'error';
                });
            };
        OobVerifyEmailComponent.decorators = [
            { type: i0.Component, args: [{
                        selector: 'ngx-firebase-auth-oob-verify-email',
                        template: "<div *ngIf=\"'wait' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-secondary\">\n    <i class=\"fas fa-spin fa-spinner fa-fw\" aria-hidden=\"true\"></i>\n    Please wait...\n  </div>\n</div>\n\n<div *ngIf=\"'success' === screen\" [@screen]=\"'in'\">\n  <div class=\"alert alert-success\">\n    <i class=\"fas fa-check fa-fw\" aria-hidden=\"true\"></i>\n    The email {{info.data.email}} has been verified.\n  </div>\n</div>\n\n<div *ngIf=\"screen === 'error'\" [@screen]=\"'in'\">\n  <div class=\"alert alert-danger\">\n    <p>\n      <i class=\"fas fa-exclamation-triangle fa-fw\" aria-hidden=\"true\"></i>\n      Woops! An error occurred.\n    </p>\n    <div [ngSwitch]=\"unhandledError.code\">\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/expired-action-code'\">\n        The verify email link you used has expired.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/invalid-action-code'\">\n        The verify email link you used is not valid. This may be because it\n        has already been used.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/user-disabled'\">\n        The account associated with the verify email link you used has been disabled.\n      </p>\n      <p class=\"mb-0\" *ngSwitchCase=\"'auth/user-not-found'\">\n        The account associated with the verify email link you used has been removed.\n      </p>\n      <div *ngSwitchDefault>\n        <p>Code: {{unhandledError.code}}</p>\n        <p class=\"mb-0\">\n          Message: {{unhandledError.message}}\n        </p>\n      </div>\n    </div>\n  </div>\n</div>\n",
                        styles: [""],
                        animations: [screenAnimation]
                    },] },
        ];
        /** @nocollapse */
        OobVerifyEmailComponent.ctorParameters = function () {
            return [
                { type: i1.AngularFireAuth }
            ];
        };
        OobVerifyEmailComponent.propDecorators = {
            oobCode: [{ type: i0.Input }],
            success: [{ type: i0.Output }]
        };
        return OobVerifyEmailComponent;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */
    var NgxFirebaseAuthOobModule = (function () {
        function NgxFirebaseAuthOobModule() {
        }
        NgxFirebaseAuthOobModule.decorators = [
            { type: i0.NgModule, args: [{
                        imports: [
                            common.CommonModule,
                            forms.ReactiveFormsModule,
                            router.RouterModule,
                            NgxFirebaseAuthModule
                        ],
                        declarations: [
                            OobComponent,
                            OobRecoverEmailComponent,
                            OobResetPasswordComponent,
                            OobVerifyEmailComponent
                        ],
                        exports: [
                            OobComponent,
                        ]
                    },] },
        ];
        return NgxFirebaseAuthOobModule;
    }());

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */

    /**
     * @fileoverview added by tsickle
     * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
     */

    exports.fadeInOutAnimation = fadeInOutAnimation;
    exports.screenAnimation = screenAnimation;
    exports.getOAuthProviderName = getOAuthProviderName;
    exports.getOAuthProviderIcon = getOAuthProviderIcon;
    exports.NgxFirebaseAuthService = NgxFirebaseAuthService;
    exports.SignInComponent = SignInComponent;
    exports.OobComponent = OobComponent;
    exports.NgxFirebaseAuthSignInModule = NgxFirebaseAuthSignInModule;
    exports.NgxFirebaseAuthOobModule = NgxFirebaseAuthOobModule;
    exports.NgxFirebaseAuthModule = NgxFirebaseAuthModule;
    exports.ɵf = OobRecoverEmailComponent;
    exports.ɵg = OobResetPasswordComponent;
    exports.ɵh = OobVerifyEmailComponent;
    exports.ɵd = ResetPasswordSendFormComponent;
    exports.ɵb = SignInFormComponent;
    exports.ɵa = SignInMethodsFormComponent;
    exports.ɵe = SignInOauthComponent;
    exports.ɵc = SignUpFormComponent;

    Object.defineProperty(exports, '__esModule', { value: true });

})));

//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm93em9vLW5neC1maXJlYmFzZS1hdXRoLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvc2hhcmVkLnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlLnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaWduLWluL3NpZ24taW4uY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivb29iLmNvbXBvbmVudC50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvZm9ybS1oZWxwZXIudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi1tZXRob2RzLWZvcm0vc2lnbi1pbi1tZXRob2RzLWZvcm0uY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaWduLWluL3NpZ24taW4tZm9ybS9zaWduLWluLWZvcm0uY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaWduLWluL3NpZ24tdXAtZm9ybS9zaWduLXVwLWZvcm0uY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaWduLWluL3Jlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybS9yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0uY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaWduLWluL3NpZ24taW4tb2F1dGgvc2lnbi1pbi1vYXV0aC5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL25neC1maXJlYmFzZS1hdXRoLm1vZHVsZS50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvc2lnbi1pbi9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLm1vZHVsZS50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvb29iL29vYi1yZXNldC1wYXNzd29yZC9vb2ItcmVzZXQtcGFzc3dvcmQuY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivb29iLXJlY292ZXItZW1haWwvb29iLXJlY292ZXItZW1haWwuY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivb29iLXZlcmlmeS1lbWFpbC9vb2ItdmVyaWZ5LWVtYWlsLmNvbXBvbmVudC50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvb29iL25neC1maXJlYmFzZS1hdXRoLW9vYi5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhLCB0cmlnZ2VyLCBzdGF0ZSwgc3R5bGUsIGFuaW1hdGUsIHRyYW5zaXRpb24gfSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuXG5cbmV4cG9ydCBpbnRlcmZhY2UgSVNpZ25Jbk1ldGhvZHNGb3JFbWFpbFJlc3VsdCB7XG4gIGVtYWlsOiBzdHJpbmc7XG4gIG1ldGhvZHM6IHN0cmluZ1tdO1xuICBzdGF0dXM6ICd1bmZldGNoZWQnIHwgJ2ZldGNoaW5nJyB8ICdmZXRjaGVkJztcbn1cblxuXG5leHBvcnQgaW50ZXJmYWNlIElOZ3hGaXJlYmFzZUF1dGhSZW1lbWJlclJlY29yZCB7XG4gIHJlbWVtYmVyOiBib29sZWFuO1xuICBlbWFpbDogc3RyaW5nO1xufVxuXG5cbmV4cG9ydCBjb25zdCBmYWRlSW5PdXRBbmltYXRpb246IEFuaW1hdGlvblRyaWdnZXJNZXRhZGF0YSA9IHRyaWdnZXIoJ2ZhZGVJbk91dCcsIFtcbiAgc3RhdGUoJ2luJywgc3R5bGUoe29wYWNpdHk6IDEsIGRpc3BsYXk6ICdibG9jayd9KSksXG4gIHRyYW5zaXRpb24oJ3ZvaWQgPT4gKicsIFtcbiAgICBzdHlsZSh7b3BhY2l0eTogMH0pLFxuICAgIGFuaW1hdGUoMzAwKVxuICBdKSxcbiAgdHJhbnNpdGlvbignKiA9PiB2b2lkJywgW1xuICAgIGFuaW1hdGUoMzAwLCBzdHlsZSh7b3BhY2l0eTogMH0pKVxuICBdKVxuXSk7XG5cbmV4cG9ydCBjb25zdCBzY3JlZW5BbmltYXRpb246IEFuaW1hdGlvblRyaWdnZXJNZXRhZGF0YSA9IHRyaWdnZXIoJ3NjcmVlbicsIFtcbiAgc3RhdGUoJ2luJywgc3R5bGUoe29wYWNpdHk6IDF9KSksXG4gIHRyYW5zaXRpb24oJ3ZvaWQgPT4gKicsIFtcbiAgICBzdHlsZSh7b3BhY2l0eTogMH0pLFxuICAgIGFuaW1hdGUoMzAwKVxuICBdKSxcbiAgdHJhbnNpdGlvbignKiA9PiB2b2lkJywgW1xuICAgIGFuaW1hdGUoMCwgc3R5bGUoe29wYWNpdHk6IDB9KSlcbiAgXSlcbl0pO1xuXG5leHBvcnQgY29uc3QgZ2V0T0F1dGhQcm92aWRlck5hbWUgPSAoaWQ6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gIHN3aXRjaCAoaWQpIHtcbiAgICBjYXNlICd0d2l0dGVyLmNvbSc6IHJldHVybiAnVHdpdHRlcic7XG4gICAgY2FzZSAnZmFjZWJvb2suY29tJzogcmV0dXJuICdGYWNlYm9vayc7XG4gICAgY2FzZSAnZ29vZ2xlLmNvbSc6IHJldHVybiAnR29vZ2xlJztcbiAgICBjYXNlICdnaXRodWIuY29tJzogcmV0dXJuICdHaXRIdWInO1xuICAgIGRlZmF1bHQ6IHJldHVybiBpZDtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGdldE9BdXRoUHJvdmlkZXJJY29uID0gKGlkOiBzdHJpbmcpOiBzdHJpbmcgID0+IHtcbiAgc3dpdGNoIChpZCkge1xuICAgIGNhc2UgJ3R3aXR0ZXIuY29tJzpcbiAgICBjYXNlICdmYWNlYm9vay5jb20nOlxuICAgIGNhc2UgJ2dvb2dsZS5jb20nOlxuICAgIGNhc2UgJ2dpdGh1Yi5jb20nOlxuICAgICAgcmV0dXJuICdmYWIgZmEtZncgZmEtJyArIGlkLnJlcGxhY2UoJy5jb20nLCAnJyk7XG4gICAgZGVmYXVsdDogcmV0dXJuICdmYXMgZmEtZncgZmEtc2lnbi1pbi1hbHQnO1xuICB9XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzIHtcbiAgbW9kZTogJ3Jlc2V0UGFzc3dvcmQnIHwgJ3ZlcmlmeUVtYWlsJyB8ICdyZWNvdmVyRW1haWwnO1xuICBpbmZvOiBhdXRoLkFjdGlvbkNvZGVJbmZvO1xuICBjcmVkPzogYXV0aC5Vc2VyQ3JlZGVudGlhbDtcbiAgdXNlcj86IFVzZXI7XG59XG4iLCJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IElOZ3hGaXJlYmFzZUF1dGhSZW1lbWJlclJlY29yZCB9IGZyb20gJy4vc2hhcmVkJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB7XG4gIHN0YXRpYyByZW1lbWJlcktleSA9ICduZ3gtZmlyZWJhc2UtYXV0aC1yZW1lbWJlcic7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGhcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuICBnZXQgc3RvcmFnZSgpOiBTdG9yYWdlIHtcbiAgICByZXR1cm4gd2luZG93LmxvY2FsU3RvcmFnZTtcbiAgfVxuXG4gIGdldFJlbWVtYmVyZWQoKTogSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkIHtcbiAgICBjb25zdCBzdHIgPSB0aGlzLnN0b3JhZ2UuZ2V0SXRlbShOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLnJlbWVtYmVyS2V5KTtcbiAgICBpZiAoc3RyKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShzdHIpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4ge2VtYWlsOiAnJywgcmVtZW1iZXI6IHRydWV9O1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4ge2VtYWlsOiAnJywgcmVtZW1iZXI6IHRydWV9O1xuICB9XG5cbiAgc2V0UmVtZW1iZXJlZChyZW1lbWJlcjogYm9vbGVhbiwgZW1haWw6IHN0cmluZyk6IFByb21pc2U8SU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkPiB7XG4gICAgY29uc3QgcGVyc2lzdGVuY2U6IGF1dGguQXV0aC5QZXJzaXN0ZW5jZSA9IHJlbWVtYmVyID9cbiAgICAgIGF1dGguQXV0aC5QZXJzaXN0ZW5jZS5MT0NBTCA6IGF1dGguQXV0aC5QZXJzaXN0ZW5jZS5TRVNTSU9OO1xuICAgIHJldHVybiB0aGlzLmF1dGguc2V0UGVyc2lzdGVuY2UocGVyc2lzdGVuY2UpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGNvbnN0IG86IElOZ3hGaXJlYmFzZUF1dGhSZW1lbWJlclJlY29yZCA9IHtcbiAgICAgICAgICBlbWFpbDogcmVtZW1iZXIgPyBlbWFpbCA6ICcnLFxuICAgICAgICAgIHJlbWVtYmVyOiByZW1lbWJlclxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBzdHIgPSBKU09OLnN0cmluZ2lmeShvKTtcbiAgICAgICAgdGhpcy5zdG9yYWdlLnNldEl0ZW0oTmd4RmlyZWJhc2VBdXRoU2VydmljZS5yZW1lbWJlcktleSwgc3RyKTtcbiAgICAgICAgcmV0dXJuIG87XG4gICAgICB9KTtcbiAgfVxuXG5cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIE9uRGVzdHJveSwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBUZW1wbGF0ZVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUm91dGVyLCBBY3RpdmF0ZWRSb3V0ZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1Db250cm9sLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgU3ViamVjdCwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVBdXRoIH0gZnJvbSAnYW5ndWxhcmZpcmUyL2F1dGgnO1xuaW1wb3J0IHsgYXV0aCwgVXNlciB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aFNlcnZpY2UgfSBmcm9tICcuLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcblxuXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4nLFxuICB0ZW1wbGF0ZTogYDxkaXYgKm5nSWY9XCInd2FpdCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXNlY29uZGFyeVwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNwaW4gZmEtc3Bpbm5lciBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBQbGVhc2Ugd2FpdC4uLlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3VuaGFuZGxlZEVycm9yJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZncgdGV4dC1kYW5nZXJcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgPHN0cm9uZz5Xb29wcyE8L3N0cm9uZz4gQW4gdW5leHBlY3RlZCBlcnJvciBvY2N1cnJlZC5cbiAgPC9kaXY+XG4gIDxwIGNsYXNzPVwidGV4dC1tdXRlZFwiPlxuICAgIENvZGU6IHt7dW5oYW5kbGVkRXJyb3IuY29kZX19LiBNZXNzYWdlOiB7e3VuaGFuZGxlZEVycm9yLm1lc3NhZ2V9fVxuICA8L3A+XG4gIDxwPlxuICAgIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW4nfVwiPlN0YXJ0IE92ZXI8L2E+XG4gIDwvcD5cbjwvZGl2PlxuXG5cbjxkaXYgKm5nSWY9XCInc2lnbkluU3VjY2VzcycgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBXZWxjb21lLCB7e2NyZWQudXNlci5kaXNwbGF5TmFtZX19IVxuICA8L2Rpdj5cbjwvZGl2PlxuXG5cblxuXG48ZGl2ICpuZ0lmPVwiJ3NpZ25JbicgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIiAqbmdJZj1cInNpZ25lZE91dFwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFlvdcOiwoDCmXJlIHNpZ25lZCBvdXQuXG4gIDwvZGl2PlxuICA8bmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1tZXRob2RzLWZvcm1cbiAgICBbKGVtYWlsKV09XCJlbWFpbFwiXG4gICAgWyhyZW1lbWJlcildPVwicmVtZW1iZXJcIlxuICAgIFtvQXV0aFByb3ZpZGVySWRzXT1cIm9BdXRoUHJvdmlkZXJJZHNcIlxuICAgIChlcnJvcik9XCJzaG93VW5oYW5kbGVkRXJyb3IoJGV2ZW50KVwiXG4gICAgKHN1Y2Nlc3MpPVwic2hvd1NpZ25JblN1Y2Nlc3MoJGV2ZW50KVwiPjwvbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1tZXRob2RzLWZvcm0+XG4gIDxzbWFsbCBjbGFzcz1cInRleHQtY2VudGVyIHRleHQtbXV0ZWQgbXktMiBmb3JtLXRleHRcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidG9zVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgPC9zbWFsbD5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3NpZ25JblBhc3N3b3JkJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1mb3JtXG4gICAgW2VtYWlsXT1cImVtYWlsXCJcbiAgICBbKHJlbWVtYmVyKV09XCJyZW1lbWJlclwiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCJcbiAgICAoc3VjY2Vzcyk9XCJzaG93U2lnbkluU3VjY2VzcygkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLWZvcm0+XG4gIDxzbWFsbCBjbGFzcz1cInRleHQtY2VudGVyIHRleHQtbXV0ZWQgbXktMiBmb3JtLXRleHRcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidG9zVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgPC9zbWFsbD5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3NpZ25VcFBhc3N3b3JkJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtc2lnbi11cC1mb3JtXG4gICAgW2VtYWlsXT1cImVtYWlsXCJcbiAgICBbKHJlbWVtYmVyKV09XCJyZW1lbWJlclwiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCJcbiAgICAoc3VjY2Vzcyk9XCJzaG93U2lnbkluU3VjY2VzcygkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLXVwLWZvcm0+XG4gIDxzbWFsbCBjbGFzcz1cInRleHQtY2VudGVyIHRleHQtbXV0ZWQgbXktMiBmb3JtLXRleHRcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidG9zVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgPC9zbWFsbD5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3NpZ25Jbk9BdXRoJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1vYXV0aFxuICAgIFtwcm92aWRlcklkXT1cIm9BdXRoUHJvdmlkZXJJZFwiXG4gICAgW2luaXRpYWxFcnJvcl09XCJpbml0aWFsT0F1dGhFcnJvclwiXG4gICAgW3VzZU9BdXRoUG9wdXBdPVwidXNlT0F1dGhQb3B1cFwiXG4gICAgW29BdXRoUHJvdmlkZXJGYWN0b3J5XT1cIm9BdXRoUHJvdmlkZXJGYWN0b3J5XCJcbiAgICBbKGVtYWlsKV09XCJlbWFpbFwiXG4gICAgWyhyZW1lbWJlcildPVwicmVtZW1iZXJcIlxuICAgIChlcnJvcik9XCJzaG93VW5oYW5kbGVkRXJyb3IoJGV2ZW50KVwiXG4gICAgKHN1Y2Nlc3MpPVwic2hvd1NpZ25JblN1Y2Nlc3MoJGV2ZW50KVwiPjwvbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1vYXV0aD5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cblxuXG48ZGl2ICpuZ0lmPVwiJ3Jlc2V0UGFzc3dvcmQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxoNj5SZXNldCBQYXNzd29yZDwvaDY+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1yZXNldC1wYXNzd29yZC1zZW5kLWZvcm1cbiAgICBbKGVtYWlsKV09XCJlbWFpbFwiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgU2lnbkluQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIG5nVW5zdWJzY3JpYmU6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBASW5wdXQoKSBvQXV0aFByb3ZpZGVySWRzOiBzdHJpbmdbXTtcbiAgQElucHV0KCkgdXNlT0F1dGhQb3B1cDogYm9vbGVhbjtcbiAgQElucHV0KCkgb0F1dGhQcm92aWRlckZhY3Rvcnk6IChwcm92aWRlcklkOiBzdHJpbmcpID0+IGF1dGguQXV0aFByb3ZpZGVyO1xuICBASW5wdXQoKSB0b3NUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PiA9IG51bGw7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBtb2RlOiBFdmVudEVtaXR0ZXI8J3NpZ25JbicgfCAncmVzZXRQYXNzd29yZCc+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHJlbWVtYmVyOiBib29sZWFuO1xuICBlbWFpbDogc3RyaW5nO1xuICBpbml0aWFsT0F1dGhFcnJvcjogYXV0aC5FcnJvciA9IG51bGw7XG4gIHNpZ25lZE91dCA9IGZhbHNlO1xuICBvQXV0aFByb3ZpZGVySWQ6IHN0cmluZyA9IG51bGw7XG4gIGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwgPSBudWxsO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvciA9IG51bGw7XG5cbiAgc2NyZWVuOiAnd2FpdCcgfFxuICAgICdzaWduSW4nIHwgJ3NpZ25JblBhc3N3b3JkJyB8ICdzaWduVXBQYXNzd29yZCcgfCAnc2lnbkluT0F1dGgnIHwgJ3NpZ25JblN1Y2Nlc3MnIHxcbiAgICAncmVzZXRQYXNzd29yZCcgfCAndW5oYW5kbGVkRXJyb3InID0gJ3dhaXQnO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2FmQXV0aDogQW5ndWxhckZpcmVBdXRoLFxuICAgIHByaXZhdGUgX3N2YzogTmd4RmlyZWJhc2VBdXRoU2VydmljZSxcbiAgICBwcml2YXRlIF9yb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgcHJpdmF0ZSBfcm91dGVyOiBSb3V0ZXIsXG4gICkge31cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fc3ZjO1xuICB9XG5cbiAgZ2V0IHJvdXRlcigpOiBSb3V0ZXIge1xuICAgIHJldHVybiB0aGlzLl9yb3V0ZXI7XG4gIH1cblxuICBnZXQgcm91dGUoKTogQWN0aXZhdGVkUm91dGUge1xuICAgIHJldHVybiB0aGlzLl9yb3V0ZTtcbiAgfVxuXG4gIGdldCBxdWVyeVBhcmFtcygpOiBPYnNlcnZhYmxlPHtba2V5OiBzdHJpbmddOiBhbnl9PiB7XG4gICAgcmV0dXJuIHRoaXMucm91dGUucXVlcnlQYXJhbXM7XG4gIH1cblxuICBnZXQgc25hcHNob3RRdWVyeVBhcmFtcygpOiB7W2tleTogc3RyaW5nXTogYW55fSB7XG4gICAgcmV0dXJuIHRoaXMucm91dGUuc25hcHNob3QucXVlcnlQYXJhbXM7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmluaXQoKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHRoaXMubmdVbnN1YnNjcmliZS5uZXh0KCk7XG4gICAgdGhpcy5uZ1Vuc3Vic2NyaWJlLmNvbXBsZXRlKCk7XG4gIH1cblxuICBpbml0KCkge1xuICAgIGNvbnN0IHJlbWVtYmVyUmVjb3JkID0gdGhpcy5hdXRoU2VydmljZS5nZXRSZW1lbWJlcmVkKCk7XG4gICAgdGhpcy5yZW1lbWJlciA9IHJlbWVtYmVyUmVjb3JkLnJlbWVtYmVyO1xuICAgIHRoaXMuZW1haWwgPSByZW1lbWJlclJlY29yZC5lbWFpbDtcbiAgICByZXR1cm4gdGhpcy5vbkluaXRIYW5kbGVTaWduT3V0KClcbiAgICAgIC50aGVuKChoYW5kbGVkOiBib29sZWFuKSA9PiB7XG4gICAgICAgIGlmIChoYW5kbGVkKSB7XG4gICAgICAgICAgcmV0dXJuIGhhbmRsZWQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMub25Jbml0SGFuZGxlT0F1dGhSZWRpcmVjdCgpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKChoYW5kbGVkOiBib29sZWFuKSA9PiB7XG4gICAgICAgIGlmICghIGhhbmRsZWQpIHtcbiAgICAgICAgICB0aGlzLnNob3dTaWduSW4oKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnF1ZXJ5UGFyYW1zLnBpcGUodGFrZVVudGlsKHRoaXMubmdVbnN1YnNjcmliZSkpLnN1YnNjcmliZShwYXJhbXMgPT4ge1xuICAgICAgICAgIGNvbnN0IGFjdGlvbiA9IHBhcmFtcy5hY3Rpb24gfHwgbnVsbDtcbiAgICAgICAgICBzd2l0Y2ggKGFjdGlvbikge1xuICAgICAgICAgICAgY2FzZSAnc2lnbk91dCc6XG4gICAgICAgICAgICAgIHRoaXMuc2hvd1NpZ25PdXQoKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdyZXNldFBhc3N3b3JkJzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93UmVzZXRQYXNzd29yZCgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NpZ25Jbic6XG4gICAgICAgICAgICAgIHRoaXMuc2hvd1NpZ25JbigpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NpZ25JblBhc3N3b3JkJzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnbkluUGFzc3dvcmQoKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzaWduVXBQYXNzd29yZCc6XG4gICAgICAgICAgICAgIHRoaXMuc2hvd1NpZ25VcFBhc3N3b3JkKCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2lnbkluT0F1dGgnOlxuICAgICAgICAgICAgICB0aGlzLnNob3dTaWduSW5PQXV0aChwYXJhbXMucHJvdmlkZXJJZCwgbnVsbCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIG9uSW5pdEhhbmRsZVNpZ25PdXQoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKHRoaXMuc25hcHNob3RRdWVyeVBhcmFtcy5hY3Rpb24gIT09ICdzaWduT3V0Jykge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNob3dTaWduT3V0KCkudGhlbigoKSA9PiB0cnVlKTtcbiAgfVxuICBvbkluaXRIYW5kbGVPQXV0aFJlZGlyZWN0KCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIGNvbnN0IHJlbWVtYmVyOiBib29sZWFuID0gdGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcy5yZW1lbWJlciA9PT0gJ3RydWUnO1xuICAgICAgcmV0dXJuIHRoaXMuYXV0aC5nZXRSZWRpcmVjdFJlc3VsdCgpXG4gICAgICAgIC50aGVuKChjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuYXV0aC5jdXJyZW50VXNlciAmJiBjcmVkLnVzZXIpIHtcbiAgICAgICAgICAgIHRoaXMuYXV0aFNlcnZpY2Uuc2V0UmVtZW1iZXJlZChyZW1lbWJlciwgY3JlZC51c2VyLmVtYWlsKVxuICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zaG93U2lnbkluU3VjY2VzcyhjcmVkKTtcbiAgICAgICAgICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzb2x2ZShmYWxzZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yOiBhdXRoLkVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5zaG93U2lnbkluT0F1dGgobnVsbCwgZXJyb3IgKTtcbiAgICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG5cblxuXG4gIHNob3dTaWduT3V0KCk6IFByb21pc2U8YW55PiB7XG4gICAgdGhpcy5zaWduZWRPdXQgPSBmYWxzZTtcbiAgICB0aGlzLnNjcmVlbiA9ICd3YWl0JztcbiAgICByZXR1cm4gdGhpcy5hdXRoLnNpZ25PdXQoKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnNob3dTaWduSW4odHJ1ZSk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHNob3dTaWduSW4oc2lnbmVkT3V0PzogYm9vbGVhbikge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IHNpZ25lZE91dCA9PT0gdHJ1ZTtcbiAgICB0aGlzLnNjcmVlbiA9ICdzaWduSW4nO1xuICB9XG5cbiAgc2hvd1NpZ25JblBhc3N3b3JkKCkge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3NpZ25JblBhc3N3b3JkJztcbiAgfVxuXG4gIHNob3dTaWduVXBQYXNzd29yZCgpIHtcbiAgICB0aGlzLm1vZGUuZW1pdCgnc2lnbkluJyk7XG4gICAgdGhpcy5zaWduZWRPdXQgPSBmYWxzZTtcbiAgICB0aGlzLnNjcmVlbiA9ICdzaWduVXBQYXNzd29yZCc7XG5cbiAgfVxuXG4gIHNob3dTaWduSW5PQXV0aChvQXV0aFByb3ZpZGVySWQ6IHN0cmluZywgZXJyb3I6IGF1dGguRXJyb3IpIHtcbiAgICB0aGlzLm1vZGUuZW1pdCgnc2lnbkluJyk7XG4gICAgdGhpcy5zaWduZWRPdXQgPSBmYWxzZTtcbiAgICB0aGlzLm9BdXRoUHJvdmlkZXJJZCA9IG9BdXRoUHJvdmlkZXJJZDtcbiAgICB0aGlzLmluaXRpYWxPQXV0aEVycm9yID0gZXJyb3I7XG4gICAgdGhpcy5zY3JlZW4gPSAnc2lnbkluT0F1dGgnO1xuICB9XG5cbiAgc2hvd1NpZ25JblN1Y2Nlc3MoY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbCkge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMuY3JlZCA9IGNyZWQ7XG4gICAgdGhpcy5zY3JlZW4gPSAnc2lnbkluU3VjY2Vzcyc7XG4gICAgdGhpcy5zdWNjZXNzLmVtaXQoY3JlZCk7XG4gIH1cblxuICBzaG93UmVzZXRQYXNzd29yZCgpIHtcbiAgICB0aGlzLm1vZGUuZW1pdCgncmVzZXRQYXNzd29yZCcpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy5zY3JlZW4gPSAncmVzZXRQYXNzd29yZCc7XG4gIH1cblxuICBzaG93VW5oYW5kbGVkRXJyb3IoZXJyb3I6IGF1dGguRXJyb3IpIHtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMudW5oYW5kbGVkRXJyb3IgPSBlcnJvcjtcbiAgICB0aGlzLnNjcmVlbiA9ICd1bmhhbmRsZWRFcnJvcic7XG4gIH1cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgc2NyZWVuQW5pbWF0aW9uIH0gZnJvbSAnLi4vc2hhcmVkJztcbmltcG9ydCB7IElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzIH0gZnJvbSAnLi4vc2hhcmVkJztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1vb2InLFxuICB0ZW1wbGF0ZTogYDxkaXYgKm5nSWY9XCIncmVzZXRQYXNzd29yZCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPG5neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZFxuICAgIFtvb2JDb2RlXT1cIm9vYkNvZGVcIlxuICAgIChzdWNjZXNzKT1cInN1Y2Nlc3MuZW1pdCgkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1vb2ItcmVzZXQtcGFzc3dvcmQ+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cIid2ZXJpZnlFbWFpbCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPG5neC1maXJlYmFzZS1hdXRoLW9vYi12ZXJpZnktZW1haWxcbiAgICBbb29iQ29kZV09XCJvb2JDb2RlXCJcbiAgICAoc3VjY2Vzcyk9XCJzdWNjZXNzLmVtaXQoJGV2ZW50KVwiPjwvbmd4LWZpcmViYXNlLWF1dGgtb29iLXZlcmlmeS1lbWFpbD5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3JlY292ZXJFbWFpbCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPG5neC1maXJlYmFzZS1hdXRoLW9vYi1yZWNvdmVyLWVtYWlsXG4gICAgW29vYkNvZGVdPVwib29iQ29kZVwiXG4gICAgKHN1Y2Nlc3MpPVwic3VjY2Vzcy5lbWl0KCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLW9vYi1yZWNvdmVyLWVtYWlsPlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIE9vYkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgb29iQ29kZTogc3RyaW5nO1xuICBzY3JlZW46ICdyZXNldFBhc3N3b3JkJyB8ICd2ZXJpZnlFbWFpbCcgfCAncmVjb3ZlckVtYWlsJyA9IG51bGw7XG5cbiAgQE91dHB1dCgpIG1vZGU6IEV2ZW50RW1pdHRlcjwncmVzZXRQYXNzd29yZCcgfCAndmVyaWZ5RW1haWwnIHwgJ3JlY292ZXJFbWFpbCc+ICA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIG5hdmlnYXRpb25FcnJvcjogRXZlbnRFbWl0dGVyPHZvaWQ+ICA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxJTmd4RmlyZWJhc2VBdXRoT29iU3VjY2Vzcz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9yb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICkgeyB9XG5cblxuICBnZXQgcXVlcnlQYXJhbXMoKToge1trZXk6IHN0cmluZ106IGFueX0ge1xuICAgIHJldHVybiB0aGlzLl9yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcztcbiAgfVxuXG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5vb2JDb2RlID0gdGhpcy5xdWVyeVBhcmFtcy5vb2JDb2RlIHx8IG51bGw7XG4gICAgaWYgKCEgdGhpcy5vb2JDb2RlKSB7XG4gICAgICB0aGlzLm5hdmlnYXRpb25FcnJvci5lbWl0KCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHN3aXRjaCAodGhpcy5xdWVyeVBhcmFtcy5tb2RlKSB7XG4gICAgICBjYXNlICdyZXNldFBhc3N3b3JkJzpcbiAgICAgIGNhc2UgJ3ZlcmlmeUVtYWlsJzpcbiAgICAgIGNhc2UgJ3JlY292ZXJFbWFpbCc6XG4gICAgICAgIHRoaXMuc2NyZWVuID0gdGhpcy5xdWVyeVBhcmFtcy5tb2RlO1xuICAgICAgICB0aGlzLm1vZGUuZW1pdCh0aGlzLnF1ZXJ5UGFyYW1zLm1vZGUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRoaXMubmF2aWdhdGlvbkVycm9yLmVtaXQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gIH1cbn1cbiIsImltcG9ydCB7IEFic3RyYWN0Q29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IHRha2UgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB7XG4gIHN0YXRpYyBzZXRFcnJvclVudGlsQ2hhbmdlZChmYzogQWJzdHJhY3RDb250cm9sLCBrZXk6IHN0cmluZywgdmFsdWU6IGFueSA9IHRydWUpIHtcbiAgICBjb25zdCBlcnJvciA9IHt9O1xuICAgIGVycm9yW2tleV0gPSB2YWx1ZTtcbiAgICBmYy5zZXRFcnJvcnMoZXJyb3IpO1xuICAgIGZjLnZhbHVlQ2hhbmdlcy5waXBlKHRha2UoMSkpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLmNsZWFyRXJyb3IoZmMsIGtleSk7XG4gICAgfSk7XG5cbiAgfVxuXG4gIHN0YXRpYyBjbGVhckVycm9yKGZjOiBBYnN0cmFjdENvbnRyb2wsIGtleTogc3RyaW5nKSB7XG4gICAgY29uc3QgZXJyb3JzID0ge307XG4gICAgaWYgKCEgZmMuZXJyb3JzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIE9iamVjdC5rZXlzKGZjLmVycm9ycykuZm9yRWFjaCgoaykgPT4ge1xuICAgICAgaWYgKGsgIT09IGtleSkge1xuICAgICAgICBlcnJvcnNba10gPSBmYy5lcnJvcnNba107XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKE9iamVjdC5rZXlzKGVycm9ycykubGVuZ3RoID09PSAwKSB7XG4gICAgICBmYy5zZXRFcnJvcnMobnVsbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZjLnNldEVycm9ycyhlcnJvcnMpO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyByZXF1aXJlZE5vbkVtcHR5KGZjOiBBYnN0cmFjdENvbnRyb2wpIHtcbiAgICBjb25zdCB2YWx1ZSA9IGZjLnZhbHVlO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlLnRyaW0oKS5sZW5ndGggPT09IDAgPyB7cmVxdWlyZWQ6IHRydWV9IDogbnVsbDtcbiAgfVxuXG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlclZpZXdJbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE5nWm9uZSwgVmlld0NoaWxkLCBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVBdXRoIH0gZnJvbSAnYW5ndWxhcmZpcmUyL2F1dGgnO1xuaW1wb3J0IHsgYXV0aCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBJU2lnbkluTWV0aG9kc0ZvckVtYWlsUmVzdWx0LCBnZXRPQXV0aFByb3ZpZGVySWNvbiwgZ2V0T0F1dGhQcm92aWRlck5hbWUgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aFNlcnZpY2UgfSBmcm9tICcuLi8uLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcbmltcG9ydCB7IGZhZGVJbk91dEFuaW1hdGlvbiwgc2NyZWVuQW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1tZXRob2RzLWZvcm0nLFxuICB0ZW1wbGF0ZTogYDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICdlbWFpbCdcIj5FbWFpbCBBZGRyZXNzPC9sYWJlbD5cbiAgICA8aW5wdXRcbiAgICAgICNlbWFpbElucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICB0eXBlPVwiZW1haWxcIlxuICAgICAgYXV0b2NvbXBsZXRlPVwiZW1haWxcIlxuICAgICAgcGxhY2Vob2xkZXI9XCJFbWFpbCBBZGRyZXNzXCJcbiAgICAgIGZvcm1Db250cm9sTmFtZT1cImVtYWlsXCJcbiAgICAgIChibHVyKT1cImZldGNoKClcIlxuICAgICAgKGtleXVwLmVudGVyKT1cImVtYWlsSW5wdXQuYmx1cigpXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmludmFsaWRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaGFzRXJyb3IoJ2VtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaGFzRXJyb3IoJ2F1dGgvaW52YWxpZC1lbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgZm9ybS10ZXh0XCIgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiIFtuZ1N3aXRjaF09XCJmZXRjaFN0YXR1c1wiPlxuICAgICAgPHNwYW4gKm5nU3dpdGNoQ2FzZT1cIid1bmZldGNoZWQnXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiPlxuICAgICAgICBUbyBnZXQgc3RhcnRlZCwgZW50ZXIgeW91ciBlbWFpbCBhZGRyZXNzLlxuICAgICAgICBJZiB5b3UgZG9uw6LCgMKZdCB5ZXQgaGF2ZSBhbiBhY2NvdW50IHdlw6LCgMKZbGwgY3JlYXRlIG9uZSBmb3IgeW91LlxuICAgICAgPC9zcGFuPlxuICAgICAgPHNwYW4gKm5nU3dpdGNoQ2FzZT1cIidmZXRjaGluZydcIiBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNwaW4gZmEtc3Bpbm5lciBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgTG9va2luZyB1cCBhY2NvdW50Li4uXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdTd2l0Y2hDYXNlPVwiJ2ZldGNoZWQnXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1mdyB0ZXh0LXN1Y2Nlc3NcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudEV4aXN0c1wiPkFjY291bnQgZm91bmQuPC9zcGFuPlxuICAgICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRJc05ld1wiPldlJ2xsIGNyZWF0ZSBhbiBhY2NvdW50Ljwvc3Bhbj5cbiAgICAgIDwvc3Bhbj5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVja1wiPlxuICAgICAgPGlucHV0XG4gICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiXG4gICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVtZW1iZXJcIlxuICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgUmVtZW1iZXIgbWUgb24gdGhpcyBkZXZpY2UuXG4gICAgICA8L2xhYmVsPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZm9ybT5cbjxkaXYgKm5nSWY9XCJtZXRob2RzRmV0Y2hlZCAmJiBhY2NvdW50RXhpc3RzXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIG1iLTEgZm9ybS10ZXh0XCI+XG4gICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50SGFzUGFzc3dvcmRcIj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudE9BdXRoTWV0aG9kcy5sZW5ndGggPT09IDBcIj5cbiAgICAgICAgUGxlYXNlIHNpZ24gaW4gd2l0aCB5b3VyIHBhc3N3b3JkLi4uXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID09PSAxXCI+XG4gICAgICAgIFBsZWFzZSBzaWduIGluIHdpdGggeW91ciBwYXNzd29yZCBvciB5b3VyXG4gICAgICAgIGxpbmtlZCB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKGFjY291bnRPQXV0aE1ldGhvZHNbMF0pfX0gYWNjb3VudC4uLlxuICAgICAgPC9zcGFuPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA+IDFcIj5cbiAgICAgICAgUGxlYXNlIHNpZ24gaW4gd2l0aCB5b3VyIHBhc3N3b3JkIG9yIG9uZSBvZiB5b3VyIGxpbmtlZCBhY2NvdW50cy4uLlxuICAgICAgPC9zcGFuPlxuICAgIDwvc3Bhbj5cbiAgICA8c3BhbiAqbmdJZj1cIiFhY2NvdW50SGFzUGFzc3dvcmRcIj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudE9BdXRoTWV0aG9kcy5sZW5ndGggPT09IDFcIj5cbiAgICAgICAgUGxlYXNlIHNpZ24gaW4gd2l0aCB5b3VyXG4gICAgICAgIGxpbmtlZCB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKGFjY291bnRPQXV0aE1ldGhvZHNbMF0pfX0gYWNjb3VudC4uLlxuICAgICAgPC9zcGFuPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA+IDFcIj5cbiAgICAgICAgUGxlYXNlIHNpZ24gaW4gd2l0aCBvbmUgb2YgeW91ciBsaW5rZWQgYWNjb3VudHMuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICA8L3NwYW4+XG5cbiAgPC9zbWFsbD5cblxuICA8ZGl2IGNsYXNzPVwibGlzdC1ncm91cFwiPlxuICAgIDxhXG4gICAgICAqbmdJZj1cImFjY291bnRIYXNQYXNzd29yZFwiXG4gICAgICByb3V0ZXJMaW5rPVwiLlwiXG4gICAgICBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25JblBhc3N3b3JkJ31cIlxuICAgICAgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbG9jayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlxuICAgICAgICBTaWduIEluIHdpdGggWW91ciBQYXNzd29yZFxuICAgICAgPC9zcGFuPlxuICAgIDwvYT5cbiAgICA8YVxuICAgICAgKm5nRm9yPVwibGV0IGlkIG9mIGFjY291bnRPQXV0aE1ldGhvZHNcIlxuICAgICAgcm91dGVyTGluaz1cIi5cIlxuICAgICAgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW5PQXV0aCcsIHByb3ZpZGVySWQ6IGlkfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihpZClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5cbiAgICAgICAgU2lnbiBJbiB3aXRoIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoaWQpfX1cbiAgICAgIDwvc3Bhbj5cbiAgICA8L2E+XG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCJtZXRob2RzRmV0Y2hlZCAmJiBhY2NvdW50SXNOZXdcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMSBmb3JtLXRleHRcIj5cbiAgICA8c3BhbiAqbmdJZj1cIm9BdXRoUHJvdmlkZXJJZHMubGVuZ3RoID09PSAwXCI+XG4gICAgICBQbGVhc2UgY3JlYXRlIGFuIGFjY291bnQuLi5cbiAgICA8L3NwYW4+XG4gICAgPHNwYW4gKm5nSWY9XCJvQXV0aFByb3ZpZGVySWRzLmxlbmd0aCA9PT0gMVwiPlxuICAgICAgUGxlYXNlIHNpZ24gdXAgd2l0aCB5b3VyXG4gICAgICB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKG9BdXRoUHJvdmlkZXJJZHNbMF0pfX0gYWNjb3VudCxcbiAgICAgIG9yIGNyZWF0ZSBhIHNlcGFyYXRlIGFjY291bnQgd2l0aCBhIHBhc3N3b3JkLi4uLlxuICAgIDwvc3Bhbj5cbiAgICA8c3BhbiAqbmdJZj1cIm9BdXRoUHJvdmlkZXJJZHMubGVuZ3RoID4xXCI+XG4gICAgICBQbGVhc2Ugc2lnbiB1cCB3aXRoIG9uZSBvZiB0aGUgc2VydmljZXMgbGlzdGVkIGJlbG93LFxuICAgICAgb3IgY3JlYXRlIGEgc2VwYXJhdGUgYWNjb3VudCB3aXRoIGEgcGFzc3dvcmQuLi4uXG4gICAgPC9zcGFuPlxuICA8L3NtYWxsPlxuICA8ZGl2IGNsYXNzPVwibGlzdC1ncm91cFwiPlxuXG4gICAgPGFcbiAgICAgICpuZ0Zvcj1cImxldCBpZCBvZiBvQXV0aFByb3ZpZGVySWRzXCJcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluT0F1dGgnLCBwcm92aWRlcklkOiBpZH1cIlxuICAgICAgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiPlxuICAgICAgPGkgW2F0dHIuY2xhc3NdPVwiZ2V0T0F1dGhQcm92aWRlckljb24oaWQpXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+XG4gICAgICAgIFNpZ24gVXAgd2l0aCB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKGlkKX19XG4gICAgICA8L3NwYW4+XG4gICAgPC9hPlxuICAgIDxhXG4gICAgICByb3V0ZXJMaW5rPVwiLlwiXG4gICAgICBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25VcFBhc3N3b3JkJ31cIlxuICAgICAgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbG9jayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlxuICAgICAgICBDcmVhdGVcbiAgICAgICAgPHNwYW4gKm5nSWY9XCJvQXV0aFByb3ZpZGVySWRzLmxlbmd0aCA+IDBcIj5cbiAgICAgICAgICBhIFNlcGFyYXRlXG4gICAgICAgIDwvc3Bhbj5cbiAgICAgICAgQWNjb3VudFxuICAgICAgPC9zcGFuPlxuICAgIDwvYT5cbiAgPC9kaXY+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW2ZhZGVJbk91dEFuaW1hdGlvbiwgc2NyZWVuQW5pbWF0aW9uXVxufSlcbmV4cG9ydCBjbGFzcyBTaWduSW5NZXRob2RzRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cblxuICBAVmlld0NoaWxkKCdlbWFpbElucHV0JykgZW1haWxJbnB1dDogRWxlbWVudFJlZjtcbiAgQElucHV0KCkgZW1haWw6IHN0cmluZztcbiAgQElucHV0KCkgcmVtZW1iZXI6IGJvb2xlYW47XG4gIEBJbnB1dCgpIG9BdXRoUHJvdmlkZXJJZHM6IHN0cmluZ1tdID0gW107XG4gIEBPdXRwdXQoKSBlbWFpbENoYW5nZTogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSByZW1lbWJlckNoYW5nZTogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPGF1dGguVXNlckNyZWRlbnRpYWw+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZXJyb3I6IEV2ZW50RW1pdHRlcjxhdXRoLkVycm9yPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybS0nO1xuICBzdWJtaXR0aW5nID0gZmFsc2U7XG4gIGZnOiBGb3JtR3JvdXA7XG4gIGVtYWlsRmM6IEZvcm1Db250cm9sO1xuICByZW1lbWJlckZjOiBGb3JtQ29udHJvbDtcbiAgZ2V0T0F1dGhQcm92aWRlckljb24gPSBnZXRPQXV0aFByb3ZpZGVySWNvbjtcbiAgZ2V0T0F1dGhQcm92aWRlck5hbWUgPSBnZXRPQXV0aFByb3ZpZGVyTmFtZTtcbiAgbWV0aG9kc0ZvckVtYWlsOiBJU2lnbkluTWV0aG9kc0ZvckVtYWlsUmVzdWx0ID0ge3N0YXR1czogJ3VuZmV0Y2hlZCcsIG1ldGhvZHM6IFtdLCBlbWFpbDogbnVsbH07XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfYXV0aFNlcnZpY2U6IE5neEZpcmViYXNlQXV0aFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBfbmdab25lOiBOZ1pvbmVcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuICBnZXQgYXV0aFNlcnZpY2UoKTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSB7XG4gICAgcmV0dXJuIHRoaXMuX2F1dGhTZXJ2aWNlO1xuICB9XG5cblxuICBnZXQgbWV0aG9kcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZvckVtYWlsLm1ldGhvZHM7XG4gIH1cblxuICBnZXQgZmV0Y2hTdGF0dXMoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRm9yRW1haWwuc3RhdHVzO1xuICB9XG5cbiAgZ2V0IG1ldGhvZHNGZXRjaGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1ldGhvZHNGb3JFbWFpbC5zdGF0dXMgPT09ICdmZXRjaGVkJztcbiAgfVxuXG4gIGdldCBhY2NvdW50SXNOZXcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZldGNoZWQgJiYgdGhpcy5tZXRob2RzLmxlbmd0aCA9PT0gMDtcbiAgfVxuXG4gIGdldCBhY2NvdW50RXhpc3RzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1ldGhvZHNGZXRjaGVkICYmIHRoaXMubWV0aG9kcy5sZW5ndGggPiAwO1xuICB9XG5cbiAgZ2V0IGFjY291bnRIYXNQYXNzd29yZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5hY2NvdW50RXhpc3RzICYmIHRoaXMubWV0aG9kcy5pbmRleE9mKCdwYXNzd29yZCcpICE9PSAtMTtcbiAgfVxuXG4gIGdldCBhY2NvdW50T0F1dGhNZXRob2RzKCk6IHN0cmluZ1tdIHtcbiAgICBpZiAoISB0aGlzLmFjY291bnRFeGlzdHMpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kcy5maWx0ZXIoaWQgPT4gaWQgIT09ICdwYXNzd29yZCcpO1xuICB9XG5cblxuXG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5lbWFpbEZjID0gbmV3IEZvcm1Db250cm9sKFxuICAgICAgdGhpcy5lbWFpbCxcbiAgICAgIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5lbWFpbF19XG4gICAgKTtcbiAgICB0aGlzLnJlbWVtYmVyRmMgPSBuZXcgRm9ybUNvbnRyb2wodGhpcy5yZW1lbWJlcik7XG4gICAgdGhpcy5yZW1lbWJlckZjLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4gdGhpcy5yZW1lbWJlckNoYW5nZS5lbWl0KHRoaXMucmVtZW1iZXJGYy52YWx1ZSkpO1xuICAgIHRoaXMuZmcgPSBuZXcgRm9ybUdyb3VwKHtlbWFpbDogdGhpcy5lbWFpbEZjLCByZW1lbWJlcjogdGhpcy5yZW1lbWJlckZjfSk7XG4gICAgdGhpcy5lbWFpbEZjLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4gdGhpcy5lbWFpbENoYW5nZS5lbWl0KHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCkpKTtcbiAgICB0aGlzLmVtYWlsRmMudmFsdWVDaGFuZ2VzLnBpcGUoZGVib3VuY2VUaW1lKDUwMCkpLnN1YnNjcmliZSgoKSA9PiB0aGlzLmZldGNoKCkpO1xuICAgIHRoaXMuZmV0Y2goKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmVtYWlsSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuXG4gIH1cblxuXG4gIGZldGNoKCkge1xuICAgIGNvbnN0IGVtYWlsID0gdGhpcy5lbWFpbEZjLnZhbHVlLnRyaW0oKTtcbiAgICBpZiAoZW1haWwgPT09IHRoaXMubWV0aG9kc0ZvckVtYWlsLmVtYWlsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICgnZmV0Y2hpbmcnID09PSB0aGlzLm1ldGhvZHNGb3JFbWFpbC5zdGF0dXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSB7c3RhdHVzOiAnZmV0Y2hpbmcnLCBtZXRob2RzOiBbXSwgZW1haWw6IGVtYWlsfTtcbiAgICBpZiAodGhpcy5lbWFpbEZjLmludmFsaWQpIHtcbiAgICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0ge3N0YXR1czogJ3VuZmV0Y2hlZCcsIG1ldGhvZHM6IFtdLCBlbWFpbDogZW1haWx9O1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmF1dGguZmV0Y2hTaWduSW5NZXRob2RzRm9yRW1haWwoZW1haWwpXG4gICAgICAudGhlbihyZXN1bHRzID0+IHtcbiAgICAgICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSB7c3RhdHVzOiAnZmV0Y2hlZCcsIG1ldGhvZHM6IHJlc3VsdHMsIGVtYWlsOiBlbWFpbH07XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgc3dpdGNoIChlcnJvci5jb2RlKSB7XG4gICAgICAgICAgY2FzZSAnYXV0aC9pbnZhbGlkLWVtYWlsJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5lbWFpbEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0ge2VtYWlsOiB0aGlzLmVtYWlsLCBzdGF0dXM6ICd1bmZldGNoZWQnLCBtZXRob2RzOiBbXX07XG4gICAgICB9KTtcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcblxuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aFNlcnZpY2UgfSBmcm9tICcuLi8uLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcbmltcG9ydCB7IGdldE9BdXRoUHJvdmlkZXJJY29uLCBnZXRPQXV0aFByb3ZpZGVyTmFtZSwgZmFkZUluT3V0QW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLWZvcm0nLFxuICB0ZW1wbGF0ZTogYDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIiAobmdTdWJtaXQpPVwic3VibWl0KClcIj5cblxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiPkVtYWlsIEFkZHJlc3M8L2xhYmVsPlxuXG4gICAgPGlucHV0XG4gICAgICByZWFkb25seVxuICAgICAgI2VtYWlsSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJlbWFpbFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2F1dGgvaW52YWxpZC1lbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2F1dGgvdXNlci1ub3QtZm91bmQnKVwiPlxuICAgICAgV2UgY291bGQgbm90IGZpbmQgYW4gYWNjb3VudCB3aXRoIHRoYXQgZW1haWwgYWRkcmVzcy5cbiAgICAgIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW4nfVwiPkNyZWF0ZSBBY2NvdW50PC9hPlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2F1dGgvdXNlci1kaXNhYmxlZCcpXCI+XG4gICAgICBUaGUgYWNjb3VudCB3aXRoIHRoYXQgZW1haWwgYWRkcmVzcyBoYXMgYmVlbiBkaXNhYmxlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCduZ3gtZmlyZWJhc2UtYXV0aC9uby1wYXNzd29yZCcpXCI+XG4gICAgICBUaGUgYWNjb3VudCB3aXRoIHRoYXQgZW1haWwgYWRkcmVzcyBkb2VzIG5vdCBoYXZlIGEgcGFzc3dvcmQuXG4gICAgICBQbGVhc2Ugc2lnbiBpbiB1c2luZzpcbiAgICAgIDxzcGFuICpuZ0Zvcj1cImxldCBpZCBvZiBtZXRob2RzRm9yRW1haWw7IGxldCBpc0xhc3QgPSBsYXN0XCI+XG4gICAgICAgIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW5PQXV0aCcsIHByb3ZpZGVySWQ6IGlkfVwiPnt7Z2V0T0F1dGhQcm92aWRlck5hbWUoaWQpfX08L2E+XG4gICAgICAgIDxzcGFuICpuZ0lmPVwiIWlzTGFzdFwiPlxuICAgICAgICAgIHxcbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9zcGFuPlxuICAgIDwvZGl2PlxuXG4gICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBmb3JtLXRleHRcIiBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCIgPlxuICAgICAgTm90IHlvdXIgZW1haWwgYWRkcmVzcz9cbiAgICAgIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW4nfVwiPlN0YXJ0IE92ZXI8L2E+XG4gICAgPC9zbWFsbD5cbiAgPC9kaXY+XG5cblxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtZW5kXCI+XG4gICAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICdwYXNzd29yZCdcIj5QYXNzd29yZDwvbGFiZWw+XG4gICAgICA8c21hbGw+XG4gICAgICAgIDxhIChjbGljayk9XCIkZXZlbnQucHJldmVudERlZmF1bHQoKTsgcGFzc3dvcmRJbnB1dC50eXBlID0gJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlICA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgIGhyZWY9XCIjXCIgdGFiaW5kZXg9XCItMVwiIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2tcIj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIidwYXNzd29yZCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPlNob3c8L3NwYW4+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIndGV4dCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPkhpZGU8L3NwYW4+XG4gICAgICAgIDwvYT5cbiAgICAgIDwvc21hbGw+XG4gICAgPC9kaXY+XG4gICAgPGlucHV0XG4gICAgICAjcGFzc3dvcmRJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiXG4gICAgICB0eXBlPVwicGFzc3dvcmRcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicGFzc3dvcmRcIlxuICAgICAgcGxhY2Vob2xkZXI9XCJQYXNzd29yZFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJwYXNzd29yZFwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5pbnZhbGlkXCI+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIlxuICAgICAgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiXG4gICAgICBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiXG4gICAgICAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdhdXRoL3dyb25nLXBhc3N3b3JkJylcIlxuICAgICAgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiPlxuICAgICAgV3JvbmcgcGFzc3dvcmQuXG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIFthdHRyLmlkXT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiIGNsYXNzPVwiZm9ybS10ZXh0IHRleHQtbXV0ZWRcIj5cbiAgICAgIEZvcmdvdD8gPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3Jlc2V0UGFzc3dvcmQnfVwiPlJlc2V0IFBhc3N3b3JkPC9hPlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgIDwvbGFiZWw+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICBjbGFzcz1cImJ0biBidG4tc3VjY2VzcyBidG4tYmxvY2tcIlxuICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbG9jayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIFNpZ24gSW5cbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Zvcm0+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtmYWRlSW5PdXRBbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25JbkZvcm1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG4gIEBWaWV3Q2hpbGQoJ3Bhc3N3b3JkSW5wdXQnKSBwYXNzd29yZElucHV0OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLWZvcm0tJztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICBmZzogRm9ybUdyb3VwO1xuICBlbWFpbEZjOiBGb3JtQ29udHJvbDtcbiAgcGFzc3dvcmRGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICBtZXRob2RzRm9yRW1haWw6IHN0cmluZ1tdID0gW107XG4gIGdldE9BdXRoUHJvdmlkZXJJY29uID0gZ2V0T0F1dGhQcm92aWRlckljb247XG4gIGdldE9BdXRoUHJvdmlkZXJOYW1lID0gZ2V0T0F1dGhQcm92aWRlck5hbWU7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2FmQXV0aDogQW5ndWxhckZpcmVBdXRoLFxuICAgIHByaXZhdGUgX2F1dGhTZXJ2aWNlOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlXG4gICkgeyB9XG5cbiAgZ2V0IGF1dGgoKTogYXV0aC5BdXRoIHtcbiAgICByZXR1cm4gdGhpcy5fYWZBdXRoLmF1dGg7XG4gIH1cblxuICBnZXQgYXV0aFNlcnZpY2UoKTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSB7XG4gICAgcmV0dXJuIHRoaXMuX2F1dGhTZXJ2aWNlO1xuICB9XG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmVtYWlsRmMgPSBuZXcgRm9ybUNvbnRyb2woXG4gICAgICB0aGlzLmVtYWlsLFxuICAgICAge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLmVtYWlsXX1cbiAgICApO1xuICAgIHRoaXMucGFzc3dvcmRGYyA9IG5ldyBGb3JtQ29udHJvbCgnJywge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkXX0pO1xuICAgIHRoaXMucmVtZW1iZXJGYyA9IG5ldyBGb3JtQ29udHJvbCh0aGlzLnJlbWVtYmVyKTtcbiAgICB0aGlzLnJlbWVtYmVyRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSh2YWwgPT4gdGhpcy5yZW1lbWJlckNoYW5nZS5lbWl0KHZhbCkpO1xuICAgIHRoaXMuZmcgPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgIGVtYWlsOiB0aGlzLmVtYWlsRmMsXG4gICAgICBwYXNzd29yZDogdGhpcy5wYXNzd29yZEZjLFxuICAgICAgcmVtZW1iZXI6IHRoaXMucmVtZW1iZXJGY1xuICAgIH0pO1xuICB9XG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLnBhc3N3b3JkSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICB9XG5cblxuXG4gIHN1Ym1pdCgpIHtcbiAgICBjb25zdCBlbWFpbCA9IHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCk7XG4gICAgdGhpcy5zdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IFtdO1xuICAgIGxldCBjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsO1xuICAgIHRoaXMuYXV0aC5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChlbWFpbClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHJlc3VsdHM7XG4gICAgICAgIGlmIChyZXN1bHRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCh7XG4gICAgICAgICAgICBjb2RlOiAnYXV0aC91c2VyLW5vdC1mb3VuZCdcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzdWx0cy5pbmRleE9mKCdwYXNzd29yZCcpID09PSAtMSkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCh7XG4gICAgICAgICAgICBjb2RlOiAnbmd4LWZpcmViYXNlLWF1dGgvbm8tcGFzc3dvcmQnLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGguc2lnbkluV2l0aEVtYWlsQW5kUGFzc3dvcmQoZW1haWwsIHRoaXMucGFzc3dvcmRGYy52YWx1ZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzdWx0ID0+IHtcbiAgICAgICAgY3JlZCA9IHJlc3VsdDtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aFNlcnZpY2Uuc2V0UmVtZW1iZXJlZCh0aGlzLnJlbWVtYmVyRmMudmFsdWUgPT09IHRydWUsIGVtYWlsKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc3VjY2Vzcy5lbWl0KGNyZWQpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHRoaXMuc3VibWl0dGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1lbWFpbCc6XG4gICAgICAgICAgY2FzZSAnYXV0aC91c2VyLW5vdC1mb3VuZCc6XG4gICAgICAgICAgY2FzZSAnYXV0aC91c2VyLWRpc2FibGVkJzpcbiAgICAgICAgICBjYXNlICduZ3gtZmlyZWJhc2UtYXV0aC9uby1wYXNzd29yZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMuZW1haWxGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdhdXRoL3dyb25nLXBhc3N3b3JkJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5wYXNzd29yZEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aGlzLmVycm9yLmVtaXQoZXJyb3IpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlclZpZXdJbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuXG5pbXBvcnQgeyBmYWRlSW5PdXRBbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aFNlcnZpY2UgfSBmcm9tICcuLi8uLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXNpZ24tdXAtZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiIChuZ1N1Ym1pdCk9XCJzdWJtaXQoKVwiPlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiPkVtYWlsIEFkZHJlc3M8L2xhYmVsPlxuICAgIDxpbnB1dFxuICAgICAgcmVhZG9ubHlcbiAgICAgICNlbWFpbElucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICB0eXBlPVwiZW1haWxcIlxuICAgICAgYXV0b2NvbXBsZXRlPVwiZW1haWxcIlxuICAgICAgcGxhY2Vob2xkZXI9XCJFbWFpbCBBZGRyZXNzXCJcbiAgICAgIGZvcm1Db250cm9sTmFtZT1cImVtYWlsXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCI+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdhdXRoL2ludmFsaWQtZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCduZ3gtZmlyZWJhc2UtYXV0aC9hY2NvdW50LWV4aXN0cycpXCI+XG4gICAgICBXZSBmb3VuZCBhbiBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzLlxuICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U2lnbiBJbjwvYT5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIGZvcm0tdGV4dFwiIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIiA+XG4gICAgICBOb3QgeW91ciBlbWFpbCBhZGRyZXNzP1xuICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+R28gQmFjazwvYT5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtZW5kXCI+XG4gICAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICdwYXNzd29yZCdcIj5DaG9vc2UgUGFzc3dvcmQ8L2xhYmVsPlxuICAgICAgPHNtYWxsPlxuICAgICAgICA8YSAoY2xpY2spPVwiJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IHBhc3N3b3JkSW5wdXQudHlwZSA9ICdwYXNzd29yZCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZSAgPyAndGV4dCcgOiAncGFzc3dvcmQnXCJcbiAgICAgICAgICBocmVmPVwiI1wiIHRhYmluZGV4PVwiLTFcIiBjbGFzcz1cImQtaW5saW5lLWJsb2NrXCI+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5TaG93PC9zcGFuPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3RleHQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5IaWRlPC9zcGFuPlxuICAgICAgICA8L2E+XG4gICAgICA8L3NtYWxsPlxuICAgIDwvZGl2PlxuICAgIDxpbnB1dFxuICAgICAgI3Bhc3N3b3JkSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdwYXNzd29yZCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAncGFzc3dvcmQtaGVscCdcIlxuICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgIGZvcm1Db250cm9sTmFtZT1cInBhc3N3b3JkXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiQ2hvb3NlIFBhc3N3b3JkXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cInBhc3N3b3JkXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmludmFsaWRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaGFzRXJyb3IoJ2F1dGgvd3JvbmctcGFzc3dvcmQnKVwiPlxuICAgICAgV3JvbmcgcGFzc3dvcmQuXG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIFthdHRyLmlkXT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiIGNsYXNzPVwiZm9ybS10ZXh0IHRleHQtbXV0ZWRcIj5cbiAgICAgIFBsZWFzZSBjaG9vc2UgYSBzdHJvbmcgcGFzc3dvcmQuXG4gICAgPC9zbWFsbD5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnbmFtZSdcIj5Zb3VyIE5hbWU8L2xhYmVsPlxuICAgIDxpbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ25hbWUnXCJcbiAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgIGZvcm1Db250cm9sTmFtZT1cIm5hbWVcIlxuICAgICAgcGxhY2Vob2xkZXI9XCJZb3VyIE5hbWVcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwibmFtZUZjLnRvdWNoZWQgJiYgbmFtZUZjLmludmFsaWRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJuYW1lRmMudG91Y2hlZCAmJiBuYW1lRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVja1wiPlxuICAgICAgPGlucHV0XG4gICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiXG4gICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVtZW1iZXJcIlxuICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgUmVtZW1iZXIgbWUgb24gdGhpcyBkZXZpY2UuXG4gICAgICA8L2xhYmVsPlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIlxuICAgICAgY2xhc3M9XCJidG4gYnRuLXN1Y2Nlc3MgYnRuLWJsb2NrXCJcbiAgICAgIFtkaXNhYmxlZF09XCJmZy5pbnZhbGlkIHx8IHN1Ym1pdHRpbmdcIj5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWxvY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBDcmVhdGUgQWNjb3VudFxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cbjwvZm9ybT5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogWyBmYWRlSW5PdXRBbmltYXRpb24gXVxufSlcbmV4cG9ydCBjbGFzcyBTaWduVXBGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcblxuICBAVmlld0NoaWxkKCdwYXNzd29yZElucHV0JykgcGFzc3dvcmRJbnB1dDogRWxlbWVudFJlZjtcbiAgQElucHV0KCkgZW1haWw6IHN0cmluZztcbiAgQElucHV0KCkgcmVtZW1iZXI6IGJvb2xlYW47XG4gIEBPdXRwdXQoKSByZW1lbWJlckNoYW5nZTogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPGF1dGguVXNlckNyZWRlbnRpYWw+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZXJyb3I6IEV2ZW50RW1pdHRlcjxhdXRoLkVycm9yPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBmb3JtSWQgPSAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi11cC1mb3JtLSc7XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHBhc3N3b3JkRmM6IEZvcm1Db250cm9sO1xuICBuYW1lRmM6IEZvcm1Db250cm9sO1xuICByZW1lbWJlckZjOiBGb3JtQ29udHJvbDtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfYXV0aFNlcnZpY2U6IE5neEZpcmViYXNlQXV0aFNlcnZpY2VcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbChcbiAgICAgIHRoaXMuZW1haWwsXG4gICAgICB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMuZW1haWxdfVxuICAgICk7XG4gICAgdGhpcy5wYXNzd29yZEZjID0gbmV3IEZvcm1Db250cm9sKCcnLCB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWRdfSk7XG4gICAgdGhpcy5uYW1lRmMgPSBuZXcgRm9ybUNvbnRyb2woJycsIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5yZXF1aXJlZE5vbkVtcHR5XX0pO1xuICAgIHRoaXMucmVtZW1iZXJGYyA9IG5ldyBGb3JtQ29udHJvbCh0aGlzLnJlbWVtYmVyKTtcbiAgICB0aGlzLnJlbWVtYmVyRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSh2YWwgPT4gdGhpcy5yZW1lbWJlckNoYW5nZS5lbWl0KHZhbCkpO1xuICAgIHRoaXMuZmcgPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgIGVtYWlsOiB0aGlzLmVtYWlsRmMsXG4gICAgICBwYXNzd29yZDogdGhpcy5wYXNzd29yZEZjLFxuICAgICAgbmFtZTogdGhpcy5uYW1lRmMsXG4gICAgICByZW1lbWJlcjogdGhpcy5yZW1lbWJlckZjXG4gICAgfSk7XG4gIH1cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMucGFzc3dvcmRJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuICBzdWJtaXQoKSB7XG5cbiAgICB0aGlzLnN1Ym1pdHRpbmcgPSB0cnVlO1xuICAgIGxldCBjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsO1xuICAgIHRoaXMuYXV0aC5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbCh0aGlzLmVtYWlsKVxuICAgICAgLnRoZW4oKHJlc3VsdHMpID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCh7XG4gICAgICAgICAgICBjb2RlOiAnbmd4LWZpcmViYXNlLWF1dGgvYWNjb3VudC1leGlzdHMnXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5jcmVhdGVVc2VyV2l0aEVtYWlsQW5kUGFzc3dvcmQodGhpcy5lbWFpbCwgdGhpcy5wYXNzd29yZEZjLnZhbHVlKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBjcmVkID0gcmVzdWx0O1xuICAgICAgICByZXR1cm4gY3JlZC51c2VyLnVwZGF0ZVByb2ZpbGUoe2Rpc3BsYXlOYW1lOiB0aGlzLm5hbWVGYy52YWx1ZS50cmltKCksIHBob3RvVVJMOiBudWxsfSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoU2VydmljZS5zZXRSZW1lbWJlcmVkKHRoaXMucmVtZW1iZXJGYy52YWx1ZSA9PT0gdHJ1ZSwgdGhpcy5lbWFpbCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdChjcmVkKTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLnBhc3N3b3JkRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlICdhdXRoL2ludmFsaWQtZW1haWwnOlxuICAgICAgICAgIGNhc2UgJ25neC1maXJlYmFzZS1hdXRoL2FjY291bnQtZXhpc3RzJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5lbWFpbEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2F1dGgvd2Vhay1wYXNzd29yZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMucGFzc3dvcmRGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy5lcnJvci5lbWl0KGVycm9yKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIgfSBmcm9tICcuLi8uLi9mb3JtLWhlbHBlcic7XG5pbXBvcnQgeyBmYWRlSW5PdXRBbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0nLFxuICB0ZW1wbGF0ZTogYDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIiAobmdTdWJtaXQpPVwic3VibWl0KClcIj5cbiAgPGRpdiAqbmdJZj1cInNlbnRcIiBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgV2XDosKAwpl2ZSBzZW50IGEgcmVzZXQgcGFzc3dvcmQgbGluayB0byB7e3NlbnR9fS5cbiAgICAgIFBsZWFzZSBhbGxvdyBhIGZldyBtb21lbnRzIGZvciB0aGUgZW1haWwgdG8gYXJyaXZlLlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiPkVtYWlsIEFkZHJlc3M8L2xhYmVsPlxuICAgIDxpbnB1dFxuICAgICAgI2VtYWlsSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwtaGVscCdcIlxuICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgIGZvcm1Db250cm9sTmFtZT1cImVtYWlsXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmludmFsaWRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaGFzRXJyb3IoJ2F1dGgvdXNlci1ub3QtZm91bmQnKVwiPlxuICAgICAgV2UgY291bGQgbm90IGZpbmQgYW4gYWNjb3VudCB3aXRoIHRoYXQgZW1haWwgYWRkcmVzcy5cbiAgICAgIFBsZWFzZSA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbklVcFBhc3N3b3JkJ31cIj5zaWduIHVwPC9hPi5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignYXV0aC9pbnZhbGlkLWVtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbC1oZWxwJ1wiIGNsYXNzPVwiZm9ybS10ZXh0IHRleHQtbXV0ZWRcIj5cbiAgICAgIEVudGVyIHRoZSBlbWFpbCBhZGRyZXNzIHlvdSB1c2VkIHRvIHNpZ24gdXAuIFdlw6LCgMKZbGxcbiAgICAgIHNlbmQgYSByZXNldCBwYXNzd29yZCBsaW5rIHRvIHRoYXQgYWRkcmVzcy5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIlxuICAgICAgY2xhc3M9XCJidG4gYnRuLWJsb2NrIGJ0bi1zdWNjZXNzXCJcbiAgICAgIFtkaXNhYmxlZF09XCJmZy5pbnZhbGlkIHx8IHN1Ym1pdHRpbmdcIj5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWZ3IGZhLWVudmVsb3BlXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgU2VuZCBMaW5rXG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuPC9mb3JtPlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbZmFkZUluT3V0QW5pbWF0aW9uXVxufSlcbmV4cG9ydCBjbGFzcyBSZXNldFBhc3N3b3JkU2VuZEZvcm1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG4gIEBWaWV3Q2hpbGQoJ2VtYWlsSW5wdXQnKSBlbWFpbElucHV0OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBAT3V0cHV0KCkgZW1haWxDaGFuZ2U6IEV2ZW50RW1pdHRlcjxzdHJpbmc+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZXJyb3I6IEV2ZW50RW1pdHRlcjxhdXRoLkVycm9yPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBmb3JtSWQgPSAnbmd4LWZpcmViYXNlLWF1dGgtcmVzZXQtcGFzc3dvcmQtc2VuZC1mb3JtLSc7XG4gIGZnOiBGb3JtR3JvdXA7XG4gIGVtYWlsRmM6IEZvcm1Db250cm9sO1xuICBzdWJtaXR0aW5nID0gZmFsc2U7XG4gIHNlbnQ6IHN0cmluZyA9IG51bGw7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2FmQXV0aDogQW5ndWxhckZpcmVBdXRoLFxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cblxuXG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmVtYWlsRmMgPSBuZXcgRm9ybUNvbnRyb2woXG4gICAgICB0aGlzLmVtYWlsLFxuICAgICAge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLmVtYWlsXX1cbiAgICApO1xuICAgIHRoaXMuZW1haWxGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKCgpID0+IHRoaXMuZW1haWxDaGFuZ2UuZW1pdCh0aGlzLmVtYWlsRmMudmFsdWUudHJpbSgpKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe2VtYWlsOiB0aGlzLmVtYWlsRmN9KTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpIHtcbiAgICB0aGlzLmVtYWlsSW5wdXQubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICB9XG5cblxuICBzdWJtaXQoKSB7XG4gICAgY29uc3QgZW1haWwgPSB0aGlzLmVtYWlsRmMudmFsdWUudHJpbSgpO1xuICAgIHRoaXMuc3VibWl0dGluZyA9IHRydWU7XG4gICAgdGhpcy5zZW50ID0gbnVsbDtcbiAgICB0aGlzLmF1dGguc2VuZFBhc3N3b3JkUmVzZXRFbWFpbChlbWFpbClcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5zdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2VudCA9IGVtYWlsO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy5zdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlICdhdXRoL2ludmFsaWQtZW1haWwnOlxuICAgICAgICAgIGNhc2UgJ2F1dGgvdXNlci1ub3QtZm91bmQnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLmVtYWlsRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRoaXMuZXJyb3IuZW1pdChlcnJvcik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSk7XG5cblxuICB9XG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgZ2V0T0F1dGhQcm92aWRlckljb24sIGdldE9BdXRoUHJvdmlkZXJOYW1lIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aFNlcnZpY2UgfSBmcm9tICcuLi8uLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1vYXV0aCcsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInbWV0aG9kRXJyb3InID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1leGNsYW1hdGlvbi10cmlhbmdsZSBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBXZSBjb3VsZCBub3Qgc2lnbiB5b3UgaW4gd2l0aCB7e21ldGhvZEVycm9yLmNyZWRlbnRpYWwucHJvdmlkZXJJZH19LlxuICA8L2Rpdj5cblxuICA8cCBjbGFzcz1cInRleHQtbXV0ZWRcIj5cbiAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIG9uZSBvZiB0aGUgbWV0aG9kcyBhc3NvY2lhdGVkIHdpdGhcbiAgICB7e21ldGhvZEVycm9yLmVtYWlsfX06XG4gIDwvcD5cblxuICA8ZGl2IGNsYXNzPVwibGlzdC1ncm91cFwiPlxuICAgIDxhXG4gICAgICAqbmdJZj1cIm1ldGhvZEVycm9yLmFjY291bnRIYXNQYXNzd29yZFwiXG4gICAgICByb3V0ZXJMaW5rPVwiLlwiXG4gICAgICBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25JblBhc3N3b3JkJ31cIlxuICAgICAgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtdW5sb2NrXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+U2lnbiBJbiB3aXRoIFlvdXIgUGFzc3dvcmQ8L3NwYW4+XG4gICAgPC9hPlxuICAgIDxidXR0b25cbiAgICAgICpuZ0Zvcj1cImxldCBpZCBvZiBtZXRob2RFcnJvci5hY2NvdW50T0F1dGhNZXRob2RzXCJcbiAgICAgIChjbGljayk9XCJvQXV0aFNpZ25JbihpZClcIlxuICAgICAgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiPlxuICAgICAgPGkgW2F0dHIuY2xhc3NdPVwiZ2V0T0F1dGhQcm92aWRlckljb24oaWQpXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+U2lnbiBJbiB3aXRoIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoaWQpfX08L3NwYW4+XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuXG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Zvcm0+XG5cbiAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+XG4gICAgSXMge3ttZXRob2RFcnJvci5lbWFpbH19IG5vdCB5b3VyIGVtYWlsIGFkZHJlc3M/XG4gICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U3RhcnQgT3ZlcjwvYT5cbiAgPC9wPlxuXG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cIidyZXRyeScgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIEl0IGxvb2tzIGxpa2UgeW91IGNhbmNlbGxlZCBzaWduaW5nIGluIHdpdGhcbiAgICB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKHByb3ZpZGVySWQpfX0uIFRyeSBhZ2FpbjpcbiAgPC9kaXY+XG5cbiAgPGRpdiBjbGFzcz1cImxpc3QtZ3JvdXBcIj5cbiAgICA8YnV0dG9uXG4gICAgICAoY2xpY2spPVwib0F1dGhTaWduSW4ocHJvdmlkZXJJZClcIlxuICAgICAgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiPlxuICAgICAgPGkgW2F0dHIuY2xhc3NdPVwiZ2V0T0F1dGhQcm92aWRlckljb24ocHJvdmlkZXJJZClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5TaWduIEluIHdpdGgge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShwcm92aWRlcklkKX19PC9zcGFuPlxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cblxuICA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCI+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiXG4gICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICBbdmFsdWVdPVwidHJ1ZVwiXG4gICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVtZW1iZXJcIlxuICAgICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgICAgUmVtZW1iZXIgbWUgb24gdGhpcyBkZXZpY2UuXG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9mb3JtPlxuXG5cbiAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+XG4gICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U3RhcnQgT3ZlcjwvYT5cbiAgPC9wPlxuXG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogWyBzY3JlZW5BbmltYXRpb24gXVxufSlcbmV4cG9ydCBjbGFzcyBTaWduSW5PYXV0aENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgcHJvdmlkZXJJZDogc3RyaW5nO1xuICBASW5wdXQoKSBpbml0aWFsRXJyb3I6IGF1dGguRXJyb3I7XG4gIEBJbnB1dCgpIHVzZU9BdXRoUG9wdXA6IGJvb2xlYW47XG4gIEBJbnB1dCgpIG9BdXRoUHJvdmlkZXJGYWN0b3J5OiAocHJvdmlkZXJJZDogc3RyaW5nKSA9PiBhdXRoLkF1dGhQcm92aWRlcjtcbiAgQElucHV0KCkgZW1haWw6IHN0cmluZztcbiAgQElucHV0KCkgcmVtZW1iZXI6IGJvb2xlYW47XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlbWFpbENoYW5nZTogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSByZW1lbWJlckNoYW5nZTogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgZXJyb3I6IEV2ZW50RW1pdHRlcjxhdXRoLkVycm9yPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXG4gIHNjcmVlbjogJ3dhaXQnIHwgJ21ldGhvZEVycm9yJyB8ICdyZXRyeScgPSAnd2FpdCc7XG4gIG1ldGhvZEVycm9yOiBhdXRoLkVycm9yfGFueSA9IG51bGw7XG4gIGdldE9BdXRoUHJvdmlkZXJJY29uID0gZ2V0T0F1dGhQcm92aWRlckljb247XG4gIGdldE9BdXRoUHJvdmlkZXJOYW1lID0gZ2V0T0F1dGhQcm92aWRlck5hbWU7XG4gIGZnOiBGb3JtR3JvdXA7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICBmb3JtSWQgPSAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbi1vYXV0aC0nO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX2FmQXV0aDogQW5ndWxhckZpcmVBdXRoLFxuICAgIHByaXZhdGUgX3N2YzogTmd4RmlyZWJhc2VBdXRoU2VydmljZSxcbiAgICBwcml2YXRlIF9yb3V0ZTogQWN0aXZhdGVkUm91dGUsXG4gICAgcHJpdmF0ZSBfcm91dGVyOiBSb3V0ZXJcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fc3ZjO1xuICB9XG5cbiAgZ2V0IHJvdXRlKCk6IEFjdGl2YXRlZFJvdXRlIHtcbiAgICByZXR1cm4gdGhpcy5fcm91dGU7XG4gIH1cblxuICBnZXQgcm91dGVyKCk6IFJvdXRlciB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlcjtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMucmVtZW1iZXJGYyA9IG5ldyBGb3JtQ29udHJvbCh0aGlzLnJlbWVtYmVyKTtcbiAgICB0aGlzLnJlbWVtYmVyRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSh2YWwgPT4gdGhpcy5yZW1lbWJlckNoYW5nZS5lbWl0KHZhbCkpO1xuICAgIHRoaXMuZmcgPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmNcbiAgICB9KTtcbiAgICBpZiAodGhpcy5pbml0aWFsRXJyb3IpIHtcbiAgICAgIHRoaXMuaGFuZGxlT0F1dGhFcnJvcih0aGlzLmluaXRpYWxFcnJvcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMub0F1dGhTaWduSW4odGhpcy5wcm92aWRlcklkKTtcbiAgICB9XG4gIH1cblxuXG4gIG9BdXRoU2lnbkluKGlkOiBzdHJpbmcsIGZvcmNlUmVkaXJlY3Q/OiBib29sZWFuKSB7XG4gICAgdGhpcy5tZXRob2RFcnJvciA9IG51bGw7XG4gICAgbGV0IGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWw7XG4gICAgaWYgKHRoaXMudXNlT0F1dGhQb3B1cCAgJiYgZm9yY2VSZWRpcmVjdCAhPT0gdHJ1ZSkge1xuICAgICAgdGhpcy5nZXRPQXV0aFByb3ZpZGVyKGlkKVxuICAgICAgICAudGhlbihwcm92aWRlciA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduSW5XaXRoUG9wdXAocHJvdmlkZXIpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigocmVzdWx0OiBhdXRoLlVzZXJDcmVkZW50aWFsKSA9PiB7XG4gICAgICAgICAgY3JlZCA9IHJlc3VsdDtcbiAgICAgICAgICByZXR1cm4gdGhpcy5hdXRoU2VydmljZS5zZXRSZW1lbWJlcmVkKHRoaXMucmVtZW1iZXJGYy52YWx1ZSA9PT0gdHJ1ZSwgcmVzdWx0LnVzZXIuZW1haWwpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoY3JlZCk7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChlcnJvciA9PiB0aGlzLmhhbmRsZU9BdXRoRXJyb3IoZXJyb3IsIGlkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnLiddLCB7cmVsYXRpdmVUbzogdGhpcy5yb3V0ZSwgcXVlcnlQYXJhbXM6IHtyZW1lbWJlcjogdGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlfX0pXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5nZXRPQXV0aFByb3ZpZGVyKGlkKTtcbiAgICAgICAgfSlcbiAgICAgICAgLnRoZW4ocHJvdmlkZXIgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLmF1dGguc2lnbkluV2l0aFJlZGlyZWN0KHByb3ZpZGVyKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHRoaXMuaGFuZGxlT0F1dGhFcnJvcihlcnJvciwgaWQpKTtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVPQXV0aEVycm9yKGVycm9yOiBhdXRoLkVycm9yLCBwcm92aWRlcklkPzogc3RyaW5nKSB7XG4gICAgaWYgKGVycm9yWydlbWFpbCddICYmIGVycm9yWydjcmVkZW50aWFsJ10pIHtcbiAgICAgIHRoaXMuZW1haWxDaGFuZ2UuZW1pdChlcnJvclsnZW1haWwnXSk7XG4gICAgICB0aGlzLmF1dGguZmV0Y2hTaWduSW5NZXRob2RzRm9yRW1haWwoZXJyb3JbJ2VtYWlsJ10pXG4gICAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICAgIGVycm9yWydtZXRob2RzJ10gPSByZXN1bHRzO1xuICAgICAgICAgIGVycm9yWydhY2NvdW50SGFzUGFzc3dvcmQnXSA9IHJlc3VsdHMuaW5kZXhPZigncGFzc3dvcmQnKSAhPT0gLTE7XG4gICAgICAgICAgZXJyb3JbJ2FjY291bnRPQXV0aE1ldGhvZHMnXSA9IHJlc3VsdHMuZmlsdGVyKGlkID0+IGlkICE9PSAncGFzc3dvcmQnKTtcbiAgICAgICAgICB0aGlzLm1ldGhvZEVycm9yID0gZXJyb3I7XG4gICAgICAgICAgdGhpcy5zY3JlZW4gPSAnbWV0aG9kRXJyb3InO1xuICAgICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3dpdGNoIChlcnJvci5jb2RlKSB7XG4gICAgICBjYXNlICdhdXRoL2NhbmNlbGxlZC1wb3B1cC1yZXF1ZXN0JzpcbiAgICAgIGNhc2UgJ2F1dGgvcG9wdXAtY2xvc2VkLWJ5LXVzZXInOlxuICAgICAgICB0aGlzLnNjcmVlbiA9ICdyZXRyeSc7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnYXV0aC9wb3B1cC1ibG9ja2VkJzpcbiAgICAgICAgdGhpcy5vQXV0aFNpZ25Jbihwcm92aWRlcklkLCB0cnVlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aGlzLmVycm9yLmVtaXQoZXJyb3IpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBnZXRPQXV0aFByb3ZpZGVyKGlkOiBzdHJpbmcpOiBQcm9taXNlPGF1dGguQXV0aFByb3ZpZGVyPiB7XG4gICAgbGV0IHByb3ZpZGVyOiBhdXRoLkF1dGhQcm92aWRlciA9IG51bGw7XG4gICAgaWYgKHRoaXMub0F1dGhQcm92aWRlckZhY3RvcnkpIHtcbiAgICAgIHByb3ZpZGVyID0gdGhpcy5vQXV0aFByb3ZpZGVyRmFjdG9yeShpZCk7XG4gICAgfVxuICAgIGlmICghIHByb3ZpZGVyKSB7XG4gICAgICBzd2l0Y2ggKGlkKSB7XG4gICAgICAgIGNhc2UgJ3R3aXR0ZXIuY29tJzpcbiAgICAgICAgICBwcm92aWRlciA9IG5ldyBhdXRoLlR3aXR0ZXJBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZmFjZWJvb2suY29tJzpcbiAgICAgICAgICBwcm92aWRlciA9IG5ldyBhdXRoLkZhY2Vib29rQXV0aFByb3ZpZGVyKCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2dvb2dsZS5jb20nOlxuICAgICAgICAgIHByb3ZpZGVyID0gbmV3IGF1dGguR29vZ2xlQXV0aFByb3ZpZGVyKCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2dpdGh1Yi5jb20nOlxuICAgICAgICAgIHByb3ZpZGVyID0gbmV3IGF1dGguR2l0aHViQXV0aFByb3ZpZGVyKCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChwcm92aWRlcikge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShwcm92aWRlcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCh7XG4gICAgICAgIGNvZGU6ICduZ3gtZmlyZWJhc2UtYXV0aC9uby1wcm92aWRlci1mb3VuZCcsXG4gICAgICAgIG1lc3NhZ2U6IGBXZSBjb3VsZCBub3QgY3JlYXRlIGFuIE9BdXRoIHByb3ZpZGVyIGZvciBwcm92aWRlciBpZCBcIiR7aWR9XCIuYFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbn1cbiIsImltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4vbmd4LWZpcmViYXNlLWF1dGguc2VydmljZSc7XG5cblxuXG5cbkBOZ01vZHVsZSh7XG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGVcbiAgXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAgTmd4RmlyZWJhc2VBdXRoU2VydmljZVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIE5neEZpcmViYXNlQXV0aE1vZHVsZSB7IH1cbiIsImltcG9ydCB7IE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgUm91dGVyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTaWduSW5Db21wb25lbnQgfSBmcm9tICcuL3NpZ24taW4uY29tcG9uZW50JztcbmltcG9ydCB7IFNpZ25Jbk1ldGhvZHNGb3JtQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLWluLW1ldGhvZHMtZm9ybS9zaWduLWluLW1ldGhvZHMtZm9ybS5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2lnbkluRm9ybUNvbXBvbmVudCB9IGZyb20gJy4vc2lnbi1pbi1mb3JtL3NpZ24taW4tZm9ybS5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2lnblVwRm9ybUNvbXBvbmVudCB9IGZyb20gJy4vc2lnbi11cC1mb3JtL3NpZ24tdXAtZm9ybS5jb21wb25lbnQnO1xuaW1wb3J0IHsgUmVzZXRQYXNzd29yZFNlbmRGb3JtQ29tcG9uZW50IH0gZnJvbSAnLi9yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0vcmVzZXQtcGFzc3dvcmQtc2VuZC1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTaWduSW5PYXV0aENvbXBvbmVudCB9IGZyb20gJy4vc2lnbi1pbi1vYXV0aC9zaWduLWluLW9hdXRoLmNvbXBvbmVudCc7XG5cbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aE1vZHVsZSB9IGZyb20gJy4uL25neC1maXJlYmFzZS1hdXRoLm1vZHVsZSc7XG5cbkBOZ01vZHVsZSh7XG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgICBSb3V0ZXJNb2R1bGUsXG4gICAgTmd4RmlyZWJhc2VBdXRoTW9kdWxlXG4gIF0sXG4gIGRlY2xhcmF0aW9uczogW1xuICAgIFNpZ25JbkNvbXBvbmVudCxcbiAgICBTaWduSW5NZXRob2RzRm9ybUNvbXBvbmVudCxcbiAgICBTaWduSW5Gb3JtQ29tcG9uZW50LFxuICAgIFNpZ25VcEZvcm1Db21wb25lbnQsXG4gICAgUmVzZXRQYXNzd29yZFNlbmRGb3JtQ29tcG9uZW50LFxuICAgIFNpZ25Jbk9hdXRoQ29tcG9uZW50LFxuICBdLFxuICBleHBvcnRzOiBbXG4gICAgU2lnbkluQ29tcG9uZW50LFxuICBdXG59KVxuZXhwb3J0IGNsYXNzIE5neEZpcmViYXNlQXV0aFNpZ25Jbk1vZHVsZSB7IH1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIgfSBmcm9tICcuLi8uLi9mb3JtLWhlbHBlcic7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbmd4LWZpcmViYXNlLWF1dGguc2VydmljZSc7XG5pbXBvcnQgeyBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1vb2ItcmVzZXQtcGFzc3dvcmQnLFxuICB0ZW1wbGF0ZTogYDxkaXYgKm5nSWY9XCInd2FpdCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXNlY29uZGFyeVwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNwaW4gZmEtc3Bpbm5lciBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBQbGVhc2Ugd2FpdC4uLlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3N1Y2Nlc3MnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1zdWNjZXNzXCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgV2VsY29tZSwge3tjcmVkLnVzZXIuZGlzcGxheU5hbWV9fSFcbiAgICBZb3VyIG5ldyBwYXNzd29yZCBoYXMgYmVlbiBzYXZlZCBhbmQgeW91IGFyZSBzaWduZWQgaW4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdlcnJvcidcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8cD5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgV29vcHMhIEFuIGVycm9yIG9jY3VycmVkLlxuICAgIDwvcD5cbiAgICA8ZGl2IFtuZ1N3aXRjaF09XCJ1bmhhbmRsZWRFcnJvci5jb2RlXCI+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvZXhwaXJlZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHJlc2V0IHBhc3N3b3JkIGxpbmsgeW91IHVzZWQgaGFzIGV4cGlyZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvaW52YWxpZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHJlc2V0IHBhc3N3b3JkIGxpbmsgeW91IHVzZWQgaXMgbm90IHZhbGlkLiBUaGlzIG1heSBiZSBiZWNhdXNlIGl0XG4gICAgICAgIGhhcyBhbHJlYWR5IGJlZW4gdXNlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC91c2VyLWRpc2FibGVkJ1wiPlxuICAgICAgICBUaGUgYWNjb3VudCBhc3NvY2lhdGVkIHdpdGggdGhlIHJlc2V0IHBhc3N3b3JkIGxpbmsgeW91IHVzZWQgaGFzIGJlZW4gZGlzYWJsZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1ub3QtZm91bmQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBoYXMgYmVlbiByZW1vdmVkLlxuICAgICAgPC9wPlxuICAgICAgPGRpdiAqbmdTd2l0Y2hEZWZhdWx0PlxuICAgICAgICA8cD5Db2RlOiB7e3VuaGFuZGxlZEVycm9yLmNvZGV9fTwvcD5cbiAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+XG4gICAgICAgICAgTWVzc2FnZToge3t1bmhhbmRsZWRFcnJvci5tZXNzYWdlfX1cbiAgICAgICAgPC9wPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuPGRpdiAqbmdJZj1cIidmb3JtJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCIgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCI+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiPkVtYWlsIEFkZHJlc3M8L2xhYmVsPlxuXG4gICAgICA8aW5wdXRcbiAgICAgICAgcmVhZG9ubHlcbiAgICAgICAgI2VtYWlsSW5wdXRcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICAgIGF1dG9jb21wbGV0ZT1cImVtYWlsXCJcbiAgICAgICAgcGxhY2Vob2xkZXI9XCJFbWFpbCBBZGRyZXNzXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiPlxuICAgICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBmb3JtLXRleHRcIiBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCIgPlxuICAgICAgICBZb3UgYXJlIHJlc2V0dGluZyB0aGUgcGFzc3dvcmQgZm9yIHt7ZW1haWxGYy52YWx1ZX19LlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cblxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWVuZFwiPlxuICAgICAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICdwYXNzd29yZCdcIj5QYXNzd29yZDwvbGFiZWw+XG4gICAgICAgIDxzbWFsbD5cbiAgICAgICAgICA8YSAoY2xpY2spPVwiJGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IHBhc3N3b3JkSW5wdXQudHlwZSA9ICdwYXNzd29yZCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZSAgPyAndGV4dCcgOiAncGFzc3dvcmQnXCJcbiAgICAgICAgICAgIGhyZWY9XCIjXCIgdGFiaW5kZXg9XCItMVwiIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2tcIj5cbiAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+U2hvdzwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3RleHQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5IaWRlPC9zcGFuPlxuICAgICAgICAgIDwvYT5cbiAgICAgICAgPC9zbWFsbD5cbiAgICAgIDwvZGl2PlxuICAgICAgPGlucHV0XG4gICAgICAgICNwYXNzd29yZElucHV0XG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdwYXNzd29yZCdcIlxuICAgICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiXG4gICAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInBhc3N3b3JkXCJcbiAgICAgICAgcGxhY2Vob2xkZXI9XCJQYXNzd29yZFwiXG4gICAgICAgIGF1dG9jb21wbGV0ZT1cInBhc3N3b3JkXCJcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5pbnZhbGlkXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiICpuZ0lmPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgICAgUmVxdWlyZWQuXG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcignYXV0aC93ZWFrLXBhc3N3b3JkJylcIj5cbiAgICAgICAgVGhhdCBwYXNzd29yZCBpcyB0b28gd2Vhay5cbiAgICAgIDwvZGl2PlxuICAgICAgPHNtYWxsIFthdHRyLmlkXT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiIGNsYXNzPVwiZm9ybS10ZXh0IHRleHQtbXV0ZWRcIj5cbiAgICAgICAgUGxlYXNlIGNob29zZSBhIHN0cm9uZyBwYXNzd29yZC5cbiAgICAgIDwvc21hbGw+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiXG4gICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICBbdmFsdWVdPVwidHJ1ZVwiXG4gICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVtZW1iZXJcIlxuICAgICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgICAgUmVtZW1iZXIgbWUgb24gdGhpcyBkZXZpY2UuXG4gICAgICAgIDwvbGFiZWw+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXN1Y2Nlc3MgYnRuLWJsb2NrXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1zYXZlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICBTYXZlIFBhc3N3b3JkIGFuZCBTaWduIEluXG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9mb3JtPlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIE9vYlJlc2V0UGFzc3dvcmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIEBJbnB1dCgpIG9vYkNvZGU6IHN0cmluZztcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxJTmd4RmlyZWJhc2VBdXRoT29iU3VjY2Vzcz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgc2NyZWVuOiAnd2FpdCcgfCAnZm9ybScgfCAnZXJyb3InIHwgJ3N1Y2Nlc3MnID0gJ3dhaXQnO1xuICBpbmZvOiBhdXRoLkFjdGlvbkNvZGVJbmZvO1xuICBzdWJtaXR0aW5nID0gZmFsc2U7XG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1vb2ItcmVzZXQtcGFzc3dvcmQtJztcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHBhc3N3b3JkRmM6IEZvcm1Db250cm9sO1xuICByZW1lbWJlckZjOiBGb3JtQ29udHJvbDtcbiAgdW5oYW5kbGVkRXJyb3I6IGF1dGguRXJyb3IgPSBudWxsO1xuICBjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsID0gbnVsbDtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSxcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuICBnZXQgYXV0aFNlcnZpY2UoKTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSB7XG4gICAgcmV0dXJuIHRoaXMuX2F1dGhTZXJ2aWNlO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgY29uc3QgcmVtZW1iZXJlZCA9IHRoaXMuYXV0aFNlcnZpY2UuZ2V0UmVtZW1iZXJlZCgpO1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbCgnJyk7XG4gICAgdGhpcy5wYXNzd29yZEZjID0gbmV3IEZvcm1Db250cm9sKCcnLCB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWRdfSk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHJlbWVtYmVyZWQucmVtZW1iZXIpO1xuICAgIHRoaXMuZmcgPSBuZXcgRm9ybUdyb3VwKHtlbWFpbDogdGhpcy5lbWFpbEZjLCBwYXNzd29yZDogdGhpcy5wYXNzd29yZEZjLCByZW1lbWJlcjogdGhpcy5yZW1lbWJlckZjfSk7XG4gICAgdGhpcy5hdXRoLmNoZWNrQWN0aW9uQ29kZSh0aGlzLm9vYkNvZGUpXG4gICAgICAudGhlbigocmVzdWx0OiBhdXRoLkFjdGlvbkNvZGVJbmZvKSA9PiB7XG4gICAgICAgIHRoaXMuaW5mbyA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5lbWFpbEZjLnNldFZhbHVlKHJlc3VsdC5kYXRhLmVtYWlsKTtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZm9ybSc7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnVuaGFuZGxlZEVycm9yID0gZXJyb3I7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgIH0pO1xuICB9XG5cbiAgc3VibWl0KCkge1xuICAgIHRoaXMuc3VibWl0dGluZyA9IHRydWU7XG4gICAgdGhpcy5hdXRoLmNvbmZpcm1QYXNzd29yZFJlc2V0KHRoaXMub29iQ29kZSwgdGhpcy5wYXNzd29yZEZjLnZhbHVlKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLnNpZ25JbldpdGhFbWFpbEFuZFBhc3N3b3JkKHRoaXMuaW5mby5kYXRhLmVtYWlsLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKChjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsKSA9PiB7XG4gICAgICAgIHRoaXMuY3JlZCA9IGNyZWQ7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCB0aGlzLmluZm8uZGF0YS5lbWFpbCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdzdWNjZXNzJztcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoe1xuICAgICAgICAgIG1vZGU6ICdyZXNldFBhc3N3b3JkJyxcbiAgICAgICAgICBpbmZvOiB0aGlzLmluZm8sXG4gICAgICAgICAgY3JlZDogdGhpcy5jcmVkLFxuICAgICAgICAgIHVzZXI6IHRoaXMuY3JlZC51c2VyXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy5zdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLnBhc3N3b3JkRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlICdhdXRoL3dlYWstcGFzc3dvcmQnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLnBhc3N3b3JkRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRoaXMudW5oYW5kbGVkRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1Db250cm9sLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVBdXRoIH0gZnJvbSAnYW5ndWxhcmZpcmUyL2F1dGgnO1xuaW1wb3J0IHsgYXV0aCwgVXNlciB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBJTmd4RmlyZWJhc2VBdXRoT29iU3VjY2VzcyB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1vb2ItcmVjb3Zlci1lbWFpbCcsXG4gIHRlbXBsYXRlOiBgXG5cbjxkaXYgKm5nSWY9XCInd2FpdCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXNlY29uZGFyeVwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNwaW4gZmEtc3Bpbm5lciBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBQbGVhc2Ugd2FpdC4uLlxuICA8L2Rpdj5cbjwvZGl2PlxuXG5cbjxkaXYgKm5nSWY9XCInc3VjY2VzcycgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBZb3VyIGVtYWlsIGhhcyBiZWVuIGNoYW5nZWQgYmFjayB0byB7e2luZm8uZGF0YS5lbWFpbH19O1xuICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwic2NyZWVuID09PSAnZm9ybSdcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPHA+XG4gICAgICBBcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gY2hhbmdlIHlvdXIgZW1haWwgYmFjayB0b1xuICAgICAge3tpbmZvLmRhdGEuZW1haWx9fSBmcm9tIHt7aW5mby5kYXRhLmZyb21FbWFpbH19P1xuICAgIDwvcD5cbiAgICA8YnV0dG9uXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIFtkaXNhYmxlZF09XCJzdWJtaXR0aW5nXCJcbiAgICAgIChjbGljayk9XCJzdWJtaXQoKVwiXG4gICAgICBjbGFzcz1cImJ0biBidG4tYmxvY2sgYnRuLXN1Y2Nlc3NcIj5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNhdmUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBZZXMsIENvbnRpbnVlXG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuXG48ZGl2ICpuZ0lmPVwic2NyZWVuID09PSAnZXJyb3InXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCI+XG4gICAgPHA+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1leGNsYW1hdGlvbi10cmlhbmdsZSBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIFdvb3BzISBBbiBlcnJvciBvY2N1cnJlZC5cbiAgICA8L3A+XG4gICAgPGRpdiBbbmdTd2l0Y2hdPVwidW5oYW5kbGVkRXJyb3IuY29kZVwiPlxuICAgICAgPHAgY2xhc3M9XCJtYi0wXCIgKm5nU3dpdGNoQ2FzZT1cIidhdXRoL2V4cGlyZWQtYWN0aW9uLWNvZGUnXCI+XG4gICAgICAgIFRoZSByZWNvdmVyIGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGV4cGlyZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvaW52YWxpZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHJlY292ZXIgZW1haWwgbGluayB5b3UgdXNlZCBpcyBub3QgdmFsaWQuIFRoaXMgbWF5IGJlIGJlY2F1c2UgaXRcbiAgICAgICAgaGFzIGFscmVhZHkgYmVlbiB1c2VkLlxuICAgICAgPC9wPlxuICAgICAgPHAgY2xhc3M9XCJtYi0wXCIgKm5nU3dpdGNoQ2FzZT1cIidhdXRoL3VzZXItZGlzYWJsZWQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVjb3ZlciBlbWFpbCBsaW5rIHlvdSB1c2VkIGhhcyBiZWVuIGRpc2FibGVkLlxuICAgICAgPC9wPlxuICAgICAgPHAgY2xhc3M9XCJtYi0wXCIgKm5nU3dpdGNoQ2FzZT1cIidhdXRoL3VzZXItbm90LWZvdW5kJ1wiPlxuICAgICAgICBUaGUgYWNjb3VudCBhc3NvY2lhdGVkIHdpdGggdGhlIHJlY292ZXIgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgYmVlbiByZW1vdmVkLlxuICAgICAgPC9wPlxuICAgICAgPGRpdiAqbmdTd2l0Y2hEZWZhdWx0PlxuICAgICAgICA8cD5Db2RlOiB7e3VuaGFuZGxlZEVycm9yLmNvZGV9fTwvcD5cbiAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+XG4gICAgICAgICAgTWVzc2FnZToge3t1bmhhbmRsZWRFcnJvci5tZXNzYWdlfX1cbiAgICAgICAgPC9wPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIE9vYlJlY292ZXJFbWFpbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgb29iQ29kZTogc3RyaW5nO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBzY3JlZW46ICd3YWl0JyB8ICdmb3JtJyB8ICdlcnJvcicgfCAnc3VjY2VzcycgPSAnd2FpdCc7XG4gIGluZm86IGF1dGguQWN0aW9uQ29kZUluZm87XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgdW5oYW5kbGVkRXJyb3I6IGF1dGguRXJyb3I7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICkgeyB9XG5cbiAgZ2V0IGF1dGgoKTogYXV0aC5BdXRoIHtcbiAgICByZXR1cm4gdGhpcy5fYWZBdXRoLmF1dGg7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcblxuICAgIHRoaXMuYXV0aC5jaGVja0FjdGlvbkNvZGUodGhpcy5vb2JDb2RlKVxuICAgICAgLnRoZW4oKHJlc3VsdDogYXV0aC5BY3Rpb25Db2RlSW5mbykgPT4ge1xuICAgICAgICB0aGlzLmluZm8gPSByZXN1bHQ7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Zvcm0nO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdlcnJvcic7XG4gICAgICB9KTtcbiAgfVxuXG4gIHN1Ym1pdCgpIHtcbiAgICB0aGlzLmF1dGguYXBwbHlBY3Rpb25Db2RlKHRoaXMub29iQ29kZSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnc3VjY2Vzcyc7XG4gICAgICAgIHRoaXMuc3VjY2Vzcy5lbWl0KHtcbiAgICAgICAgICBtb2RlOiAncmVjb3ZlckVtYWlsJyxcbiAgICAgICAgICBpbmZvOiB0aGlzLmluZm8sXG4gICAgICAgICAgdXNlcjogdGhpcy5hdXRoLmN1cnJlbnRVc2VyXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdlcnJvcic7XG4gICAgICB9KTtcbiAgfVxuXG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYi12ZXJpZnktZW1haWwnLFxuICB0ZW1wbGF0ZTogYDxkaXYgKm5nSWY9XCInd2FpdCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXNlY29uZGFyeVwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNwaW4gZmEtc3Bpbm5lciBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBQbGVhc2Ugd2FpdC4uLlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3N1Y2Nlc3MnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1zdWNjZXNzXCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgVGhlIGVtYWlsIHt7aW5mby5kYXRhLmVtYWlsfX0gaGFzIGJlZW4gdmVyaWZpZWQuXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdlcnJvcidcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8cD5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgV29vcHMhIEFuIGVycm9yIG9jY3VycmVkLlxuICAgIDwvcD5cbiAgICA8ZGl2IFtuZ1N3aXRjaF09XCJ1bmhhbmRsZWRFcnJvci5jb2RlXCI+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvZXhwaXJlZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHZlcmlmeSBlbWFpbCBsaW5rIHlvdSB1c2VkIGhhcyBleHBpcmVkLlxuICAgICAgPC9wPlxuICAgICAgPHAgY2xhc3M9XCJtYi0wXCIgKm5nU3dpdGNoQ2FzZT1cIidhdXRoL2ludmFsaWQtYWN0aW9uLWNvZGUnXCI+XG4gICAgICAgIFRoZSB2ZXJpZnkgZW1haWwgbGluayB5b3UgdXNlZCBpcyBub3QgdmFsaWQuIFRoaXMgbWF5IGJlIGJlY2F1c2UgaXRcbiAgICAgICAgaGFzIGFscmVhZHkgYmVlbiB1c2VkLlxuICAgICAgPC9wPlxuICAgICAgPHAgY2xhc3M9XCJtYi0wXCIgKm5nU3dpdGNoQ2FzZT1cIidhdXRoL3VzZXItZGlzYWJsZWQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgdmVyaWZ5IGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGJlZW4gZGlzYWJsZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1ub3QtZm91bmQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgdmVyaWZ5IGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGJlZW4gcmVtb3ZlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxkaXYgKm5nU3dpdGNoRGVmYXVsdD5cbiAgICAgICAgPHA+Q29kZToge3t1bmhhbmRsZWRFcnJvci5jb2RlfX08L3A+XG4gICAgICAgIDxwIGNsYXNzPVwibWItMFwiPlxuICAgICAgICAgIE1lc3NhZ2U6IHt7dW5oYW5kbGVkRXJyb3IubWVzc2FnZX19XG4gICAgICAgIDwvcD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbc2NyZWVuQW5pbWF0aW9uXVxufSlcbmV4cG9ydCBjbGFzcyBPb2JWZXJpZnlFbWFpbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgb29iQ29kZTogc3RyaW5nO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBzY3JlZW46ICd3YWl0JyB8ICdlcnJvcicgfCAnc3VjY2VzcycgPSAnd2FpdCc7XG4gIGluZm86IGF1dGguQWN0aW9uQ29kZUluZm87XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgdW5oYW5kbGVkRXJyb3I6IGF1dGguRXJyb3I7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICkgeyB9XG5cbiAgZ2V0IGF1dGgoKTogYXV0aC5BdXRoIHtcbiAgICByZXR1cm4gdGhpcy5fYWZBdXRoLmF1dGg7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcblxuICAgIHRoaXMuYXV0aC5jaGVja0FjdGlvbkNvZGUodGhpcy5vb2JDb2RlKVxuICAgICAgLnRoZW4oKHJlc3VsdDogYXV0aC5BY3Rpb25Db2RlSW5mbykgPT4ge1xuICAgICAgICB0aGlzLmluZm8gPSByZXN1bHQ7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGguYXBwbHlBY3Rpb25Db2RlKHRoaXMub29iQ29kZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdzdWNjZXNzJztcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoe1xuICAgICAgICAgIG1vZGU6ICd2ZXJpZnlFbWFpbCcsXG4gICAgICAgICAgaW5mbzogdGhpcy5pbmZvLFxuICAgICAgICAgIHVzZXI6IHRoaXMuYXV0aC5jdXJyZW50VXNlclxuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yOiBhdXRoLkVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMudW5oYW5kbGVkRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZXJyb3InO1xuICAgICAgfSk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBSb3V0ZXJNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgT29iQ29tcG9uZW50IH0gZnJvbSAnLi9vb2IuY29tcG9uZW50JztcbmltcG9ydCB7IE9vYlJlc2V0UGFzc3dvcmRDb21wb25lbnQgfSBmcm9tICcuL29vYi1yZXNldC1wYXNzd29yZC9vb2ItcmVzZXQtcGFzc3dvcmQuY29tcG9uZW50JztcbmltcG9ydCB7IE9vYlJlY292ZXJFbWFpbENvbXBvbmVudCB9IGZyb20gJy4vb29iLXJlY292ZXItZW1haWwvb29iLXJlY292ZXItZW1haWwuY29tcG9uZW50JztcbmltcG9ydCB7IE9vYlZlcmlmeUVtYWlsQ29tcG9uZW50IH0gZnJvbSAnLi9vb2ItdmVyaWZ5LWVtYWlsL29vYi12ZXJpZnktZW1haWwuY29tcG9uZW50JztcblxuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoTW9kdWxlIH0gZnJvbSAnLi4vbmd4LWZpcmViYXNlLWF1dGgubW9kdWxlJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIFJvdXRlck1vZHVsZSxcbiAgICBOZ3hGaXJlYmFzZUF1dGhNb2R1bGVcbiAgXSxcbiAgZGVjbGFyYXRpb25zOiBbXG4gICAgT29iQ29tcG9uZW50LFxuICAgIE9vYlJlY292ZXJFbWFpbENvbXBvbmVudCxcbiAgICBPb2JSZXNldFBhc3N3b3JkQ29tcG9uZW50LFxuICAgIE9vYlZlcmlmeUVtYWlsQ29tcG9uZW50XG4gIF0sXG4gIGV4cG9ydHM6IFtcbiAgICBPb2JDb21wb25lbnQsXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoT29iTW9kdWxlIHsgfVxuIl0sIm5hbWVzIjpbInRyaWdnZXIiLCJzdGF0ZSIsInN0eWxlIiwidHJhbnNpdGlvbiIsImFuaW1hdGUiLCJhdXRoIiwiSW5qZWN0YWJsZSIsIkFuZ3VsYXJGaXJlQXV0aCIsIlN1YmplY3QiLCJFdmVudEVtaXR0ZXIiLCJ0YWtlVW50aWwiLCJDb21wb25lbnQiLCJBY3RpdmF0ZWRSb3V0ZSIsIlJvdXRlciIsIklucHV0IiwiT3V0cHV0IiwidGFrZSIsIkZvcm1Db250cm9sIiwiVmFsaWRhdG9ycyIsIkZvcm1Hcm91cCIsImRlYm91bmNlVGltZSIsIk5nWm9uZSIsIlZpZXdDaGlsZCIsIk5nTW9kdWxlIiwiQ29tbW9uTW9kdWxlIiwiUmVhY3RpdmVGb3Jtc01vZHVsZSIsIlJvdXRlck1vZHVsZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBaUJBLFFBQWEsa0JBQWtCLEdBQTZCQSxrQkFBTyxDQUFDLFdBQVcsRUFBRTtRQUMvRUMsZ0JBQUssQ0FBQyxJQUFJLEVBQUVDLGdCQUFLLENBQUMsRUFBQyxPQUFPLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUMsQ0FBQyxDQUFDO1FBQ2xEQyxxQkFBVSxDQUFDLFdBQVcsRUFBRTtZQUN0QkQsZ0JBQUssQ0FBQyxFQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUMsQ0FBQztZQUNuQkUsa0JBQU8sQ0FBQyxHQUFHLENBQUM7U0FDYixDQUFDO1FBQ0ZELHFCQUFVLENBQUMsV0FBVyxFQUFFO1lBQ3RCQyxrQkFBTyxDQUFDLEdBQUcsRUFBRUYsZ0JBQUssQ0FBQyxFQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUMsQ0FBQyxDQUFDO1NBQ2xDLENBQUM7S0FDSCxDQUFDLENBQUM7O0FBRUgsUUFBYSxlQUFlLEdBQTZCRixrQkFBTyxDQUFDLFFBQVEsRUFBRTtRQUN6RUMsZ0JBQUssQ0FBQyxJQUFJLEVBQUVDLGdCQUFLLENBQUMsRUFBQyxPQUFPLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQztRQUNoQ0MscUJBQVUsQ0FBQyxXQUFXLEVBQUU7WUFDdEJELGdCQUFLLENBQUMsRUFBQyxPQUFPLEVBQUUsQ0FBQyxFQUFDLENBQUM7WUFDbkJFLGtCQUFPLENBQUMsR0FBRyxDQUFDO1NBQ2IsQ0FBQztRQUNGRCxxQkFBVSxDQUFDLFdBQVcsRUFBRTtZQUN0QkMsa0JBQU8sQ0FBQyxDQUFDLEVBQUVGLGdCQUFLLENBQUMsRUFBQyxPQUFPLEVBQUUsQ0FBQyxFQUFDLENBQUMsQ0FBQztTQUNoQyxDQUFDO0tB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