UNPKG

67.3 kBJavaScriptView Raw
1import { __decorate, __metadata, __awaiter } from 'tslib';
2import { forwardRef, Injectable, InjectionToken, Component, NgModule } from '@angular/core';
3import { Type, plainToClass } from 'class-transformer';
4import { Router, ActivatedRoute, RouterModule } from '@angular/router';
5import { Storage, UbudStorageModule } from '@ubud/storage';
6import { forkJoin, Observable, of } from 'rxjs';
7import { fromPromise } from 'rxjs/internal/observable/fromPromise';
8import { catchError, map, switchMap, tap, first } from 'rxjs/internal/operators';
9import { HttpClient } from '@angular/common/http';
10import { Location } from '@angular/common';
11import { ErrorObservable } from 'rxjs-compat/observable/ErrorObservable';
12
13/**
14 * @fileoverview added by tsickle
15 * @suppress {checkTypes} checked by tsc
16 */
17class Config {
18 /**
19 * @param {?=} data
20 */
21 constructor(data) {
22 this.endpoint = 'https://account.kemnaker.go.id';
23 Object.assign(this, data);
24 }
25}
26
27/**
28 * @fileoverview added by tsickle
29 * @suppress {checkTypes} checked by tsc
30 */
31class User {
32}
33__decorate([
34 Type(/** @type {?} */ (forwardRef(() => Date))),
35 __metadata("design:type", Date)
36], User.prototype, "updatedAt", void 0);
37
38/**
39 * @fileoverview added by tsickle
40 * @suppress {checkTypes} checked by tsc
41 */
42class NacoService {
43 /**
44 * @param {?} config
45 * @param {?} router
46 * @param {?} storage
47 * @param {?} http
48 * @param {?} location
49 */
50 constructor(config, router, storage, http, location) {
51 this.config = config;
52 this.router = router;
53 this.storage = storage;
54 this.http = http;
55 this.location = location;
56 this.VERSION = 'v1';
57 this.signature = null;
58 this.user = null;
59 this.refreshToken = null;
60 this.clientSecret = null;
61 }
62 /**
63 * @param {?} user
64 * @return {?}
65 */
66 setUser(user) {
67 this.user = user;
68 this.storage.set('user', user);
69 }
70 /**
71 * @return {?}
72 */
73 getUser() {
74 if (null !== this.user) {
75 return of(this.user);
76 }
77 return fromPromise(this.storage.get('user')).pipe(switchMap((user) => {
78 if (user) {
79 return of(user);
80 }
81 const /** @type {?} */ uri = this.getUri('/users/me');
82 return fromPromise(this.getSignature()).pipe(switchMap((signature) => {
83 if (null === signature) {
84 return this.refreshUser();
85 }
86 const /** @type {?} */ options = {
87 headers: {
88 Authorization: `${signature.type} ${signature.token}`,
89 },
90 };
91 return this.http.get(uri, options).pipe(map((res) => {
92 if (res.data) {
93 return res.data;
94 }
95 throw new Error('There are no body to be transformed');
96 }), map((data) => {
97 const /** @type {?} */ authUser = plainToClass(User, data);
98 this.setUser(authUser);
99 return authUser;
100 }), catchError((e) => {
101 if (401 === e.status) {
102 return this.refreshUser().pipe(switchMap((refreshUser) => {
103 if (refreshUser) {
104 return of(refreshUser);
105 }
106 return ErrorObservable.create(e);
107 }));
108 }
109 return ErrorObservable.create(e);
110 }));
111 }));
112 }));
113 }
114 /**
115 * @return {?}
116 */
117 getSignature() {
118 if (this.signature) {
119 return Promise.resolve(this.signature);
120 }
121 return this.storage.get('signature');
122 }
123 /**
124 * @param {?} signature
125 * @return {?}
126 */
127 setSignature(signature) {
128 this.signature = signature;
129 this.storage.set('signature', signature);
130 }
131 /**
132 * @param {?} secret
133 * @return {?}
134 */
135 setClientSecret(secret) {
136 this.clientSecret = secret;
137 this.storage.set('client_secret', secret);
138 }
139 /**
140 * @param {?} refreshToken
141 * @return {?}
142 */
143 setRefreshToken(refreshToken) {
144 this.refreshToken = refreshToken;
145 this.storage.set('refresh_token', refreshToken);
146 }
147 /**
148 * @param {?=} scopes
149 * @return {?}
150 */
151 refreshUser(scopes) {
152 this.setUser(null);
153 this.setSignature(null);
154 return forkJoin(this.getRefreshToken(), this.getClientSecret()).pipe(switchMap((results) => {
155 const /** @type {?} */ refreshToken = results[0];
156 const /** @type {?} */ clientSecret = results[1];
157 if (refreshToken && clientSecret) {
158 return this.refreshWithRefreshToken(clientSecret, refreshToken.token, scopes);
159 }
160 return this.refreshWithSilentAuth();
161 }));
162 }
163 /**
164 * @param {?} clientSecret
165 * @param {?} refreshToken
166 * @param {?=} scopes
167 * @return {?}
168 */
169 refreshWithRefreshToken(clientSecret, refreshToken, scopes) {
170 const /** @type {?} */ request = this.http.post(this.getUri('/tokens'), {
171 grant_type: 'refresh_token',
172 scopes: scopes || 'basic email',
173 client_id: this.config.clientId,
174 client_secret: clientSecret,
175 refresh_token: refreshToken,
176 });
177 return request.pipe(tap((tokens) => {
178 if (tokens && tokens.data) {
179 this.setSignature({
180 expiresIn: tokens.data.expires_in,
181 type: tokens.data.token_type,
182 token: tokens.data.access_token,
183 });
184 this.setRefreshToken({
185 type: tokens.data.token_type,
186 token: tokens.data.refresh_token,
187 });
188 }
189 }), map((tokens) => tokens && tokens.data), switchMap((hasToken) => {
190 if (hasToken) {
191 return this.getUser();
192 }
193 return of(null);
194 }));
195 }
196 /**
197 * @return {?}
198 */
199 refreshWithSilentAuth() {
200 return new Observable((observer) => {
201 const /** @type {?} */ redirectUri = this.getCurrentOrigin('auth/silent');
202 const /** @type {?} */ uri = this.login('basic email', redirectUri, false);
203 const /** @type {?} */ iframe = document.createElement('iframe');
204 iframe.setAttribute('src', uri);
205 iframe.style.display = 'none';
206 iframe.addEventListener('load', () => __awaiter(this, void 0, void 0, function* () {
207 try {
208 const /** @type {?} */ queryString = iframe.contentWindow.location.search.substring(1);
209 iframe.parentNode.removeChild(iframe);
210 if (queryString) {
211 const /** @type {?} */ queryParts = queryString.split('&');
212 const /** @type {?} */ params = {};
213 for (const /** @type {?} */ item of queryParts) {
214 const /** @type {?} */ itemParts = item.split('=');
215 params[itemParts[0]] = itemParts[1];
216 }
217 if (params.hasOwnProperty('access_token')) {
218 this.setSignature({
219 token: params['access_token'],
220 type: params['token_type'],
221 expiresIn: params['ttl'],
222 });
223 const /** @type {?} */ user = yield this.getUser().toPromise();
224 if (user) {
225 this.setUser(user);
226 }
227 observer.next(user);
228 }
229 else {
230 observer.next(null);
231 }
232 return;
233 }
234 observer.next(null);
235 }
236 catch (/** @type {?} */ e) {
237 observer.next(null);
238 }
239 }), false);
240 document.body.appendChild(iframe);
241 });
242 }
243 /**
244 * @param {?} scopes
245 * @param {?=} redirectUri
246 * @param {?=} needState
247 * @return {?}
248 */
249 login(scopes, redirectUri, needState = true) {
250 if (!redirectUri) {
251 redirectUri = this.router.url;
252 }
253 const /** @type {?} */ params = {
254 'response_type': 'token',
255 'scopes': scopes,
256 'client': this.config.clientId,
257 'silent': true,
258 'continue': encodeURIComponent(redirectUri),
259 };
260 if (needState) {
261 const /** @type {?} */ state = this.generateState();
262 this.storage.set('state', state);
263 params.state = state;
264 }
265 const /** @type {?} */ query = this.buildQueryString(params);
266 return this.config.endpoint + '/auth?' + query;
267 }
268 /**
269 * @param {?=} redirectUri
270 * @return {?}
271 */
272 logout(redirectUri) {
273 this.signature = null;
274 this.user = null;
275 return new Promise(resolve => {
276 Promise.all([
277 this.storage.remove('signature'),
278 this.storage.remove('user'),
279 ]).then(() => {
280 let /** @type {?} */ endpoint = this.config.endpoint + '/auth/logout';
281 if (redirectUri) {
282 endpoint += '?continue=' + encodeURIComponent(redirectUri);
283 }
284 resolve(endpoint);
285 });
286 });
287 }
288 /**
289 * @return {?}
290 */
291 getState() {
292 return this.storage.get('state');
293 }
294 /**
295 * @param {?} route
296 * @return {?}
297 */
298 buildNestedUri(route) {
299 let /** @type {?} */ uri = '';
300 if (route.routeConfig && route.routeConfig.path) {
301 let /** @type {?} */ routePath = route.routeConfig.path;
302 for (const /** @type {?} */ key in route.params) {
303 if (key) {
304 const /** @type {?} */ re = new RegExp('\:' + key);
305 routePath = routePath.replace(re, route.params[key]);
306 }
307 }
308 uri += '/' + routePath;
309 }
310 if (route.children) {
311 route.children.forEach((item) => {
312 uri += this.buildNestedUri(item);
313 });
314 }
315 return uri;
316 }
317 /**
318 * @return {?}
319 */
320 getRefreshToken() {
321 if (null !== this.refreshToken) {
322 return Promise.resolve(this.refreshToken);
323 }
324 return this.storage.get('refresh_token');
325 }
326 /**
327 * @return {?}
328 */
329 getClientSecret() {
330 if (null !== this.clientSecret) {
331 return Promise.resolve(this.clientSecret);
332 }
333 return this.storage.get('client_secret');
334 }
335 /**
336 * @param {?} path
337 * @return {?}
338 */
339 getUri(path) {
340 return this.config.endpoint + '/api/' + this.VERSION + path;
341 }
342 /**
343 * @param {?=} path
344 * @return {?}
345 */
346 getCurrentOrigin(path) {
347 return window.location.origin + this.location.prepareExternalUrl(path || '');
348 }
349 /**
350 * @return {?}
351 */
352 generateState() {
353 const /** @type {?} */ possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
354 let /** @type {?} */ text = '';
355 for (let /** @type {?} */ i = 0; i < 5; i++) {
356 text += possible.charAt(Math.floor(Math.random() * possible.length));
357 }
358 return text;
359 }
360 /**
361 * @param {?} params
362 * @return {?}
363 */
364 buildQueryString(params) {
365 const /** @type {?} */ queryParams = Object.keys(params).map((key) => {
366 return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
367 });
368 return queryParams.join('&');
369 }
370}
371NacoService.decorators = [
372 { type: Injectable },
373];
374/** @nocollapse */
375NacoService.ctorParameters = () => [
376 { type: Config },
377 { type: Router },
378 { type: Storage },
379 { type: HttpClient },
380 { type: Location }
381];
382
383/**
384 * @fileoverview added by tsickle
385 * @suppress {checkTypes} checked by tsc
386 */
387class Signature {
388}
389
390/**
391 * @fileoverview added by tsickle
392 * @suppress {checkTypes} checked by tsc
393 */
394class AuthenticatedGuard {
395 /**
396 * @param {?} naco
397 * @param {?} storage
398 */
399 constructor(naco, storage) {
400 this.naco = naco;
401 this.storage = storage;
402 }
403 /**
404 * @param {?} route
405 * @return {?}
406 */
407 canActivate(route) {
408 return this.naco.getUser().pipe(first(), map((user) => {
409 if (null === user) {
410 const /** @type {?} */ uri = this.naco.buildNestedUri(route.root);
411 const /** @type {?} */ next = this.naco.getCurrentOrigin('/' + this.ltrim(uri));
412 this.storage.set('naco_intended_url', next).then(() => {
413 window.location.href = this.naco.login('basic email', this.naco.getCurrentOrigin('/auth'));
414 });
415 }
416 return !!user;
417 }));
418 }
419 /**
420 * @param {?} route
421 * @return {?}
422 */
423 canActivateChild(route) {
424 return this.canActivate(route);
425 }
426 /**
427 * @param {?} text
428 * @return {?}
429 */
430 ltrim(text) {
431 return text.replace(/^\/+/, '');
432 }
433 /**
434 * @param {?} text
435 * @return {?}
436 */
437 rtrim(text) {
438 return text.replace(/\/+$/, '');
439 }
440}
441AuthenticatedGuard.decorators = [
442 { type: Injectable },
443];
444/** @nocollapse */
445AuthenticatedGuard.ctorParameters = () => [
446 { type: NacoService },
447 { type: Storage }
448];
449
450/**
451 * @fileoverview added by tsickle
452 * @suppress {checkTypes} checked by tsc
453 */
454class AuthInterceptor {
455 /**
456 * @param {?} naco
457 */
458 constructor(naco) {
459 this.naco = naco;
460 }
461 /**
462 * @param {?} req
463 * @param {?} next
464 * @return {?}
465 */
466 intercept(req, next) {
467 return fromPromise(this.naco.getSignature()).pipe(switchMap((signature) => {
468 if (!signature) {
469 return next.handle(req);
470 }
471 return next
472 .handle(req.clone({
473 setHeaders: {
474 Authorization: `${signature.type} ${signature.token}`,
475 },
476 }))
477 .pipe(catchError((error) => {
478 if (error.status === 401) {
479 return this.naco.refreshUser().pipe(switchMap((user) => {
480 if (user) {
481 return fromPromise(this.naco.getSignature()).pipe(switchMap((newSignature) => {
482 return next.handle(req.clone({
483 setHeaders: {
484 Authorization: `${newSignature.type} ${newSignature.token}`,
485 },
486 }));
487 }));
488 }
489 return ErrorObservable.create(error);
490 }));
491 }
492 return ErrorObservable.create(error);
493 }));
494 }));
495 }
496}
497AuthInterceptor.decorators = [
498 { type: Injectable },
499];
500/** @nocollapse */
501AuthInterceptor.ctorParameters = () => [
502 { type: NacoService }
503];
504
505/**
506 * @fileoverview added by tsickle
507 * @suppress {checkTypes} checked by tsc
508 */
509/**
510 * @param {?} config
511 * @param {?} router
512 * @param {?} storage
513 * @param {?} http
514 * @param {?} location
515 * @return {?}
516 */
517function nacoFactory(config, router, storage, http, location) {
518 return new NacoService(new Config(Object.assign({}, config)), router, storage, http, location);
519}
520const /** @type {?} */ NACO_CONFIG = new InjectionToken('NACO_CONFIG');
521
522/**
523 * @fileoverview added by tsickle
524 * @suppress {checkTypes} checked by tsc
525 */
526class AuthPage {
527 /**
528 * @param {?} route
529 * @param {?} naco
530 * @param {?} storage
531 */
532 constructor(route, naco, storage) {
533 this.route = route;
534 this.naco = naco;
535 this.storage = storage;
536 this.message = 'Authenticating...';
537 this.route.queryParams.subscribe((params) => this.handle(params));
538 }
539 /**
540 * @param {?} params
541 * @return {?}
542 */
543 handle(params) {
544 if (params["state"]) {
545 this.naco.getState().then((state) => {
546 if (state !== params["state"]) {
547 this.message = 'Invalid CSRF';
548 return;
549 }
550 this.authenticate(params);
551 });
552 }
553 else {
554 this.authenticate(params);
555 }
556 }
557 /**
558 * @param {?} params
559 * @return {?}
560 */
561 authenticate(params) {
562 const /** @type {?} */ signature = {
563 expiresIn: params["expires_in"],
564 type: params["token_type"],
565 token: params["access_token"],
566 };
567 this.naco.setUser(null);
568 this.naco.setSignature(signature);
569 this.naco.getUser().subscribe((user) => {
570 if (null !== user) {
571 this.storage.get('naco_intended_url').then((url) => {
572 this.storage.remove('naco_intended_url').then(() => {
573 window.location.href = url ? url : '/';
574 });
575 });
576 return;
577 }
578 this.message = 'Unauthenticated!';
579 });
580 }
581}
582AuthPage.decorators = [
583 { type: Component, args: [{
584 selector: 'naker-auth-page',
585 template: '{{ message }}',
586 },] },
587];
588/** @nocollapse */
589AuthPage.ctorParameters = () => [
590 { type: ActivatedRoute },
591 { type: NacoService },
592 { type: Storage }
593];
594
595/**
596 * @fileoverview added by tsickle
597 * @suppress {checkTypes} checked by tsc
598 */
599class AuthSilentPage {
600}
601AuthSilentPage.decorators = [
602 { type: Component, args: [{
603 selector: 'naker-auth-silent',
604 template: 'Processing silent auth...',
605 },] },
606];
607
608/**
609 * @fileoverview added by tsickle
610 * @suppress {checkTypes} checked by tsc
611 */
612const /** @type {?} */ routes = [
613 {
614 path: 'auth',
615 component: AuthPage
616 },
617 {
618 path: 'auth/silent',
619 component: AuthSilentPage
620 },
621];
622const /** @type {?} */ AUTH_ROUTING = RouterModule.forChild(routes);
623
624/**
625 * @fileoverview added by tsickle
626 * @suppress {checkTypes} checked by tsc
627 */
628class NacoViewModule {
629}
630NacoViewModule.decorators = [
631 { type: NgModule, args: [{
632 imports: [
633 AUTH_ROUTING,
634 ],
635 declarations: [
636 AuthPage,
637 AuthSilentPage,
638 ],
639 },] },
640];
641
642/**
643 * @fileoverview added by tsickle
644 * @suppress {checkTypes} checked by tsc
645 */
646class NacoModule {
647 /**
648 * @param {?} config
649 * @return {?}
650 */
651 static forRoot(config) {
652 return {
653 ngModule: NacoModule,
654 providers: [
655 {
656 provide: NACO_CONFIG,
657 useValue: config,
658 },
659 {
660 provide: NacoService,
661 useFactory: nacoFactory,
662 deps: [NACO_CONFIG, Router, Storage, HttpClient, Location],
663 },
664 AuthenticatedGuard,
665 ],
666 };
667 }
668}
669NacoModule.decorators = [
670 { type: NgModule, args: [{
671 imports: [
672 UbudStorageModule,
673 NacoViewModule,
674 ],
675 },] },
676];
677
678/**
679 * @fileoverview added by tsickle
680 * @suppress {checkTypes} checked by tsc
681 */
682
683/**
684 * @fileoverview added by tsickle
685 * @suppress {checkTypes} checked by tsc
686 */
687
688export { NacoService, User, Signature, Config, AuthenticatedGuard, AuthInterceptor, NacoModule, NACO_CONFIG as ɵf, nacoFactory as ɵe, NacoViewModule as ɵa, AuthSilentPage as ɵd, AuthPage as ɵc, AUTH_ROUTING as ɵb };
689
690//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFrZXItbmFjby5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQG5ha2VyL25hY28vZG9tYWlucy92YWx1ZXMvY29uZmlnLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9kb21haW5zL21vZGVscy91c2VyLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZS50cyIsIm5nOi8vQG5ha2VyL25hY28vZG9tYWlucy92YWx1ZXMvc2lnbmF0dXJlLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9ndWFyZHMvYXV0aGVudGljYXRlZC5ndWFyZC50cyIsIm5nOi8vQG5ha2VyL25hY28vaW50ZXJjZXB0b3JzL2F1dGguaW50ZXJjZXB0b3IudHMiLCJuZzovL0BuYWtlci9uYWNvL2ZhY3Rvcmllcy9uYWNvLWZhY3RvcnkudHMiLCJuZzovL0BuYWtlci9uYWNvL3ZpZXdzL3BhZ2VzL2F1dGgucGFnZS50cyIsIm5nOi8vQG5ha2VyL25hY28vdmlld3MvcGFnZXMvYXV0aC1zaWxlbnQucGFnZS50cyIsIm5nOi8vQG5ha2VyL25hY28vdmlld3Mvcm91dGVzLnRzIiwibmc6Ly9AbmFrZXIvbmFjby92aWV3cy9tb2R1bGUudHMiLCJuZzovL0BuYWtlci9uYWNvL25hY28ubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBDb25maWcge1xuICAgIHB1YmxpYyBlbmRwb2ludDogc3RyaW5nID0gJ2h0dHBzOi8vYWNjb3VudC5rZW1uYWtlci5nby5pZCc7XG4gICAgcHVibGljIGNsaWVudElkOiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoZGF0YT86IFBhcnRpYWw8Q29uZmlnPikge1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGRhdGEpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IGZvcndhcmRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFR5cGUgfSBmcm9tICdjbGFzcy10cmFuc2Zvcm1lcic7XG5cbmV4cG9ydCBjbGFzcyBVc2VyIHtcbiAgICBwdWJsaWMgaWQ6IHN0cmluZztcbiAgICBwdWJsaWMgdXNlcm5hbWU6IHN0cmluZztcbiAgICBwdWJsaWMgZW1haWw/OiBzdHJpbmc7XG4gICAgcHVibGljIG5hbWU6IHN0cmluZztcbiAgICBwdWJsaWMgc3RhdHVzOiBudW1iZXI7XG5cbiAgICBAVHlwZShmb3J3YXJkUmVmKCgpID0+IERhdGUpIGFzIGFueSlcbiAgICBwdWJsaWMgdXBkYXRlZEF0OiBEYXRlO1xufVxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGVTbmFwc2hvdCwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uL3ZhbHVlcy9jb25maWcnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL21vZGVscy91c2VyJztcbmltcG9ydCB7IGZvcmtKb2luLCBPYnNlcnZhYmxlLCBPYnNlcnZlciwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFNpZ25hdHVyZSB9IGZyb20gJy4uL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgZnJvbVByb21pc2UgfSBmcm9tICdyeGpzL2ludGVybmFsL29ic2VydmFibGUvZnJvbVByb21pc2UnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgbWFwLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb3BlcmF0b3JzJztcbmltcG9ydCB7IHBsYWluVG9DbGFzcyB9IGZyb20gJ2NsYXNzLXRyYW5zZm9ybWVyJztcbmltcG9ydCB7IEh0dHBDbGllbnQsIEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgTG9jYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRXJyb3JPYnNlcnZhYmxlIH0gZnJvbSAncnhqcy1jb21wYXQvb2JzZXJ2YWJsZS9FcnJvck9ic2VydmFibGUnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTmFjb1NlcnZpY2Uge1xuICAgIHB1YmxpYyByZWFkb25seSBWRVJTSU9OID0gJ3YxJztcblxuICAgIHByaXZhdGUgc2lnbmF0dXJlOiBTaWduYXR1cmUgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIHVzZXI6IFVzZXIgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIHJlZnJlc2hUb2tlbjogU2lnbmF0dXJlIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBjbGllbnRTZWNyZXQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgY29uZmlnOiBDb25maWcsIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsIHByaXZhdGUgc3RvcmFnZTogU3RvcmFnZSwgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50LCBwcml2YXRlIGxvY2F0aW9uOiBMb2NhdGlvbikge1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRVc2VyKHVzZXI6IFVzZXIgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXNlciA9IHVzZXI7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3VzZXInLCB1c2VyKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0VXNlcigpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnVzZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBvZih0aGlzLnVzZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMuc3RvcmFnZS5nZXQoJ3VzZXInKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgodXNlcjogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHVzZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9mKHVzZXIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IHVyaSA9IHRoaXMuZ2V0VXJpKCcvdXNlcnMvbWUnKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBmcm9tUHJvbWlzZSh0aGlzLmdldFNpZ25hdHVyZSgpKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG51bGwgPT09IHNpZ25hdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJlZnJlc2hVc2VyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgJHtzaWduYXR1cmUudHlwZX0gJHtzaWduYXR1cmUudG9rZW59YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8YW55Pih1cmksIG9wdGlvbnMpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXMuZGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgYXJlIG5vIGJvZHkgdG8gYmUgdHJhbnNmb3JtZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAoKGRhdGE6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhdXRoVXNlcjogYW55ID0gcGxhaW5Ub0NsYXNzKFVzZXIsIGRhdGEpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0VXNlcihhdXRoVXNlcik7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGF1dGhVc2VyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGNoRXJyb3IoKGU6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICg0MDEgPT09IGUuc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoVXNlcigpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoTWFwKChyZWZyZXNoVXNlcjogVXNlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlZnJlc2hVc2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2YocmVmcmVzaFVzZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEVycm9yT2JzZXJ2YWJsZS5jcmVhdGUoZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEVycm9yT2JzZXJ2YWJsZS5jcmVhdGUoZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFNpZ25hdHVyZSgpOiBQcm9taXNlPFNpZ25hdHVyZSB8IG51bGw+IHtcbiAgICAgICAgaWYgKHRoaXMuc2lnbmF0dXJlKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuc2lnbmF0dXJlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZ2V0KCdzaWduYXR1cmUnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0U2lnbmF0dXJlKHNpZ25hdHVyZTogU2lnbmF0dXJlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlID0gc2lnbmF0dXJlO1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdzaWduYXR1cmUnLCBzaWduYXR1cmUpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRDbGllbnRTZWNyZXQoc2VjcmV0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jbGllbnRTZWNyZXQgPSBzZWNyZXQ7XG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ2NsaWVudF9zZWNyZXQnLCBzZWNyZXQpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRSZWZyZXNoVG9rZW4ocmVmcmVzaFRva2VuOiBTaWduYXR1cmUpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoVG9rZW4gPSByZWZyZXNoVG9rZW47XG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3JlZnJlc2hfdG9rZW4nLCByZWZyZXNoVG9rZW4pO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWZyZXNoVXNlcihzY29wZXM/OiBzdHJpbmcpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIHRoaXMuc2V0VXNlcihudWxsKTtcbiAgICAgICAgdGhpcy5zZXRTaWduYXR1cmUobnVsbCk7XG5cbiAgICAgICAgcmV0dXJuIGZvcmtKb2luKHRoaXMuZ2V0UmVmcmVzaFRva2VuKCksIHRoaXMuZ2V0Q2xpZW50U2VjcmV0KCkpLnBpcGUoXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKHJlc3VsdHM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlZnJlc2hUb2tlbjogU2lnbmF0dXJlID0gcmVzdWx0c1swXTtcbiAgICAgICAgICAgICAgICBjb25zdCBjbGllbnRTZWNyZXQ6IHN0cmluZyA9IHJlc3VsdHNbMV07XG5cbiAgICAgICAgICAgICAgICBpZiAocmVmcmVzaFRva2VuICYmIGNsaWVudFNlY3JldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoV2l0aFJlZnJlc2hUb2tlbihjbGllbnRTZWNyZXQsIHJlZnJlc2hUb2tlbi50b2tlbiwgc2NvcGVzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoV2l0aFNpbGVudEF1dGgoKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWZyZXNoV2l0aFJlZnJlc2hUb2tlbihjbGllbnRTZWNyZXQ6IHN0cmluZywgcmVmcmVzaFRva2VuOiBzdHJpbmcsIHNjb3Blcz86IHN0cmluZyk6IE9ic2VydmFibGU8VXNlciB8IG51bGw+IHtcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHRoaXMuaHR0cC5wb3N0KHRoaXMuZ2V0VXJpKCcvdG9rZW5zJyksIHtcbiAgICAgICAgICAgIGdyYW50X3R5cGU6ICdyZWZyZXNoX3Rva2VuJyxcbiAgICAgICAgICAgIHNjb3Blczogc2NvcGVzIHx8ICdiYXNpYyBlbWFpbCcsXG4gICAgICAgICAgICBjbGllbnRfaWQ6IHRoaXMuY29uZmlnLmNsaWVudElkLFxuICAgICAgICAgICAgY2xpZW50X3NlY3JldDogY2xpZW50U2VjcmV0LFxuICAgICAgICAgICAgcmVmcmVzaF90b2tlbjogcmVmcmVzaFRva2VuLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmVxdWVzdC5waXBlKFxuICAgICAgICAgICAgdGFwKCh0b2tlbnM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0b2tlbnMgJiYgdG9rZW5zLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTaWduYXR1cmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwaXJlc0luOiB0b2tlbnMuZGF0YS5leHBpcmVzX2luLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogdG9rZW5zLmRhdGEudG9rZW5fdHlwZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiB0b2tlbnMuZGF0YS5hY2Nlc3NfdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0UmVmcmVzaFRva2VuKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHRva2Vucy5kYXRhLnRva2VuX3R5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogdG9rZW5zLmRhdGEucmVmcmVzaF90b2tlbixcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBtYXAoKHRva2VuczogYW55KSA9PiB0b2tlbnMgJiYgdG9rZW5zLmRhdGEpLFxuICAgICAgICAgICAgc3dpdGNoTWFwKChoYXNUb2tlbjogYm9vbGVhbikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChoYXNUb2tlbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRVc2VyKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9mKG51bGwpO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlZnJlc2hXaXRoU2lsZW50QXV0aCgpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIHJldHVybiBuZXcgT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4oKG9ic2VydmVyOiBPYnNlcnZlcjxVc2VyIHwgbnVsbD4pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlZGlyZWN0VXJpID0gdGhpcy5nZXRDdXJyZW50T3JpZ2luKCdhdXRoL3NpbGVudCcpO1xuICAgICAgICAgICAgY29uc3QgdXJpID0gdGhpcy5sb2dpbignYmFzaWMgZW1haWwnLCByZWRpcmVjdFVyaSwgZmFsc2UpO1xuXG4gICAgICAgICAgICBjb25zdCBpZnJhbWUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpZnJhbWUnKTtcbiAgICAgICAgICAgIGlmcmFtZS5zZXRBdHRyaWJ1dGUoJ3NyYycsIHVyaSk7XG4gICAgICAgICAgICBpZnJhbWUuc3R5bGUuZGlzcGxheSA9ICdub25lJztcblxuICAgICAgICAgICAgaWZyYW1lLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcXVlcnlTdHJpbmcgPSBpZnJhbWUuY29udGVudFdpbmRvdy5sb2NhdGlvbi5zZWFyY2guc3Vic3RyaW5nKDEpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmcmFtZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGlmcmFtZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHF1ZXJ5U3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWVyeVBhcnRzID0gcXVlcnlTdHJpbmcuc3BsaXQoJyYnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgcXVlcnlQYXJ0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGl0ZW1QYXJ0cyA9IGl0ZW0uc3BsaXQoJz0nKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtc1tpdGVtUGFydHNbMF1dID0gaXRlbVBhcnRzWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocGFyYW1zLmhhc093blByb3BlcnR5KCdhY2Nlc3NfdG9rZW4nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U2lnbmF0dXJlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46IHBhcmFtc1snYWNjZXNzX3Rva2VuJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHBhcmFtc1sndG9rZW5fdHlwZSddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBpcmVzSW46IHBhcmFtc1sndHRsJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5nZXRVc2VyKCkudG9Qcm9taXNlKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXNlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFVzZXIodXNlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCh1c2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChudWxsKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQobnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgZmFsc2UpO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGlmcmFtZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBsb2dpbihzY29wZXM6IHN0cmluZywgcmVkaXJlY3RVcmk/OiBzdHJpbmcsIG5lZWRTdGF0ZTogYm9vbGVhbiA9IHRydWUpOiBzdHJpbmcge1xuICAgICAgICBpZiAoIXJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICByZWRpcmVjdFVyaSA9IHRoaXMucm91dGVyLnVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhcmFtczogYW55ID0ge1xuICAgICAgICAgICAgJ3Jlc3BvbnNlX3R5cGUnOiAndG9rZW4nLFxuICAgICAgICAgICAgJ3Njb3Blcyc6IHNjb3BlcyxcbiAgICAgICAgICAgICdjbGllbnQnOiB0aGlzLmNvbmZpZy5jbGllbnRJZCxcbiAgICAgICAgICAgICdzaWxlbnQnOiB0cnVlLFxuICAgICAgICAgICAgJ2NvbnRpbnVlJzogZW5jb2RlVVJJQ29tcG9uZW50KHJlZGlyZWN0VXJpKSxcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAobmVlZFN0YXRlKSB7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZSA9IHRoaXMuZ2VuZXJhdGVTdGF0ZSgpO1xuXG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdzdGF0ZScsIHN0YXRlKTtcbiAgICAgICAgICAgIHBhcmFtcy5zdGF0ZSA9IHN0YXRlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcXVlcnk6IHN0cmluZyA9IHRoaXMuYnVpbGRRdWVyeVN0cmluZyhwYXJhbXMpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXV0aD8nICsgcXVlcnk7XG4gICAgfVxuXG4gICAgcHVibGljIGxvZ291dChyZWRpcmVjdFVyaT86IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgICAgIHRoaXMuc2lnbmF0dXJlID0gbnVsbDtcbiAgICAgICAgdGhpcy51c2VyID0gbnVsbDtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZSgnc2lnbmF0dXJlJyksXG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZSgndXNlcicpLFxuICAgICAgICAgICAgXSkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IGVuZHBvaW50ID0gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2F1dGgvbG9nb3V0JztcblxuICAgICAgICAgICAgICAgIGlmIChyZWRpcmVjdFVyaSkge1xuICAgICAgICAgICAgICAgICAgICBlbmRwb2ludCArPSAnP2NvbnRpbnVlPScgKyBlbmNvZGVVUklDb21wb25lbnQocmVkaXJlY3RVcmkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJlc29sdmUoZW5kcG9pbnQpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTdGF0ZSgpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ3N0YXRlJyk7XG4gICAgfVxuXG4gICAgcHVibGljIGJ1aWxkTmVzdGVkVXJpKHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KTogc3RyaW5nIHtcbiAgICAgICAgbGV0IHVyaSA9ICcnO1xuXG4gICAgICAgIGlmIChyb3V0ZS5yb3V0ZUNvbmZpZyAmJiByb3V0ZS5yb3V0ZUNvbmZpZy5wYXRoKSB7XG4gICAgICAgICAgICBsZXQgcm91dGVQYXRoID0gcm91dGUucm91dGVDb25maWcucGF0aDtcblxuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gcm91dGUucGFyYW1zKSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZSA9IG5ldyBSZWdFeHAoJ1xcOicgKyBrZXkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJvdXRlUGF0aCA9IHJvdXRlUGF0aC5yZXBsYWNlKHJlLCByb3V0ZS5wYXJhbXNba2V5XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1cmkgKz0gJy8nICsgcm91dGVQYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJvdXRlLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICByb3V0ZS5jaGlsZHJlbi5mb3JFYWNoKChpdGVtOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSA9PiB7XG4gICAgICAgICAgICAgICAgdXJpICs9IHRoaXMuYnVpbGROZXN0ZWRVcmkoaXRlbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1cmk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZWZyZXNoVG9rZW4oKTogUHJvbWlzZTxTaWduYXR1cmUgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnJlZnJlc2hUb2tlbikge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLnJlZnJlc2hUb2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgncmVmcmVzaF90b2tlbicpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q2xpZW50U2VjcmV0KCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy5jbGllbnRTZWNyZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5jbGllbnRTZWNyZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ2NsaWVudF9zZWNyZXQnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFVyaShwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2FwaS8nICsgdGhpcy5WRVJTSU9OICsgcGF0aDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0Q3VycmVudE9yaWdpbihwYXRoPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4gKyB0aGlzLmxvY2F0aW9uLnByZXBhcmVFeHRlcm5hbFVybChwYXRoIHx8ICcnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdlbmVyYXRlU3RhdGUoKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcG9zc2libGUgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xuICAgICAgICBsZXQgdGV4dCA9ICcnO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICAgICAgICB0ZXh0ICs9IHBvc3NpYmxlLmNoYXJBdChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBwb3NzaWJsZS5sZW5ndGgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRRdWVyeVN0cmluZyhwYXJhbXM6IG9iamVjdCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHF1ZXJ5UGFyYW1zID0gT2JqZWN0LmtleXMocGFyYW1zKS5tYXAoKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQocGFyYW1zW2tleV0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcXVlcnlQYXJhbXMuam9pbignJicpO1xuICAgIH1cbn1cbiIsImV4cG9ydCBjbGFzcyBTaWduYXR1cmUge1xuICAgIHB1YmxpYyBleHBpcmVzSW4/OiBudW1iZXI7XG4gICAgcHVibGljIHRva2VuOiBzdHJpbmc7XG4gICAgcHVibGljIHR5cGU6IHN0cmluZztcbn1cbiIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENhbkFjdGl2YXRlLCBDYW5BY3RpdmF0ZUNoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IE5hY29TZXJ2aWNlIH0gZnJvbSAnLi4vZG9tYWlucy9zZXJ2aWNlcy9uYWNvLnNlcnZpY2UnO1xuaW1wb3J0IHsgZmlyc3QsIG1hcCB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb3BlcmF0b3JzJztcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi9kb21haW5zL21vZGVscy91c2VyJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlU25hcHNob3QgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXIvc3JjL3JvdXRlcl9zdGF0ZSc7XG5cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBdXRoZW50aWNhdGVkR3VhcmQgaW1wbGVtZW50cyBDYW5BY3RpdmF0ZSwgQ2FuQWN0aXZhdGVDaGlsZCB7XG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgbmFjbzogTmFjb1NlcnZpY2UsIHByaXZhdGUgc3RvcmFnZTogU3RvcmFnZSkge1xuICAgIH1cblxuICAgIHB1YmxpYyBjYW5BY3RpdmF0ZShyb3V0ZTogQWN0aXZhdGVkUm91dGVTbmFwc2hvdCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5uYWNvLmdldFVzZXIoKS5waXBlKFxuICAgICAgICAgICAgZmlyc3QoKSxcbiAgICAgICAgICAgIG1hcCgodXNlcjogVXNlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobnVsbCA9PT0gdXNlcikge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB1cmkgPSB0aGlzLm5hY28uYnVpbGROZXN0ZWRVcmkocm91dGUucm9vdCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHQgPSB0aGlzLm5hY28uZ2V0Q3VycmVudE9yaWdpbignLycgKyB0aGlzLmx0cmltKHVyaSkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ25hY29faW50ZW5kZWRfdXJsJywgbmV4dCkudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHRoaXMubmFjby5sb2dpbihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYmFzaWMgZW1haWwnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmFjby5nZXRDdXJyZW50T3JpZ2luKCcvYXV0aCcpLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuICEhdXNlcjtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBjYW5BY3RpdmF0ZUNoaWxkKHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KTogT2JzZXJ2YWJsZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbkFjdGl2YXRlKHJvdXRlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGx0cmltKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0ZXh0LnJlcGxhY2UoL15cXC8rLywnJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBydHJpbSh0ZXh0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKC9cXC8rJC8sJycpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IEh0dHBFcnJvclJlc3BvbnNlLCBIdHRwRXZlbnQsIEh0dHBIYW5kbGVyLCBIdHRwSW50ZXJjZXB0b3IsIEh0dHBSZXF1ZXN0IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTmFjb1NlcnZpY2UgfSBmcm9tICcuLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBmcm9tUHJvbWlzZSB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb2JzZXJ2YWJsZS9mcm9tUHJvbWlzZSc7XG5pbXBvcnQgeyBTaWduYXR1cmUgfSBmcm9tICcuLi9kb21haW5zL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgRXJyb3JPYnNlcnZhYmxlIH0gZnJvbSAncnhqcy1jb21wYXQvb2JzZXJ2YWJsZS9FcnJvck9ic2VydmFibGUnO1xuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQXV0aEludGVyY2VwdG9yIGltcGxlbWVudHMgSHR0cEludGVyY2VwdG9yIHtcbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSBuYWNvOiBOYWNvU2VydmljZSkge1xuICAgIH1cblxuICAgIHB1YmxpYyBpbnRlcmNlcHQocmVxOiBIdHRwUmVxdWVzdDxhbnk+LCBuZXh0OiBIdHRwSGFuZGxlcik6IE9ic2VydmFibGU8SHR0cEV2ZW50PGFueT4+IHtcbiAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMubmFjby5nZXRTaWduYXR1cmUoKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoc2lnbmF0dXJlOiBTaWduYXR1cmUgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFzaWduYXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKHJlcSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5leHRcbiAgICAgICAgICAgICAgICAgICAgLmhhbmRsZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcS5jbG9uZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0SGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgJHtzaWduYXR1cmUudHlwZX0gJHtzaWduYXR1cmUudG9rZW59YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRjaEVycm9yKChlcnJvcjogSHR0cEVycm9yUmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3Iuc3RhdHVzID09PSA0MDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubmFjby5yZWZyZXNoVXNlcigpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKHVzZXI6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1c2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmcm9tUHJvbWlzZSh0aGlzLm5hY28uZ2V0U2lnbmF0dXJlKCkpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKG5ld1NpZ25hdHVyZTogU2lnbmF0dXJlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5leHQuaGFuZGxlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXEuY2xvbmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V0SGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGAke25ld1NpZ25hdHVyZS50eXBlfSAke25ld1NpZ25hdHVyZS50b2tlbn1gLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBFcnJvck9ic2VydmFibGUuY3JlYXRlKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBFcnJvck9ic2VydmFibGUuY3JlYXRlKGVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfVxufVxuIiwiaW1wb3J0IHsgTmFjb1NlcnZpY2UgfSBmcm9tICcuLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBDb25maWcgfSBmcm9tICcuLi9kb21haW5zL3ZhbHVlcy9jb25maWcnO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IEluamVjdGlvblRva2VuIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgTG9jYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuXG5leHBvcnQgZnVuY3Rpb24gbmFjb0ZhY3RvcnkoY29uZmlnOiBvYmplY3QsIHJvdXRlcjogUm91dGVyLCBzdG9yYWdlOiBTdG9yYWdlLCBodHRwOiBIdHRwQ2xpZW50LCBsb2NhdGlvbjogTG9jYXRpb24pIHtcbiAgICByZXR1cm4gbmV3IE5hY29TZXJ2aWNlKFxuICAgICAgICBuZXcgQ29uZmlnKHsgLi4uY29uZmlnIH0pLFxuICAgICAgICByb3V0ZXIsXG4gICAgICAgIHN0b3JhZ2UsXG4gICAgICAgIGh0dHAsXG4gICAgICAgIGxvY2F0aW9uXG4gICAgKTtcbn1cblxuZXhwb3J0IGNvbnN0IE5BQ09fQ09ORklHID0gbmV3IEluamVjdGlvblRva2VuPG9iamVjdD4oJ05BQ09fQ09ORklHJyk7XG4iLCJpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlLCBQYXJhbXMgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgTmFjb1NlcnZpY2UgfSBmcm9tICcuLi8uLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBTaWduYXR1cmUgfSBmcm9tICcuLi8uLi9kb21haW5zL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uLy4uL2RvbWFpbnMvbW9kZWxzL3VzZXInO1xuaW1wb3J0IHsgU3RvcmFnZSB9IGZyb20gJ0B1YnVkL3N0b3JhZ2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ25ha2VyLWF1dGgtcGFnZScsXG4gICAgdGVtcGxhdGU6ICd7eyBtZXNzYWdlIH19Jyxcbn0pXG5leHBvcnQgY2xhc3MgQXV0aFBhZ2Uge1xuICAgIHB1YmxpYyBtZXNzYWdlOiBzdHJpbmcgPSAnQXV0aGVudGljYXRpbmcuLi4nO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLCBwcml2YXRlIG5hY286IE5hY29TZXJ2aWNlLCBwcml2YXRlIHN0b3JhZ2U6IFN0b3JhZ2UpIHtcbiAgICAgICAgdGhpcy5yb3V0ZS5xdWVyeVBhcmFtcy5zdWJzY3JpYmUoKHBhcmFtczogUGFyYW1zKSA9PiB0aGlzLmhhbmRsZShwYXJhbXMpKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaGFuZGxlKHBhcmFtczogUGFyYW1zKTogdm9pZCB7XG4gICAgICAgIGlmIChwYXJhbXMuc3RhdGUpIHtcbiAgICAgICAgICAgIHRoaXMubmFjby5nZXRTdGF0ZSgpLnRoZW4oKHN0YXRlOiBzdHJpbmcgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHN0YXRlICE9PSBwYXJhbXMuc3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZXNzYWdlID0gJ0ludmFsaWQgQ1NSRic7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuYXV0aGVudGljYXRlKHBhcmFtcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYXV0aGVudGljYXRlKHBhcmFtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGF1dGhlbnRpY2F0ZShwYXJhbXM6IFBhcmFtcyk6IHZvaWQge1xuICAgICAgICBjb25zdCBzaWduYXR1cmU6IFNpZ25hdHVyZSA9IHtcbiAgICAgICAgICAgIGV4cGlyZXNJbjogcGFyYW1zLmV4cGlyZXNfaW4sXG4gICAgICAgICAgICB0eXBlOiBwYXJhbXMudG9rZW5fdHlwZSxcbiAgICAgICAgICAgIHRva2VuOiBwYXJhbXMuYWNjZXNzX3Rva2VuLFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMubmFjby5zZXRVc2VyKG51bGwpO1xuICAgICAgICB0aGlzLm5hY28uc2V0U2lnbmF0dXJlKHNpZ25hdHVyZSk7XG5cbiAgICAgICAgdGhpcy5uYWNvLmdldFVzZXIoKS5zdWJzY3JpYmUoKHVzZXI6IFVzZXIgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICBpZiAobnVsbCAhPT0gdXNlcikge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5nZXQoJ25hY29faW50ZW5kZWRfdXJsJykudGhlbigodXJsOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZSgnbmFjb19pbnRlbmRlZF91cmwnKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5ocmVmID0gdXJsID8gdXJsIDogJy8nO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlID0gJ1VuYXV0aGVudGljYXRlZCEnO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbiIsImltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ25ha2VyLWF1dGgtc2lsZW50JyxcbiAgICB0ZW1wbGF0ZTogJ1Byb2Nlc3Npbmcgc2lsZW50IGF1dGguLi4nLFxufSlcbmV4cG9ydCBjbGFzcyBBdXRoU2lsZW50UGFnZSB7XG59XG4iLCJpbXBvcnQgeyBNb2R1bGVXaXRoUHJvdmlkZXJzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSb3V0ZXJNb2R1bGUsIFJvdXRlcyB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBBdXRoUGFnZSB9IGZyb20gJy4vcGFnZXMvYXV0aC5wYWdlJztcbmltcG9ydCB7IEF1dGhTaWxlbnRQYWdlIH0gZnJvbSAnLi9wYWdlcy9hdXRoLXNpbGVudC5wYWdlJztcblxuY29uc3Qgcm91dGVzOiBSb3V0ZXMgPSBbXG4gICAge1xuICAgICAgICBwYXRoOiAnYXV0aCcsXG4gICAgICAgIGNvbXBvbmVudDogQXV0aFBhZ2VcbiAgICB9LFxuICAgIHtcbiAgICAgICAgcGF0aDogJ2F1dGgvc2lsZW50JyxcbiAgICAgICAgY29tcG9uZW50OiBBdXRoU2lsZW50UGFnZVxuICAgIH0sXG5dO1xuXG5leHBvcnQgY29uc3QgQVVUSF9ST1VUSU5HOiBNb2R1bGVXaXRoUHJvdmlkZXJzID0gUm91dGVyTW9kdWxlLmZvckNoaWxkKHJvdXRlcyk7XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQVVUSF9ST1VUSU5HIH0gZnJvbSAnLi9yb3V0ZXMnO1xuaW1wb3J0IHsgQXV0aFBhZ2UgfSBmcm9tICcuL3BhZ2VzL2F1dGgucGFnZSc7XG5pbXBvcnQgeyBBdXRoU2lsZW50UGFnZSB9IGZyb20gJy4vcGFnZXMvYXV0aC1zaWxlbnQucGFnZSc7XG5cbkBOZ01vZHVsZSh7XG4gICAgaW1wb3J0czogW1xuICAgICAgICBBVVRIX1JPVVRJTkcsXG4gICAgXSxcbiAgICBkZWNsYXJhdGlvbnM6IFtcbiAgICAgICAgQXV0aFBhZ2UsXG4gICAgICAgIEF1dGhTaWxlbnRQYWdlLFxuICAgIF0sXG59KVxuZXhwb3J0IGNsYXNzIE5hY29WaWV3TW9kdWxlIHtcbn1cbiIsImltcG9ydCB7IE1vZHVsZVdpdGhQcm92aWRlcnMsIE5nTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOYWNvU2VydmljZSB9IGZyb20gJy4vZG9tYWlucy9zZXJ2aWNlcy9uYWNvLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXV0aGVudGljYXRlZEd1YXJkIH0gZnJvbSAnLi9ndWFyZHMvYXV0aGVudGljYXRlZC5ndWFyZCc7XG5pbXBvcnQgeyBOQUNPX0NPTkZJRywgbmFjb0ZhY3RvcnkgfSBmcm9tICcuL2ZhY3Rvcmllcy9uYWNvLWZhY3RvcnknO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UsIFVidWRTdG9yYWdlTW9kdWxlIH0gZnJvbSAnQHVidWQvc3RvcmFnZSc7XG5pbXBvcnQgeyBOYWNvVmlld01vZHVsZSB9IGZyb20gJy4vdmlld3MvbW9kdWxlJztcbmltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBMb2NhdGlvbiB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5cbkBOZ01vZHVsZSh7XG4gICAgaW1wb3J0czogW1xuICAgICAgICBVYnVkU3RvcmFnZU1vZHVsZSxcbiAgICAgICAgTmFjb1ZpZXdNb2R1bGUsXG4gICAgXSxcbn0pXG5leHBvcnQgY2xhc3MgTmFjb01vZHVsZSB7XG4gICAgcHVibGljIHN0YXRpYyBmb3JSb290KGNvbmZpZzogeyBjbGllbnRJZDogc3RyaW5nLCBlbmRwb2ludD86IHN0cmluZyB9KTogTW9kdWxlV2l0aFByb3ZpZGVycyB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBuZ01vZHVsZTogTmFjb01vZHVsZSxcbiAgICAgICAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZTogTkFDT19DT05GSUcsXG4gICAgICAgICAgICAgICAgICAgIHVzZVZhbHVlOiBjb25maWcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgIHByb3ZpZGU6IE5hY29TZXJ2aWNlLFxuICAgICAgICAgICAgICAgICAgICB1c2VGYWN0b3J5OiBuYWNvRmFjdG9yeSxcbiAgICAgICAgICAgICAgICAgICAgZGVwczogW05BQ09fQ09ORklHLCBSb3V0ZXIsIFN0b3JhZ2UsIEh0dHBDbGllbnQsIExvY2F0aW9uXSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIEF1dGhlbnRpY2F0ZWRHdWFyZCxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgfVxufVxu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
\No newline at end of file