UNPKG

ng-dynami-social-login

Version:

This is social login API for Angular 7.0.3 (Facebook, Google and Linkedin)

450 lines (434 loc) 42 kB
import { Injectable, NgModule } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @abstract */ class BaseLoginProvider { constructor() { } /** * @param {?} obj * @param {?} onload * @return {?} */ loadScript(obj, onload) { if (document.getElementById(obj.name)) { return; } /** @type {?} */ let signInJS = document.createElement('script'); signInJS.async = true; signInJS.src = obj.url; signInJS.onload = onload; if (obj.name === 'LINKEDIN') { signInJS.async = false; signInJS.text = ('api_key: ' + obj.id).replace('\'', ''); } document.head.appendChild(signInJS); } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class LinkedInResponseModel { } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class LoginProviderClassModel { } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class SocialUserModel { } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class FacebookLoginProvider extends BaseLoginProvider { /** * @param {?} clientId */ constructor(clientId) { super(); this.clientId = clientId; this.loginProviderObj = new LoginProviderClassModel(); this.loginProviderObj.id = clientId; this.loginProviderObj.name = 'facebook'; this.loginProviderObj.url = 'https://connect.facebook.net/en_US/sdk.js'; } /** * @return {?} */ initialize() { return new Promise((resolve, reject) => { this.loadScript(this.loginProviderObj, () => { FB.init({ appId: this.clientId, autoLogAppEvents: true, cookie: true, xfbml: true, version: 'v2.10' }); FB.AppEvents.logPageView(); FB.getLoginStatus(function (response) { if (response.status === 'connected') { /** @type {?} */ const accessToken = FB.getAuthResponse()['accessToken']; FB.api('/me?fields=name,email,picture', (res) => { resolve(FacebookLoginProvider.drawUser(Object.assign({}, { token: accessToken }, res))); }); } }); }); }); } /** * @param {?} response * @return {?} */ static drawUser(response) { /** @type {?} */ let user = new SocialUserModel(); user.id = response.id; user.name = response.name; user.email = response.email; user.token = response.token; user.image = 'https://graph.facebook.com/' + response.id + '/picture?type=normal'; return user; } /** * @return {?} */ signIn() { return new Promise((resolve, reject) => { FB.login((response) => { if (response.authResponse) { /** @type {?} */ const accessToken = FB.getAuthResponse()['accessToken']; FB.api('/me?fields=name,email,picture', (res) => { resolve(FacebookLoginProvider.drawUser(Object.assign({}, { token: accessToken }, res))); }); } }, { scope: 'email,public_profile' }); }); } /** * @return {?} */ signOut() { return new Promise((resolve, reject) => { FB.logout((response) => { resolve(); }); }); } } FacebookLoginProvider.PROVIDER_ID = 'facebook'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class GoogleLoginProvider extends BaseLoginProvider { /** * @param {?} clientId */ constructor(clientId) { super(); this.clientId = clientId; this.loginProviderObj = new LoginProviderClassModel(); this.loginProviderObj.id = clientId; this.loginProviderObj.name = 'google'; this.loginProviderObj.url = 'https://apis.google.com/js/platform.js'; } /** * @return {?} */ initialize() { return new Promise((resolve, reject) => { this.loadScript(this.loginProviderObj, () => { gapi.load('auth2', () => { this.auth2 = gapi.auth2.init({ client_id: this.clientId, scope: 'email' }); this.auth2.then(() => { if (this.auth2.isSignedIn.get()) { resolve(this.drawUser()); } }); }); }); }); } /** * @return {?} */ drawUser() { /** @type {?} */ let user = new SocialUserModel(); /** @type {?} */ let profile = this.auth2.currentUser.get().getBasicProfile(); /** @type {?} */ let authResponseObj = this.auth2.currentUser.get().getAuthResponse(true); user.id = profile.getId(); user.name = profile.getName(); user.email = profile.getEmail(); user.image = profile.getImageUrl(); user.token = authResponseObj.access_token; user.idToken = authResponseObj.id_token; return user; } /** * @return {?} */ signIn() { return new Promise((resolve, reject) => { /** @type {?} */ let promise = this.auth2.signIn(); promise.then(() => { resolve(this.drawUser()); }); }); } /** * @return {?} */ signOut() { return new Promise((resolve, reject) => { this.auth2.signOut().then((err) => { if (err) { reject(err); } else { resolve(); } }); }); } } GoogleLoginProvider.PROVIDER_ID = 'google'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class LinkedinLoginProvider extends BaseLoginProvider { /** * @param {?} clientId */ constructor(clientId) { super(); this.clientId = clientId; this.loginProviderObj = new LoginProviderClassModel(); this.loginProviderObj.id = clientId; this.loginProviderObj.name = 'linkedin'; this.loginProviderObj.url = 'https://platform.linkedin.com/in.js'; } /** * @return {?} */ initialize() { return new Promise((resolve, reject) => { this.loadScript(this.loginProviderObj, () => { IN.init({ api_key: this.clientId, authorize: true, onLoad: this.onLinkedInLoad() }); IN.Event.on(IN, 'auth', () => { if (IN.User.isAuthorized()) { IN.API.Raw('/people/~:(id,first-name,last-name,email-address,picture-url)').result((res) => { resolve(this.drawUser(res)); }); } }); }); }); } /** * @return {?} */ onLinkedInLoad() { IN.Event.on(IN, 'systemReady', () => { IN.User.refresh(); }); } /** * @param {?} response * @return {?} */ drawUser(response) { /** @type {?} */ let user = new SocialUserModel(); user.id = response.emailAddress; user.name = response.firstName + ' ' + response.lastName; user.email = response.emailAddress; user.image = response.pictureUrl; user.token = IN.ENV.auth.oauth_token; return user; } /** * @return {?} */ signIn() { return new Promise((resolve, reject) => { IN.User.authorize(() => { IN.API.Raw('/people/~:(id,first-name,last-name,email-address,picture-url)').result((res) => { resolve(this.drawUser(res)); }); }); }); } /** * @return {?} */ signOut() { return new Promise((resolve, reject) => { IN.User.logout((response) => { resolve(); }, (err) => { reject(err); }); }); } } LinkedinLoginProvider.PROVIDER_ID = 'linkedin'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class AuthServiceConfig { /** * @param {?} providers */ constructor(providers) { this.providers = new Map(); for (let i = 0; i < providers.length; i++) { /** @type {?} */ let element = providers[i]; this.providers.set(element.id, element.provider); } } } /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class AuthService { /** * @param {?} config */ constructor(config) { this._user = null; this._authState = new BehaviorSubject(null); this.providers = config.providers; this.providers.forEach((provider, key) => { provider.initialize().then((user) => { user.provider = key; this._user = user; this._authState.next(user); }).catch((err) => { // this._authState.next(null); }); }); } /** * @return {?} */ get authState() { return this._authState.asObservable(); } /** * @param {?} providerId * @return {?} */ signIn(providerId) { return new Promise((resolve, reject) => { /** @type {?} */ let providerObject = this.providers.get(providerId); if (providerObject) { providerObject.signIn().then((user) => { user.provider = providerId; resolve(user); this._user = user; this._authState.next(user); }); } else { reject(AuthService.LOGIN_PROVIDER_NOT_FOUND); } }); } /** * @return {?} */ signOut() { return new Promise((resolve, reject) => { if (this._user && this._user.provider) { /** @type {?} */ let providerId = this._user.provider; /** @type {?} */ let providerObject = this.providers.get(providerId); providerObject.signOut().then(() => { this._user = null; this._authState.next(null); resolve(); }).catch((err) => { this._authState.next(null); }); } else { reject(AuthService.LOGIN_PROVIDER_NOT_FOUND); } }); } } AuthService.LOGIN_PROVIDER_NOT_FOUND = 'Login provider not found'; AuthService.decorators = [ { type: Injectable } ]; /** @nocollapse */ AuthService.ctorParameters = () => [ { type: AuthServiceConfig } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ class DynamiSocialLoginModule { } DynamiSocialLoginModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule ], declarations: [], providers: [AuthService], },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingReturn,uselessCode} checked by tsc */ export { BaseLoginProvider, LinkedInResponseModel, LoginProviderClassModel, SocialUserModel, FacebookLoginProvider, GoogleLoginProvider, LinkedinLoginProvider, AuthServiceConfig, AuthService, DynamiSocialLoginModule }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctZHluYW1pLXNvY2lhbC1sb2dpbi5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vbmctZHluYW1pLXNvY2lhbC1sb2dpbi9saWIvZHluYW1pLXNvY2lhbC1sb2dpbi9tb2RlbHMvYmFzZS5sb2dpbi5wcm92aWRlci50cyIsIm5nOi8vbmctZHluYW1pLXNvY2lhbC1sb2dpbi9saWIvZHluYW1pLXNvY2lhbC1sb2dpbi9tb2RlbHMvbGlua2VkaW4ucmVzcG9uc2UubW9kZWwudHMiLCJuZzovL25nLWR5bmFtaS1zb2NpYWwtbG9naW4vbGliL2R5bmFtaS1zb2NpYWwtbG9naW4vbW9kZWxzL2xvZ2luLnByb3ZpZGVyLmNsYXNzLm1vZGVsLnRzIiwibmc6Ly9uZy1keW5hbWktc29jaWFsLWxvZ2luL2xpYi9keW5hbWktc29jaWFsLWxvZ2luL21vZGVscy9zb2NpYWwudXNlci5tb2RlbC50cyIsIm5nOi8vbmctZHluYW1pLXNvY2lhbC1sb2dpbi9saWIvZHluYW1pLXNvY2lhbC1sb2dpbi9wcm92aWRlcnMvZmFjZWJvb2subG9naW4ucHJvdmlkZXIudHMiLCJuZzovL25nLWR5bmFtaS1zb2NpYWwtbG9naW4vbGliL2R5bmFtaS1zb2NpYWwtbG9naW4vcHJvdmlkZXJzL2dvb2dsZS5sb2dpbi5wcm92aWRlci50cyIsIm5nOi8vbmctZHluYW1pLXNvY2lhbC1sb2dpbi9saWIvZHluYW1pLXNvY2lhbC1sb2dpbi9wcm92aWRlcnMvbGlua2VkaW4ubG9naW4ucHJvdmlkZXIudHMiLCJuZzovL25nLWR5bmFtaS1zb2NpYWwtbG9naW4vbGliL2R5bmFtaS1zb2NpYWwtbG9naW4vc2VydmljZXMvYXV0aC5zZXJ2aWNlLmNvbmZpZy50cyIsIm5nOi8vbmctZHluYW1pLXNvY2lhbC1sb2dpbi9saWIvZHluYW1pLXNvY2lhbC1sb2dpbi9zZXJ2aWNlcy9hdXRoLnNlcnZpY2UudHMiLCJuZzovL25nLWR5bmFtaS1zb2NpYWwtbG9naW4vbGliL2R5bmFtaS1zb2NpYWwtbG9naW4vZHluYW1pLXNvY2lhbC1sb2dpbi5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU29jaWFsVXNlck1vZGVsIH0gZnJvbSBcIi4vc29jaWFsLnVzZXIubW9kZWxcIjtcclxuaW1wb3J0IHsgTG9naW5Qcm92aWRlciB9IGZyb20gXCIuL2xvZ2luLnByb3ZpZGVyXCI7XHJcbmltcG9ydCB7IExvZ2luUHJvdmlkZXJDbGFzc01vZGVsIH0gZnJvbSBcIi4vbG9naW4ucHJvdmlkZXIuY2xhc3MubW9kZWxcIjtcclxuXHJcblxyXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQmFzZUxvZ2luUHJvdmlkZXIgaW1wbGVtZW50cyBMb2dpblByb3ZpZGVyIHtcclxuICBjb25zdHJ1Y3RvcigpIHt9XHJcblxyXG4gIGFic3RyYWN0IGluaXRpYWxpemUoKTogUHJvbWlzZTxTb2NpYWxVc2VyTW9kZWw+O1xyXG4gIGFic3RyYWN0IHNpZ25JbigpOiBQcm9taXNlPFNvY2lhbFVzZXJNb2RlbD47XHJcbiAgYWJzdHJhY3Qgc2lnbk91dCgpOiBQcm9taXNlPGFueT47XHJcblxyXG4gIGxvYWRTY3JpcHQob2JqOiBMb2dpblByb3ZpZGVyQ2xhc3NNb2RlbCwgb25sb2FkOiBhbnkpOiB2b2lkIHtcclxuICAgIGlmIChkb2N1bWVudC5nZXRFbGVtZW50QnlJZChvYmoubmFtZSkpIHsgcmV0dXJuOyB9XHJcbiAgICBsZXQgc2lnbkluSlMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtcclxuICAgIHNpZ25JbkpTLmFzeW5jID0gdHJ1ZTtcclxuICAgIHNpZ25JbkpTLnNyYyA9IG9iai51cmw7XHJcbiAgICBzaWduSW5KUy5vbmxvYWQgPSBvbmxvYWQ7XHJcbiAgICBpZiAob2JqLm5hbWUgPT09ICdMSU5LRURJTicpIHtcclxuICAgICAgc2lnbkluSlMuYXN5bmMgPSBmYWxzZTtcclxuICAgICAgc2lnbkluSlMudGV4dCA9ICgnYXBpX2tleTogJyArIG9iai5pZCkucmVwbGFjZSgnXFwnJywgJycpO1xyXG4gICAgfVxyXG4gICAgZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChzaWduSW5KUyk7XHJcbiAgfVxyXG59IiwiZXhwb3J0IGNsYXNzIExpbmtlZEluUmVzcG9uc2VNb2RlbCB7XHJcbiAgICBlbWFpbEFkZHJlc3M6IHN0cmluZztcclxuICAgIGZpcnN0TmFtZTogc3RyaW5nO1xyXG4gICAgaWQ6IHN0cmluZztcclxuICAgIGxhc3ROYW1lOiBzdHJpbmc7XHJcbiAgICBwaWN0dXJlVXJsOiBzdHJpbmc7XHJcbiAgfSIsImV4cG9ydCBjbGFzcyBMb2dpblByb3ZpZGVyQ2xhc3NNb2RlbCB7XHJcbiAgICBuYW1lOiBzdHJpbmc7XHJcbiAgICBpZDogc3RyaW5nO1xyXG4gICAgdXJsOiBzdHJpbmc7XHJcbiAgfSIsImV4cG9ydCBjbGFzcyBTb2NpYWxVc2VyTW9kZWwge1xyXG4gICAgcHJvdmlkZXI6IHN0cmluZztcclxuICAgIGlkOiBzdHJpbmc7XHJcbiAgICBlbWFpbDogc3RyaW5nO1xyXG4gICAgbmFtZTogc3RyaW5nO1xyXG4gICAgaW1hZ2U6IHN0cmluZztcclxuICAgIHRva2VuPzogc3RyaW5nO1xyXG4gICAgaWRUb2tlbj86IHN0cmluZ1xyXG4gIH1cclxuICBcclxuXHJcbiAgXHJcbiIsImltcG9ydCB7IEJhc2VMb2dpblByb3ZpZGVyIH0gZnJvbSBcIi4uL21vZGVscy9iYXNlLmxvZ2luLnByb3ZpZGVyXCI7XHJcbmltcG9ydCB7IExvZ2luUHJvdmlkZXJDbGFzc01vZGVsIH0gZnJvbSBcIi4uL21vZGVscy9sb2dpbi5wcm92aWRlci5jbGFzcy5tb2RlbFwiO1xyXG5pbXBvcnQgeyBTb2NpYWxVc2VyTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxzL3NvY2lhbC51c2VyLm1vZGVsXCI7XHJcblxyXG5cclxuZGVjbGFyZSBsZXQgRkI6IGFueTtcclxuXHJcbmV4cG9ydCBjbGFzcyBGYWNlYm9va0xvZ2luUHJvdmlkZXIgZXh0ZW5kcyBCYXNlTG9naW5Qcm92aWRlciB7XHJcblxyXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUFJPVklERVJfSUQgPSAnZmFjZWJvb2snO1xyXG4gIHB1YmxpYyBsb2dpblByb3ZpZGVyT2JqOiBMb2dpblByb3ZpZGVyQ2xhc3NNb2RlbCA9IG5ldyBMb2dpblByb3ZpZGVyQ2xhc3NNb2RlbCgpO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNsaWVudElkOiBzdHJpbmcpIHtcclxuICAgIHN1cGVyKCk7XHJcbiAgICB0aGlzLmxvZ2luUHJvdmlkZXJPYmouaWQgPSBjbGllbnRJZDtcclxuICAgIHRoaXMubG9naW5Qcm92aWRlck9iai5uYW1lID0gJ2ZhY2Vib29rJztcclxuICAgIHRoaXMubG9naW5Qcm92aWRlck9iai51cmwgPSAnaHR0cHM6Ly9jb25uZWN0LmZhY2Vib29rLm5ldC9lbl9VUy9zZGsuanMnO1xyXG4gIH1cclxuXHJcbiAgaW5pdGlhbGl6ZSgpOiBQcm9taXNlPFNvY2lhbFVzZXJNb2RlbD4ge1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgdGhpcy5sb2FkU2NyaXB0KHRoaXMubG9naW5Qcm92aWRlck9iaiwgKCkgPT4ge1xyXG4gICAgICAgICAgRkIuaW5pdCh7XHJcbiAgICAgICAgICAgIGFwcElkOiB0aGlzLmNsaWVudElkLFxyXG4gICAgICAgICAgICBhdXRvTG9nQXBwRXZlbnRzOiB0cnVlLFxyXG4gICAgICAgICAgICBjb29raWU6IHRydWUsXHJcbiAgICAgICAgICAgIHhmYm1sOiB0cnVlLFxyXG4gICAgICAgICAgICB2ZXJzaW9uOiAndjIuMTAnXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICAgIEZCLkFwcEV2ZW50cy5sb2dQYWdlVmlldygpO1xyXG5cclxuICAgICAgICAgIEZCLmdldExvZ2luU3RhdHVzKGZ1bmN0aW9uIChyZXNwb25zZTogYW55KSB7XHJcbiAgICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXMgPT09ICdjb25uZWN0ZWQnKSB7XHJcbiAgICAgICAgICAgICAgY29uc3QgYWNjZXNzVG9rZW4gPSBGQi5nZXRBdXRoUmVzcG9uc2UoKVsnYWNjZXNzVG9rZW4nXTtcclxuICAgICAgICAgICAgICBGQi5hcGkoJy9tZT9maWVsZHM9bmFtZSxlbWFpbCxwaWN0dXJlJywgKHJlczogYW55KSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXNvbHZlKEZhY2Vib29rTG9naW5Qcm92aWRlci5kcmF3VXNlcihPYmplY3QuYXNzaWduKHt9LCB7dG9rZW46IGFjY2Vzc1Rva2VufSwgcmVzKSkpO1xyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc3RhdGljIGRyYXdVc2VyKHJlc3BvbnNlOiBhbnkpOiBTb2NpYWxVc2VyTW9kZWwge1xyXG4gICAgbGV0IHVzZXI6IFNvY2lhbFVzZXJNb2RlbCA9IG5ldyBTb2NpYWxVc2VyTW9kZWwoKTtcclxuICAgIHVzZXIuaWQgPSByZXNwb25zZS5pZDtcclxuICAgIHVzZXIubmFtZSA9IHJlc3BvbnNlLm5hbWU7XHJcbiAgICB1c2VyLmVtYWlsID0gcmVzcG9uc2UuZW1haWw7XHJcbiAgICB1c2VyLnRva2VuID0gcmVzcG9uc2UudG9rZW47XHJcbiAgICB1c2VyLmltYWdlID0gJ2h0dHBzOi8vZ3JhcGguZmFjZWJvb2suY29tLycgKyByZXNwb25zZS5pZCArICcvcGljdHVyZT90eXBlPW5vcm1hbCc7XHJcbiAgICByZXR1cm4gdXNlcjtcclxuICB9XHJcblxyXG4gIHNpZ25JbigpOiBQcm9taXNlPFNvY2lhbFVzZXJNb2RlbD4ge1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgRkIubG9naW4oKHJlc3BvbnNlOiBhbnkpID0+IHtcclxuICAgICAgICBpZiAocmVzcG9uc2UuYXV0aFJlc3BvbnNlKSB7XHJcbiAgICAgICAgICBjb25zdCBhY2Nlc3NUb2tlbiA9IEZCLmdldEF1dGhSZXNwb25zZSgpWydhY2Nlc3NUb2tlbiddO1xyXG4gICAgICAgICAgRkIuYXBpKCcvbWU/ZmllbGRzPW5hbWUsZW1haWwscGljdHVyZScsIChyZXM6IGFueSkgPT4ge1xyXG4gICAgICAgICAgICByZXNvbHZlKEZhY2Vib29rTG9naW5Qcm92aWRlci5kcmF3VXNlcihPYmplY3QuYXNzaWduKHt9LCB7dG9rZW46IGFjY2Vzc1Rva2VufSwgcmVzKSkpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9LCB7IHNjb3BlOiAnZW1haWwscHVibGljX3Byb2ZpbGUnIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzaWduT3V0KCk6IFByb21pc2U8YW55PiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICBGQi5sb2dvdXQoKHJlc3BvbnNlOiBhbnkpID0+IHtcclxuICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxufVxyXG4iLCJpbXBvcnQgeyBCYXNlTG9naW5Qcm92aWRlciB9IGZyb20gXCIuLi9tb2RlbHMvYmFzZS5sb2dpbi5wcm92aWRlclwiO1xyXG5pbXBvcnQgeyBMb2dpblByb3ZpZGVyQ2xhc3NNb2RlbCB9IGZyb20gXCIuLi9tb2RlbHMvbG9naW4ucHJvdmlkZXIuY2xhc3MubW9kZWxcIjtcclxuaW1wb3J0IHsgU29jaWFsVXNlck1vZGVsIH0gZnJvbSBcIi4uL21vZGVscy9zb2NpYWwudXNlci5tb2RlbFwiO1xyXG5cclxuXHJcbmRlY2xhcmUgbGV0IGdhcGk6IGFueTtcclxuXHJcbmV4cG9ydCBjbGFzcyBHb29nbGVMb2dpblByb3ZpZGVyIGV4dGVuZHMgQmFzZUxvZ2luUHJvdmlkZXIge1xyXG5cclxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFBST1ZJREVSX0lEID0gJ2dvb2dsZSc7XHJcbiAgcHVibGljIGxvZ2luUHJvdmlkZXJPYmo6IExvZ2luUHJvdmlkZXJDbGFzc01vZGVsID0gbmV3IExvZ2luUHJvdmlkZXJDbGFzc01vZGVsKCk7XHJcbiAgcHJpdmF0ZSBhdXRoMjogYW55O1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNsaWVudElkOiBzdHJpbmcpIHtcclxuICAgIHN1cGVyKCk7XHJcbiAgICB0aGlzLmxvZ2luUHJvdmlkZXJPYmouaWQgPSBjbGllbnRJZDtcclxuICAgIHRoaXMubG9naW5Qcm92aWRlck9iai5uYW1lID0gJ2dvb2dsZSc7XHJcbiAgICB0aGlzLmxvZ2luUHJvdmlkZXJPYmoudXJsID0gJ2h0dHBzOi8vYXBpcy5nb29nbGUuY29tL2pzL3BsYXRmb3JtLmpzJztcclxuICB9XHJcblxyXG4gIGluaXRpYWxpemUoKTogUHJvbWlzZTxTb2NpYWxVc2VyTW9kZWw+IHtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgIHRoaXMubG9hZFNjcmlwdCh0aGlzLmxvZ2luUHJvdmlkZXJPYmosICgpID0+IHtcclxuICAgICAgICAgIGdhcGkubG9hZCgnYXV0aDInLCAoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuYXV0aDIgPSBnYXBpLmF1dGgyLmluaXQoe1xyXG4gICAgICAgICAgICAgIGNsaWVudF9pZDogdGhpcy5jbGllbnRJZCxcclxuICAgICAgICAgICAgICBzY29wZTogJ2VtYWlsJ1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuYXV0aDIudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgaWYgKHRoaXMuYXV0aDIuaXNTaWduZWRJbi5nZXQoKSkge1xyXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmRyYXdVc2VyKCkpO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgfSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGRyYXdVc2VyKCk6IFNvY2lhbFVzZXJNb2RlbCB7XHJcbiAgICBsZXQgdXNlcjogU29jaWFsVXNlck1vZGVsID0gbmV3IFNvY2lhbFVzZXJNb2RlbCgpO1xyXG4gICAgbGV0IHByb2ZpbGUgPSB0aGlzLmF1dGgyLmN1cnJlbnRVc2VyLmdldCgpLmdldEJhc2ljUHJvZmlsZSgpO1xyXG4gICAgbGV0IGF1dGhSZXNwb25zZU9iaiA9IHRoaXMuYXV0aDIuY3VycmVudFVzZXIuZ2V0KCkuZ2V0QXV0aFJlc3BvbnNlKHRydWUpO1xyXG4gICAgdXNlci5pZCA9IHByb2ZpbGUuZ2V0SWQoKTtcclxuICAgIHVzZXIubmFtZSA9IHByb2ZpbGUuZ2V0TmFtZSgpO1xyXG4gICAgdXNlci5lbWFpbCA9IHByb2ZpbGUuZ2V0RW1haWwoKTtcclxuICAgIHVzZXIuaW1hZ2UgPSBwcm9maWxlLmdldEltYWdlVXJsKCk7XHJcbiAgICB1c2VyLnRva2VuID0gYXV0aFJlc3BvbnNlT2JqLmFjY2Vzc190b2tlbjtcclxuICAgIHVzZXIuaWRUb2tlbiA9IGF1dGhSZXNwb25zZU9iai5pZF90b2tlbjtcclxuICAgIHJldHVybiB1c2VyO1xyXG4gIH1cclxuXHJcbiAgc2lnbkluKCk6IFByb21pc2U8U29jaWFsVXNlck1vZGVsPiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICBsZXQgcHJvbWlzZSA9IHRoaXMuYXV0aDIuc2lnbkluKCk7XHJcbiAgICAgIHByb21pc2UudGhlbigoKSA9PiB7XHJcbiAgICAgICAgcmVzb2x2ZSh0aGlzLmRyYXdVc2VyKCkpO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc2lnbk91dCgpOiBQcm9taXNlPGFueT4ge1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgdGhpcy5hdXRoMi5zaWduT3V0KCkudGhlbigoZXJyOiBhbnkpID0+IHtcclxuICAgICAgICBpZiAoZXJyKSB7XHJcbiAgICAgICAgICByZWplY3QoZXJyKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG59XHJcbiIsImltcG9ydCB7IEJhc2VMb2dpblByb3ZpZGVyIH0gZnJvbSBcIi4uL21vZGVscy9iYXNlLmxvZ2luLnByb3ZpZGVyXCI7XHJcbmltcG9ydCB7IExvZ2luUHJvdmlkZXJDbGFzc01vZGVsIH0gZnJvbSBcIi4uL21vZGVscy9sb2dpbi5wcm92aWRlci5jbGFzcy5tb2RlbFwiO1xyXG5pbXBvcnQgeyBTb2NpYWxVc2VyTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxzL3NvY2lhbC51c2VyLm1vZGVsXCI7XHJcbmltcG9ydCB7IExpbmtlZEluUmVzcG9uc2VNb2RlbCB9IGZyb20gXCIuLi9tb2RlbHMvbGlua2VkaW4ucmVzcG9uc2UubW9kZWxcIjtcclxuXHJcblxyXG5kZWNsYXJlIGxldCBJTjogYW55O1xyXG5cclxuZXhwb3J0IGNsYXNzIExpbmtlZGluTG9naW5Qcm92aWRlciBleHRlbmRzIEJhc2VMb2dpblByb3ZpZGVyIHtcclxuXHJcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBQUk9WSURFUl9JRCA9ICdsaW5rZWRpbic7XHJcbiAgcHVibGljIGxvZ2luUHJvdmlkZXJPYmo6IExvZ2luUHJvdmlkZXJDbGFzc01vZGVsID0gbmV3IExvZ2luUHJvdmlkZXJDbGFzc01vZGVsKCk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2xpZW50SWQ6IHN0cmluZykge1xyXG4gICAgc3VwZXIoKTtcclxuICAgIHRoaXMubG9naW5Qcm92aWRlck9iai5pZCA9IGNsaWVudElkO1xyXG4gICAgdGhpcy5sb2dpblByb3ZpZGVyT2JqLm5hbWUgPSAnbGlua2VkaW4nO1xyXG4gICAgdGhpcy5sb2dpblByb3ZpZGVyT2JqLnVybCA9ICdodHRwczovL3BsYXRmb3JtLmxpbmtlZGluLmNvbS9pbi5qcyc7XHJcbiAgfVxyXG5cclxuICBpbml0aWFsaXplKCk6IFByb21pc2U8U29jaWFsVXNlck1vZGVsPiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICB0aGlzLmxvYWRTY3JpcHQodGhpcy5sb2dpblByb3ZpZGVyT2JqLCAoKSA9PiB7XHJcbiAgICAgICAgICBJTi5pbml0KHtcclxuICAgICAgICAgICAgYXBpX2tleTogdGhpcy5jbGllbnRJZCxcclxuICAgICAgICAgICAgYXV0aG9yaXplOiB0cnVlLFxyXG4gICAgICAgICAgICBvbkxvYWQ6IHRoaXMub25MaW5rZWRJbkxvYWQoKVxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgSU4uRXZlbnQub24oSU4sICdhdXRoJywgKCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAoSU4uVXNlci5pc0F1dGhvcml6ZWQoKSkge1xyXG4gICAgICAgICAgICAgIElOLkFQSS5SYXcoXHJcbiAgICAgICAgICAgICAgICAnL3Blb3BsZS9+OihpZCxmaXJzdC1uYW1lLGxhc3QtbmFtZSxlbWFpbC1hZGRyZXNzLHBpY3R1cmUtdXJsKSdcclxuICAgICAgICAgICAgICApLnJlc3VsdCggKHJlczogTGlua2VkSW5SZXNwb25zZU1vZGVsKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXNvbHZlKHRoaXMuZHJhd1VzZXIocmVzKSk7XHJcbiAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgb25MaW5rZWRJbkxvYWQoKSB7XHJcbiAgICBJTi5FdmVudC5vbihJTiwgJ3N5c3RlbVJlYWR5JywgKCkgPT4ge1xyXG4gICAgICBJTi5Vc2VyLnJlZnJlc2goKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZHJhd1VzZXIocmVzcG9uc2U6IExpbmtlZEluUmVzcG9uc2VNb2RlbCk6IFNvY2lhbFVzZXJNb2RlbCB7XHJcbiAgICBsZXQgdXNlcjogU29jaWFsVXNlck1vZGVsID0gbmV3IFNvY2lhbFVzZXJNb2RlbCgpO1xyXG4gICAgdXNlci5pZCA9IHJlc3BvbnNlLmVtYWlsQWRkcmVzcztcclxuICAgIHVzZXIubmFtZSA9IHJlc3BvbnNlLmZpcnN0TmFtZSArICcgJyArIHJlc3BvbnNlLmxhc3ROYW1lO1xyXG4gICAgdXNlci5lbWFpbCA9IHJlc3BvbnNlLmVtYWlsQWRkcmVzcztcclxuICAgIHVzZXIuaW1hZ2UgPSByZXNwb25zZS5waWN0dXJlVXJsO1xyXG4gICAgdXNlci50b2tlbiA9IElOLkVOVi5hdXRoLm9hdXRoX3Rva2VuO1xyXG4gICAgcmV0dXJuIHVzZXI7XHJcbiAgfVxyXG5cclxuICBzaWduSW4oKTogUHJvbWlzZTxTb2NpYWxVc2VyTW9kZWw+IHtcclxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgIElOLlVzZXIuYXV0aG9yaXplKCAoKSA9PiB7XHJcbiAgICAgICAgSU4uQVBJLlJhdygnL3Blb3BsZS9+OihpZCxmaXJzdC1uYW1lLGxhc3QtbmFtZSxlbWFpbC1hZGRyZXNzLHBpY3R1cmUtdXJsKScpLnJlc3VsdCggKHJlczogTGlua2VkSW5SZXNwb25zZU1vZGVsKSA9PiB7XHJcbiAgICAgICAgICByZXNvbHZlKHRoaXMuZHJhd1VzZXIocmVzKSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzaWduT3V0KCk6IFByb21pc2U8YW55PiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICBJTi5Vc2VyLmxvZ291dCgocmVzcG9uc2U6IGFueSkgPT4ge1xyXG4gICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgfSwgKGVycjogYW55KSA9PiB7XHJcbiAgICAgICAgcmVqZWN0KGVycik7XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxufVxyXG4iLCJpbXBvcnQgeyBMb2dpblByb3ZpZGVyIH0gZnJvbSBcIi4uL21vZGVscy9sb2dpbi5wcm92aWRlclwiO1xyXG5pbXBvcnQgeyBBdXRoU2VydmljZUNvbmZpZ0l0ZW0gfSBmcm9tIFwiLi9hdXRoLnNlcnZpY2UuY29uZmlnLml0ZW1cIjtcclxuXHJcbmV4cG9ydCBjbGFzcyBBdXRoU2VydmljZUNvbmZpZyB7XHJcbiAgICBwcm92aWRlcnM6IE1hcDxzdHJpbmcsIExvZ2luUHJvdmlkZXI+ID0gbmV3IE1hcDxzdHJpbmcsIExvZ2luUHJvdmlkZXI+KCk7XHJcbiAgXHJcbiAgICBjb25zdHJ1Y3Rvcihwcm92aWRlcnM6IEF1dGhTZXJ2aWNlQ29uZmlnSXRlbVtdKSB7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHJvdmlkZXJzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgbGV0IGVsZW1lbnQgPSBwcm92aWRlcnNbaV07XHJcbiAgICAgICAgdGhpcy5wcm92aWRlcnMuc2V0KGVsZW1lbnQuaWQsIGVsZW1lbnQucHJvdmlkZXIpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfSIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xyXG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIE9ic2VydmFibGUgfSBmcm9tIFwicnhqc1wiO1xyXG5pbXBvcnQgeyBMb2dpblByb3ZpZGVyIH0gZnJvbSBcIi4uL21vZGVscy9sb2dpbi5wcm92aWRlclwiO1xyXG5pbXBvcnQgeyBTb2NpYWxVc2VyTW9kZWwgfSBmcm9tIFwiLi4vbW9kZWxzL3NvY2lhbC51c2VyLm1vZGVsXCI7XHJcbmltcG9ydCB7IEF1dGhTZXJ2aWNlQ29uZmlnIH0gZnJvbSBcIi4vYXV0aC5zZXJ2aWNlLmNvbmZpZ1wiO1xyXG5cclxuXHJcbkBJbmplY3RhYmxlKClcclxuZXhwb3J0IGNsYXNzIEF1dGhTZXJ2aWNlIHtcclxuXHJcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgTE9HSU5fUFJPVklERVJfTk9UX0ZPVU5EID0gJ0xvZ2luIHByb3ZpZGVyIG5vdCBmb3VuZCc7XHJcblxyXG4gIHByaXZhdGUgcHJvdmlkZXJzOiBNYXA8c3RyaW5nLCBMb2dpblByb3ZpZGVyPjtcclxuXHJcbiAgcHJpdmF0ZSBfdXNlcjogU29jaWFsVXNlck1vZGVsID0gbnVsbDtcclxuICBwcml2YXRlIF9hdXRoU3RhdGU6IEJlaGF2aW9yU3ViamVjdDxTb2NpYWxVc2VyTW9kZWw+ID0gbmV3IEJlaGF2aW9yU3ViamVjdChudWxsKTtcclxuXHJcbiAgZ2V0IGF1dGhTdGF0ZSgpOiBPYnNlcnZhYmxlPFNvY2lhbFVzZXJNb2RlbD4ge1xyXG4gICAgcmV0dXJuIHRoaXMuX2F1dGhTdGF0ZS5hc09ic2VydmFibGUoKTtcclxuICB9XHJcblxyXG4gIGNvbnN0cnVjdG9yKGNvbmZpZzogQXV0aFNlcnZpY2VDb25maWcpIHtcclxuICAgIHRoaXMucHJvdmlkZXJzID0gY29uZmlnLnByb3ZpZGVycztcclxuICAgIHRoaXMucHJvdmlkZXJzLmZvckVhY2goKHByb3ZpZGVyOiBMb2dpblByb3ZpZGVyLCBrZXk6IHN0cmluZykgPT4ge1xyXG4gICAgICBwcm92aWRlci5pbml0aWFsaXplKCkudGhlbigodXNlcjogU29jaWFsVXNlck1vZGVsKSA9PiB7XHJcbiAgICAgICAgdXNlci5wcm92aWRlciA9IGtleTtcclxuICAgICAgICB0aGlzLl91c2VyID0gdXNlcjtcclxuICAgICAgICB0aGlzLl9hdXRoU3RhdGUubmV4dCh1c2VyKTtcclxuICAgICAgfSkuY2F0Y2goKGVycikgPT4ge1xyXG4gICAgICAgIC8vIHRoaXMuX2F1dGhTdGF0ZS5uZXh0KG51bGwpO1xyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc2lnbkluKHByb3ZpZGVySWQ6IHN0cmluZyk6IFByb21pc2U8U29jaWFsVXNlck1vZGVsPiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICBsZXQgcHJvdmlkZXJPYmplY3QgPSB0aGlzLnByb3ZpZGVycy5nZXQocHJvdmlkZXJJZCk7XHJcbiAgICAgIGlmIChwcm92aWRlck9iamVjdCkge1xyXG4gICAgICAgIHByb3ZpZGVyT2JqZWN0LnNpZ25JbigpLnRoZW4oKHVzZXI6IFNvY2lhbFVzZXJNb2RlbCkgPT4ge1xyXG4gICAgICAgICAgdXNlci5wcm92aWRlciA9IHByb3ZpZGVySWQ7XHJcbiAgICAgICAgICByZXNvbHZlKHVzZXIpO1xyXG4gICAgICAgICAgdGhpcy5fdXNlciA9IHVzZXI7XHJcbiAgICAgICAgICB0aGlzLl9hdXRoU3RhdGUubmV4dCh1c2VyKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZWplY3QoQXV0aFNlcnZpY2UuTE9HSU5fUFJPVklERVJfTk9UX0ZPVU5EKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzaWduT3V0KCk6IFByb21pc2U8YW55PiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICBpZiAodGhpcy5fdXNlciAmJiB0aGlzLl91c2VyLnByb3ZpZGVyKSB7XHJcbiAgICAgICAgbGV0IHByb3ZpZGVySWQgPSB0aGlzLl91c2VyLnByb3ZpZGVyO1xyXG4gICAgICAgIGxldCBwcm92aWRlck9iamVjdCA9IHRoaXMucHJvdmlkZXJzLmdldChwcm92aWRlcklkKTtcclxuICAgICAgICBwcm92aWRlck9iamVjdC5zaWduT3V0KCkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLl91c2VyID0gbnVsbDtcclxuICAgICAgICAgIHRoaXMuX2F1dGhTdGF0ZS5uZXh0KG51bGwpO1xyXG4gICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgIH0pLmNhdGNoKChlcnIpID0+IHtcclxuICAgICAgICAgIHRoaXMuX2F1dGhTdGF0ZS5uZXh0KG51bGwpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJlamVjdChBdXRoU2VydmljZS5MT0dJTl9QUk9WSURFUl9OT1RfRk9VTkQpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG59IiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBBdXRoU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvYXV0aC5zZXJ2aWNlJztcblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZVxuICBdLFxuICBkZWNsYXJhdGlvbnM6IFtdLFxuICBwcm92aWRlcnM6IFtBdXRoU2VydmljZV0sXG59KVxuZXhwb3J0IGNsYXNzIER5bmFtaVNvY2lhbExvZ2luTW9kdWxlIHsgfVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0FBS0EsTUFBc0IsaUJBQWlCO0lBQ3JDLGlCQUFnQjs7Ozs7O0lBTWhCLFVBQVUsQ0FBQyxHQUE0QixFQUFFLE1BQVc7UUFDbEQsSUFBSSxRQUFRLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUFFLE9BQU87U0FBRTs7WUFDOUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDO1FBQy9DLFFBQVEsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLFFBQVEsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLEdBQUcsQ0FBQztRQUN2QixRQUFRLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztRQUN6QixJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssVUFBVSxFQUFFO1lBQzNCLFFBQVEsQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1lBQ3ZCLFFBQVEsQ0FBQyxJ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