UNPKG

ehandler

Version:

Exception handler for Angular Applications

351 lines (343 loc) 32.1 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 */ class HookService { /** * @param {?} http * @param {?} config */ constructor(http, config) { this.http = http; this.config = config; } /** * Send Message * @param {?} payload * @return {?} */ sendMessage(payload) { this.http.post(this.config.hook, payload, { observe: 'response', responseType: 'text' }).subscribe(response => { console.info('Message sent'); }); } /** * Send Exception to hook * @param {?} error * @param {?=} couse * @return {?} */ exceptionNotify(error$$1, couse = '') { /** @type {?} */ const status = error$$1.status ? error$$1.status : 'Application Error'; /** * * Error Payload @type {?} */ const 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 {?} */ const headers = new HttpHeaders({ 'Content-Type': 'text/plain' }); this.http.post(this.config.hook, JSON.stringify(payload), { observe: 'response', responseType: 'text', headers }) .pipe(catchError(e => { this.bugged = true; console.log('Hook stopped working'); throw e; })) .subscribe(response => { console.log('Exception Sent'); }); } } } HookService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ HookService.ctorParameters = () => [ { type: HttpClient }, { type: undefined, decorators: [{ type: Inject, args: ['configurations',] }] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class EHandlerService { /** * @param {?} injector * @param {?} config * @param {?} hook */ constructor(injector, config, hook) { this.injector = injector; this.config = config; this.hook = hook; } /** * Global Error Handler * @param {?} error * @return {?} */ handleError(error$$1) { /** * * Error Message for view @type {?} */ let message; /** * * Error TimeStamp @type {?} */ const 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 * @param {?=} message * @return {?} */ logout(message) { error(this.config.message.unAuthenticated); if (message) { error(message); } setTimeout(() => { window.location.replace(this.config.logout); }, 5000); } /** * Show Error Message * @param {?} message * @param {?=} code * @return {?} */ errorMSG(message, code = null) { error(message, code); } /** * Log Error Message * @param {?} error * @param {?=} date * @return {?} */ statusMessage(error$$1, 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 * @param {?} error * @param {?=} date * @return {?} */ commonMessage(error$$1, 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 = () => [ { 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" }); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class EIntercepterService { /** * @param {?} config * @param {?} eh */ constructor(config, eh) { this.config = config; this.eh = eh; } /** * @param {?} req * @param {?} next * @return {?} */ intercept(req, next) { return next.handle(req).pipe(map(event => { if (event instanceof HttpResponse) { /** @type {?} */ const 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 {?} */ const 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 {?} */ const 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(error$$1 => { this.eh.handleError(error$$1); throw error$$1; }), finalize(() => { })); } } EIntercepterService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ EIntercepterService.ctorParameters = () => [ { type: undefined, decorators: [{ type: Inject, args: ['configurations',] }] }, { type: EHandlerService } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** @type {?} */ const 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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', }; class EHandlerModule { /** * @param {?=} configurations * @return {?} */ static forRoot(configurations = InitialConfig) { return { ngModule: EHandlerModule, providers: [ { provide: 'configurations', useValue: configurations }, ], }; } /** * @return {?} */ static forChild() { 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: [] },] }, ]; /** * @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+IHt9KVxuICAgICk7XG4gIH1cbn1cbiIsImltcG9ydCB7RXJyb3JIYW5kbGVyLCBNb2R1bGVXaXRoUHJvdmlkZXJzLCBOZ01vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0NvbmZpZ30gZnJvbSAnLi9jb25zdC9jb25maWcnO1xuaW1wb3J0IHtFSW50ZXJjZXB0ZXJTZXJ2aWNlfSBmcm9tICcuL2VpbnRlcmNlcHRlci5zZXJ2aWNlJztcbmltcG9ydCB7RUhhbmRsZXJTZXJ2aWNlfSBmcm9tICcuL2VoYW5kbGVyLnNlcnZpY2UnO1xuaW1wb3J0IHtIVFRQX0lOVEVSQ0VQVE9SUywgSHR0cENsaWVudE1vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHtCcm93c2VyQW5pbWF0aW9uc01vZHVsZX0gZnJvbSAnQGFuZ3VsYXIvcGxhdGZvcm0tYnJvd3Nlci9hbmltYXRpb25zJztcbmltcG9ydCB7SG9va1NlcnZpY2V9IGZyb20gJy4vaG9vay5zZXJ2aWNlJztcblxuZXhwb3J0IGNvbnN0IEluaXRpYWxDb25maWc6IENvbmZpZyA9IHtcbiAgbWVzc2FnZToge1xuICAgIHVuQXV0aGVudGljYXRlZDogJ1hhaGnDhcKfIG9sdW51ciBzaXN0ZW3DicKZIGRheGlsIG9sdW4hJyxcbiAgICBzdGF0dXNFeGNlcHRpb246ICdTdGF0dXMgeMOJwpl0YXPDhMKxJyxcbiAgICBzZXJ2ZXJFeGNlcHRpb246ICdTZXJ2ZXIgeMOJwpl0YXPDhMKxJyxcbiAgICBhcHBFeGNlcHRpb246ICdTaXN0ZW0geMOJwpl0YXPDhMKxJ1xuICB9LFxuICBsb2dvdXQ6ICcvbG9nb3V0JyxcbiAgbG9nb3V0Q29kZXM6IFtcbiAgICA0MDEsICAvLyBCdSDDg8K8bnZhbmEgaWNhesOJwpluaXogeW94ZHVyXG4gICAgMTAwNSwgLy8gWW91IGFyZSBub3QgYWxsb3dlZCB0byByZXF1ZXN0IHRoaXMgcmVzb3VyY2VcbiAgICAxMDA2LCAvLyBUb2tlbiB0YXDDhMKxbG1hZMOEwrFcbiAgICAxMDE0LCAvLyBUb2tlbiB0YXDDhMKxbG1hZMOEwrEsIHrDicKZaG3DicKZdCBvbG1hc2Egc2lzdGVtw4nCmSB5ZW5pZMOJwpluIGRheGlsIG9sdW5cbiAgICAxMDE1LCAvLyBTaXppbiBzaXN0ZW1sw4nCmXJkw4nCmW4gaXN0aWbDicKZZMOJwpkgaMODwrxxdXF1bnV6IHlveGR1clxuICAgIDEwMTYsIC8vIFNpemluIGJ1IHNpc3RlbcOJwpkgaXN0aWbDicKZZMOJwpkgaMODwrxxdXF1bnV6IHlveGR1clxuICAgIDEwMTcsIC8vIFNlc3NpeWEgYmHDhMKfbGFubcOEwrHDhcKfZMOEwrFyLCB6w4nCmWhtw4nCmXQgb2xtYXNhIHNpc3RlbcOJwpkgeWVuaWTDicKZbiBkYXhpbCBvbHVuLlxuICAgIDE0MDEsIC8vIFNlc3NpeWEgbcODwrxkZMOJwpl0aSBiaXRtacOFwp9kaXIsIHrDicKZaG3DicKZdCBvbG1henNhIHNpc3RlbcOJwpkgeWVuaWTDicKZbiBkYXhpbCBvbHVuXG4gICAgLy8gMTQwMiAgLy8gU2l6aW4gYnUgc2Vydmlzw4nCmSBpY2F6w4nCmW5peiB5b3hkdXJcbiAgXSxcbiAgaG9vazogJ2h0dHBzOi8vaG9va3Muc2xhY2suY29tL3NlcnZpY2VzL1RDMTBHSDQ4Wi9CQzJBMjlZMlovdHB4VjBpSUhoajJmVFM2Rk8wUEExQ3pjJyxcbn1cblxuQE5nTW9kdWxlKHtcbiAgaW1wb3J0czogW1xuICAgIEh0dHBDbGllbnRNb2R1bGUsXG4gICAgQnJvd3NlckFuaW1hdGlvbnNNb2R1bGVcbiAgXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAgeyBwcm92aWRlOiBFcnJvckhhbmRsZXIsIHVzZUNsYXNzOiBFSGFuZGxlclNlcnZpY2UgfSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBIVFRQX0lOVEVSQ0VQVE9SUyxcbiAgICAgIHVzZUNsYXNzOiBFSW50ZXJjZXB0ZXJTZXJ2aWNlLFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9LFxuICAgIEhvb2tTZXJ2aWNlXG4gIF0sXG4gIGRlY2xhcmF0aW9uczogW10sXG4gIGV4cG9ydHM6IFtdXG59KVxuZXhwb3J0IGNsYXNzIEVIYW5kbGVyTW9kdWxlIHtcbiAgc3RhdGljIGZvclJvb3QoY29uZmlndXJhdGlvbnMgPSBJbml0aWFsQ29uZmlnKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5nTW9kdWxlOiBFSGFuZGxlck1vZHVsZSxcbiAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7cHJvdmlkZTogJ2NvbmZpZ3VyYXRpb25zJywgdXNlVmFsdWU6IGNvbmZpZ3VyYXRpb25zfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuICBzdGF0aWMgZm9yQ2hpbGQoKTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG5cbiAgICByZXR1cm57XG4gICAgICBuZ01vZHVsZTogRUhhbmRsZXJNb2R1bGUsXG4gICAgfTtcblxuICB9XG5cbn1cbiJdLCJuYW1lcyI6WyJlcnJvciIsInRvYXN0ci5lcnJvciJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBOzs7OztJQVFFLFlBQW9CLElBQWdCLEVBQW9DLE1BQWM7UUFBbEUsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUFvQyxXQUFNLEdBQU4sTUFBTSxDQUFRO0tBQUk7Ozs7OztJQUsxRixXQUFXLENBQUMsT0FBWTtRQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsRUFBQyxPQUFPLEVBQUUsVUFB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