UNPKG

ehandler

Version:

Exception handler for Angular Applications

424 lines (416 loc) 34.7 kB
import { Inject, Injectable, Injector, ErrorHandler, NgModule, defineInjectable, inject, INJECTOR } from '@angular/core'; import { HttpClient, HttpHeaders, HttpErrorResponse, HttpResponse, HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http'; import { catchError, finalize, map } from 'rxjs/operators'; import { error } from 'toastr'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var HookService = /** @class */ (function () { function HookService(http, config) { this.http = http; this.config = config; } /** * Send Message */ /** * Send Message * @param {?} payload * @return {?} */ HookService.prototype.sendMessage = /** * Send Message * @param {?} payload * @return {?} */ function (payload) { this.http.post(this.config.hook, payload, { observe: 'response', responseType: 'text' }).subscribe(function (response) { console.info('Message sent'); }); }; /** * Send Exception to hook */ /** * Send Exception to hook * @param {?} error * @param {?=} couse * @return {?} */ HookService.prototype.exceptionNotify = /** * Send Exception to hook * @param {?} error * @param {?=} couse * @return {?} */ function (error$$1, couse) { var _this = this; if (couse === void 0) { couse = ''; } /** @type {?} */ var status = error$$1.status ? error$$1.status : 'Application Error'; /** * * Error Payload @type {?} */ var payload = { text: '--------------------------[ ' + status + ' ]--------------------------', attachments: [ { author_name: 'Cause: ' + couse + '\nURL: ' + window.location.href, title: 'Message: ' + error$$1.message, text: 'Date: ' + new Date() + '\nUserAgent: ' + navigator.userAgent + '\n---------------------------------------------------------' } ] }; if (!this.bugged) { /** @type {?} */ var headers = new HttpHeaders({ 'Content-Type': 'text/plain' }); this.http.post(this.config.hook, JSON.stringify(payload), { observe: 'response', responseType: 'text', headers: headers }) .pipe(catchError(function (e) { _this.bugged = true; console.log('Hook stopped working'); throw e; })) .subscribe(function (response) { console.log('Exception Sent'); }); } }; HookService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ HookService.ctorParameters = function () { return [ { type: HttpClient }, { type: undefined, decorators: [{ type: Inject, args: ['configurations',] }] } ]; }; return HookService; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var EHandlerService = /** @class */ (function () { function EHandlerService(injector, config, hook) { this.injector = injector; this.config = config; this.hook = hook; } /** * Global Error Handler */ /** * Global Error Handler * @param {?} error * @return {?} */ EHandlerService.prototype.handleError = /** * Global Error Handler * @param {?} error * @return {?} */ function (error$$1) { /** * * Error Message for view @type {?} */ var message; /** * * Error TimeStamp @type {?} */ var date = new Date(); /** * Handle errors occured while making server call */ if (error$$1 instanceof HttpErrorResponse) { message = this.config.message.statusException; /** * If UnAuthorized * Else If Server Error */ switch (error$$1.status) { case 400: case 401: this.logout(); break; case 500: message = this.config.message.serverException; } // Backend returns unsuccessful response codes such as 404, 500 etc. this.statusMessage(error$$1, date); } else { // A client-side or network error occurred. this.commonMessage(error$$1, date); message = this.config.message.appException; } this.errorMSG(message); }; /** * Logout of system */ /** * Logout of system * @param {?=} message * @return {?} */ EHandlerService.prototype.logout = /** * Logout of system * @param {?=} message * @return {?} */ function (message) { var _this = this; error(this.config.message.unAuthenticated); if (message) { error(message); } setTimeout(function () { window.location.replace(_this.config.logout); }, 5000); }; /** * Show Error Message */ /** * Show Error Message * @param {?} message * @param {?=} code * @return {?} */ EHandlerService.prototype.errorMSG = /** * Show Error Message * @param {?} message * @param {?=} code * @return {?} */ function (message, code) { if (code === void 0) { code = null; } error(message, code); }; /** * Log Error Message */ /** * Log Error Message * @param {?} error * @param {?=} date * @return {?} */ EHandlerService.prototype.statusMessage = /** * Log Error Message * @param {?} error * @param {?=} date * @return {?} */ function (error$$1, date) { if (date === void 0) { date = new Date(); } console.error('--------------------------------------------\n', 'Backend returned status code: ' + error$$1.status + '\n', 'Response body ehandler:' + error$$1.message + '\n', date + '\n', '--------------------------------------------'); this.hook.exceptionNotify(error$$1.message, '----HTTP Error----'); }; /** * Log Common Error */ /** * Log Common Error * @param {?} error * @param {?=} date * @return {?} */ EHandlerService.prototype.commonMessage = /** * Log Common Error * @param {?} error * @param {?=} date * @return {?} */ function (error$$1, date) { if (date === void 0) { date = new Date(); } console.error('--------------------------------------------\n', 'An error occurred ehandler:' + error$$1.message + '\n', date + '\n', '--------------------------------------------'); this.hook.exceptionNotify(error$$1.message, '----Common Error----'); }; EHandlerService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] }, ]; /** @nocollapse */ EHandlerService.ctorParameters = function () { return [ { type: Injector }, { type: undefined, decorators: [{ type: Inject, args: ['configurations',] }] }, { type: HookService } ]; }; /** @nocollapse */ EHandlerService.ngInjectableDef = defineInjectable({ factory: function EHandlerService_Factory() { return new EHandlerService(inject(INJECTOR), inject("configurations"), inject(HookService)); }, token: EHandlerService, providedIn: "root" }); return EHandlerService; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var EIntercepterService = /** @class */ (function () { function EIntercepterService(config, eh) { this.config = config; this.eh = eh; } /** * @param {?} req * @param {?} next * @return {?} */ EIntercepterService.prototype.intercept = /** * @param {?} req * @param {?} next * @return {?} */ function (req, next) { var _this = this; return next.handle(req).pipe(map(function (event) { if (event instanceof HttpResponse) { /** @type {?} */ var requestData = event.body; if (requestData) { if (requestData.exception && requestData.exception.code) { try { if (_this.config && _this.config.logoutCodes && _this.config.logoutCodes.indexOf(requestData.exception.code) !== -1) { _this.eh.logout(); } else { /** @type {?} */ var error$$1 = { code: requestData.exception.code, message: requestData.exception.message }; _this.eh.errorMSG(error$$1.message, error$$1.code); _this.eh.statusMessage(error$$1); } } catch (e) { console.log('There was an error while trying to send message'); } } else if (requestData.error && requestData.error.code) { try { if (_this.config && _this.config.logoutCodes && _this.config.logoutCodes.indexOf(requestData.error.code) !== -1) { _this.eh.logout(); } else { /** @type {?} */ var error$$1 = { code: requestData.error.code, message: requestData.error.message }; _this.eh.errorMSG(error$$1.message, error$$1.code); _this.eh.statusMessage(error$$1); } } catch (e) { console.log('There was an error while trying to send message'); } } } } return event; }), catchError(function (error$$1) { _this.eh.handleError(error$$1); throw error$$1; }), finalize(function () { })); }; EIntercepterService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ EIntercepterService.ctorParameters = function () { return [ { type: undefined, decorators: [{ type: Inject, args: ['configurations',] }] }, { type: EHandlerService } ]; }; return EIntercepterService; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** @type {?} */ var InitialConfig = { message: { unAuthenticated: 'Xahiş olunur sistemə daxil olun!', statusException: 'Status xətası', serverException: 'Server xətası', appException: 'Sistem xətası' }, logout: '/logout', logoutCodes: [ 401, 1005, 1006, 1014, 1015, 1016, 1017, 1401, ], hook: 'https://hooks.slack.com/services/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', }; var EHandlerModule = /** @class */ (function () { function EHandlerModule() { } /** * @param {?=} configurations * @return {?} */ EHandlerModule.forRoot = /** * @param {?=} configurations * @return {?} */ function (configurations) { if (configurations === void 0) { configurations = InitialConfig; } return { ngModule: EHandlerModule, providers: [ { provide: 'configurations', useValue: configurations }, ], }; }; /** * @return {?} */ EHandlerModule.forChild = /** * @return {?} */ function () { return { ngModule: EHandlerModule, }; }; EHandlerModule.decorators = [ { type: NgModule, args: [{ imports: [ HttpClientModule, BrowserAnimationsModule ], providers: [ { provide: ErrorHandler, useClass: EHandlerService }, { provide: HTTP_INTERCEPTORS, useClass: EIntercepterService, multi: true }, HookService ], declarations: [], exports: [] },] }, ]; return EHandlerModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ export { EHandlerService, EIntercepterService, InitialConfig, EHandlerModule, HookService as ɵb }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWhhbmRsZXIuanMubWFwIiwic291cmNlcyI6WyJuZzovL2VoYW5kbGVyL2xpYi9ob29rLnNlcnZpY2UudHMiLCJuZzovL2VoYW5kbGVyL2xpYi9laGFuZGxlci5zZXJ2aWNlLnRzIiwibmc6Ly9laGFuZGxlci9saWIvZWludGVyY2VwdGVyLnNlcnZpY2UudHMiLCJuZzovL2VoYW5kbGVyL2xpYi9laGFuZGxlci5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtJbmplY3QsIEluamVjdGFibGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge0h0dHBDbGllbnQsIEh0dHBIZWFkZXJzfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcbmltcG9ydCB7Q29uZmlnfSBmcm9tICcuL2NvbnN0L2NvbmZpZyc7XHJcbmltcG9ydCB7Y2F0Y2hFcnJvciwgbWFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG5ASW5qZWN0YWJsZSgpXHJcblxyXG5leHBvcnQgY2xhc3MgSG9va1NlcnZpY2Uge1xyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaHR0cDogSHR0cENsaWVudCwgQEluamVjdCgnY29uZmlndXJhdGlvbnMnKSBwcml2YXRlIGNvbmZpZzogQ29uZmlnKSB7fVxyXG4gIHByaXZhdGUgYnVnZ2VkOiBib29sZWFuO1xyXG4gIC8qKlxyXG4gICAqIFNlbmQgTWVzc2FnZVxyXG4gICAqL1xyXG4gIHNlbmRNZXNzYWdlKHBheWxvYWQ6IGFueSkge1xyXG4gICAgdGhpcy5odHRwLnBvc3QodGhpcy5jb25maWcuaG9vaywgcGF5bG9hZCwge29ic2VydmU6ICdyZXNwb25zZScsIHJlc3BvbnNlVHlwZTogJ3RleHQnfSkuc3Vic2NyaWJlKCByZXNwb25zZSA9PiB7XHJcbiAgICAgIGNvbnNvbGUuaW5mbygnTWVzc2FnZSBzZW50Jyk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqICBTZW5kIEV4Y2VwdGlvbiB0byBob29rXHJcbiAgICovXHJcbiAgZXhjZXB0aW9uTm90aWZ5KGVycm9yLCBjb3VzZSA9ICcnKSB7XHJcbiAgICBjb25zdCBzdGF0dXMgPSBlcnJvci5zdGF0dXMgPyBlcnJvci5zdGF0dXMgOiAnQXBwbGljYXRpb24gRXJyb3InO1xyXG4gICAgLyoqXHJcbiAgICAgKiBFcnJvciBQYXlsb2FkXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IHBheWxvYWQgPSB7XHJcbiAgICAgIHRleHQ6ICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVsgJyArIHN0YXR1cyArICcgXS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJyxcclxuICAgICAgYXR0YWNobWVudHM6IFtcclxuICAgICAgICB7XHJcbiAgICAgICAgICBhdXRob3JfbmFtZTogJ0NhdXNlOiAnICsgY291c2UgKyAnXFxuVVJMOiAnICsgd2luZG93LmxvY2F0aW9uLmhyZWYsXHJcbiAgICAgICAgICB0aXRsZTogJ01lc3NhZ2U6ICcgKyBlcnJvci5tZXNzYWdlLFxyXG4gICAgICAgICAgdGV4dDogJ0RhdGU6ICcgKyBuZXcgRGF0ZSgpICsgJ1xcblVzZXJBZ2VudDogJyArIG5hdmlnYXRvci51c2VyQWdlbnQgK1xyXG4gICAgICAgICAgJ1xcbi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSdcclxuICAgICAgICB9XHJcbiAgICAgIF1cclxuICAgIH07XHJcbiAgICBpZiAoIXRoaXMuYnVnZ2VkKSB7XHJcbiAgICAgIGNvbnN0IGhlYWRlcnMgPSBuZXcgSHR0cEhlYWRlcnMoe1xyXG4gICAgICAgICdDb250ZW50LVR5cGUnOiAndGV4dC9wbGFpbidcclxuICAgICAgfSlcclxuICAgICAgdGhpcy5odHRwLnBvc3QodGhpcy5jb25maWcuaG9vaywgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCksIHtvYnNlcnZlOiAncmVzcG9uc2UnLCByZXNwb25zZVR5cGU6ICd0ZXh0JywgaGVhZGVyc30pXHJcbiAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICBjYXRjaEVycm9yKGUgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmJ1Z2dlZCA9IHRydWU7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdIb29rIHN0b3BwZWQgd29ya2luZycpO1xyXG4gICAgICAgICAgICB0aHJvdyBlO1xyXG4gICAgICAgICAgfSlcclxuICAgICAgICApXHJcbiAgICAgICAgLnN1YnNjcmliZSggcmVzcG9uc2UgPT4ge1xyXG4gICAgICAgICAgY29uc29sZS5sb2coJ0V4Y2VwdGlvbiBTZW50Jyk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQge0Vycm9ySGFuZGxlciwgSW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3Rvcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7SHR0cEVycm9yUmVzcG9uc2V9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHtDb25maWd9IGZyb20gJy4vY29uc3QvY29uZmlnJztcclxuaW1wb3J0IHtIb29rU2VydmljZX0gZnJvbSAnLi9ob29rLnNlcnZpY2UnO1xyXG5pbXBvcnQgKiBhcyB0b2FzdHIgZnJvbSAndG9hc3RyJztcclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290J1xyXG59KVxyXG5leHBvcnQgY2xhc3MgRUhhbmRsZXJTZXJ2aWNlIGltcGxlbWVudHMgRXJyb3JIYW5kbGVyIHtcclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgaW5qZWN0b3I6IEluamVjdG9yLFxyXG4gICAgQEluamVjdCgnY29uZmlndXJhdGlvbnMnKSBwcml2YXRlIGNvbmZpZzogQ29uZmlnLFxyXG4gICAgcHJpdmF0ZSBob29rOiBIb29rU2VydmljZSxcclxuICApIHtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogR2xvYmFsIEVycm9yIEhhbmRsZXJcclxuICAgKi9cclxuICBoYW5kbGVFcnJvcihlcnJvcjogYW55KSB7XHJcbiAgICAvKipcclxuICAgICAqIEVycm9yIE1lc3NhZ2UgZm9yIHZpZXdcclxuICAgICAqL1xyXG4gICAgbGV0IG1lc3NhZ2U6IHN0cmluZztcclxuICAgIC8qKlxyXG4gICAgICogRXJyb3IgVGltZVN0YW1wXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IGRhdGU6IERhdGUgPSBuZXcgRGF0ZSgpO1xyXG4gICAgLyoqXHJcbiAgICAgKiBIYW5kbGUgZXJyb3JzIG9jY3VyZWQgd2hpbGUgbWFraW5nIHNlcnZlciBjYWxsXHJcbiAgICAgKi9cclxuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEh0dHBFcnJvclJlc3BvbnNlKSB7XHJcbiAgICAgIG1lc3NhZ2UgPSB0aGlzLmNvbmZpZy5tZXNzYWdlLnN0YXR1c0V4Y2VwdGlvbjtcclxuICAgICAgLyoqXHJcbiAgICAgICAqIElmIFVuQXV0aG9yaXplZFxyXG4gICAgICAgKiBFbHNlIElmIFNlcnZlciBFcnJvclxyXG4gICAgICAgKi9cclxuICAgICAgc3dpdGNoIChlcnJvci5zdGF0dXMpIHtcclxuICAgICAgICBjYXNlIDQwMDpcclxuICAgICAgICBjYXNlIDQwMTpcclxuICAgICAgICAgIHRoaXMubG9nb3V0KCk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIDUwMDpcclxuICAgICAgICAgIG1lc3NhZ2UgPSB0aGlzLmNvbmZpZy5tZXNzYWdlLnNlcnZlckV4Y2VwdGlvbjtcclxuICAgICAgfVxyXG4gICAgICAvLyBCYWNrZW5kIHJldHVybnMgdW5zdWNjZXNzZnVsIHJlc3BvbnNlIGNvZGVzIHN1Y2ggYXMgNDA0LCA1MDAgZXRjLlxyXG4gICAgICB0aGlzLnN0YXR1c01lc3NhZ2UoZXJyb3IsIGRhdGUpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gQSBjbGllbnQtc2lkZSBvciBuZXR3b3JrIGVycm9yIG9jY3VycmVkLlxyXG4gICAgICB0aGlzLmNvbW1vbk1lc3NhZ2UoZXJyb3IsIGRhdGUpO1xyXG4gICAgICBtZXNzYWdlID0gdGhpcy5jb25maWcubWVzc2FnZS5hcHBFeGNlcHRpb247XHJcbiAgICB9XHJcbiAgICB0aGlzLmVycm9yTVNHKG1lc3NhZ2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTG9nb3V0IG9mIHN5c3RlbVxyXG4gICAqL1xyXG4gIGxvZ291dChtZXNzYWdlPzogc3RyaW5nKSB7XHJcbiAgICB0b2FzdHIuZXJyb3IodGhpcy5jb25maWcubWVzc2FnZS51bkF1dGhlbnRpY2F0ZWQpO1xyXG4gICAgaWYgKG1lc3NhZ2UpIHtcclxuICAgICAgdG9hc3RyLmVycm9yKG1lc3NhZ2UpO1xyXG4gICAgfVxyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKHRoaXMuY29uZmlnLmxvZ291dCk7XHJcbiAgICB9LCA1MDAwKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNob3cgRXJyb3IgTWVzc2FnZVxyXG4gICAqL1xyXG4gIGVycm9yTVNHKG1lc3NhZ2UsIGNvZGUgPSBudWxsKSB7XHJcbiAgICB0b2FzdHIuZXJyb3IobWVzc2FnZSwgY29kZSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIExvZyBFcnJvciBNZXNzYWdlXHJcbiAgICovXHJcbiAgc3RhdHVzTWVzc2FnZShlcnJvciwgZGF0ZSA9IG5ldyBEYXRlKCkpIHtcclxuICAgIGNvbnNvbGUuZXJyb3IoXHJcbiAgICAgICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbicsXHJcbiAgICAgICdCYWNrZW5kIHJldHVybmVkIHN0YXR1cyBjb2RlOiAnICsgZXJyb3Iuc3RhdHVzICsgJ1xcbicsXHJcbiAgICAgICdSZXNwb25zZSBib2R5IGVoYW5kbGVyOicgKyBlcnJvci5tZXNzYWdlICsgJ1xcbicsXHJcbiAgICAgIGRhdGUgKyAnXFxuJyxcclxuICAgICAgJy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJ1xyXG4gICAgKTtcclxuICAgICAgdGhpcy5ob29rLmV4Y2VwdGlvbk5vdGlmeShlcnJvci5tZXNzYWdlLCAnLS0tLUhUVFAgRXJyb3ItLS0tJyk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBMb2cgQ29tbW9uIEVycm9yXHJcbiAgICovXHJcbiAgY29tbW9uTWVzc2FnZShlcnJvciwgZGF0ZSA9IG5ldyBEYXRlKCkpIHtcclxuICAgIGNvbnNvbGUuZXJyb3IoXHJcbiAgICAgICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcbicsXHJcbiAgICAgICdBbiBlcnJvciBvY2N1cnJlZCBlaGFuZGxlcjonICsgZXJyb3IubWVzc2FnZSArICdcXG4nLFxyXG4gICAgICBkYXRlICsgJ1xcbicsXHJcbiAgICAgICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSdcclxuICAgICk7XHJcbiAgICB0aGlzLmhvb2suZXhjZXB0aW9uTm90aWZ5KGVycm9yLm1lc3NhZ2UsICctLS0tQ29tbW9uIEVycm9yLS0tLScpO1xyXG4gIH1cclxufVxyXG4iLCJpbXBvcnQge0luamVjdCwgSW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0h0dHBFdmVudCwgSHR0cEhhbmRsZXIsIEh0dHBJbnRlcmNlcHRvciwgSHR0cFJlcXVlc3QsIEh0dHBSZXNwb25zZX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHtPYnNlcnZhYmxlfSBmcm9tICdyeGpzJztcbmltcG9ydCB7Y2F0Y2hFcnJvciwgZmluYWxpemUsIG1hcH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtDb25maWd9IGZyb20gJy4vY29uc3QvY29uZmlnJztcbmltcG9ydCB7RUhhbmRsZXJTZXJ2aWNlfSBmcm9tICcuL2VoYW5kbGVyLnNlcnZpY2UnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgRUludGVyY2VwdGVyU2VydmljZSBpbXBsZW1lbnRzIEh0dHBJbnRlcmNlcHRvciB7XG4gIGNvbnN0cnVjdG9yKEBJbmplY3QoJ2NvbmZpZ3VyYXRpb25zJykgcHJpdmF0ZSBjb25maWc6IENvbmZpZywgcHJpdmF0ZSBlaDogRUhhbmRsZXJTZXJ2aWNlKSB7IH1cbiAgaW50ZXJjZXB0KFxuICAgIHJlcTogSHR0cFJlcXVlc3Q8YW55PixcbiAgICBuZXh0OiBIdHRwSGFuZGxlclxuICApOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxhbnk+PiB7XG4gICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcSkucGlwZShcbiAgICAgIG1hcChldmVudCA9PiB7XG4gICAgICAgIGlmIChldmVudCBpbnN0YW5jZW9mIEh0dHBSZXNwb25zZSkge1xuICAgICAgICAgIGNvbnN0IHJlcXVlc3REYXRhID0gZXZlbnQuYm9keTtcbiAgICAgICAgICBpZiAocmVxdWVzdERhdGEpIHtcbiAgICAgICAgICAgIGlmIChyZXF1ZXN0RGF0YS5leGNlcHRpb24gJiYgcmVxdWVzdERhdGEuZXhjZXB0aW9uLmNvZGUpIHtcbiAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25maWcgJiYgdGhpcy5jb25maWcubG9nb3V0Q29kZXMgJiYgdGhpcy5jb25maWcubG9nb3V0Q29kZXMuaW5kZXhPZihyZXF1ZXN0RGF0YS5leGNlcHRpb24uY29kZSkgIT09IC0xICkge1xuICAgICAgICAgICAgICAgICAgdGhpcy5laC5sb2dvdXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSB7XG4gICAgICAgICAgICAgICAgICAgIGNvZGU6IHJlcXVlc3REYXRhLmV4Y2VwdGlvbi5jb2RlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiByZXF1ZXN0RGF0YS5leGNlcHRpb24ubWVzc2FnZVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgdGhpcy5laC5lcnJvck1TRyhlcnJvci5tZXNzYWdlLCBlcnJvci5jb2RlKTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuZWguc3RhdHVzTWVzc2FnZShlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1RoZXJlIHdhcyBhbiBlcnJvciB3aGlsZSB0cnlpbmcgdG8gc2VuZCBtZXNzYWdlJyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmVxdWVzdERhdGEuZXJyb3IgJiYgcmVxdWVzdERhdGEuZXJyb3IuY29kZSkge1xuICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZyAmJiB0aGlzLmNvbmZpZy5sb2dvdXRDb2RlcyAmJiB0aGlzLmNvbmZpZy5sb2dvdXRDb2Rlcy5pbmRleE9mKHJlcXVlc3REYXRhLmVycm9yLmNvZGUpICE9PSAtMSApIHtcbiAgICAgICAgICAgICAgICAgIHRoaXMuZWgubG9nb3V0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yID0ge1xuICAgICAgICAgICAgICAgICAgICBjb2RlOiByZXF1ZXN0RGF0YS5lcnJvci5jb2RlLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiByZXF1ZXN0RGF0YS5lcnJvci5tZXNzYWdlXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB0aGlzLmVoLmVycm9yTVNHKGVycm9yLm1lc3NhZ2UsIGVycm9yLmNvZGUpO1xuICAgICAgICAgICAgICAgICAgdGhpcy5laC5zdGF0dXNNZXNzYWdlKGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZygnVGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIHRyeWluZyB0byBzZW5kIG1lc3NhZ2UnKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZXZlbnQ7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoZXJyb3IgPT4ge1xuICAgICAgICB0aGlzLmVoLmhhbmRsZUVycm9yKGVycm9yKTtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9KSxcbiAgICAgIGZpbmFsaXplKCgpID0+IHt9KVxuICAgICk7XG4gIH1cbn1cbiIsImltcG9ydCB7RXJyb3JIYW5kbGVyLCBNb2R1bGVXaXRoUHJvdmlkZXJzLCBOZ01vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0NvbmZpZ30gZnJvbSAnLi9jb25zdC9jb25maWcnO1xuaW1wb3J0IHtFSW50ZXJjZXB0ZXJTZXJ2aWNlfSBmcm9tICcuL2VpbnRlcmNlcHRlci5zZXJ2aWNlJztcbmltcG9ydCB7RUhhbmRsZXJTZXJ2aWNlfSBmcm9tICcuL2VoYW5kbGVyLnNlcnZpY2UnO1xuaW1wb3J0IHtIVFRQX0lOVEVSQ0VQVE9SUywgSHR0cENsaWVudE1vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHtCcm93c2VyQW5pbWF0aW9uc01vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlci9hbmltYXRpb25zJztcbmltcG9ydCB7SG9va1NlcnZpY2V9IGZyb20gJy4vaG9vay5zZXJ2aWNlJztcblxuZXhwb3J0IGNvbnN0IEluaXRpYWxDb25maWc6IENvbmZpZyA9IHtcbiAgbWVzc2FnZToge1xuICAgIHVuQXV0aGVudGljYXRlZDogJ1hhaGnDhcKfIG9sdW51ciBzaXN0ZW3DicKZIGRheGlsIG9sdW4hJyxcbiAgICBzdGF0dXNFeGNlcHRpb246ICdTdGF0dXMgeMOJwpl0YXPDhMKxJyxcbiAgICBzZXJ2ZXJFeGNlcHRpb246ICdTZXJ2ZXIgeMOJwpl0YXPDhMKxJyxcbiAgICBhcHBFeGNlcHRpb246ICdTaXN0ZW0geMOJwpl0YXPDhMKxJ1xuICB9LFxuICBsb2dvdXQ6ICcvbG9nb3V0JyxcbiAgbG9nb3V0Q29kZXM6IFtcbiAgICA0MDEsICAvLyBCdSDDg8K8bnZhbmEgaWNhesOJwpluaXogeW94ZHVyXG4gICAgMTAwNSwgLy8gWW91IGFyZSBub3QgYWxsb3dlZCB0byByZXF1ZXN0IHRoaXMgcmVzb3VyY2VcbiAgICAxMDA2LCAvLyBUb2tlbiB0YXDDhMKxbG1hZMOEwrFcbiAgICAxMDE0LCAvLyBUb2tlbiB0YXDDhMKxbG1hZMOEwrEsIHrDicKZaG3DicKZdCBvbG1hc2Egc2lzdGVtw4nCmSB5ZW5pZMOJwpluIGRheGlsIG9sdW5cbiAgICAxMDE1LCAvLyBTaXppbiBzaXN0ZW1sw4nCmXJkw4nCmW4gaXN0aWbDicKZZMOJwpkgaMODwrxxdXF1bnV6IHlveGR1clxuICAgIDEwMTYsIC8vIFNpemluIGJ1IHNpc3RlbcOJwpkgaXN0aWbDicKZZMOJwpkgaMODwrxxdXF1bnV6IHlveGR1clxuICAgIDEwMTcsIC8vIFNlc3NpeWEgYmHDhMKfbGFubcOEwrHDhcKfZMOEwrFyLCB6w4nCmWhtw4nCmXQgb2xtYXNhIHNpc3RlbcOJwpkgeWVuaWTDicKZbiBkYXhpbCBvbHVuLlxuICAgIDE0MDEsIC8vIFNlc3NpeWEgbcODwrxkZMOJwpl0aSBiaXRtacOFwp9kaXIsIHrDicKZaG3DicKZdCBvbG1henNhIHNpc3RlbcOJwpkgeWVuaWTDicKZbiBkYXhpbCBvbHVuXG4gICAgLy8gMTQwMiAgLy8gU2l6aW4gYnUgc2Vydmlzw4nCmSBpY2F6w4nCmW5peiB5b3hkdXJcbiAgXSxcbiAgaG9vazogJ2h0dHBzOi8vaG9va3Muc2xhY2suY29tL3NlcnZpY2VzL1RDMTBHSDQ4Wi9CQzJBMjlZMlovdHB4VjBpSUhoajJmVFM2Rk8wUEExQ3pjJyxcbn1cblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIEh0dHBDbGllbnRNb2R1bGUsXG4gICAgQnJvd3NlckFuaW1hdGlvbnNNb2R1bGVcbiAgXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAgeyBwcm92aWRlOiBFcnJvckhhbmRsZXIsIHVzZUNsYXNzOiBFSGFuZGxlclNlcnZpY2UgfSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBIVFRQX0lOVEVSQ0VQVE9SUyxcbiAgICAgIHVzZUNsYXNzOiBFSW50ZXJjZXB0ZXJTZXJ2aWNlLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9LFxuICAgIEhvb2tTZXJ2aWNlXG4gIF0sXG4gIGRlY2xhcmF0aW9uczogW10sXG4gIGV4cG9ydHM6IFtdXG59KVxuZXhwb3J0IGNsYXNzIEVIYW5kbGVyTW9kdWxlIHtcbiAgc3RhdGljIGZvclJvb3QoY29uZmlndXJhdGlvbnMgPSBJbml0aWFsQ29uZmlnKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5nTW9kdWxlOiBFSGFuZGxlck1vZHVsZSxcbiAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7cHJvdmlkZTogJ2NvbmZpZ3VyYXRpb25zJywgdXNlVmFsdWU6IGNvbmZpZ3VyYXRpb25zfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuICBzdGF0aWMgZm9yQ2hpbGQoKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG5cbiAgICByZXR1cm57XG4gICAgICBuZ01vZHVsZTogRUhhbmRsZXJNb2R1bGUsXG4gICAgfTtcblxuICB9XG5cbn1cbiJdLCJuYW1lcyI6WyJlcnJvciIsInRvYXN0ci5lcnJvciJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0lBUUUscUJBQW9CLElBQWdCLEVBQW9DLE1BQWM7UUFBbEUsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUFvQyxXQUFNLEdBQU4sTUFBTSxDQUFRO0tBQUk7Ozs7Ozs7OztJQUsxRixpQ0FBVzs7Ozs7SUFBWCxVQUFZLE9BQVk7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEVBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFDLENBQUMsQ0FBQyxTQUFTLENBQUUsVUFBQSxRQUFRO1lBQ3hHLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7U0FDOUIsQ0FBQyxDQUFDO0tBQ0o7Ozs7Ozs7Ozs7SUFLRCxxQ0FBZTs7Ozs7O0lBQWYsVUFBZ0JBLFFBQUssRUFBRSxLQUFVO1FBQWpDLGlCQWlDQztRQWpDc0Isc0JBQUEsRUFBQSxVQUFVOztRQUMvQixJQUFNLE1BQU0sR0FBR0EsUUFBSyxDQUFDLE1BQU0sR0FBR0EsUUFBSyxDQUFDLE1BQU0sR0FBRyxtQkFBbUIsQ0FBQzs7OztRQUlqRSxJQUFNLE9BQU8sR0FBRztZQUNkLElBQUksRUFBRSw4QkFBOEIsR0FBRyxNQUFNLEdBQUcsOEJBQThCO1lBQzlFLFdBQVcsRUFBRTtnQkFDWDtvQkFDRSxXQUFXLEVBQUUsU0FBUyxHQUFHLEtBQUssR0FBRyxTQUFTLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJO29CQUNqRSxLQUFLLEVBQUUsV0FBVyxHQUFHQSxRQUFLLENBQUMsT0FBTztvQkFDbEMsSUFBSSxFQUFFLFFBQVEsR0FBRyxJQUFJLElBQUksRUFBRSxHQUFHLGVBQWUsR0FBRyxTQUFTLENBQUMsU0FBUzt3QkFDbkUsNkRBQTZEO2lCQUM5RDthQUNGO1NBQ0YsQ0FBQztRQUNGLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFOztZQUNoQixJQUFNLE9BQU8sR0FBRyxJQUFJLFdBQVcsQ0FBQztnQkFDOUIsY0FBYyxFQUFFLFlBQVk7YUFDN0IsQ0FBQyxDQUFBO1lBQ0YsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxPQUFPLFNBQUEsRUFBQyxDQUFDO2lCQUM1RyxJQUFJLENBQ0gsVUFBVSxDQUFDLFVBQUEsQ0FBQztnQkFDVixLQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztnQkFDbkIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO2dCQUNwQyxNQUFNLENBQUMsQ0FBQzthQUNULENBQUMsQ0FDSDtpQkFDQSxTQUFTLENBQUUsVUFBQSxRQUFRO2dCQUNsQixPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUM7YUFDL0IsQ0FBQyxDQUFDO1NBQ047S0FFRjs7Z0JBbERGLFVBQVU7Ozs7Z0JBSkgsVUFBVTtnREFPdUIsTUFBTSxTQUFDLGdCQUFnQjs7c0JBUmhFOzs7Ozs7O0FDQUE7SUFTRSx5QkFDVSxVQUMwQixNQUFjLEVBQ3hDO1FBRkEsYUFBUSxHQUFSLFFBQVE7UUFDa0IsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUN4QyxTQUFJLEdBQUosSUFBSTtLQUViOzs7Ozs7Ozs7SUFJRCxxQ0FBVzs7Ozs7SUFBWCxVQUFZQSxRQUFVOzs7O1FBSXBCLElBQUksT0FBTyxDQUFTOzs7O1FBSXBCLElBQU0sSUFBSSxHQUFTLElBQUksSUFBSSxFQUFFLENBQUM7Ozs7UUFJOUIsSUFBSUEsUUFBSyxZQUFZLGlCQUFpQixFQUFFO1lBQ3RDLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUM7Ozs7O1lBSzlDLFFBQVFBLFFBQUssQ0FBQyxNQUFNO2dCQUNsQixLQUFLLEdBQUcsQ0FBQztnQkFDVCxLQUFLLEdBQUc7b0JBQ04sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNkLE1BQU07Z0JBQ1IsS0FBSyxHQUFHO29CQUNOLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUM7YUFDakQ7O1lBRUQsSUFBSSxDQUFDLGFBQWEsQ0FBQ0EsUUFBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1NBQ2pDO2FBQU07O1lBRUwsSUFBSSxDQUFDLGFBQWEsQ0FBQ0EsUUFBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2hDLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7U0FDNUM7UUFDRCxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0tBQ3hCOzs7Ozs7Ozs7SUFLRCxnQ0FBTTs7Ozs7SUFBTixVQUFPLE9BQWdCO1FBQXZCLGlCQVFDO1FBUENDLEtBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNsRCxJQUFJLE9BQU8sRUFBRTtZQUNYQSxLQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7U0FDdkI7UUFDRCxVQUFVLENBQUM7WUFDVCxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQzdDLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDVjs7Ozs7Ozs7OztJQUtELGtDQUFROzs7Ozs7SUFBUixVQUFTLE9BQU8sRUFBRSxJQUFXO1FBQVgscUJBQUEsRUFBQSxXQUFXO1FBQzNCQSxLQUFZLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQzdCOzs7Ozs7Ozs7O0lBSUQsdUNBQWE7Ozs7OztJQUFiLFVBQWNELFFBQUssRUFBRSxJQUFpQjtRQUFqQixxQkFBQSxFQUFBLFdBQVcsSUFBSSxFQUFFO1FBQ3BDLE9BQU8sQ0FBQyxLQUFLLENBQ1gsZ0RBQWdELEVBQ2hELGdDQUFnQyxHQUFHQSxRQUFLLENBQUMsTUFBTSxHQUFHLElBQUksRUFDdEQseUJBQXlCLEdBQUdBLFFBQUssQ0FBQyxPQUFPLEdBQUcsSUFBSSxFQUNoRCxJQUFJLEdBQUcsSUFBSSxFQUNYLDhDQUE4QyxDQUMvQyxDQUFDO1FBQ0EsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUNBLFFBQUssQ0FBQyxPQUFPLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztLQUNsRTs7Ozs7Ozs7OztJQUtELHVDQUFhOzs7Ozs7SUFBYixVQUFjQSxRQUFLLEVBQUUsSUFBaUI7UUFBakIscUJBQUEsRUFBQSxXQUFXLElBQUksRUFBRTtRQUNwQyxPQUFPLENBQUMsS0FBSyxDQUNYLGdEQUFnRCxFQUNoRCw2QkFBNkIsR0FBR0EsUUFBSyxDQUFDLE9BQU8sR0FBRyxJQUFJLEVBQ3BELElBQUksR0FBRyxJQUFJLEVBQ1gsOENBQThDLENBQy9DLENBQUM7UUFDRixJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQ0EsUUFBSyxDQUFDLE9BQU8sRUFBRSxzQkFBc0IsQ0FBQyxDQUFDO0tBQ2xFOztnQkE3RkYsVUFBVSxTQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQjs7OztnQkFQeUMsUUFBUTtnREFXN0MsTUFBTSxTQUFDLGdCQUFnQjtnQkFScEIsV0FBVzs7OzBCQUhuQjs7Ozs7OztBQ0FBO0lBU0UsNkJBQThDLE1BQWMsRUFBVSxFQUFtQjtRQUEzQyxXQUFNLEdBQU4sTUFBTSxDQUFRO1FBQVUsT0FBRSxHQUFGLEVBQUUsQ0FBaUI7S0FBSzs7Ozs7O0lBQzlGLHVDQUFTOzs7OztJQUFULFVBQ0UsR0FBcUIsRUFDckIsSUFBaUI7UUFGbkIsaUJBa0RDO1FBOUNDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQzFCLEdBQUcsQ0FBQyxVQUFBLEtBQUs7WUFDUCxJQUFJLEtBQUssWUFBWSxZQUFZLEVBQUU7O2dCQUNqQyxJQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDO2dCQUMvQixJQUFJLFdBQVcsRUFBRTtvQkFDZixJQUFJLFdBQVcsQ0FBQyxTQUFTLElBQUksV0FBVyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUU7d0JBQ3ZELElBQUk7NEJBQ0YsSUFBSSxLQUFJLENBQUMsTUFBTSxJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxJQUFJLEtBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBRSxFQUFFO2dDQUNqSCxLQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDOzZCQUNsQjtpQ0FBTTs7Z0NBQ0wsSUFBTUEsUUFBSyxHQUFHO29DQUNaLElBQUksRUFBRSxXQUFXLENBQUMsU0FBUyxDQUFDLElBQUk7b0NBQ2hDLE9BQU8sRUFBRSxXQUFXLENBQUMsU0FBUyxDQUFDLE9BQU87aUNBQ3ZDLENBQUE7Z0NBQ0QsS0FBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUNBLFFBQUssQ0FBQyxPQUFPLEVBQUVBLFFBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztnQ0FDNUMsS0FBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUNBLFFBQUssQ0FBQyxDQUFDOzZCQUM5Qjt5QkFDRjt3QkFBQyxPQUFPLENBQUMsRUFBRTs0QkFDVixPQUFPLENBQUMsR0FBRyxDQUFDLGlEQUFpRCxDQUFDLENBQUM7eUJBQ2hFO3FCQUNGO3lCQUFNLElBQUksV0FBVyxDQUFDLEtBQUssSUFBSSxXQUFXLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRTt3QkFDdEQsSUFBSTs0QkFDRixJQUFJLEtBQUksQ0FBQyxNQUFNLElBQUksS0FBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLElBQUksS0FBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFFLEVBQUU7Z0NBQzdHLEtBQUksQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUM7NkJBQ2xCO2lDQUFNOztnQ0FDTCxJQUFNQSxRQUFLLEdBQUc7b0NBQ1osSUFBSSxFQUFFLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSTtvQ0FDNUIsT0FBTyxFQUFFLFdBQVcsQ0FBQyxLQUFLLENBQUMsT0FBTztpQ0FDbkMsQ0FBQTtnQ0FDRCxLQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQ0EsUUFBSyxDQUFDLE9BQU8sRUFBRUEsUUFBSyxDQUFDLElBQUksQ0FBQyxDQUFDO2dDQUM1QyxLQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsQ0FBQ0EsUUFBSyxDQUFDLENBQUM7NkJBQzlCO3lCQUNGO3dCQUFDLE9BQU8sQ0FBQyxFQUFFOzRCQUNWLE9BQU8sQ0FBQyxHQUFHLENBQUMsaURBQWlELENBQUMsQ0FBQzt5QkFDaEU7cUJBQ0Y7aUJBQ0Y7YUFDRjtZQUNELE9BQU8sS0FBSyxDQUFDO1NBQ2QsQ0FBQyxFQUNGLFVBQVUsQ0FBQyxVQUFBQSxRQUFLO1lBQ2QsS0FBSSxDQUFDLEVBQUUsQ0FBQyxXQUFXLENBQUNBLFFBQUssQ0FBQyxDQUFDO1lBQzNCLE1BQU1BLFFBQUssQ0FBQztTQUNiLENBQUMsRUFDRixRQUFRLENBQUMsZUFBUSxDQUFDLENBQ25CLENBQUM7S0FDSDs7Z0JBckRGLFVBQVU7Ozs7Z0RBRUksTUFBTSxTQUFDLGdCQUFnQjtnQkFKOUIsZUFBZTs7OEJBTHZCOzs7Ozs7O0FDQUE7QUFRQSxJQUFhLGFBQWEsR0FBVztJQUNuQyxPQUFPLEVBQUU7UUFDUCxlQUFlLEVBQUUsa0NBQWtDO1FBQ25ELGVBQWUsRUFBRSxlQUFlO1FBQ2hDLGVBQWUsRUFBRSxlQUFlO1FBQ2hDLFlBQVksRUFBRSxlQUFlO0tBQzlCO0lBQ0QsTUFBTSxFQUFFLFNBQVM7SUFDakIsV0FBVyxFQUFFO1FBQ1gsR0FBRztRQUNILElBQUk7UUFDSixJQUFJO1FBQ0osSUFBSTtRQUNKLElBQUk7UUFDSixJQUFJO1FBQ0osSUFBSTtRQUNKLElBQUk7S0FFTDtJQUNELElBQUksRUFBRSwrRUFBK0U7Q0FDdEYsQ0FBQTs7Ozs7Ozs7SUFvQlEsc0JBQU87Ozs7SUFBZCxVQUFlLGNBQThCO1FBQTlCLCtCQUFBLEVBQUEsOEJBQThCO1FBQzNDLE9BQU87WUFDTCxRQUFRLEVBQUUsY0FBYztZQUN4QixTQUFTLEVBQUU7Z0JBQ1QsRUFBQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBQzthQUN0RDtTQUNGLENBQUM7S0FDSDs7OztJQUNNLHVCQUFROzs7SUFBZjtRQUVFLE9BQU07WUFDSixRQUFRLEVBQUUsY0FBYztTQUN6QixDQUFDO0tBRUg7O2dCQWhDRixRQUFRLFNBQUM7b0JBQ1IsT0FBTyxFQUFFO3dCQUNQLGdCQUFnQjt3QkFDaEIsdUJBQXVCO3FCQUN4QjtvQkFDRCxTQUFTLEVBQUU7d0JBQ1QsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUU7d0JBQ3BEOzRCQUNFLE9BQU8sRUFBRSxpQkFBaUI7NEJBQzFCLFFBQVEsRUFBRSxtQkFBbUI7NEJBQzdCLEtBQUssRUFBRSxJQUFJO3lCQUNaO3dCQUNELFdBQVc7cUJBQ1o7b0JBQ0QsWUFBWSxFQUFFLEVBQUU7b0JBQ2hCLE9BQU8sRUFBRSxFQUFFO2lCQUNaOzt5QkE5Q0Q7Ozs7Ozs7Ozs7Ozs7OzsifQ==