UNPKG

@nowzoo/ngx-firebase-auth

Version:

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

1,780 lines 220 kB
import { trigger, state, style, animate, transition } from '@angular/animations';
import { Injectable, Component, Input, Output, EventEmitter, ViewChild, NgZone, NgModule, defineInjectable, inject } from '@angular/core';
import { AngularFireAuth } from 'angularfire2/auth';
import { auth } from 'firebase/app';
import { Router, ActivatedRoute, RouterModule } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil, take, debounceTime } from 'rxjs/operators';
import { FormControl, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
/** @type {?} */
var fadeInOutAnimation = trigger('fadeInOut', [
    state('in', style({ opacity: 1, display: 'block' })),
    transition('void => *', [
        style({ opacity: 0 }),
        animate(300)
    ]),
    transition('* => void', [
        animate(300, style({ opacity: 0 }))
    ])
]);
/** @type {?} */
var screenAnimation = trigger('screen', [
    state('in', style({ opacity: 1 })),
    transition('void => *', [
        style({ opacity: 0 }),
        animate(300)
    ]),
    transition('* => void', [
        animate(0, 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 = /** @class */ (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 ?
            auth.Auth.Persistence.LOCAL : 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: Injectable, args: [{
                    providedIn: 'root'
                },] },
    ];
    /** @nocollapse */
    NgxFirebaseAuthService.ctorParameters = function () { return [
        { type: AngularFireAuth }
    ]; };
    /** @nocollapse */ NgxFirebaseAuthService.ngInjectableDef = defineInjectable({ factory: function NgxFirebaseAuthService_Factory() { return new NgxFirebaseAuthService(inject(AngularFireAuth)); }, token: NgxFirebaseAuthService, providedIn: "root" });
    return NgxFirebaseAuthService;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var SignInComponent = /** @class */ (function () {
    function SignInComponent(_afAuth, _svc, _route, _router) {
        this._afAuth = _afAuth;
        this._svc = _svc;
        this._route = _route;
        this._router = _router;
        this.ngUnsubscribe = new Subject();
        this.tosTemplate = null;
        this.success = new EventEmitter();
        this.mode = new 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(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: 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: AngularFireAuth },
        { type: NgxFirebaseAuthService },
        { type: ActivatedRoute },
        { type: Router }
    ]; };
    SignInComponent.propDecorators = {
        oAuthProviderIds: [{ type: Input }],
        useOAuthPopup: [{ type: Input }],
        oAuthProviderFactory: [{ type: Input }],
        tosTemplate: [{ type: Input }],
        success: [{ type: Output }],
        mode: [{ type: Output }]
    };
    return SignInComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var OobComponent = /** @class */ (function () {
    function OobComponent(_route) {
        this._route = _route;
        this.screen = null;
        this.mode = new EventEmitter();
        this.navigationError = new EventEmitter();
        this.success = new 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: 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: ActivatedRoute }
    ]; };
    OobComponent.propDecorators = {
        mode: [{ type: Output }],
        navigationError: [{ type: Output }],
        success: [{ type: Output }]
    };
    return OobComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var NgxFirebaseAuthFormHelper = /** @class */ (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(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 = /** @class */ (function () {
    function SignInMethodsFormComponent(_afAuth, _authService, _ngZone) {
        this._afAuth = _afAuth;
        this._authService = _authService;
        this._ngZone = _ngZone;
        this.oAuthProviderIds = [];
        this.emailChange = new EventEmitter();
        this.rememberChange = new EventEmitter();
        this.success = new EventEmitter();
        this.error = new EventEmitter();
        this.formId = 'ngx-firebase-auth-sign-in-methods-form-';
        this.submitting = false;
        this.getOAuthProviderIcon = getOAuthProviderIcon;
        this.getOAuthProviderName = getOAuthProviderName;
        this.methodsForEmail = { status: 'unfetched', methods: [], email: null };
    }
    Object.defineProperty(SignInMethodsFormComponent.prototype, "auth", {
        get: /**
         * @return {?}
         */
        function () {
            return this._afAuth.auth;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SignInMethodsFormComponent.prototype, "authService", {
        get: /**
         * @return {?}
         */
        function () {
            return this._authService;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SignInMethodsFormComponent.prototype, "methods", {
        get: /**
         * @return {?}
         */
        function () {
            return this.methodsForEmail.methods;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SignInMethodsFormComponent.prototype, "fetchStatus", {
        get: /**
         * @return {?}
         */
        function () {
            return this.methodsForEmail.status;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SignInMethodsFormComponent.prototype, "methodsFetched", {
        get: /**
         * @return {?}
         */
        function () {
            return this.methodsForEmail.status === 'fetched';
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SignInMethodsFormComponent.prototype, "accountIsNew", {
        get: /**
         * @return {?}
         */
        function () {
            return this.methodsFetched && this.methods.length === 0;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SignInMethodsFormComponent.prototype, "accountExists", {
        get: /**
         * @return {?}
         */
        function () {
            return this.methodsFetched && this.methods.length > 0;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SignInMethodsFormComponent.prototype, "accountHasPassword", {
        get: /**
         * @return {?}
         */
        function () {
            return this.accountExists && this.methods.indexOf('password') !== -1;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(SignInMethodsFormComponent.prototype, "accountOAuthMethods", {
        get: /**
         * @return {?}
         */
        function () {
            if (!this.accountExists) {
                return [];
            }
            return this.methods.filter(function (id) { return id !== 'password'; });
        },
        enumerable: true,
        configurable: true
    });
    /**
     * @return {?}
     */
    SignInMethodsFormComponent.prototype.ngOnInit = /**
     * @return {?}
     */
    function () {
        var _this = this;
        this.emailFc = new FormControl(this.email, { validators: [Validators.required, Validators.email] });
        this.rememberFc = new FormControl(this.remember);
        this.rememberFc.valueChanges.subscribe(function () { return _this.rememberChange.emit(_this.rememberFc.value); });
        this.fg = new FormGroup({ email: this.emailFc, remember: this.rememberFc });
        this.emailFc.valueChanges.subscribe(function () { return _this.emailChange.emit(_this.emailFc.value.trim()); });
        this.emailFc.valueChanges.pipe(debounceTime(500)).subscribe(function () { return _this.fetch(); });
        this.fetch();
    };
    /**
     * @return {?}
     */
    SignInMethodsFormComponent.prototype.ngAfterViewInit = /**
     * @return {?}
     */
    function () {
        this.emailInput.nativeElement.focus();
    };
    /**
     * @return {?}
     */
    SignInMethodsFormComponent.prototype.fetch = /**
     * @return {?}
     */
    function () {
        var _this = this;
        /** @type {?} */
        var email = this.emailFc.value.trim();
        if (email === this.methodsForEmail.email) {
            return;
        }
        if ('fetching' === this.methodsForEmail.status) {
            return;
        }
        this.methodsForEmail = { status: 'fetching', methods: [], email: email };
        if (this.emailFc.invalid) {
            this.methodsForEmail = { status: 'unfetched', methods: [], email: email };
            return;
        }
        this.auth.fetchSignInMethodsForEmail(email)
            .then(function (results) {
            _this.methodsForEmail = { status: 'fetched', methods: results, email: email };
        })
            .catch(function (error) {
            _this.emailFc.markAsDirty();
            _this.emailFc.markAsTouched();
            switch (error.code) {
                case 'auth/invalid-email':
                    NgxFirebaseAuthFormHelper.setErrorUntilChanged(_this.emailFc, error.code);
                    break;
            }
            _this.methodsForEmail = { email: _this.email, status: 'unfetched', methods: [] };
        });
    };
    SignInMethodsFormComponent.decorators = [
        { type: Component, args: [{
                    selector: 'ngx-firebase-auth-sign-in-methods-form',
                    template: "<form [formGroup]=\"fg\">\n  <div class=\"form-group\">\n    <label [attr.for]=\"formId + 'email'\">Email Address</label>\n    <input\n      #emailInput\n      [attr.id]=\"formId + 'email'\"\n      [attr.aria-describedby]=\"formId + 'email'\"\n      type=\"email\"\n      autocomplete=\"email\"\n      placeholder=\"Email Address\"\n      formControlName=\"email\"\n      (blur)=\"fetch()\"\n      (keyup.enter)=\"emailInput.blur()\"\n      class=\"form-control\"\n      [class.is-invalid]=\"emailFc.touched && emailFc.invalid\">\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.touched && emailFc.hasError('required')\">\n      Required.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.touched && emailFc.hasError('email')\">\n      Invalid email.\n    </div>\n    <div class=\"invalid-feedback\" [@fadeInOut]=\"'in'\"\n      *ngIf=\"emailFc.touched && emailFc.hasError('auth/invalid-email')\">\n      Invalid email.\n    </div>\n    <small class=\"text-muted form-text\" [attr.id]=\"formId + 'email'\" [ngSwitch]=\"fetchStatus\">\n      <span *ngSwitchCase=\"'unfetched'\" [@fadeInOut]=\"'in'\">\n        To get started, enter your email address.\n        If you don\u2019t yet have an account we\u2019ll create one for you.\n      </span>\n      <span *ngSwitchCase=\"'fetching'\" [@fadeInOut]=\"'in'\">\n        <i class=\"fas fa-spin fa-spinner fa-fw\" aria-hidden=\"true\"></i>\n        Looking up account...\n      </span>\n      <span *ngSwitchCase=\"'fetched'\" [@fadeInOut]=\"'in'\">\n        <i class=\"fas fa-check fa-fw text-success\" aria-hidden=\"true\"></i>\n        <span *ngIf=\"accountExists\">Account found.</span>\n        <span *ngIf=\"accountIsNew\">We'll create an account.</span>\n      </span>\n    </small>\n  </div>\n  <div class=\"form-group\">\n    <div class=\"form-check\">\n      <input\n        class=\"form-check-input\"\n        type=\"checkbox\"\n        [value]=\"true\"\n        formControlName=\"remember\"\n        [attr.id]=\"formId + 'remember'\">\n      <label class=\"form-check-label\" [attr.for]=\"formId + 'remember'\">\n        Remember me on this device.\n      </label>\n    </div>\n  </div>\n</form>\n<div *ngIf=\"methodsFetched && accountExists\" [@screen]=\"'in'\">\n  <small class=\"text-muted mb-1 form-text\">\n    <span *ngIf=\"accountHasPassword\">\n      <span *ngIf=\"accountOAuthMethods.length === 0\">\n        Please sign in with your password...\n      </span>\n      <span *ngIf=\"accountOAuthMethods.length === 1\">\n        Please sign in with your password or your\n        linked {{getOAuthProviderName(accountOAuthMethods[0])}} account...\n      </span>\n      <span *ngIf=\"accountOAuthMethods.length > 1\">\n        Please sign in with your password or one of your linked accounts...\n      </span>\n    </span>\n    <span *ngIf=\"!accountHasPassword\">\n      <span *ngIf=\"accountOAuthMethods.length === 1\">\n        Please sign in with your\n        linked {{getOAuthProviderName(accountOAuthMethods[0])}} account...\n      </span>\n      <span *ngIf=\"accountOAuthMethods.length > 1\">\n        Please sign in with one of your linked accounts...\n      </span>\n    </span>\n\n  </small>\n\n  <div class=\"list-group\">\n    <a\n      *ngIf=\"accountHasPassword\"\n      routerLink=\".\"\n      [queryParams]=\"{action: 'signInPassword'}\"\n      class=\"list-group-item list-group-item-action\">\n      <i class=\"fas fa-lock fa-fw\" aria-hidden=\"true\"></i>\n      <span class=\"ml-2\">\n        Sign In with Your Password\n      </span>\n    </a>\n    <a\n      *ngFor=\"let id of accountOAuthMethods\"\n      routerLink=\".\"\n      [queryParams]=\"{action: 'signInOAuth', providerId: id}\"\n      class=\"list-group-item list-group-item-action\">\n      <i [attr.class]=\"getOAuthProviderIcon(id)\" aria-hidden=\"true\"></i>\n      <span class=\"ml-2\">\n        Sign In with {{getOAuthProviderName(id)}}\n      </span>\n    </a>\n  </div>\n</div>\n\n<div *ngIf=\"methodsFetched && accountIsNew\" [@screen]=\"'in'\">\n  <small class=\"text-muted mb-1 form-text\">\n    <span *ngIf=\"oAuthProviderIds.length === 0\">\n      Please create an account...\n    </span>\n    <span *ngIf=\"oAuthProviderIds.length === 1\">\n      Please sign up with your\n      {{getOAuthProviderName(oAuthProviderIds[0])}} account,\n      or create a separate account with a password....\n    </span>\n    <span *ngIf=\"oAuthProviderIds.length >1\">\n      Please sign up with one of the services listed below,\n      or create a separate account with a password....\n    </span>\n  </small>\n  <div class=\"list-group\">\n\n    <a\n      *ngFor=\"let id of oAuthProviderIds\"\n      routerLink=\".\"\n      [queryParams]=\"{action: 'signInOAuth', providerId: id}\"\n      class=\"list-group-item list-group-item-action\">\n      <i [attr.class]=\"getOAuthProviderIcon(id)\" aria-hidden=\"true\"></i>\n      <span class=\"ml-2\">\n        Sign Up with {{getOAuthProviderName(id)}}\n      </span>\n    </a>\n    <a\n      routerLink=\".\"\n      [queryParams]=\"{action: 'signUpPassword'}\"\n      class=\"list-group-item list-group-item-action\">\n      <i class=\"fas fa-lock fa-fw\" aria-hidden=\"true\"></i>\n      <span class=\"ml-2\">\n        Create\n        <span *ngIf=\"oAuthProviderIds.length > 0\">\n          a Separate\n        </span>\n        Account\n      </span>\n    </a>\n  </div>\n</div>\n",
                    styles: [""],
                    animations: [fadeInOutAnimation, screenAnimation]
                },] },
    ];
    /** @nocollapse */
    SignInMethodsFormComponent.ctorParameters = function () { return [
        { type: AngularFireAuth },
        { type: NgxFirebaseAuthService },
        { type: NgZone }
    ]; };
    SignInMethodsFormComponent.propDecorators = {
        emailInput: [{ type: ViewChild, args: ['emailInput',] }],
        email: [{ type: Input }],
        remember: [{ type: Input }],
        oAuthProviderIds: [{ type: Input }],
        emailChange: [{ type: Output }],
        rememberChange: [{ type: Output }],
        success: [{ type: Output }],
        error: [{ type: Output }]
    };
    return SignInMethodsFormComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var SignInFormComponent = /** @class */ (function () {
    function SignInFormComponent(_afAuth, _authService) {
        this._afAuth = _afAuth;
        this._authService = _authService;
        this.rememberChange = new EventEmitter();
        this.success = new EventEmitter();
        this.error = new 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 FormControl(this.email, { validators: [Validators.required, Validators.email] });
        this.passwordFc = new FormControl('', { validators: [Validators.required] });
        this.rememberFc = new FormControl(this.remember);
        this.rememberFc.valueChanges.subscribe(function (val) { return _this.rememberChange.emit(val); });
        this.fg = new 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: 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: AngularFireAuth },
        { type: NgxFirebaseAuthService }
    ]; };
    SignInFormComponent.propDecorators = {
        passwordInput: [{ type: ViewChild, args: ['passwordInput',] }],
        email: [{ type: Input }],
        remember: [{ type: Input }],
        rememberChange: [{ type: Output }],
        success: [{ type: Output }],
        error: [{ type: Output }]
    };
    return SignInFormComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var SignUpFormComponent = /** @class */ (function () {
    function SignUpFormComponent(_afAuth, _authService) {
        this._afAuth = _afAuth;
        this._authService = _authService;
        this.rememberChange = new EventEmitter();
        this.success = new EventEmitter();
        this.error = new 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 FormControl(this.email, { validators: [Validators.required, Validators.email] });
        this.passwordFc = new FormControl('', { validators: [Validators.required] });
        this.nameFc = new FormControl('', { validators: [Validators.required, NgxFirebaseAuthFormHelper.requiredNonEmpty] });
        this.rememberFc = new FormControl(this.remember);
        this.rememberFc.valueChanges.subscribe(function (val) { return _this.rememberChange.emit(val); });
        this.fg = new 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: 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: AngularFireAuth },
        { type: NgxFirebaseAuthService }
    ]; };
    SignUpFormComponent.propDecorators = {
        passwordInput: [{ type: ViewChild, args: ['passwordInput',] }],
        email: [{ type: Input }],
        remember: [{ type: Input }],
        rememberChange: [{ type: Output }],
        success: [{ type: Output }],
        error: [{ type: Output }]
    };
    return SignUpFormComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var ResetPasswordSendFormComponent = /** @class */ (function () {
    function ResetPasswordSendFormComponent(_afAuth) {
        this._afAuth = _afAuth;
        this.emailChange = new EventEmitter();
        this.error = new 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 FormControl(this.email, { validators: [Validators.required, Validators.email] });
        this.emailFc.valueChanges.subscribe(function () { return _this.emailChange.emit(_this.emailFc.value.trim()); });
        this.fg = new 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: 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: AngularFireAuth }
    ]; };
    ResetPasswordSendFormComponent.propDecorators = {
        emailInput: [{ type: ViewChild, args: ['emailInput',] }],
        email: [{ type: Input }],
        emailChange: [{ type: Output }],
        error: [{ type: Output }]
    };
    return ResetPasswordSendFormComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var SignInOauthComponent = /** @class */ (function () {
    function SignInOauthComponent(_afAuth, _svc, _route, _router) {
        this._afAuth = _afAuth;
        this._svc = _svc;
        this._route = _route;
        this._router = _router;
        this.success = new EventEmitter();
        this.emailChange = new EventEmitter();
        this.rememberChange = new EventEmitter();
        this.error = new 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 FormControl(this.remember);
        this.rememberFc.valueChanges.subscribe(function (val) { return _this.rememberChange.emit(val); });
        this.fg = new 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 auth.TwitterAuthProvider();
                    break;
                case 'facebook.com':
                    provider = new auth.FacebookAuthProvider();
                    break;
                case 'google.com':
                    provider = new auth.GoogleAuthProvider();
                    break;
                case 'github.com':
                    provider = new 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: 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: AngularFireAuth },
        { type: NgxFirebaseAuthService },
        { type: ActivatedRoute },
        { type: Router }
    ]; };
    SignInOauthComponent.propDecorators = {
        providerId: [{ type: Input }],
        initialError: [{ type: Input }],
        useOAuthPopup: [{ type: Input }],
        oAuthProviderFactory: [{ type: Input }],
        email: [{ type: Input }],
        remember: [{ type: Input }],
        success: [{ type: Output }],
        emailChange: [{ type: Output }],
        rememberChange: [{ type: Output }],
        error: [{ type: Output }]
    };
    return SignInOauthComponent;
}());

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

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var NgxFirebaseAuthSignInModule = /** @class */ (function () {
    function NgxFirebaseAuthSignInModule() {
    }
    NgxFirebaseAuthSignInModule.decorators = [
        { type: NgModule, args: [{
                    imports: [
                        CommonModule,
                        ReactiveFormsModule,
                        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 = /** @class */ (function () {
    function OobResetPasswordComponent(_afAuth, _authService) {
        this._afAuth = _afAuth;
        this._authService = _authService;
        this.success = new 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 FormControl('');
        this.passwordFc = new FormControl('', { validators: [Validators.required] });
        this.rememberFc = new FormControl(remembered.remember);
        this.fg = new 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: 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: AngularFireAuth },
        { type: NgxFirebaseAuthService }
    ]; };
    OobResetPasswordComponent.propDecorators = {
        oobCode: [{ type: Input }],
        success: [{ type: Output }]
    };
    return OobResetPasswordComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var OobRecoverEmailComponent = /** @class */ (function () {
    function OobRecoverEmailComponent(_afAuth) {
        this._afAuth = _afAuth;
        this.success = new 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: 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: AngularFireAuth }
    ]; };
    OobRecoverEmailComponent.propDecorators = {
        oobCode: [{ type: Input }],
        success: [{ type: Output }]
    };
    return OobRecoverEmailComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var OobVerifyEmailComponent = /** @class */ (function () {
    function OobVerifyEmailComponent(_afAuth) {
        this._afAuth = _afAuth;
        this.success = new 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: 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: AngularFireAuth }
    ]; };
    OobVerifyEmailComponent.propDecorators = {
        oobCode: [{ type: Input }],
        success: [{ type: Output }]
    };
    return OobVerifyEmailComponent;
}());

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
 */
var NgxFirebaseAuthOobModule = /** @class */ (function () {
    function NgxFirebaseAuthOobModule() {
    }
    NgxFirebaseAuthOobModule.decorators = [
        { type: NgModule, args: [{
                    imports: [
                        CommonModule,
                        ReactiveFormsModule,
                        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
 */

export { fadeInOutAnimation, screenAnimation, getOAuthProviderName, getOAuthProviderIcon, NgxFirebaseAuthService, SignInComponent, OobComponent, NgxFirebaseAuthSignInModule, NgxFirebaseAuthOobModule, NgxFirebaseAuthModule, OobRecoverEmailComponent as ɵf, OobResetPasswordComponent as ɵg, OobVerifyEmailComponent as ɵh, ResetPasswordSendFormComponent as ɵd, SignInFormComponent as ɵb, SignInMethodsFormComponent as ɵa, SignInOauthComponent as ɵe, SignUpFormComponent as ɵc };

//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm93em9vLW5neC1maXJlYmFzZS1hdXRoLmpzLm1hcCIsInNvdXJjZXMiOlsibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaGFyZWQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2IuY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9mb3JtLWhlbHBlci50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvc2lnbi1pbi9zaWduLWluLW1ldGhvZHMtZm9ybS9zaWduLWluLW1ldGhvZHMtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi1mb3JtL3NpZ24taW4tZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi11cC1mb3JtL3NpZ24tdXAtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vcmVzZXQtcGFzc3dvcmQtc2VuZC1mb3JtL3Jlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybS5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL3NpZ24taW4vc2lnbi1pbi1vYXV0aC9zaWduLWluLW9hdXRoLmNvbXBvbmVudC50cyIsIm5nOi8vQG5vd3pvby9uZ3gtZmlyZWJhc2UtYXV0aC9saWIvbmd4LWZpcmViYXNlLWF1dGgubW9kdWxlLnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9zaWduLWluL25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4ubW9kdWxlLnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivb29iLXJlc2V0LXBhc3N3b3JkL29vYi1yZXNldC1wYXNzd29yZC5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2ItcmVjb3Zlci1lbWFpbC9vb2ItcmVjb3Zlci1lbWFpbC5jb21wb25lbnQudHMiLCJuZzovL0Bub3d6b28vbmd4LWZpcmViYXNlLWF1dGgvbGliL29vYi9vb2ItdmVyaWZ5LWVtYWlsL29vYi12ZXJpZnktZW1haWwuY29tcG9uZW50LnRzIiwibmc6Ly9Abm93em9vL25neC1maXJlYmFzZS1hdXRoL2xpYi9vb2Ivbmd4LWZpcmViYXNlLWF1dGgtb29iLm1vZHVsZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBbmltYXRpb25UcmlnZ2VyTWV0YWRhdGEsIHRyaWdnZXIsIHN0YXRlLCBzdHlsZSwgYW5pbWF0ZSwgdHJhbnNpdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuaW1wb3J0IHsgYXV0aCwgVXNlciB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5cblxuZXhwb3J0IGludGVyZmFjZSBJU2lnbkluTWV0aG9kc0ZvckVtYWlsUmVzdWx0IHtcbiAgZW1haWw6IHN0cmluZztcbiAgbWV0aG9kczogc3RyaW5nW107XG4gIHN0YXR1czogJ3VuZmV0Y2hlZCcgfCAnZmV0Y2hpbmcnIHwgJ2ZldGNoZWQnO1xufVxuXG5cbmV4cG9ydCBpbnRlcmZhY2UgSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkIHtcbiAgcmVtZW1iZXI6IGJvb2xlYW47XG4gIGVtYWlsOiBzdHJpbmc7XG59XG5cblxuZXhwb3J0IGNvbnN0IGZhZGVJbk91dEFuaW1hdGlvbjogQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhID0gdHJpZ2dlcignZmFkZUluT3V0JywgW1xuICBzdGF0ZSgnaW4nLCBzdHlsZSh7b3BhY2l0eTogMSwgZGlzcGxheTogJ2Jsb2NrJ30pKSxcbiAgdHJhbnNpdGlvbigndm9pZCA9PiAqJywgW1xuICAgIHN0eWxlKHtvcGFjaXR5OiAwfSksXG4gICAgYW5pbWF0ZSgzMDApXG4gIF0pLFxuICB0cmFuc2l0aW9uKCcqID0+IHZvaWQnLCBbXG4gICAgYW5pbWF0ZSgzMDAsIHN0eWxlKHtvcGFjaXR5OiAwfSkpXG4gIF0pXG5dKTtcblxuZXhwb3J0IGNvbnN0IHNjcmVlbkFuaW1hdGlvbjogQW5pbWF0aW9uVHJpZ2dlck1ldGFkYXRhID0gdHJpZ2dlcignc2NyZWVuJywgW1xuICBzdGF0ZSgnaW4nLCBzdHlsZSh7b3BhY2l0eTogMX0pKSxcbiAgdHJhbnNpdGlvbigndm9pZCA9PiAqJywgW1xuICAgIHN0eWxlKHtvcGFjaXR5OiAwfSksXG4gICAgYW5pbWF0ZSgzMDApXG4gIF0pLFxuICB0cmFuc2l0aW9uKCcqID0+IHZvaWQnLCBbXG4gICAgYW5pbWF0ZSgwLCBzdHlsZSh7b3BhY2l0eTogMH0pKVxuICBdKVxuXSk7XG5cbmV4cG9ydCBjb25zdCBnZXRPQXV0aFByb3ZpZGVyTmFtZSA9IChpZDogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgc3dpdGNoIChpZCkge1xuICAgIGNhc2UgJ3R3aXR0ZXIuY29tJzogcmV0dXJuICdUd2l0dGVyJztcbiAgICBjYXNlICdmYWNlYm9vay5jb20nOiByZXR1cm4gJ0ZhY2Vib29rJztcbiAgICBjYXNlICdnb29nbGUuY29tJzogcmV0dXJuICdHb29nbGUnO1xuICAgIGNhc2UgJ2dpdGh1Yi5jb20nOiByZXR1cm4gJ0dpdEh1Yic7XG4gICAgZGVmYXVsdDogcmV0dXJuIGlkO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZ2V0T0F1dGhQcm92aWRlckljb24gPSAoaWQ6IHN0cmluZyk6IHN0cmluZyAgPT4ge1xuICBzd2l0Y2ggKGlkKSB7XG4gICAgY2FzZSAndHdpdHRlci5jb20nOlxuICAgIGNhc2UgJ2ZhY2Vib29rLmNvbSc6XG4gICAgY2FzZSAnZ29vZ2xlLmNvbSc6XG4gICAgY2FzZSAnZ2l0aHViLmNvbSc6XG4gICAgICByZXR1cm4gJ2ZhYiBmYS1mdyBmYS0nICsgaWQucmVwbGFjZSgnLmNvbScsICcnKTtcbiAgICBkZWZhdWx0OiByZXR1cm4gJ2ZhcyBmYS1mdyBmYS1zaWduLWluLWFsdCc7XG4gIH1cbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3Mge1xuICBtb2RlOiAncmVzZXRQYXNzd29yZCcgfCAndmVyaWZ5RW1haWwnIHwgJ3JlY292ZXJFbWFpbCc7XG4gIGluZm86IGF1dGguQWN0aW9uQ29kZUluZm87XG4gIGNyZWQ/OiBhdXRoLlVzZXJDcmVkZW50aWFsO1xuICB1c2VyPzogVXNlcjtcbn1cbiIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkIH0gZnJvbSAnLi9zaGFyZWQnO1xuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgc3RhdGljIHJlbWVtYmVyS2V5ID0gJ25neC1maXJlYmFzZS1hdXRoLXJlbWVtYmVyJztcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aFxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBzdG9yYWdlKCk6IFN0b3JhZ2Uge1xuICAgIHJldHVybiB3aW5kb3cubG9jYWxTdG9yYWdlO1xuICB9XG5cbiAgZ2V0UmVtZW1iZXJlZCgpOiBJTmd4RmlyZWJhc2VBdXRoUmVtZW1iZXJSZWNvcmQge1xuICAgIGNvbnN0IHN0ciA9IHRoaXMuc3RvcmFnZS5nZXRJdGVtKE5neEZpcmViYXNlQXV0aFNlcnZpY2UucmVtZW1iZXJLZXkpO1xuICAgIGlmIChzdHIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKHN0cik7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiB7ZW1haWw6ICcnLCByZW1lbWJlcjogdHJ1ZX07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7ZW1haWw6ICcnLCByZW1lbWJlcjogdHJ1ZX07XG4gIH1cblxuICBzZXRSZW1lbWJlcmVkKHJlbWVtYmVyOiBib29sZWFuLCBlbWFpbDogc3RyaW5nKTogUHJvbWlzZTxJTmd4RmlyZWJhc2VBdXRoUmVtZW1iZXJSZWNvcmQ+IHtcbiAgICBjb25zdCBwZXJzaXN0ZW5jZTogYXV0aC5BdXRoLlBlcnNpc3RlbmNlID0gcmVtZW1iZXIgP1xuICAgICAgYXV0aC5BdXRoLlBlcnNpc3RlbmNlLkxPQ0FMIDogYXV0aC5BdXRoLlBlcnNpc3RlbmNlLlNFU1NJT047XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5zZXRQZXJzaXN0ZW5jZShwZXJzaXN0ZW5jZSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgbzogSU5neEZpcmViYXNlQXV0aFJlbWVtYmVyUmVjb3JkID0ge1xuICAgICAgICAgIGVtYWlsOiByZW1lbWJlciA/IGVtYWlsIDogJycsXG4gICAgICAgICAgcmVtZW1iZXI6IHJlbWVtYmVyXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHN0ciA9IEpTT04uc3RyaW5naWZ5KG8pO1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0SXRlbShOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLnJlbWVtYmVyS2V5LCBzdHIpO1xuICAgICAgICByZXR1cm4gbztcbiAgICAgIH0pO1xuICB9XG5cblxuXG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgT25EZXN0cm95LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFRlbXBsYXRlUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZXIsIEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuXG5cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi1pbicsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCIndW5oYW5kbGVkRXJyb3InID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1leGNsYW1hdGlvbi10cmlhbmdsZSBmYS1mdyB0ZXh0LWRhbmdlclwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICA8c3Ryb25nPldvb3BzITwvc3Ryb25nPiBBbiB1bmV4cGVjdGVkIGVycm9yIG9jY3VycmVkLlxuICA8L2Rpdj5cbiAgPHAgY2xhc3M9XCJ0ZXh0LW11dGVkXCI+XG4gICAgQ29kZToge3t1bmhhbmRsZWRFcnJvci5jb2RlfX0uIE1lc3NhZ2U6IHt7dW5oYW5kbGVkRXJyb3IubWVzc2FnZX19XG4gIDwvcD5cbiAgPHA+XG4gICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U3RhcnQgT3ZlcjwvYT5cbiAgPC9wPlxuPC9kaXY+XG5cblxuPGRpdiAqbmdJZj1cIidzaWduSW5TdWNjZXNzJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFdlbGNvbWUsIHt7Y3JlZC51c2VyLmRpc3BsYXlOYW1lfX0hXG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuXG5cbjxkaXYgKm5nSWY9XCInc2lnbkluJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiICpuZ0lmPVwic2lnbmVkT3V0XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgWW91w6LCgMKZcmUgc2lnbmVkIG91dC5cbiAgPC9kaXY+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybVxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICBbKHJlbWVtYmVyKV09XCJyZW1lbWJlclwiXG4gICAgW29BdXRoUHJvdmlkZXJJZHNdPVwib0F1dGhQcm92aWRlcklkc1wiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCJcbiAgICAoc3VjY2Vzcyk9XCJzaG93U2lnbkluU3VjY2VzcygkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnbkluUGFzc3dvcmQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLWZvcm1cbiAgICBbZW1haWxdPVwiZW1haWxcIlxuICAgIFsocmVtZW1iZXIpXT1cInJlbWVtYmVyXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIlxuICAgIChzdWNjZXNzKT1cInNob3dTaWduSW5TdWNjZXNzKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnblVwUGFzc3dvcmQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLXVwLWZvcm1cbiAgICBbZW1haWxdPVwiZW1haWxcIlxuICAgIFsocmVtZW1iZXIpXT1cInJlbWVtYmVyXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIlxuICAgIChzdWNjZXNzKT1cInNob3dTaWduSW5TdWNjZXNzKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXNpZ24tdXAtZm9ybT5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1tdXRlZCBteS0yIGZvcm0tdGV4dFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0b3NUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICA8L3NtYWxsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc2lnbkluT0F1dGgnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxuZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoXG4gICAgW3Byb3ZpZGVySWRdPVwib0F1dGhQcm92aWRlcklkXCJcbiAgICBbaW5pdGlhbEVycm9yXT1cImluaXRpYWxPQXV0aEVycm9yXCJcbiAgICBbdXNlT0F1dGhQb3B1cF09XCJ1c2VPQXV0aFBvcHVwXCJcbiAgICBbb0F1dGhQcm92aWRlckZhY3RvcnldPVwib0F1dGhQcm92aWRlckZhY3RvcnlcIlxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICBbKHJlbWVtYmVyKV09XCJyZW1lbWJlclwiXG4gICAgKGVycm9yKT1cInNob3dVbmhhbmRsZWRFcnJvcigkZXZlbnQpXCJcbiAgICAoc3VjY2Vzcyk9XCJzaG93U2lnbkluU3VjY2VzcygkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoPlxuICA8c21hbGwgY2xhc3M9XCJ0ZXh0LWNlbnRlciB0ZXh0LW11dGVkIG15LTIgZm9ybS10ZXh0XCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRvc1RlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XG4gIDwvc21hbGw+XG48L2Rpdj5cblxuXG5cbjxkaXYgKm5nSWY9XCIncmVzZXRQYXNzd29yZCcgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGg2PlJlc2V0IFBhc3N3b3JkPC9oNj5cbiAgPG5neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybVxuICAgIFsoZW1haWwpXT1cImVtYWlsXCJcbiAgICAoZXJyb3IpPVwic2hvd1VuaGFuZGxlZEVycm9yKCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybT5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbc2NyZWVuQW5pbWF0aW9uXVxufSlcbmV4cG9ydCBjbGFzcyBTaWduSW5Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgbmdVbnN1YnNjcmliZTogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIEBJbnB1dCgpIG9BdXRoUHJvdmlkZXJJZHM6IHN0cmluZ1tdO1xuICBASW5wdXQoKSB1c2VPQXV0aFBvcHVwOiBib29sZWFuO1xuICBASW5wdXQoKSBvQXV0aFByb3ZpZGVyRmFjdG9yeTogKHByb3ZpZGVySWQ6IHN0cmluZykgPT4gYXV0aC5BdXRoUHJvdmlkZXI7XG4gIEBJbnB1dCgpIHRvc1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+ID0gbnVsbDtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIG1vZGU6IEV2ZW50RW1pdHRlcjwnc2lnbkluJyB8ICdyZXNldFBhc3N3b3JkJz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcmVtZW1iZXI6IGJvb2xlYW47XG4gIGVtYWlsOiBzdHJpbmc7XG4gIGluaXRpYWxPQXV0aEVycm9yOiBhdXRoLkVycm9yID0gbnVsbDtcbiAgc2lnbmVkT3V0ID0gZmFsc2U7XG4gIG9BdXRoUHJvdmlkZXJJZDogc3RyaW5nID0gbnVsbDtcbiAgY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbCA9IG51bGw7XG4gIHVuaGFuZGxlZEVycm9yOiBhdXRoLkVycm9yID0gbnVsbDtcblxuICBzY3JlZW46ICd3YWl0JyB8XG4gICAgJ3NpZ25JbicgfCAnc2lnbkluUGFzc3dvcmQnIHwgJ3NpZ25VcFBhc3N3b3JkJyB8ICdzaWduSW5PQXV0aCcgfCAnc2lnbkluU3VjY2VzcycgfFxuICAgICdyZXNldFBhc3N3b3JkJyB8ICd1bmhhbmRsZWRFcnJvcicgPSAnd2FpdCc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfc3ZjOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlcixcbiAgKSB7fVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9zdmM7XG4gIH1cblxuICBnZXQgcm91dGVyKCk6IFJvdXRlciB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlcjtcbiAgfVxuXG4gIGdldCByb3V0ZSgpOiBBY3RpdmF0ZWRSb3V0ZSB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlO1xuICB9XG5cbiAgZ2V0IHF1ZXJ5UGFyYW1zKCk6IE9ic2VydmFibGU8e1trZXk6IHN0cmluZ106IGFueX0+IHtcbiAgICByZXR1cm4gdGhpcy5yb3V0ZS5xdWVyeVBhcmFtcztcbiAgfVxuXG4gIGdldCBzbmFwc2hvdFF1ZXJ5UGFyYW1zKCk6IHtba2V5OiBzdHJpbmddOiBhbnl9IHtcbiAgICByZXR1cm4gdGhpcy5yb3V0ZS5zbmFwc2hvdC5xdWVyeVBhcmFtcztcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaW5pdCgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5uZ1Vuc3Vic2NyaWJlLm5leHQoKTtcbiAgICB0aGlzLm5nVW5zdWJzY3JpYmUuY29tcGxldGUoKTtcbiAgfVxuXG4gIGluaXQoKSB7XG4gICAgY29uc3QgcmVtZW1iZXJSZWNvcmQgPSB0aGlzLmF1dGhTZXJ2aWNlLmdldFJlbWVtYmVyZWQoKTtcbiAgICB0aGlzLnJlbWVtYmVyID0gcmVtZW1iZXJSZWNvcmQucmVtZW1iZXI7XG4gICAgdGhpcy5lbWFpbCA9IHJlbWVtYmVyUmVjb3JkLmVtYWlsO1xuICAgIHJldHVybiB0aGlzLm9uSW5pdEhhbmRsZVNpZ25PdXQoKVxuICAgICAgLnRoZW4oKGhhbmRsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgaWYgKGhhbmRsZWQpIHtcbiAgICAgICAgICByZXR1cm4gaGFuZGxlZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5vbkluaXRIYW5kbGVPQXV0aFJlZGlyZWN0KCk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKGhhbmRsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgaWYgKCEgaGFuZGxlZCkge1xuICAgICAgICAgIHRoaXMuc2hvd1NpZ25JbigpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucXVlcnlQYXJhbXMucGlwZSh0YWtlVW50aWwodGhpcy5uZ1Vuc3Vic2NyaWJlKSkuc3Vic2NyaWJlKHBhcmFtcyA9PiB7XG4gICAgICAgICAgY29uc3QgYWN0aW9uID0gcGFyYW1zLmFjdGlvbiB8fCBudWxsO1xuICAgICAgICAgIHN3aXRjaCAoYWN0aW9uKSB7XG4gICAgICAgICAgICBjYXNlICdzaWduT3V0JzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnbk91dCgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3Jlc2V0UGFzc3dvcmQnOlxuICAgICAgICAgICAgICB0aGlzLnNob3dSZXNldFBhc3N3b3JkKCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2lnbkluJzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnbkluKCk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2lnbkluUGFzc3dvcmQnOlxuICAgICAgICAgICAgICB0aGlzLnNob3dTaWduSW5QYXNzd29yZCgpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NpZ25VcFBhc3N3b3JkJzpcbiAgICAgICAgICAgICAgdGhpcy5zaG93U2lnblVwUGFzc3dvcmQoKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzaWduSW5PQXV0aCc6XG4gICAgICAgICAgICAgIHRoaXMuc2hvd1NpZ25Jbk9BdXRoKHBhcmFtcy5wcm92aWRlcklkLCBudWxsKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgb25Jbml0SGFuZGxlU2lnbk91dCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5zbmFwc2hvdFF1ZXJ5UGFyYW1zLmFjdGlvbiAhPT0gJ3NpZ25PdXQnKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKGZhbHNlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2hvd1NpZ25PdXQoKS50aGVuKCgpID0+IHRydWUpO1xuICB9XG4gIG9uSW5pdEhhbmRsZU9BdXRoUmVkaXJlY3QoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgY29uc3QgcmVtZW1iZXI6IGJvb2xlYW4gPSB0aGlzLnJvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zLnJlbWVtYmVyID09PSAndHJ1ZSc7XG4gICAgICByZXR1cm4gdGhpcy5hdXRoLmdldFJlZGlyZWN0UmVzdWx0KClcbiAgICAgICAgLnRoZW4oKGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5hdXRoLmN1cnJlbnRVc2VyICYmIGNyZWQudXNlcikge1xuICAgICAgICAgICAgdGhpcy5hdXRoU2VydmljZS5zZXRSZW1lbWJlcmVkKHJlbWVtYmVyLCBjcmVkLnVzZXIuZW1haWwpXG4gICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dTaWduSW5TdWNjZXNzKGNyZWQpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNvbHZlKGZhbHNlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgICB0aGlzLnNob3dTaWduSW5PQXV0aChudWxsLCBlcnJvciApO1xuICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cblxuXG5cbiAgc2hvd1NpZ25PdXQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3dhaXQnO1xuICAgIHJldHVybiB0aGlzLmF1dGguc2lnbk91dCgpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2hvd1NpZ25Jbih0cnVlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgc2hvd1NpZ25JbihzaWduZWRPdXQ/OiBib29sZWFuKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gc2lnbmVkT3V0ID09PSB0cnVlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3NpZ25Jbic7XG4gIH1cblxuICBzaG93U2lnbkluUGFzc3dvcmQoKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy5zY3JlZW4gPSAnc2lnbkluUGFzc3dvcmQnO1xuICB9XG5cbiAgc2hvd1NpZ25VcFBhc3N3b3JkKCkge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMuc2NyZWVuID0gJ3NpZ25VcFBhc3N3b3JkJztcblxuICB9XG5cbiAgc2hvd1NpZ25Jbk9BdXRoKG9BdXRoUHJvdmlkZXJJZDogc3RyaW5nLCBlcnJvcjogYXV0aC5FcnJvcikge1xuICAgIHRoaXMubW9kZS5lbWl0KCdzaWduSW4nKTtcbiAgICB0aGlzLnNpZ25lZE91dCA9IGZhbHNlO1xuICAgIHRoaXMub0F1dGhQcm92aWRlcklkID0gb0F1dGhQcm92aWRlcklkO1xuICAgIHRoaXMuaW5pdGlhbE9BdXRoRXJyb3IgPSBlcnJvcjtcbiAgICB0aGlzLnNjcmVlbiA9ICdzaWduSW5PQXV0aCc7XG4gIH1cblxuICBzaG93U2lnbkluU3VjY2VzcyhjcmVkOiBhdXRoLlVzZXJDcmVkZW50aWFsKSB7XG4gICAgdGhpcy5tb2RlLmVtaXQoJ3NpZ25JbicpO1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy5jcmVkID0gY3JlZDtcbiAgICB0aGlzLnNjcmVlbiA9ICdzaWduSW5TdWNjZXNzJztcbiAgICB0aGlzLnN1Y2Nlc3MuZW1pdChjcmVkKTtcbiAgfVxuXG4gIHNob3dSZXNldFBhc3N3b3JkKCkge1xuICAgIHRoaXMubW9kZS5lbWl0KCdyZXNldFBhc3N3b3JkJyk7XG4gICAgdGhpcy5zaWduZWRPdXQgPSBmYWxzZTtcbiAgICB0aGlzLnNjcmVlbiA9ICdyZXNldFBhc3N3b3JkJztcbiAgfVxuXG4gIHNob3dVbmhhbmRsZWRFcnJvcihlcnJvcjogYXV0aC5FcnJvcikge1xuICAgIHRoaXMuc2lnbmVkT3V0ID0gZmFsc2U7XG4gICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgIHRoaXMuc2NyZWVuID0gJ3VuaGFuZGxlZEVycm9yJztcbiAgfVxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi9zaGFyZWQnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi9zaGFyZWQnO1xuXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYicsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIidyZXNldFBhc3N3b3JkJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXJlc2V0LXBhc3N3b3JkXG4gICAgW29vYkNvZGVdPVwib29iQ29kZVwiXG4gICAgKHN1Y2Nlc3MpPVwic3VjY2Vzcy5lbWl0KCRldmVudClcIj48L25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZD5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3ZlcmlmeUVtYWlsJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXZlcmlmeS1lbWFpbFxuICAgIFtvb2JDb2RlXT1cIm9vYkNvZGVcIlxuICAgIChzdWNjZXNzKT1cInN1Y2Nlc3MuZW1pdCgkZXZlbnQpXCI+PC9uZ3gtZmlyZWJhc2UtYXV0aC1vb2ItdmVyaWZ5LWVtYWlsPlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCIncmVjb3ZlckVtYWlsJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8bmd4LWZpcmViYXNlLWF1dGgtb29iLXJlY292ZXItZW1haWxcbiAgICBbb29iQ29kZV09XCJvb2JDb2RlXCJcbiAgICAoc3VjY2Vzcyk9XCJzdWNjZXNzLmVtaXQoJGV2ZW50KVwiPjwvbmd4LWZpcmViYXNlLWF1dGgtb29iLXJlY292ZXItZW1haWw+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBvb2JDb2RlOiBzdHJpbmc7XG4gIHNjcmVlbjogJ3Jlc2V0UGFzc3dvcmQnIHwgJ3ZlcmlmeUVtYWlsJyB8ICdyZWNvdmVyRW1haWwnID0gbnVsbDtcblxuICBAT3V0cHV0KCkgbW9kZTogRXZlbnRFbWl0dGVyPCdyZXNldFBhc3N3b3JkJyB8ICd2ZXJpZnlFbWFpbCcgfCAncmVjb3ZlckVtYWlsJz4gID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgbmF2aWdhdGlvbkVycm9yOiBFdmVudEVtaXR0ZXI8dm9pZD4gID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgKSB7IH1cblxuXG4gIGdldCBxdWVyeVBhcmFtcygpOiB7W2tleTogc3RyaW5nXTogYW55fSB7XG4gICAgcmV0dXJuIHRoaXMuX3JvdXRlLnNuYXBzaG90LnF1ZXJ5UGFyYW1zO1xuICB9XG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLm9vYkNvZGUgPSB0aGlzLnF1ZXJ5UGFyYW1zLm9vYkNvZGUgfHwgbnVsbDtcbiAgICBpZiAoISB0aGlzLm9vYkNvZGUpIHtcbiAgICAgIHRoaXMubmF2aWdhdGlvbkVycm9yLmVtaXQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3dpdGNoICh0aGlzLnF1ZXJ5UGFyYW1zLm1vZGUpIHtcbiAgICAgIGNhc2UgJ3Jlc2V0UGFzc3dvcmQnOlxuICAgICAgY2FzZSAndmVyaWZ5RW1haWwnOlxuICAgICAgY2FzZSAncmVjb3ZlckVtYWlsJzpcbiAgICAgICAgdGhpcy5zY3JlZW4gPSB0aGlzLnF1ZXJ5UGFyYW1zLm1vZGU7XG4gICAgICAgIHRoaXMubW9kZS5lbWl0KHRoaXMucXVlcnlQYXJhbXMubW9kZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpcy5uYXZpZ2F0aW9uRXJyb3IuZW1pdCgpO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgfVxufVxuIiwiaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIHtcbiAgc3RhdGljIHNldEVycm9yVW50aWxDaGFuZ2VkKGZjOiBBYnN0cmFjdENvbnRyb2wsIGtleTogc3RyaW5nLCB2YWx1ZTogYW55ID0gdHJ1ZSkge1xuICAgIGNvbnN0IGVycm9yID0ge307XG4gICAgZXJyb3Jba2V5XSA9IHZhbHVlO1xuICAgIGZjLnNldEVycm9ycyhlcnJvcik7XG4gICAgZmMudmFsdWVDaGFuZ2VzLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuY2xlYXJFcnJvcihmYywga2V5KTtcbiAgICB9KTtcblxuICB9XG5cbiAgc3RhdGljIGNsZWFyRXJyb3IoZmM6IEFic3RyYWN0Q29udHJvbCwga2V5OiBzdHJpbmcpIHtcbiAgICBjb25zdCBlcnJvcnMgPSB7fTtcbiAgICBpZiAoISBmYy5lcnJvcnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgT2JqZWN0LmtleXMoZmMuZXJyb3JzKS5mb3JFYWNoKChrKSA9PiB7XG4gICAgICBpZiAoayAhPT0ga2V5KSB7XG4gICAgICAgIGVycm9yc1trXSA9IGZjLmVycm9yc1trXTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoT2JqZWN0LmtleXMoZXJyb3JzKS5sZW5ndGggPT09IDApIHtcbiAgICAgIGZjLnNldEVycm9ycyhudWxsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZmMuc2V0RXJyb3JzKGVycm9ycyk7XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIHJlcXVpcmVkTm9uRW1wdHkoZmM6IEFic3RyYWN0Q29udHJvbCkge1xuICAgIGNvbnN0IHZhbHVlID0gZmMudmFsdWU7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWUudHJpbSgpLmxlbmd0aCA9PT0gMCA/IHtyZXF1aXJlZDogdHJ1ZX0gOiBudWxsO1xuICB9XG5cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIEFmdGVyVmlld0luaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgTmdab25lLCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IElTaWduSW5NZXRob2RzRm9yRW1haWxSZXN1bHQsIGdldE9BdXRoUHJvdmlkZXJJY29uLCBnZXRPQXV0aFByb3ZpZGVyTmFtZSB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgZmFkZUluT3V0QW5pbWF0aW9uLCBzY3JlZW5BbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW1ldGhvZHMtZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiPlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiPkVtYWlsIEFkZHJlc3M8L2xhYmVsPlxuICAgIDxpbnB1dFxuICAgICAgI2VtYWlsSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJlbWFpbFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgKGJsdXIpPVwiZmV0Y2goKVwiXG4gICAgICAoa2V5dXAuZW50ZXIpPVwiZW1haWxJbnB1dC5ibHVyKClcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignYXV0aC9pbnZhbGlkLWVtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBmb3JtLXRleHRcIiBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCIgW25nU3dpdGNoXT1cImZldGNoU3RhdHVzXCI+XG4gICAgICA8c3BhbiAqbmdTd2l0Y2hDYXNlPVwiJ3VuZmV0Y2hlZCdcIiBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICAgIFRvIGdldCBzdGFydGVkLCBlbnRlciB5b3VyIGVtYWlsIGFkZHJlc3MuXG4gICAgICAgIElmIHlvdSBkb27DosKAwpl0IHlldCBoYXZlIGFuIGFjY291bnQgd2XDosKAwplsbCBjcmVhdGUgb25lIGZvciB5b3UuXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdTd2l0Y2hDYXNlPVwiJ2ZldGNoaW5nJ1wiIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgICBMb29raW5nIHVwIGFjY291bnQuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ1N3aXRjaENhc2U9XCInZmV0Y2hlZCdcIiBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3IHRleHQtc3VjY2Vzc1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50RXhpc3RzXCI+QWNjb3VudCBmb3VuZC48L3NwYW4+XG4gICAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudElzTmV3XCI+V2UnbGwgY3JlYXRlIGFuIGFjY291bnQuPC9zcGFuPlxuICAgICAgPC9zcGFuPlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgIDwvbGFiZWw+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9mb3JtPlxuPGRpdiAqbmdJZj1cIm1ldGhvZHNGZXRjaGVkICYmIGFjY291bnRFeGlzdHNcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgbWItMSBmb3JtLXRleHRcIj5cbiAgICA8c3BhbiAqbmdJZj1cImFjY291bnRIYXNQYXNzd29yZFwiPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA9PT0gMFwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXIgcGFzc3dvcmQuLi5cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiYWNjb3VudE9BdXRoTWV0aG9kcy5sZW5ndGggPT09IDFcIj5cbiAgICAgICAgUGxlYXNlIHNpZ24gaW4gd2l0aCB5b3VyIHBhc3N3b3JkIG9yIHlvdXJcbiAgICAgICAgbGlua2VkIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoYWNjb3VudE9BdXRoTWV0aG9kc1swXSl9fSBhY2NvdW50Li4uXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID4gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXIgcGFzc3dvcmQgb3Igb25lIG9mIHlvdXIgbGlua2VkIGFjY291bnRzLi4uXG4gICAgICA8L3NwYW4+XG4gICAgPC9zcGFuPlxuICAgIDxzcGFuICpuZ0lmPVwiIWFjY291bnRIYXNQYXNzd29yZFwiPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY2NvdW50T0F1dGhNZXRob2RzLmxlbmd0aCA9PT0gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIHlvdXJcbiAgICAgICAgbGlua2VkIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoYWNjb3VudE9BdXRoTWV0aG9kc1swXSl9fSBhY2NvdW50Li4uXG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjY291bnRPQXV0aE1ldGhvZHMubGVuZ3RoID4gMVwiPlxuICAgICAgICBQbGVhc2Ugc2lnbiBpbiB3aXRoIG9uZSBvZiB5b3VyIGxpbmtlZCBhY2NvdW50cy4uLlxuICAgICAgPC9zcGFuPlxuICAgIDwvc3Bhbj5cblxuICA8L3NtYWxsPlxuXG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG4gICAgPGFcbiAgICAgICpuZ0lmPVwiYWNjb3VudEhhc1Bhc3N3b3JkXCJcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+XG4gICAgICAgIFNpZ24gSW4gd2l0aCBZb3VyIFBhc3N3b3JkXG4gICAgICA8L3NwYW4+XG4gICAgPC9hPlxuICAgIDxhXG4gICAgICAqbmdGb3I9XCJsZXQgaWQgb2YgYWNjb3VudE9BdXRoTWV0aG9kc1wiXG4gICAgICByb3V0ZXJMaW5rPVwiLlwiXG4gICAgICBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbk9BdXRoJywgcHJvdmlkZXJJZDogaWR9XCJcbiAgICAgIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIj5cbiAgICAgIDxpIFthdHRyLmNsYXNzXT1cImdldE9BdXRoUHJvdmlkZXJJY29uKGlkKVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlxuICAgICAgICBTaWduIEluIHdpdGgge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fVxuICAgICAgPC9zcGFuPlxuICAgIDwvYT5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cIm1ldGhvZHNGZXRjaGVkICYmIGFjY291bnRJc05ld1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZCBtYi0xIGZvcm0tdGV4dFwiPlxuICAgIDxzcGFuICpuZ0lmPVwib0F1dGhQcm92aWRlcklkcy5sZW5ndGggPT09IDBcIj5cbiAgICAgIFBsZWFzZSBjcmVhdGUgYW4gYWNjb3VudC4uLlxuICAgIDwvc3Bhbj5cbiAgICA8c3BhbiAqbmdJZj1cIm9BdXRoUHJvdmlkZXJJZHMubGVuZ3RoID09PSAxXCI+XG4gICAgICBQbGVhc2Ugc2lnbiB1cCB3aXRoIHlvdXJcbiAgICAgIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUob0F1dGhQcm92aWRlcklkc1swXSl9fSBhY2NvdW50LFxuICAgICAgb3IgY3JlYXRlIGEgc2VwYXJhdGUgYWNjb3VudCB3aXRoIGEgcGFzc3dvcmQuLi4uXG4gICAgPC9zcGFuPlxuICAgIDxzcGFuICpuZ0lmPVwib0F1dGhQcm92aWRlcklkcy5sZW5ndGggPjFcIj5cbiAgICAgIFBsZWFzZSBzaWduIHVwIHdpdGggb25lIG9mIHRoZSBzZXJ2aWNlcyBsaXN0ZWQgYmVsb3csXG4gICAgICBvciBjcmVhdGUgYSBzZXBhcmF0ZSBhY2NvdW50IHdpdGggYSBwYXNzd29yZC4uLi5cbiAgICA8L3NwYW4+XG4gIDwvc21hbGw+XG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG5cbiAgICA8YVxuICAgICAgKm5nRm9yPVwibGV0IGlkIG9mIG9BdXRoUHJvdmlkZXJJZHNcIlxuICAgICAgcm91dGVyTGluaz1cIi5cIlxuICAgICAgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSW5PQXV0aCcsIHByb3ZpZGVySWQ6IGlkfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihpZClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5cbiAgICAgICAgU2lnbiBVcCB3aXRoIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUoaWQpfX1cbiAgICAgIDwvc3Bhbj5cbiAgICA8L2E+XG4gICAgPGFcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnblVwUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgPHNwYW4gY2xhc3M9XCJtbC0yXCI+XG4gICAgICAgIENyZWF0ZVxuICAgICAgICA8c3BhbiAqbmdJZj1cIm9BdXRoUHJvdmlkZXJJZHMubGVuZ3RoID4gMFwiPlxuICAgICAgICAgIGEgU2VwYXJhdGVcbiAgICAgICAgPC9zcGFuPlxuICAgICAgICBBY2NvdW50XG4gICAgICA8L3NwYW4+XG4gICAgPC9hPlxuICA8L2Rpdj5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbZmFkZUluT3V0QW5pbWF0aW9uLCBzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25Jbk1ldGhvZHNGb3JtQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcblxuXG4gIEBWaWV3Q2hpbGQoJ2VtYWlsSW5wdXQnKSBlbWFpbElucHV0OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQElucHV0KCkgb0F1dGhQcm92aWRlcklkczogc3RyaW5nW10gPSBbXTtcbiAgQE91dHB1dCgpIGVtYWlsQ2hhbmdlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tbWV0aG9kcy1mb3JtLSc7XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICBnZXRPQXV0aFByb3ZpZGVySWNvbiA9IGdldE9BdXRoUHJvdmlkZXJJY29uO1xuICBnZXRPQXV0aFByb3ZpZGVyTmFtZSA9IGdldE9BdXRoUHJvdmlkZXJOYW1lO1xuICBtZXRob2RzRm9yRW1haWw6IElTaWduSW5NZXRob2RzRm9yRW1haWxSZXN1bHQgPSB7c3RhdHVzOiAndW5mZXRjaGVkJywgbWV0aG9kczogW10sIGVtYWlsOiBudWxsfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZSxcbiAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZVxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuXG4gIGdldCBtZXRob2RzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRm9yRW1haWwubWV0aG9kcztcbiAgfVxuXG4gIGdldCBmZXRjaFN0YXR1cygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm1ldGhvZHNGb3JFbWFpbC5zdGF0dXM7XG4gIH1cblxuICBnZXQgbWV0aG9kc0ZldGNoZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZvckVtYWlsLnN0YXR1cyA9PT0gJ2ZldGNoZWQnO1xuICB9XG5cbiAgZ2V0IGFjY291bnRJc05ldygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tZXRob2RzRmV0Y2hlZCAmJiB0aGlzLm1ldGhvZHMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgZ2V0IGFjY291bnRFeGlzdHMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWV0aG9kc0ZldGNoZWQgJiYgdGhpcy5tZXRob2RzLmxlbmd0aCA+IDA7XG4gIH1cblxuICBnZXQgYWNjb3VudEhhc1Bhc3N3b3JkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmFjY291bnRFeGlzdHMgJiYgdGhpcy5tZXRob2RzLmluZGV4T2YoJ3Bhc3N3b3JkJykgIT09IC0xO1xuICB9XG5cbiAgZ2V0IGFjY291bnRPQXV0aE1ldGhvZHMoKTogc3RyaW5nW10ge1xuICAgIGlmICghIHRoaXMuYWNjb3VudEV4aXN0cykge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5tZXRob2RzLmZpbHRlcihpZCA9PiBpZCAhPT0gJ3Bhc3N3b3JkJyk7XG4gIH1cblxuXG5cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmVtYWlsRmMgPSBuZXcgRm9ybUNvbnRyb2woXG4gICAgICB0aGlzLmVtYWlsLFxuICAgICAge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLmVtYWlsXX1cbiAgICApO1xuICAgIHRoaXMucmVtZW1iZXJGYyA9IG5ldyBGb3JtQ29udHJvbCh0aGlzLnJlbWVtYmVyKTtcbiAgICB0aGlzLnJlbWVtYmVyRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgoKSA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodGhpcy5yZW1lbWJlckZjLnZhbHVlKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe2VtYWlsOiB0aGlzLmVtYWlsRmMsIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmN9KTtcbiAgICB0aGlzLmVtYWlsRmMudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgoKSA9PiB0aGlzLmVtYWlsQ2hhbmdlLmVtaXQodGhpcy5lbWFpbEZjLnZhbHVlLnRyaW0oKSkpO1xuICAgIHRoaXMuZW1haWxGYy52YWx1ZUNoYW5nZXMucGlwZShkZWJvdW5jZVRpbWUoNTAwKSkuc3Vic2NyaWJlKCgpID0+IHRoaXMuZmV0Y2goKSk7XG4gICAgdGhpcy5mZXRjaCgpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuZW1haWxJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG5cbiAgfVxuXG5cbiAgZmV0Y2goKSB7XG4gICAgY29uc3QgZW1haWwgPSB0aGlzLmVtYWlsRmMudmFsdWUudHJpbSgpO1xuICAgIGlmIChlbWFpbCA9PT0gdGhpcy5tZXRob2RzRm9yRW1haWwuZW1haWwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCdmZXRjaGluZycgPT09IHRoaXMubWV0aG9kc0ZvckVtYWlsLnN0YXR1cykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHtzdGF0dXM6ICdmZXRjaGluZycsIG1ldGhvZHM6IFtdLCBlbWFpbDogZW1haWx9O1xuICAgIGlmICh0aGlzLmVtYWlsRmMuaW52YWxpZCkge1xuICAgICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSB7c3RhdHVzOiAndW5mZXRjaGVkJywgbWV0aG9kczogW10sIGVtYWlsOiBlbWFpbH07XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuYXV0aC5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChlbWFpbClcbiAgICAgIC50aGVuKHJlc3VsdHMgPT4ge1xuICAgICAgICB0aGlzLm1ldGhvZHNGb3JFbWFpbCA9IHtzdGF0dXM6ICdmZXRjaGVkJywgbWV0aG9kczogcmVzdWx0cywgZW1haWw6IGVtYWlsfTtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yOiBhdXRoLkVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlICdhdXRoL2ludmFsaWQtZW1haWwnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLmVtYWlsRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5tZXRob2RzRm9yRW1haWwgPSB7ZW1haWw6IHRoaXMuZW1haWwsIHN0YXR1czogJ3VuZmV0Y2hlZCcsIG1ldGhvZHM6IFtdfTtcbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlclZpZXdJbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuXG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgZ2V0T0F1dGhQcm92aWRlckljb24sIGdldE9BdXRoUHJvdmlkZXJOYW1lLCBmYWRlSW5PdXRBbmltYXRpb24gfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuXG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiIChuZ1N1Ym1pdCk9XCJzdWJtaXQoKVwiPlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG5cbiAgICA8aW5wdXRcbiAgICAgIHJlYWRvbmx5XG4gICAgICAjZW1haWxJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cImVtYWlsXCJcbiAgICAgIHBsYWNlaG9sZGVyPVwiRW1haWwgQWRkcmVzc1wiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ3JlcXVpcmVkJylcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2VtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC9pbnZhbGlkLWVtYWlsJylcIj5cbiAgICAgIEludmFsaWQgZW1haWwuXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLW5vdC1mb3VuZCcpXCI+XG4gICAgICBXZSBjb3VsZCBub3QgZmluZCBhbiBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzLlxuICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+Q3JlYXRlIEFjY291bnQ8L2E+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiBbQGZhZGVJbk91dF09XCInaW4nXCJcbiAgICAgICpuZ0lmPVwiZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLWRpc2FibGVkJylcIj5cbiAgICAgIFRoZSBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzIGhhcyBiZWVuIGRpc2FibGVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ25neC1maXJlYmFzZS1hdXRoL25vLXBhc3N3b3JkJylcIj5cbiAgICAgIFRoZSBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzIGRvZXMgbm90IGhhdmUgYSBwYXNzd29yZC5cbiAgICAgIFBsZWFzZSBzaWduIGluIHVzaW5nOlxuICAgICAgPHNwYW4gKm5nRm9yPVwibGV0IGlkIG9mIG1ldGhvZHNGb3JFbWFpbDsgbGV0IGlzTGFzdCA9IGxhc3RcIj5cbiAgICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbk9BdXRoJywgcHJvdmlkZXJJZDogaWR9XCI+e3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fTwvYT5cbiAgICAgICAgPHNwYW4gKm5nSWY9XCIhaXNMYXN0XCI+XG4gICAgICAgICAgfFxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L3NwYW4+XG4gICAgPC9kaXY+XG5cbiAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIGZvcm0tdGV4dFwiIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIiA+XG4gICAgICBOb3QgeW91ciBlbWFpbCBhZGRyZXNzP1xuICAgICAgPGEgcm91dGVyTGluaz1cIi5cIiBbcXVlcnlQYXJhbXNdPVwie2FjdGlvbjogJ3NpZ25Jbid9XCI+U3RhcnQgT3ZlcjwvYT5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cblxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1lbmRcIj5cbiAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPlBhc3N3b3JkPC9sYWJlbD5cbiAgICAgIDxzbWFsbD5cbiAgICAgICAgPGEgKGNsaWNrKT1cIiRldmVudC5wcmV2ZW50RGVmYXVsdCgpOyBwYXNzd29yZElucHV0LnR5cGUgPSAncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGUgID8gJ3RleHQnIDogJ3Bhc3N3b3JkJ1wiXG4gICAgICAgICAgaHJlZj1cIiNcIiB0YWJpbmRleD1cIi0xXCIgY2xhc3M9XCJkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgIDxzcGFuICpuZ0lmPVwiJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+U2hvdzwvc3Bhbj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIid0ZXh0JyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlXCI+SGlkZTwvc3Bhbj5cbiAgICAgICAgPC9hPlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cbiAgICA8aW5wdXRcbiAgICAgICNwYXNzd29yZElucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncGFzc3dvcmQnXCJcbiAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCJcbiAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICBmb3JtQ29udHJvbE5hbWU9XCJwYXNzd29yZFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIlBhc3N3b3JkXCJcbiAgICAgIGF1dG9jb21wbGV0ZT1cInBhc3N3b3JkXCJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmludmFsaWRcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiXG4gICAgICAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCJcbiAgICAgIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICAgIFJlcXVpcmVkLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCJcbiAgICAgICpuZ0lmPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaGFzRXJyb3IoJ2F1dGgvd3JvbmctcGFzc3dvcmQnKVwiXG4gICAgICBbQGZhZGVJbk91dF09XCInaW4nXCI+XG4gICAgICBXcm9uZyBwYXNzd29yZC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgRm9yZ290PyA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAncmVzZXRQYXNzd29yZCd9XCI+UmVzZXQgUGFzc3dvcmQ8L2E+XG4gICAgPC9zbWFsbD5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgIDxpbnB1dFxuICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxuICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICBbdmFsdWVdPVwidHJ1ZVwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJlbWVtYmVyXCJcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbFwiIFthdHRyLmZvcl09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgIFJlbWVtYmVyIG1lIG9uIHRoaXMgZGV2aWNlLlxuICAgICAgPC9sYWJlbD5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGJ1dHRvbiB0eXBlPVwic3VibWl0XCJcbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zdWNjZXNzIGJ0bi1ibG9ja1wiXG4gICAgICBbZGlzYWJsZWRdPVwiZmcuaW52YWxpZCB8fCBzdWJtaXR0aW5nXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1sb2NrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgU2lnbiBJblxuICAgIDwvYnV0dG9uPlxuICA8L2Rpdj5cbjwvZm9ybT5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW2ZhZGVJbk91dEFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgU2lnbkluRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgQFZpZXdDaGlsZCgncGFzc3dvcmRJbnB1dCcpIHBhc3N3b3JkSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpIGVtYWlsOiBzdHJpbmc7XG4gIEBJbnB1dCgpIHJlbWVtYmVyOiBib29sZWFuO1xuICBAT3V0cHV0KCkgcmVtZW1iZXJDaGFuZ2U6IEV2ZW50RW1pdHRlcjxib29sZWFuPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVycm9yOiBFdmVudEVtaXR0ZXI8YXV0aC5FcnJvcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLXNpZ24taW4tZm9ybS0nO1xuICBzdWJtaXR0aW5nID0gZmFsc2U7XG4gIGZnOiBGb3JtR3JvdXA7XG4gIGVtYWlsRmM6IEZvcm1Db250cm9sO1xuICBwYXNzd29yZEZjOiBGb3JtQ29udHJvbDtcbiAgcmVtZW1iZXJGYzogRm9ybUNvbnRyb2w7XG4gIG1ldGhvZHNGb3JFbWFpbDogc3RyaW5nW10gPSBbXTtcbiAgZ2V0T0F1dGhQcm92aWRlckljb24gPSBnZXRPQXV0aFByb3ZpZGVySWNvbjtcbiAgZ2V0T0F1dGhQcm92aWRlck5hbWUgPSBnZXRPQXV0aFByb3ZpZGVyTmFtZTtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfYXV0aFNlcnZpY2U6IE5neEZpcmViYXNlQXV0aFNlcnZpY2VcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbChcbiAgICAgIHRoaXMuZW1haWwsXG4gICAgICB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMuZW1haWxdfVxuICAgICk7XG4gICAgdGhpcy5wYXNzd29yZEZjID0gbmV3IEZvcm1Db250cm9sKCcnLCB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWRdfSk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgZW1haWw6IHRoaXMuZW1haWxGYyxcbiAgICAgIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsXG4gICAgICByZW1lbWJlcjogdGhpcy5yZW1lbWJlckZjXG4gICAgfSk7XG4gIH1cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMucGFzc3dvcmRJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuXG5cbiAgc3VibWl0KCkge1xuICAgIGNvbnN0IGVtYWlsID0gdGhpcy5lbWFpbEZjLnZhbHVlLnRyaW0oKTtcbiAgICB0aGlzLnN1Ym1pdHRpbmcgPSB0cnVlO1xuICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0gW107XG4gICAgbGV0IGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWw7XG4gICAgdGhpcy5hdXRoLmZldGNoU2lnbkluTWV0aG9kc0ZvckVtYWlsKGVtYWlsKVxuICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgIHRoaXMubWV0aG9kc0ZvckVtYWlsID0gcmVzdWx0cztcbiAgICAgICAgaWYgKHJlc3VsdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICdhdXRoL3VzZXItbm90LWZvdW5kJ1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXN1bHRzLmluZGV4T2YoJ3Bhc3N3b3JkJykgPT09IC0xKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICduZ3gtZmlyZWJhc2UtYXV0aC9uby1wYXNzd29yZCcsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduSW5XaXRoRW1haWxBbmRQYXNzd29yZChlbWFpbCwgdGhpcy5wYXNzd29yZEZjLnZhbHVlKTtcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXN1bHQgPT4ge1xuICAgICAgICBjcmVkID0gcmVzdWx0O1xuICAgICAgICByZXR1cm4gdGhpcy5hdXRoU2VydmljZS5zZXRSZW1lbWJlcmVkKHRoaXMucmVtZW1iZXJGYy52YWx1ZSA9PT0gdHJ1ZSwgZW1haWwpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoY3JlZCk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgdGhpcy5zdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZW1haWxGYy5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICB0aGlzLnBhc3N3b3JkRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgc3dpdGNoIChlcnJvci5jb2RlKSB7XG4gICAgICAgICAgY2FzZSAnYXV0aC9pbnZhbGlkLWVtYWlsJzpcbiAgICAgICAgICBjYXNlICdhdXRoL3VzZXItbm90LWZvdW5kJzpcbiAgICAgICAgICBjYXNlICdhdXRoL3VzZXItZGlzYWJsZWQnOlxuICAgICAgICAgIGNhc2UgJ25neC1maXJlYmFzZS1hdXRoL25vLXBhc3N3b3JkJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5lbWFpbEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2F1dGgvd3JvbmctcGFzc3dvcmQnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLnBhc3N3b3JkRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRoaXMuZXJyb3IuZW1pdChlcnJvcik7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIEFmdGVyVmlld0luaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgVmlld0NoaWxkLCBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQW5ndWxhckZpcmVBdXRoIH0gZnJvbSAnYW5ndWxhcmZpcmUyL2F1dGgnO1xuaW1wb3J0IHsgYXV0aCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5cbmltcG9ydCB7IGZhZGVJbk91dEFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyIH0gZnJvbSAnLi4vLi4vZm9ybS1oZWxwZXInO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtc2lnbi11cC1mb3JtJyxcbiAgdGVtcGxhdGU6IGA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCIgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCI+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICByZWFkb25seVxuICAgICAgI2VtYWlsSW5wdXRcbiAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIlxuICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgIHR5cGU9XCJlbWFpbFwiXG4gICAgICBhdXRvY29tcGxldGU9XCJlbWFpbFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ2F1dGgvaW52YWxpZC1lbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMuaGFzRXJyb3IoJ25neC1maXJlYmFzZS1hdXRoL2FjY291bnQtZXhpc3RzJylcIj5cbiAgICAgIFdlIGZvdW5kIGFuIGFjY291bnQgd2l0aCB0aGF0IGVtYWlsIGFkZHJlc3MuXG4gICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TaWduIEluPC9hPlxuICAgIDwvZGl2PlxuICAgIDxzbWFsbCBjbGFzcz1cInRleHQtbXV0ZWQgZm9ybS10ZXh0XCIgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiID5cbiAgICAgIE5vdCB5b3VyIGVtYWlsIGFkZHJlc3M/XG4gICAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5HbyBCYWNrPC9hPlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1lbmRcIj5cbiAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPkNob29zZSBQYXNzd29yZDwvbGFiZWw+XG4gICAgICA8c21hbGw+XG4gICAgICAgIDxhIChjbGljayk9XCIkZXZlbnQucHJldmVudERlZmF1bHQoKTsgcGFzc3dvcmRJbnB1dC50eXBlID0gJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlICA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgIGhyZWY9XCIjXCIgdGFiaW5kZXg9XCItMVwiIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2tcIj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cIidwYXNzd29yZCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPlNob3c8L3NwYW4+XG4gICAgICAgICAgPHNwYW4gKm5nSWY9XCIndGV4dCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPkhpZGU8L3NwYW4+XG4gICAgICAgIDwvYT5cbiAgICAgIDwvc21hbGw+XG4gICAgPC9kaXY+XG4gICAgPGlucHV0XG4gICAgICAjcGFzc3dvcmRJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdwYXNzd29yZC1oZWxwJ1wiXG4gICAgICB0eXBlPVwicGFzc3dvcmRcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicGFzc3dvcmRcIlxuICAgICAgcGxhY2Vob2xkZXI9XCJDaG9vc2UgUGFzc3dvcmRcIlxuICAgICAgYXV0b2NvbXBsZXRlPVwicGFzc3dvcmRcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwicGFzc3dvcmRGYy50b3VjaGVkICYmIHBhc3N3b3JkRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcignYXV0aC93cm9uZy1wYXNzd29yZCcpXCI+XG4gICAgICBXcm9uZyBwYXNzd29yZC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgUGxlYXNlIGNob29zZSBhIHN0cm9uZyBwYXNzd29yZC5cbiAgICA8L3NtYWxsPlxuICA8L2Rpdj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8bGFiZWwgW2F0dHIuZm9yXT1cImZvcm1JZCArICduYW1lJ1wiPllvdXIgTmFtZTwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnbmFtZSdcIlxuICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibmFtZVwiXG4gICAgICBwbGFjZWhvbGRlcj1cIllvdXIgTmFtZVwiXG4gICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICBbY2xhc3MuaXMtaW52YWxpZF09XCJuYW1lRmMudG91Y2hlZCAmJiBuYW1lRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cIm5hbWVGYy50b3VjaGVkICYmIG5hbWVGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgUmVxdWlyZWQuXG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWNoZWNrXCI+XG4gICAgICA8aW5wdXRcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgIFthdHRyLmlkXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgIDwvbGFiZWw+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICBjbGFzcz1cImJ0biBidG4tc3VjY2VzcyBidG4tYmxvY2tcIlxuICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbG9jayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIENyZWF0ZSBBY2NvdW50XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuPC9mb3JtPlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbIGZhZGVJbk91dEFuaW1hdGlvbiBdXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25VcEZvcm1Db21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQge1xuXG4gIEBWaWV3Q2hpbGQoJ3Bhc3N3b3JkSW5wdXQnKSBwYXNzd29yZElucHV0OiBFbGVtZW50UmVmO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8YXV0aC5Vc2VyQ3JlZGVudGlhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLXVwLWZvcm0tJztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICBmZzogRm9ybUdyb3VwO1xuICBlbWFpbEZjOiBGb3JtQ29udHJvbDtcbiAgcGFzc3dvcmRGYzogRm9ybUNvbnRyb2w7XG4gIG5hbWVGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwcml2YXRlIF9hdXRoU2VydmljZTogTmd4RmlyZWJhc2VBdXRoU2VydmljZVxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9hdXRoU2VydmljZTtcbiAgfVxuXG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5lbWFpbEZjID0gbmV3IEZvcm1Db250cm9sKFxuICAgICAgdGhpcy5lbWFpbCxcbiAgICAgIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5lbWFpbF19XG4gICAgKTtcbiAgICB0aGlzLnBhc3N3b3JkRmMgPSBuZXcgRm9ybUNvbnRyb2woJycsIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZF19KTtcbiAgICB0aGlzLm5hbWVGYyA9IG5ldyBGb3JtQ29udHJvbCgnJywge3ZhbGlkYXRvcnM6IFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnJlcXVpcmVkTm9uRW1wdHldfSk7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgZW1haWw6IHRoaXMuZW1haWxGYyxcbiAgICAgIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsXG4gICAgICBuYW1lOiB0aGlzLm5hbWVGYyxcbiAgICAgIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmNcbiAgICB9KTtcbiAgfVxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5wYXNzd29yZElucHV0Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgfVxuXG4gIHN1Ym1pdCgpIHtcblxuICAgIHRoaXMuc3VibWl0dGluZyA9IHRydWU7XG4gICAgbGV0IGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWw7XG4gICAgdGhpcy5hdXRoLmZldGNoU2lnbkluTWV0aG9kc0ZvckVtYWlsKHRoaXMuZW1haWwpXG4gICAgICAudGhlbigocmVzdWx0cykgPT4ge1xuICAgICAgICBpZiAocmVzdWx0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgICAgIGNvZGU6ICduZ3gtZmlyZWJhc2UtYXV0aC9hY2NvdW50LWV4aXN0cydcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5hdXRoLmNyZWF0ZVVzZXJXaXRoRW1haWxBbmRQYXNzd29yZCh0aGlzLmVtYWlsLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpO1xuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3VsdCA9PiB7XG4gICAgICAgIGNyZWQgPSByZXN1bHQ7XG4gICAgICAgIHJldHVybiBjcmVkLnVzZXIudXBkYXRlUHJvZmlsZSh7ZGlzcGxheU5hbWU6IHRoaXMubmFtZUZjLnZhbHVlLnRyaW0oKSwgcGhvdG9VUkw6IG51bGx9KTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCB0aGlzLmVtYWlsKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc3VjY2Vzcy5lbWl0KGNyZWQpO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIHRoaXMuc3VibWl0dGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVtYWlsRmMubWFya0FzRGlydHkoKTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1lbWFpbCc6XG4gICAgICAgICAgY2FzZSAnbmd4LWZpcmViYXNlLWF1dGgvYWNjb3VudC1leGlzdHMnOlxuICAgICAgICAgICAgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlci5zZXRFcnJvclVudGlsQ2hhbmdlZCh0aGlzLmVtYWlsRmMsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnYXV0aC93ZWFrLXBhc3N3b3JkJzpcbiAgICAgICAgICAgIE5neEZpcmViYXNlQXV0aEZvcm1IZWxwZXIuc2V0RXJyb3JVbnRpbENoYW5nZWQodGhpcy5wYXNzd29yZEZjLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aGlzLmVycm9yLmVtaXQoZXJyb3IpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBBZnRlclZpZXdJbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGggfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IGZhZGVJbk91dEFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLXJlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybScsXG4gIHRlbXBsYXRlOiBgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiIChuZ1N1Ym1pdCk9XCJzdWJtaXQoKVwiPlxuICA8ZGl2ICpuZ0lmPVwic2VudFwiIFtAZmFkZUluT3V0XT1cIidpbidcIj5cbiAgICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtY2hlY2sgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXZcOiwoDCmXZlIHNlbnQgYSByZXNldCBwYXNzd29yZCBsaW5rIHRvIHt7c2VudH19LlxuICAgICAgUGxlYXNlIGFsbG93IGEgZmV3IG1vbWVudHMgZm9yIHRoZSBlbWFpbCB0byBhcnJpdmUuXG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG4gICAgPGlucHV0XG4gICAgICAjZW1haWxJbnB1dFxuICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsJ1wiXG4gICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImZvcm1JZCArICdlbWFpbC1oZWxwJ1wiXG4gICAgICB0eXBlPVwiZW1haWxcIlxuICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIlxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW2NsYXNzLmlzLWludmFsaWRdPVwiZW1haWxGYy50b3VjaGVkICYmIGVtYWlsRmMuaW52YWxpZFwiPlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdyZXF1aXJlZCcpXCI+XG4gICAgICBSZXF1aXJlZC5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFja1wiIFtAZmFkZUluT3V0XT1cIidpbidcIlxuICAgICAgKm5nSWY9XCJlbWFpbEZjLnRvdWNoZWQgJiYgZW1haWxGYy5oYXNFcnJvcignYXV0aC91c2VyLW5vdC1mb3VuZCcpXCI+XG4gICAgICBXZSBjb3VsZCBub3QgZmluZCBhbiBhY2NvdW50IHdpdGggdGhhdCBlbWFpbCBhZGRyZXNzLlxuICAgICAgUGxlYXNlIDxhIHJvdXRlckxpbms9XCIuXCIgW3F1ZXJ5UGFyYW1zXT1cInthY3Rpb246ICdzaWduSVVwUGFzc3dvcmQnfVwiPnNpZ24gdXA8L2E+LlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdlbWFpbCcpXCI+XG4gICAgICBJbnZhbGlkIGVtYWlsLlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgW0BmYWRlSW5PdXRdPVwiJ2luJ1wiXG4gICAgICAqbmdJZj1cImVtYWlsRmMudG91Y2hlZCAmJiBlbWFpbEZjLmhhc0Vycm9yKCdhdXRoL2ludmFsaWQtZW1haWwnKVwiPlxuICAgICAgSW52YWxpZCBlbWFpbC5cbiAgICA8L2Rpdj5cbiAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ2VtYWlsLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgRW50ZXIgdGhlIGVtYWlsIGFkZHJlc3MgeW91IHVzZWQgdG8gc2lnbiB1cC4gV2XDosKAwplsbFxuICAgICAgc2VuZCBhIHJlc2V0IHBhc3N3b3JkIGxpbmsgdG8gdGhhdCBhZGRyZXNzLlxuICAgIDwvc21hbGw+XG4gIDwvZGl2PlxuICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgIDxidXR0b24gdHlwZT1cInN1Ym1pdFwiXG4gICAgICBjbGFzcz1cImJ0biBidG4tYmxvY2sgYnRuLXN1Y2Nlc3NcIlxuICAgICAgW2Rpc2FibGVkXT1cImZnLmludmFsaWQgfHwgc3VibWl0dGluZ1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZncgZmEtZW52ZWxvcGVcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBTZW5kIExpbmtcbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Zvcm0+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtmYWRlSW5PdXRBbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIFJlc2V0UGFzc3dvcmRTZW5kRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XG5cbiAgQFZpZXdDaGlsZCgnZW1haWxJbnB1dCcpIGVtYWlsSW5wdXQ6IEVsZW1lbnRSZWY7XG4gIEBJbnB1dCgpIGVtYWlsOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBlbWFpbENoYW5nZTogRXZlbnRFbWl0dGVyPHN0cmluZz4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0tJztcbiAgZmc6IEZvcm1Hcm91cDtcbiAgZW1haWxGYzogRm9ybUNvbnRyb2w7XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgc2VudDogc3RyaW5nID0gbnVsbDtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICkgeyB9XG5cbiAgZ2V0IGF1dGgoKTogYXV0aC5BdXRoIHtcbiAgICByZXR1cm4gdGhpcy5fYWZBdXRoLmF1dGg7XG4gIH1cblxuXG5cblxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuZW1haWxGYyA9IG5ldyBGb3JtQ29udHJvbChcbiAgICAgIHRoaXMuZW1haWwsXG4gICAgICB7dmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMuZW1haWxdfVxuICAgICk7XG4gICAgdGhpcy5lbWFpbEZjLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4gdGhpcy5lbWFpbENoYW5nZS5lbWl0KHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCkpKTtcbiAgICB0aGlzLmZnID0gbmV3IEZvcm1Hcm91cCh7ZW1haWw6IHRoaXMuZW1haWxGY30pO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCkge1xuICAgIHRoaXMuZW1haWxJbnB1dC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuXG4gIHN1Ym1pdCgpIHtcbiAgICBjb25zdCBlbWFpbCA9IHRoaXMuZW1haWxGYy52YWx1ZS50cmltKCk7XG4gICAgdGhpcy5zdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICB0aGlzLnNlbnQgPSBudWxsO1xuICAgIHRoaXMuYXV0aC5zZW5kUGFzc3dvcmRSZXNldEVtYWlsKGVtYWlsKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5zZW50ID0gZW1haWw7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgdGhpcy5lbWFpbEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1lbWFpbCc6XG4gICAgICAgICAgY2FzZSAnYXV0aC91c2VyLW5vdC1mb3VuZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMuZW1haWxGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy5lcnJvci5lbWl0KGVycm9yKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuXG4gIH1cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgYXV0aCB9IGZyb20gJ2ZpcmViYXNlL2FwcCc7XG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1Db250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBnZXRPQXV0aFByb3ZpZGVySWNvbiwgZ2V0T0F1dGhQcm92aWRlck5hbWUgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uL25neC1maXJlYmFzZS1hdXRoLnNlcnZpY2UnO1xuaW1wb3J0IHsgc2NyZWVuQW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoJyxcbiAgdGVtcGxhdGU6IGA8ZGl2ICpuZ0lmPVwiJ3dhaXQnID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1zZWNvbmRhcnlcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1zcGluIGZhLXNwaW5uZXIgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgUGxlYXNlIHdhaXQuLi5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cIidtZXRob2RFcnJvcicgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFdlIGNvdWxkIG5vdCBzaWduIHlvdSBpbiB3aXRoIHt7bWV0aG9kRXJyb3IuY3JlZGVudGlhbC5wcm92aWRlcklkfX0uXG4gIDwvZGl2PlxuXG4gIDxwIGNsYXNzPVwidGV4dC1tdXRlZFwiPlxuICAgIFBsZWFzZSBzaWduIGluIHdpdGggb25lIG9mIHRoZSBtZXRob2RzIGFzc29jaWF0ZWQgd2l0aFxuICAgIHt7bWV0aG9kRXJyb3IuZW1haWx9fTpcbiAgPC9wPlxuXG4gIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwXCI+XG4gICAgPGFcbiAgICAgICpuZ0lmPVwibWV0aG9kRXJyb3IuYWNjb3VudEhhc1Bhc3N3b3JkXCJcbiAgICAgIHJvdXRlckxpbms9XCIuXCJcbiAgICAgIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluUGFzc3dvcmQnfVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS11bmxvY2tcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5TaWduIEluIHdpdGggWW91ciBQYXNzd29yZDwvc3Bhbj5cbiAgICA8L2E+XG4gICAgPGJ1dHRvblxuICAgICAgKm5nRm9yPVwibGV0IGlkIG9mIG1ldGhvZEVycm9yLmFjY291bnRPQXV0aE1ldGhvZHNcIlxuICAgICAgKGNsaWNrKT1cIm9BdXRoU2lnbkluKGlkKVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihpZClcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICA8c3BhbiBjbGFzcz1cIm1sLTJcIj5TaWduIEluIHdpdGgge3tnZXRPQXV0aFByb3ZpZGVyTmFtZShpZCl9fTwvc3Bhbj5cbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG5cbiAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmZ1wiPlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVja1wiPlxuICAgICAgICA8aW5wdXRcbiAgICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxuICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgW3ZhbHVlXT1cInRydWVcIlxuICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJlbWVtYmVyXCJcbiAgICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAncmVtZW1iZXInXCI+XG4gICAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWxcIiBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICAgIFJlbWVtYmVyIG1lIG9uIHRoaXMgZGV2aWNlLlxuICAgICAgICA8L2xhYmVsPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZm9ybT5cblxuICA8cCBjbGFzcz1cInRleHQtbXV0ZWRcIj5cbiAgICBJcyB7e21ldGhvZEVycm9yLmVtYWlsfX0gbm90IHlvdXIgZW1haWwgYWRkcmVzcz9cbiAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TdGFydCBPdmVyPC9hPlxuICA8L3A+XG5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiJ3JldHJ5JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtZGFuZ2VyXCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgSXQgbG9va3MgbGlrZSB5b3UgY2FuY2VsbGVkIHNpZ25pbmcgaW4gd2l0aFxuICAgIHt7Z2V0T0F1dGhQcm92aWRlck5hbWUocHJvdmlkZXJJZCl9fS4gVHJ5IGFnYWluOlxuICA8L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwibGlzdC1ncm91cFwiPlxuICAgIDxidXR0b25cbiAgICAgIChjbGljayk9XCJvQXV0aFNpZ25Jbihwcm92aWRlcklkKVwiXG4gICAgICBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBsaXN0LWdyb3VwLWl0ZW0tYWN0aW9uXCI+XG4gICAgICA8aSBbYXR0ci5jbGFzc109XCJnZXRPQXV0aFByb3ZpZGVySWNvbihwcm92aWRlcklkKVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIDxzcGFuIGNsYXNzPVwibWwtMlwiPlNpZ24gSW4gd2l0aCB7e2dldE9BdXRoUHJvdmlkZXJOYW1lKHByb3ZpZGVySWQpfX08L3NwYW4+XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuXG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Zvcm0+XG5cblxuICA8cCBjbGFzcz1cInRleHQtbXV0ZWRcIj5cbiAgICA8YSByb3V0ZXJMaW5rPVwiLlwiIFtxdWVyeVBhcmFtc109XCJ7YWN0aW9uOiAnc2lnbkluJ31cIj5TdGFydCBPdmVyPC9hPlxuICA8L3A+XG5cbjwvZGl2PlxuYCxcbiAgc3R5bGVzOiBbYGBdLFxuICBhbmltYXRpb25zOiBbIHNjcmVlbkFuaW1hdGlvbiBdXG59KVxuZXhwb3J0IGNsYXNzIFNpZ25Jbk9hdXRoQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBwcm92aWRlcklkOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGluaXRpYWxFcnJvcjogYXV0aC5FcnJvcjtcbiAgQElucHV0KCkgdXNlT0F1dGhQb3B1cDogYm9vbGVhbjtcbiAgQElucHV0KCkgb0F1dGhQcm92aWRlckZhY3Rvcnk6IChwcm92aWRlcklkOiBzdHJpbmcpID0+IGF1dGguQXV0aFByb3ZpZGVyO1xuICBASW5wdXQoKSBlbWFpbDogc3RyaW5nO1xuICBASW5wdXQoKSByZW1lbWJlcjogYm9vbGVhbjtcbiAgQE91dHB1dCgpIHN1Y2Nlc3M6IEV2ZW50RW1pdHRlcjxhdXRoLlVzZXJDcmVkZW50aWFsPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVtYWlsQ2hhbmdlOiBFdmVudEVtaXR0ZXI8c3RyaW5nPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHJlbWVtYmVyQ2hhbmdlOiBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlcnJvcjogRXZlbnRFbWl0dGVyPGF1dGguRXJyb3I+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG5cbiAgc2NyZWVuOiAnd2FpdCcgfCAnbWV0aG9kRXJyb3InIHwgJ3JldHJ5JyA9ICd3YWl0JztcbiAgbWV0aG9kRXJyb3I6IGF1dGguRXJyb3J8YW55ID0gbnVsbDtcbiAgZ2V0T0F1dGhQcm92aWRlckljb24gPSBnZXRPQXV0aFByb3ZpZGVySWNvbjtcbiAgZ2V0T0F1dGhQcm92aWRlck5hbWUgPSBnZXRPQXV0aFByb3ZpZGVyTmFtZTtcbiAgZmc6IEZvcm1Hcm91cDtcbiAgcmVtZW1iZXJGYzogRm9ybUNvbnRyb2w7XG4gIGZvcm1JZCA9ICduZ3gtZmlyZWJhc2UtYXV0aC1zaWduLWluLW9hdXRoLSc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBfYWZBdXRoOiBBbmd1bGFyRmlyZUF1dGgsXG4gICAgcHJpdmF0ZSBfc3ZjOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIF9yb3V0ZXI6IFJvdXRlclxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG5cbiAgZ2V0IGF1dGhTZXJ2aWNlKCk6IE5neEZpcmViYXNlQXV0aFNlcnZpY2Uge1xuICAgIHJldHVybiB0aGlzLl9zdmM7XG4gIH1cblxuICBnZXQgcm91dGUoKTogQWN0aXZhdGVkUm91dGUge1xuICAgIHJldHVybiB0aGlzLl9yb3V0ZTtcbiAgfVxuXG4gIGdldCByb3V0ZXIoKTogUm91dGVyIHtcbiAgICByZXR1cm4gdGhpcy5fcm91dGVyO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5yZW1lbWJlckZjID0gbmV3IEZvcm1Db250cm9sKHRoaXMucmVtZW1iZXIpO1xuICAgIHRoaXMucmVtZW1iZXJGYy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHZhbCA9PiB0aGlzLnJlbWVtYmVyQ2hhbmdlLmVtaXQodmFsKSk7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgcmVtZW1iZXI6IHRoaXMucmVtZW1iZXJGY1xuICAgIH0pO1xuICAgIGlmICh0aGlzLmluaXRpYWxFcnJvcikge1xuICAgICAgdGhpcy5oYW5kbGVPQXV0aEVycm9yKHRoaXMuaW5pdGlhbEVycm9yKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vQXV0aFNpZ25Jbih0aGlzLnByb3ZpZGVySWQpO1xuICAgIH1cbiAgfVxuXG5cbiAgb0F1dGhTaWduSW4oaWQ6IHN0cmluZywgZm9yY2VSZWRpcmVjdD86IGJvb2xlYW4pIHtcbiAgICB0aGlzLm1ldGhvZEVycm9yID0gbnVsbDtcbiAgICBsZXQgY3JlZDogYXV0aC5Vc2VyQ3JlZGVudGlhbDtcbiAgICBpZiAodGhpcy51c2VPQXV0aFBvcHVwICAmJiBmb3JjZVJlZGlyZWN0ICE9PSB0cnVlKSB7XG4gICAgICB0aGlzLmdldE9BdXRoUHJvdmlkZXIoaWQpXG4gICAgICAgIC50aGVuKHByb3ZpZGVyID0+IHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5hdXRoLnNpZ25JbldpdGhQb3B1cChwcm92aWRlcik7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKChyZXN1bHQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgICBjcmVkID0gcmVzdWx0O1xuICAgICAgICAgIHJldHVybiB0aGlzLmF1dGhTZXJ2aWNlLnNldFJlbWVtYmVyZWQodGhpcy5yZW1lbWJlckZjLnZhbHVlID09PSB0cnVlLCByZXN1bHQudXNlci5lbWFpbCk7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdChjcmVkKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGVycm9yID0+IHRoaXMuaGFuZGxlT0F1dGhFcnJvcihlcnJvciwgaWQpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycuJ10sIHtyZWxhdGl2ZVRvOiB0aGlzLnJvdXRlLCBxdWVyeVBhcmFtczoge3JlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmMudmFsdWUgPT09IHRydWV9fSlcbiAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgIHJldHVybiB0aGlzLmdldE9BdXRoUHJvdmlkZXIoaWQpO1xuICAgICAgICB9KVxuICAgICAgICAudGhlbihwcm92aWRlciA9PiB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5zaWduSW5XaXRoUmVkaXJlY3QocHJvdmlkZXIpO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyb3IgPT4gdGhpcy5oYW5kbGVPQXV0aEVycm9yKGVycm9yLCBpZCkpO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZU9BdXRoRXJyb3IoZXJyb3I6IGF1dGguRXJyb3IsIHByb3ZpZGVySWQ/OiBzdHJpbmcpIHtcbiAgICBpZiAoZXJyb3JbJ2VtYWlsJ10gJiYgZXJyb3JbJ2NyZWRlbnRpYWwnXSkge1xuICAgICAgdGhpcy5lbWFpbENoYW5nZS5lbWl0KGVycm9yWydlbWFpbCddKTtcbiAgICAgIHRoaXMuYXV0aC5mZXRjaFNpZ25Jbk1ldGhvZHNGb3JFbWFpbChlcnJvclsnZW1haWwnXSlcbiAgICAgICAgLnRoZW4ocmVzdWx0cyA9PiB7XG4gICAgICAgICAgZXJyb3JbJ21ldGhvZHMnXSA9IHJlc3VsdHM7XG4gICAgICAgICAgZXJyb3JbJ2FjY291bnRIYXNQYXNzd29yZCddID0gcmVzdWx0cy5pbmRleE9mKCdwYXNzd29yZCcpICE9PSAtMTtcbiAgICAgICAgICBlcnJvclsnYWNjb3VudE9BdXRoTWV0aG9kcyddID0gcmVzdWx0cy5maWx0ZXIoaWQgPT4gaWQgIT09ICdwYXNzd29yZCcpO1xuICAgICAgICAgIHRoaXMubWV0aG9kRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgICB0aGlzLnNjcmVlbiA9ICdtZXRob2RFcnJvcic7XG4gICAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBzd2l0Y2ggKGVycm9yLmNvZGUpIHtcbiAgICAgIGNhc2UgJ2F1dGgvY2FuY2VsbGVkLXBvcHVwLXJlcXVlc3QnOlxuICAgICAgY2FzZSAnYXV0aC9wb3B1cC1jbG9zZWQtYnktdXNlcic6XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3JldHJ5JztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdhdXRoL3BvcHVwLWJsb2NrZWQnOlxuICAgICAgICB0aGlzLm9BdXRoU2lnbkluKHByb3ZpZGVySWQsIHRydWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRoaXMuZXJyb3IuZW1pdChlcnJvcik7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGdldE9BdXRoUHJvdmlkZXIoaWQ6IHN0cmluZyk6IFByb21pc2U8YXV0aC5BdXRoUHJvdmlkZXI+IHtcbiAgICBsZXQgcHJvdmlkZXI6IGF1dGguQXV0aFByb3ZpZGVyID0gbnVsbDtcbiAgICBpZiAodGhpcy5vQXV0aFByb3ZpZGVyRmFjdG9yeSkge1xuICAgICAgcHJvdmlkZXIgPSB0aGlzLm9BdXRoUHJvdmlkZXJGYWN0b3J5KGlkKTtcbiAgICB9XG4gICAgaWYgKCEgcHJvdmlkZXIpIHtcbiAgICAgIHN3aXRjaCAoaWQpIHtcbiAgICAgICAgY2FzZSAndHdpdHRlci5jb20nOlxuICAgICAgICAgIHByb3ZpZGVyID0gbmV3IGF1dGguVHdpdHRlckF1dGhQcm92aWRlcigpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdmYWNlYm9vay5jb20nOlxuICAgICAgICAgIHByb3ZpZGVyID0gbmV3IGF1dGguRmFjZWJvb2tBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZ29vZ2xlLmNvbSc6XG4gICAgICAgICAgcHJvdmlkZXIgPSBuZXcgYXV0aC5Hb29nbGVBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZ2l0aHViLmNvbSc6XG4gICAgICAgICAgcHJvdmlkZXIgPSBuZXcgYXV0aC5HaXRodWJBdXRoUHJvdmlkZXIoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHByb3ZpZGVyKSB7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHByb3ZpZGVyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KHtcbiAgICAgICAgY29kZTogJ25neC1maXJlYmFzZS1hdXRoL25vLXByb3ZpZGVyLWZvdW5kJyxcbiAgICAgICAgbWVzc2FnZTogYFdlIGNvdWxkIG5vdCBjcmVhdGUgYW4gT0F1dGggcHJvdmlkZXIgZm9yIHByb3ZpZGVyIGlkIFwiJHtpZH1cIi5gXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxufVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIH0gZnJvbSAnLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcblxuXG5cblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZVxuICBdLFxuICBwcm92aWRlcnM6IFtcbiAgICBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoTW9kdWxlIHsgfVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBSb3V0ZXJNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IFNpZ25JbkNvbXBvbmVudCB9IGZyb20gJy4vc2lnbi1pbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2lnbkluTWV0aG9kc0Zvcm1Db21wb25lbnQgfSBmcm9tICcuL3NpZ24taW4tbWV0aG9kcy1mb3JtL3NpZ24taW4tbWV0aG9kcy1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTaWduSW5Gb3JtQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLWluLWZvcm0vc2lnbi1pbi1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTaWduVXBGb3JtQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLXVwLWZvcm0vc2lnbi11cC1mb3JtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBSZXNldFBhc3N3b3JkU2VuZEZvcm1Db21wb25lbnQgfSBmcm9tICcuL3Jlc2V0LXBhc3N3b3JkLXNlbmQtZm9ybS9yZXNldC1wYXNzd29yZC1zZW5kLWZvcm0uY29tcG9uZW50JztcbmltcG9ydCB7IFNpZ25Jbk9hdXRoQ29tcG9uZW50IH0gZnJvbSAnLi9zaWduLWluLW9hdXRoL3NpZ24taW4tb2F1dGguY29tcG9uZW50JztcblxuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoTW9kdWxlIH0gZnJvbSAnLi4vbmd4LWZpcmViYXNlLWF1dGgubW9kdWxlJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIFJvdXRlck1vZHVsZSxcbiAgICBOZ3hGaXJlYmFzZUF1dGhNb2R1bGVcbiAgXSxcbiAgZGVjbGFyYXRpb25zOiBbXG4gICAgU2lnbkluQ29tcG9uZW50LFxuICAgIFNpZ25Jbk1ldGhvZHNGb3JtQ29tcG9uZW50LFxuICAgIFNpZ25JbkZvcm1Db21wb25lbnQsXG4gICAgU2lnblVwRm9ybUNvbXBvbmVudCxcbiAgICBSZXNldFBhc3N3b3JkU2VuZEZvcm1Db21wb25lbnQsXG4gICAgU2lnbkluT2F1dGhDb21wb25lbnQsXG4gIF0sXG4gIGV4cG9ydHM6IFtcbiAgICBTaWduSW5Db21wb25lbnQsXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTmd4RmlyZWJhc2VBdXRoU2lnbkluTW9kdWxlIHsgfVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgTmd4RmlyZWJhc2VBdXRoRm9ybUhlbHBlciB9IGZyb20gJy4uLy4uL2Zvcm0taGVscGVyJztcbmltcG9ydCB7IE5neEZpcmViYXNlQXV0aFNlcnZpY2UgfSBmcm9tICcuLi8uLi9uZ3gtZmlyZWJhc2UtYXV0aC5zZXJ2aWNlJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZCcsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc3VjY2VzcycgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBXZWxjb21lLCB7e2NyZWQudXNlci5kaXNwbGF5TmFtZX19IVxuICAgIFlvdXIgbmV3IHBhc3N3b3JkIGhhcyBiZWVuIHNhdmVkIGFuZCB5b3UgYXJlIHNpZ25lZCBpbi5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cInNjcmVlbiA9PT0gJ2Vycm9yJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxwPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXb29wcyEgQW4gZXJyb3Igb2NjdXJyZWQuXG4gICAgPC9wPlxuICAgIDxkaXYgW25nU3dpdGNoXT1cInVuaGFuZGxlZEVycm9yLmNvZGVcIj5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9leHBpcmVkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBoYXMgZXhwaXJlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9pbnZhbGlkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBpcyBub3QgdmFsaWQuIFRoaXMgbWF5IGJlIGJlY2F1c2UgaXRcbiAgICAgICAgaGFzIGFscmVhZHkgYmVlbiB1c2VkLlxuICAgICAgPC9wPlxuICAgICAgPHAgY2xhc3M9XCJtYi0wXCIgKm5nU3dpdGNoQ2FzZT1cIidhdXRoL3VzZXItZGlzYWJsZWQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVzZXQgcGFzc3dvcmQgbGluayB5b3UgdXNlZCBoYXMgYmVlbiBkaXNhYmxlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC91c2VyLW5vdC1mb3VuZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSByZXNldCBwYXNzd29yZCBsaW5rIHlvdSB1c2VkIGhhcyBiZWVuIHJlbW92ZWQuXG4gICAgICA8L3A+XG4gICAgICA8ZGl2ICpuZ1N3aXRjaERlZmF1bHQ+XG4gICAgICAgIDxwPkNvZGU6IHt7dW5oYW5kbGVkRXJyb3IuY29kZX19PC9wPlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj5cbiAgICAgICAgICBNZXNzYWdlOiB7e3VuaGFuZGxlZEVycm9yLm1lc3NhZ2V9fVxuICAgICAgICA8L3A+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cblxuXG48ZGl2ICpuZ0lmPVwiJ2Zvcm0nID09PSBzY3JlZW5cIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIiAobmdTdWJtaXQpPVwic3VibWl0KClcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGxhYmVsIFthdHRyLmZvcl09XCJmb3JtSWQgKyAnZW1haWwnXCI+RW1haWwgQWRkcmVzczwvbGFiZWw+XG5cbiAgICAgIDxpbnB1dFxuICAgICAgICByZWFkb25seVxuICAgICAgICAjZW1haWxJbnB1dFxuICAgICAgICBbYXR0ci5pZF09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgICAgW2F0dHIuYXJpYS1kZXNjcmliZWRieV09XCJmb3JtSWQgKyAnZW1haWwnXCJcbiAgICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgICAgYXV0b2NvbXBsZXRlPVwiZW1haWxcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIkVtYWlsIEFkZHJlc3NcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiXG4gICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCI+XG4gICAgICA8c21hbGwgY2xhc3M9XCJ0ZXh0LW11dGVkIGZvcm0tdGV4dFwiIFthdHRyLmlkXT1cImZvcm1JZCArICdlbWFpbCdcIiA+XG4gICAgICAgIFlvdSBhcmUgcmVzZXR0aW5nIHRoZSBwYXNzd29yZCBmb3Ige3tlbWFpbEZjLnZhbHVlfX0uXG4gICAgICA8L3NtYWxsPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtZW5kXCI+XG4gICAgICAgIDxsYWJlbCBbYXR0ci5mb3JdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiPlBhc3N3b3JkPC9sYWJlbD5cbiAgICAgICAgPHNtYWxsPlxuICAgICAgICAgIDxhIChjbGljayk9XCIkZXZlbnQucHJldmVudERlZmF1bHQoKTsgcGFzc3dvcmRJbnB1dC50eXBlID0gJ3Bhc3N3b3JkJyA9PT0gcGFzc3dvcmRJbnB1dC50eXBlICA/ICd0ZXh0JyA6ICdwYXNzd29yZCdcIlxuICAgICAgICAgICAgaHJlZj1cIiNcIiB0YWJpbmRleD1cIi0xXCIgY2xhc3M9XCJkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIncGFzc3dvcmQnID09PSBwYXNzd29yZElucHV0LnR5cGVcIj5TaG93PC9zcGFuPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIndGV4dCcgPT09IHBhc3N3b3JkSW5wdXQudHlwZVwiPkhpZGU8L3NwYW4+XG4gICAgICAgICAgPC9hPlxuICAgICAgICA8L3NtYWxsPlxuICAgICAgPC9kaXY+XG4gICAgICA8aW5wdXRcbiAgICAgICAgI3Bhc3N3b3JkSW5wdXRcbiAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkJ1wiXG4gICAgICAgIFthdHRyLmFyaWEtZGVzY3JpYmVkYnldPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCJcbiAgICAgICAgdHlwZT1cInBhc3N3b3JkXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicGFzc3dvcmRcIlxuICAgICAgICBwbGFjZWhvbGRlcj1cIlBhc3N3b3JkXCJcbiAgICAgICAgYXV0b2NvbXBsZXRlPVwicGFzc3dvcmRcIlxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgIFtjbGFzcy5pcy1pbnZhbGlkXT1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmludmFsaWRcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrXCIgKm5nSWY9XCJwYXNzd29yZEZjLnRvdWNoZWQgJiYgcGFzc3dvcmRGYy5oYXNFcnJvcigncmVxdWlyZWQnKVwiPlxuICAgICAgICBSZXF1aXJlZC5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2tcIiAqbmdJZj1cInBhc3N3b3JkRmMudG91Y2hlZCAmJiBwYXNzd29yZEZjLmhhc0Vycm9yKCdhdXRoL3dlYWstcGFzc3dvcmQnKVwiPlxuICAgICAgICBUaGF0IHBhc3N3b3JkIGlzIHRvbyB3ZWFrLlxuICAgICAgPC9kaXY+XG4gICAgICA8c21hbGwgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3Bhc3N3b3JkLWhlbHAnXCIgY2xhc3M9XCJmb3JtLXRleHQgdGV4dC1tdXRlZFwiPlxuICAgICAgICBQbGVhc2UgY2hvb3NlIGEgc3Ryb25nIHBhc3N3b3JkLlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2tcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCJcbiAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgIFt2YWx1ZV09XCJ0cnVlXCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZW1lbWJlclwiXG4gICAgICAgICAgW2F0dHIuaWRdPVwiZm9ybUlkICsgJ3JlbWVtYmVyJ1wiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsXCIgW2F0dHIuZm9yXT1cImZvcm1JZCArICdyZW1lbWJlcidcIj5cbiAgICAgICAgICBSZW1lbWJlciBtZSBvbiB0aGlzIGRldmljZS5cbiAgICAgICAgPC9sYWJlbD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICA8YnV0dG9uIHR5cGU9XCJzdWJtaXRcIlxuICAgICAgICBjbGFzcz1cImJ0biBidG4tc3VjY2VzcyBidG4tYmxvY2tcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiZmcuaW52YWxpZCB8fCBzdWJtaXR0aW5nXCI+XG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXNhdmUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICAgIFNhdmUgUGFzc3dvcmQgYW5kIFNpZ24gSW5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Zvcm0+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iUmVzZXRQYXNzd29yZENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgQElucHV0KCkgb29iQ29kZTogc3RyaW5nO1xuICBAT3V0cHV0KCkgc3VjY2VzczogRXZlbnRFbWl0dGVyPElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBzY3JlZW46ICd3YWl0JyB8ICdmb3JtJyB8ICdlcnJvcicgfCAnc3VjY2VzcycgPSAnd2FpdCc7XG4gIGluZm86IGF1dGguQWN0aW9uQ29kZUluZm87XG4gIHN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgZm9ybUlkID0gJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZXNldC1wYXNzd29yZC0nO1xuICBmZzogRm9ybUdyb3VwO1xuICBlbWFpbEZjOiBGb3JtQ29udHJvbDtcbiAgcGFzc3dvcmRGYzogRm9ybUNvbnRyb2w7XG4gIHJlbWVtYmVyRmM6IEZvcm1Db250cm9sO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvciA9IG51bGw7XG4gIGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwgPSBudWxsO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICAgIHByaXZhdGUgX2F1dGhTZXJ2aWNlOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlLFxuICApIHsgfVxuXG4gIGdldCBhdXRoKCk6IGF1dGguQXV0aCB7XG4gICAgcmV0dXJuIHRoaXMuX2FmQXV0aC5hdXRoO1xuICB9XG4gIGdldCBhdXRoU2VydmljZSgpOiBOZ3hGaXJlYmFzZUF1dGhTZXJ2aWNlIHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFNlcnZpY2U7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICBjb25zdCByZW1lbWJlcmVkID0gdGhpcy5hdXRoU2VydmljZS5nZXRSZW1lbWJlcmVkKCk7XG4gICAgdGhpcy5lbWFpbEZjID0gbmV3IEZvcm1Db250cm9sKCcnKTtcbiAgICB0aGlzLnBhc3N3b3JkRmMgPSBuZXcgRm9ybUNvbnRyb2woJycsIHt2YWxpZGF0b3JzOiBbVmFsaWRhdG9ycy5yZXF1aXJlZF19KTtcbiAgICB0aGlzLnJlbWVtYmVyRmMgPSBuZXcgRm9ybUNvbnRyb2wocmVtZW1iZXJlZC5yZW1lbWJlcik7XG4gICAgdGhpcy5mZyA9IG5ldyBGb3JtR3JvdXAoe2VtYWlsOiB0aGlzLmVtYWlsRmMsIHBhc3N3b3JkOiB0aGlzLnBhc3N3b3JkRmMsIHJlbWVtYmVyOiB0aGlzLnJlbWVtYmVyRmN9KTtcbiAgICB0aGlzLmF1dGguY2hlY2tBY3Rpb25Db2RlKHRoaXMub29iQ29kZSlcbiAgICAgIC50aGVuKChyZXN1bHQ6IGF1dGguQWN0aW9uQ29kZUluZm8pID0+IHtcbiAgICAgICAgdGhpcy5pbmZvID0gcmVzdWx0O1xuICAgICAgICB0aGlzLmVtYWlsRmMuc2V0VmFsdWUocmVzdWx0LmRhdGEuZW1haWwpO1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdmb3JtJztcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yOiBhdXRoLkVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMudW5oYW5kbGVkRXJyb3IgPSBlcnJvcjtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZXJyb3InO1xuICAgICAgfSk7XG4gIH1cblxuICBzdWJtaXQoKSB7XG4gICAgdGhpcy5zdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICB0aGlzLmF1dGguY29uZmlybVBhc3N3b3JkUmVzZXQodGhpcy5vb2JDb2RlLCB0aGlzLnBhc3N3b3JkRmMudmFsdWUpXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmF1dGguc2lnbkluV2l0aEVtYWlsQW5kUGFzc3dvcmQodGhpcy5pbmZvLmRhdGEuZW1haWwsIHRoaXMucGFzc3dvcmRGYy52YWx1ZSk7XG4gICAgICB9KVxuICAgICAgLnRoZW4oKGNyZWQ6IGF1dGguVXNlckNyZWRlbnRpYWwpID0+IHtcbiAgICAgICAgdGhpcy5jcmVkID0gY3JlZDtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aFNlcnZpY2Uuc2V0UmVtZW1iZXJlZCh0aGlzLnJlbWVtYmVyRmMudmFsdWUgPT09IHRydWUsIHRoaXMuaW5mby5kYXRhLmVtYWlsKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3N1Y2Nlc3MnO1xuICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdCh7XG4gICAgICAgICAgbW9kZTogJ3Jlc2V0UGFzc3dvcmQnLFxuICAgICAgICAgIGluZm86IHRoaXMuaW5mbyxcbiAgICAgICAgICBjcmVkOiB0aGlzLmNyZWQsXG4gICAgICAgICAgdXNlcjogdGhpcy5jcmVkLnVzZXJcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5wYXNzd29yZEZjLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgIHRoaXMucGFzc3dvcmRGYy5tYXJrQXNUb3VjaGVkKCk7XG4gICAgICAgIHN3aXRjaCAoZXJyb3IuY29kZSkge1xuICAgICAgICAgIGNhc2UgJ2F1dGgvd2Vhay1wYXNzd29yZCc6XG4gICAgICAgICAgICBOZ3hGaXJlYmFzZUF1dGhGb3JtSGVscGVyLnNldEVycm9yVW50aWxDaGFuZ2VkKHRoaXMucGFzc3dvcmRGYywgZXJyb3IuY29kZSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgICAgICAgICAgdGhpcy5zY3JlZW4gPSAnZXJyb3InO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbn1cbiIsImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdhbmd1bGFyZmlyZTIvYXV0aCc7XG5pbXBvcnQgeyBhdXRoLCBVc2VyIH0gZnJvbSAnZmlyZWJhc2UvYXBwJztcbmltcG9ydCB7IElOZ3hGaXJlYmFzZUF1dGhPb2JTdWNjZXNzIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcbmltcG9ydCB7IHNjcmVlbkFuaW1hdGlvbiB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1maXJlYmFzZS1hdXRoLW9vYi1yZWNvdmVyLWVtYWlsJyxcbiAgdGVtcGxhdGU6IGBcblxuPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cblxuPGRpdiAqbmdJZj1cIidzdWNjZXNzJyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc3VjY2Vzc1wiPlxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFlvdXIgZW1haWwgaGFzIGJlZW4gY2hhbmdlZCBiYWNrIHRvIHt7aW5mby5kYXRhLmVtYWlsfX07XG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdmb3JtJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8cD5cbiAgICAgIEFyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byBjaGFuZ2UgeW91ciBlbWFpbCBiYWNrIHRvXG4gICAgICB7e2luZm8uZGF0YS5lbWFpbH19IGZyb20ge3tpbmZvLmRhdGEuZnJvbUVtYWlsfX0/XG4gICAgPC9wPlxuICAgIDxidXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgW2Rpc2FibGVkXT1cInN1Ym1pdHRpbmdcIlxuICAgICAgKGNsaWNrKT1cInN1Ym1pdCgpXCJcbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1ibG9jayBidG4tc3VjY2Vzc1wiPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtc2F2ZSBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICAgIFllcywgQ29udGludWVcbiAgICA8L2J1dHRvbj5cbiAgPC9kaXY+XG48L2Rpdj5cblxuXG5cbjxkaXYgKm5nSWY9XCJzY3JlZW4gPT09ICdlcnJvcidcIiBbQHNjcmVlbl09XCInaW4nXCI+XG4gIDxkaXYgY2xhc3M9XCJhbGVydCBhbGVydC1kYW5nZXJcIj5cbiAgICA8cD5cbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWV4Y2xhbWF0aW9uLXRyaWFuZ2xlIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgICAgV29vcHMhIEFuIGVycm9yIG9jY3VycmVkLlxuICAgIDwvcD5cbiAgICA8ZGl2IFtuZ1N3aXRjaF09XCJ1bmhhbmRsZWRFcnJvci5jb2RlXCI+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvZXhwaXJlZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHJlY292ZXIgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgZXhwaXJlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9pbnZhbGlkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgcmVjb3ZlciBlbWFpbCBsaW5rIHlvdSB1c2VkIGlzIG5vdCB2YWxpZC4gVGhpcyBtYXkgYmUgYmVjYXVzZSBpdFxuICAgICAgICBoYXMgYWxyZWFkeSBiZWVuIHVzZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1kaXNhYmxlZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSByZWNvdmVyIGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGJlZW4gZGlzYWJsZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1ub3QtZm91bmQnXCI+XG4gICAgICAgIFRoZSBhY2NvdW50IGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVjb3ZlciBlbWFpbCBsaW5rIHlvdSB1c2VkIGhhcyBiZWVuIHJlbW92ZWQuXG4gICAgICA8L3A+XG4gICAgICA8ZGl2ICpuZ1N3aXRjaERlZmF1bHQ+XG4gICAgICAgIDxwPkNvZGU6IHt7dW5oYW5kbGVkRXJyb3IuY29kZX19PC9wPlxuICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIj5cbiAgICAgICAgICBNZXNzYWdlOiB7e3VuaGFuZGxlZEVycm9yLm1lc3NhZ2V9fVxuICAgICAgICA8L3A+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbmAsXG4gIHN0eWxlczogW2BgXSxcbiAgYW5pbWF0aW9uczogW3NjcmVlbkFuaW1hdGlvbl1cbn0pXG5leHBvcnQgY2xhc3MgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBvb2JDb2RlOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8SU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3M+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHNjcmVlbjogJ3dhaXQnIHwgJ2Zvcm0nIHwgJ2Vycm9yJyB8ICdzdWNjZXNzJyA9ICd3YWl0JztcbiAgaW5mbzogYXV0aC5BY3Rpb25Db2RlSW5mbztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuXG4gICAgdGhpcy5hdXRoLmNoZWNrQWN0aW9uQ29kZSh0aGlzLm9vYkNvZGUpXG4gICAgICAudGhlbigocmVzdWx0OiBhdXRoLkFjdGlvbkNvZGVJbmZvKSA9PiB7XG4gICAgICAgIHRoaXMuaW5mbyA9IHJlc3VsdDtcbiAgICAgICAgdGhpcy5zY3JlZW4gPSAnZm9ybSc7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnVuaGFuZGxlZEVycm9yID0gZXJyb3I7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgIH0pO1xuICB9XG5cbiAgc3VibWl0KCkge1xuICAgIHRoaXMuYXV0aC5hcHBseUFjdGlvbkNvZGUodGhpcy5vb2JDb2RlKVxuICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdzdWNjZXNzJztcbiAgICAgICAgdGhpcy5zdWNjZXNzLmVtaXQoe1xuICAgICAgICAgIG1vZGU6ICdyZWNvdmVyRW1haWwnLFxuICAgICAgICAgIGluZm86IHRoaXMuaW5mbyxcbiAgICAgICAgICB1c2VyOiB0aGlzLmF1dGguY3VycmVudFVzZXJcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcjogYXV0aC5FcnJvcikgPT4ge1xuICAgICAgICB0aGlzLnVuaGFuZGxlZEVycm9yID0gZXJyb3I7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ2Vycm9yJztcbiAgICAgIH0pO1xuICB9XG5cblxufVxuIiwiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQ29udHJvbCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlQXV0aCB9IGZyb20gJ2FuZ3VsYXJmaXJlMi9hdXRoJztcbmltcG9ydCB7IGF1dGgsIFVzZXIgfSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3MgfSBmcm9tICcuLi8uLi9zaGFyZWQnO1xuaW1wb3J0IHsgc2NyZWVuQW5pbWF0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWZpcmViYXNlLWF1dGgtb29iLXZlcmlmeS1lbWFpbCcsXG4gIHRlbXBsYXRlOiBgPGRpdiAqbmdJZj1cIid3YWl0JyA9PT0gc2NyZWVuXCIgW0BzY3JlZW5dPVwiJ2luJ1wiPlxuICA8ZGl2IGNsYXNzPVwiYWxlcnQgYWxlcnQtc2Vjb25kYXJ5XCI+XG4gICAgPGkgY2xhc3M9XCJmYXMgZmEtc3BpbiBmYS1zcGlubmVyIGZhLWZ3XCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxuICAgIFBsZWFzZSB3YWl0Li4uXG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgKm5nSWY9XCInc3VjY2VzcycgPT09IHNjcmVlblwiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcIj5cbiAgICA8aSBjbGFzcz1cImZhcyBmYS1jaGVjayBmYS1md1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cbiAgICBUaGUgZW1haWwge3tpbmZvLmRhdGEuZW1haWx9fSBoYXMgYmVlbiB2ZXJpZmllZC5cbiAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiAqbmdJZj1cInNjcmVlbiA9PT0gJ2Vycm9yJ1wiIFtAc2NyZWVuXT1cIidpbidcIj5cbiAgPGRpdiBjbGFzcz1cImFsZXJ0IGFsZXJ0LWRhbmdlclwiPlxuICAgIDxwPlxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZXhjbGFtYXRpb24tdHJpYW5nbGUgZmEtZndcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgICBXb29wcyEgQW4gZXJyb3Igb2NjdXJyZWQuXG4gICAgPC9wPlxuICAgIDxkaXYgW25nU3dpdGNoXT1cInVuaGFuZGxlZEVycm9yLmNvZGVcIj5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC9leHBpcmVkLWFjdGlvbi1jb2RlJ1wiPlxuICAgICAgICBUaGUgdmVyaWZ5IGVtYWlsIGxpbmsgeW91IHVzZWQgaGFzIGV4cGlyZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvaW52YWxpZC1hY3Rpb24tY29kZSdcIj5cbiAgICAgICAgVGhlIHZlcmlmeSBlbWFpbCBsaW5rIHlvdSB1c2VkIGlzIG5vdCB2YWxpZC4gVGhpcyBtYXkgYmUgYmVjYXVzZSBpdFxuICAgICAgICBoYXMgYWxyZWFkeSBiZWVuIHVzZWQuXG4gICAgICA8L3A+XG4gICAgICA8cCBjbGFzcz1cIm1iLTBcIiAqbmdTd2l0Y2hDYXNlPVwiJ2F1dGgvdXNlci1kaXNhYmxlZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSB2ZXJpZnkgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgYmVlbiBkaXNhYmxlZC5cbiAgICAgIDwvcD5cbiAgICAgIDxwIGNsYXNzPVwibWItMFwiICpuZ1N3aXRjaENhc2U9XCInYXV0aC91c2VyLW5vdC1mb3VuZCdcIj5cbiAgICAgICAgVGhlIGFjY291bnQgYXNzb2NpYXRlZCB3aXRoIHRoZSB2ZXJpZnkgZW1haWwgbGluayB5b3UgdXNlZCBoYXMgYmVlbiByZW1vdmVkLlxuICAgICAgPC9wPlxuICAgICAgPGRpdiAqbmdTd2l0Y2hEZWZhdWx0PlxuICAgICAgICA8cD5Db2RlOiB7e3VuaGFuZGxlZEVycm9yLmNvZGV9fTwvcD5cbiAgICAgICAgPHAgY2xhc3M9XCJtYi0wXCI+XG4gICAgICAgICAgTWVzc2FnZToge3t1bmhhbmRsZWRFcnJvci5tZXNzYWdlfX1cbiAgICAgICAgPC9wPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtgYF0sXG4gIGFuaW1hdGlvbnM6IFtzY3JlZW5BbmltYXRpb25dXG59KVxuZXhwb3J0IGNsYXNzIE9vYlZlcmlmeUVtYWlsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBvb2JDb2RlOiBzdHJpbmc7XG4gIEBPdXRwdXQoKSBzdWNjZXNzOiBFdmVudEVtaXR0ZXI8SU5neEZpcmViYXNlQXV0aE9vYlN1Y2Nlc3M+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHNjcmVlbjogJ3dhaXQnIHwgJ2Vycm9yJyB8ICdzdWNjZXNzJyA9ICd3YWl0JztcbiAgaW5mbzogYXV0aC5BY3Rpb25Db2RlSW5mbztcbiAgc3VibWl0dGluZyA9IGZhbHNlO1xuICB1bmhhbmRsZWRFcnJvcjogYXV0aC5FcnJvcjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIF9hZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgKSB7IH1cblxuICBnZXQgYXV0aCgpOiBhdXRoLkF1dGgge1xuICAgIHJldHVybiB0aGlzLl9hZkF1dGguYXV0aDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuXG4gICAgdGhpcy5hdXRoLmNoZWNrQWN0aW9uQ29kZSh0aGlzLm9vYkNvZGUpXG4gICAgICAudGhlbigocmVzdWx0OiBhdXRoLkFjdGlvbkNvZGVJbmZvKSA9PiB7XG4gICAgICAgIHRoaXMuaW5mbyA9IHJlc3VsdDtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0aC5hcHBseUFjdGlvbkNvZGUodGhpcy5vb2JDb2RlKTtcbiAgICAgIH0pXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIHRoaXMuc2NyZWVuID0gJ3N1Y2Nlc3MnO1xuICAgICAgICB0aGlzLnN1Y2Nlc3MuZW1pdCh7XG4gICAgICAgICAgbW9kZTogJ3ZlcmlmeUVtYWlsJyxcbiAgICAgICAgICBpbmZvOiB0aGlzLmluZm8sXG4gICAgICAgICAgdXNlcjogdGhpcy5hdXRoLmN1cnJlbnRVc2VyXG4gICAgICAgIH0pO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IGF1dGguRXJyb3IpID0+IHtcbiAgICAgICAgdGhpcy51bmhhbmRsZWRFcnJvciA9IGVycm9yO1xuICAgICAgICB0aGlzLnNjcmVlbiA9ICdlcnJvcic7XG4gICAgICB9KTtcbiAgfVxuXG59XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFJvdXRlck1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQgeyBPb2JDb21wb25lbnQgfSBmcm9tICcuL29vYi5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iUmVzZXRQYXNzd29yZENvbXBvbmVudCB9IGZyb20gJy4vb29iLXJlc2V0LXBhc3N3b3JkL29vYi1yZXNldC1wYXNzd29yZC5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50IH0gZnJvbSAnLi9vb2ItcmVjb3Zlci1lbWFpbC9vb2ItcmVjb3Zlci1lbWFpbC5jb21wb25lbnQnO1xuaW1wb3J0IHsgT29iVmVyaWZ5RW1haWxDb21wb25lbnQgfSBmcm9tICcuL29vYi12ZXJpZnktZW1haWwvb29iLXZlcmlmeS1lbWFpbC5jb21wb25lbnQnO1xuXG5pbXBvcnQgeyBOZ3hGaXJlYmFzZUF1dGhNb2R1bGUgfSBmcm9tICcuLi9uZ3gtZmlyZWJhc2UtYXV0aC5tb2R1bGUnO1xuXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgUm91dGVyTW9kdWxlLFxuICAgIE5neEZpcmViYXNlQXV0aE1vZHVsZVxuICBdLFxuICBkZWNsYXJhdGlvbnM6IFtcbiAgICBPb2JDb21wb25lbnQsXG4gICAgT29iUmVjb3ZlckVtYWlsQ29tcG9uZW50LFxuICAgIE9vYlJlc2V0UGFzc3dvcmRDb21wb25lbnQsXG4gICAgT29iVmVyaWZ5RW1haWxDb21wb25lbnRcbiAgXSxcbiAgZXhwb3J0czogW1xuICAgIE9vYkNvbXBvbmVudCxcbiAgXVxufSlcbmV4cG9ydCBjbGFzcyBOZ3hGaXJlYmFzZUF1dGhPb2JNb2R1bGUgeyB9XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQWlCQSxJQUFhLGtCQUFrQixHQUE2QixPQUFPLENBQUMsV0FBVyxFQUFFO0lBQy9FLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLEVBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFDLENBQUMsQ0FBQztJQUNsRCxVQUFVLENBQUMsV0FB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