UNPKG

43.8 kBJavaScriptView Raw
1/**
2 * @fileoverview added by tsickle
3 * @suppress {checkTypes} checked by tsc
4 */
5import * as tslib_1 from "tslib";
6import { Injectable } from '@angular/core';
7import { Router } from '@angular/router';
8import { Storage } from '@ubud/storage';
9import { Config } from '../values/config';
10import { User } from '../models/user';
11import { forkJoin, Observable, of } from 'rxjs';
12import { fromPromise } from 'rxjs/internal/observable/fromPromise';
13import { catchError, map, switchMap, tap } from 'rxjs/internal/operators';
14import { plainToClass } from 'class-transformer';
15import { HttpClient } from '@angular/common/http';
16import { Location } from '@angular/common';
17var NacoService = /** @class */ (function () {
18 function NacoService(config, router, storage, http, location) {
19 this.config = config;
20 this.router = router;
21 this.storage = storage;
22 this.http = http;
23 this.location = location;
24 this.VERSION = 'v1';
25 this.signature = null;
26 this.user = null;
27 this.refreshToken = null;
28 this.clientSecret = null;
29 }
30 /**
31 * @param {?} user
32 * @return {?}
33 */
34 NacoService.prototype.setUser = /**
35 * @param {?} user
36 * @return {?}
37 */
38 function (user) {
39 this.user = user;
40 };
41 /**
42 * @return {?}
43 */
44 NacoService.prototype.getUser = /**
45 * @return {?}
46 */
47 function () {
48 var _this = this;
49 if (null !== this.user) {
50 return of(this.user);
51 }
52 var /** @type {?} */ uri = this.getUri('/users/me');
53 return fromPromise(this.getSignature()).pipe(switchMap(function (signature) {
54 if (null === signature) {
55 return _this.refreshUser();
56 }
57 var /** @type {?} */ options = {
58 headers: {
59 Authorization: signature.type + " " + signature.token,
60 },
61 };
62 return _this.http.get(uri, options).pipe(map(function (res) {
63 if (res.data) {
64 return res.data;
65 }
66 throw new Error('There are no body to be transformed');
67 }), map(function (data) {
68 var /** @type {?} */ authUser = plainToClass(User, data);
69 _this.setUser(authUser);
70 return authUser;
71 }), catchError(function (e) {
72 if (401 === e.status) {
73 return _this.refreshUser().pipe(switchMap(function (refreshUser) {
74 if (refreshUser) {
75 return of(refreshUser);
76 }
77 return of(null);
78 }));
79 }
80 return of(null);
81 }));
82 }));
83 };
84 /**
85 * @param {?} user
86 * @return {?}
87 */
88 NacoService.prototype.getProfilePicture = /**
89 * @param {?} user
90 * @return {?}
91 */
92 function (user) {
93 return this.config.endpoint + '/users/' + user + '/picture';
94 };
95 /**
96 * @return {?}
97 */
98 NacoService.prototype.getSignature = /**
99 * @return {?}
100 */
101 function () {
102 if (this.signature) {
103 return Promise.resolve(this.signature);
104 }
105 return this.storage.get('signature');
106 };
107 /**
108 * @param {?} signature
109 * @return {?}
110 */
111 NacoService.prototype.setSignature = /**
112 * @param {?} signature
113 * @return {?}
114 */
115 function (signature) {
116 this.signature = signature;
117 if (null === signature) {
118 this.storage.remove('signature');
119 }
120 else {
121 this.storage.set('signature', signature);
122 }
123 };
124 /**
125 * @param {?} secret
126 * @return {?}
127 */
128 NacoService.prototype.setClientSecret = /**
129 * @param {?} secret
130 * @return {?}
131 */
132 function (secret) {
133 this.clientSecret = secret;
134 this.storage.set('client_secret', secret);
135 };
136 /**
137 * @param {?} refreshToken
138 * @return {?}
139 */
140 NacoService.prototype.setRefreshToken = /**
141 * @param {?} refreshToken
142 * @return {?}
143 */
144 function (refreshToken) {
145 this.refreshToken = refreshToken;
146 this.storage.set('refresh_token', refreshToken);
147 };
148 /**
149 * @param {?=} scopes
150 * @return {?}
151 */
152 NacoService.prototype.refreshUser = /**
153 * @param {?=} scopes
154 * @return {?}
155 */
156 function (scopes) {
157 var _this = this;
158 this.setUser(null);
159 this.setSignature(null);
160 return forkJoin(this.getRefreshToken(), this.getClientSecret()).pipe(switchMap(function (results) {
161 var /** @type {?} */ refreshToken = results[0];
162 var /** @type {?} */ clientSecret = results[1];
163 if (refreshToken && clientSecret) {
164 return _this.refreshWithRefreshToken(clientSecret, refreshToken.token, scopes);
165 }
166 return _this.refreshWithSilentAuth();
167 }));
168 };
169 /**
170 * @param {?} clientSecret
171 * @param {?} refreshToken
172 * @param {?=} scopes
173 * @return {?}
174 */
175 NacoService.prototype.refreshWithRefreshToken = /**
176 * @param {?} clientSecret
177 * @param {?} refreshToken
178 * @param {?=} scopes
179 * @return {?}
180 */
181 function (clientSecret, refreshToken, scopes) {
182 var _this = this;
183 var /** @type {?} */ request = this.http.post(this.getUri('/tokens'), {
184 grant_type: 'refresh_token',
185 scopes: scopes || 'basic email',
186 client_id: this.config.clientId,
187 client_secret: clientSecret,
188 refresh_token: refreshToken,
189 });
190 return request.pipe(tap(function (tokens) {
191 if (tokens && tokens.data) {
192 _this.setSignature({
193 expiresIn: tokens.data.expires_in,
194 type: tokens.data.token_type,
195 token: tokens.data.access_token,
196 });
197 _this.setRefreshToken({
198 type: tokens.data.token_type,
199 token: tokens.data.refresh_token,
200 });
201 }
202 }), map(function (tokens) { return tokens && tokens.data; }), switchMap(function (hasToken) {
203 if (hasToken) {
204 return _this.getUser();
205 }
206 return of(null);
207 }));
208 };
209 /**
210 * @return {?}
211 */
212 NacoService.prototype.refreshWithSilentAuth = /**
213 * @return {?}
214 */
215 function () {
216 var _this = this;
217 return new Observable(function (observer) {
218 var /** @type {?} */ redirectUri = _this.getCurrentOrigin('auth/silent');
219 var /** @type {?} */ uri = _this.login('basic email', redirectUri, false);
220 var /** @type {?} */ iframe = document.createElement('iframe');
221 iframe.setAttribute('src', uri);
222 iframe.style.display = 'none';
223 iframe.addEventListener('load', function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
224 var e_1, _a, queryString, queryParts, params, queryParts_1, queryParts_1_1, item, itemParts, user, e_2;
225 return tslib_1.__generator(this, function (_b) {
226 switch (_b.label) {
227 case 0:
228 _b.trys.push([0, 5, , 6]);
229 queryString = iframe.contentWindow.location.search.substring(1);
230 iframe.parentNode.removeChild(iframe);
231 if (!queryString) return [3 /*break*/, 4];
232 queryParts = queryString.split('&');
233 params = {};
234 try {
235 for (queryParts_1 = tslib_1.__values(queryParts), queryParts_1_1 = queryParts_1.next(); !queryParts_1_1.done; queryParts_1_1 = queryParts_1.next()) {
236 item = queryParts_1_1.value;
237 itemParts = item.split('=');
238 params[itemParts[0]] = itemParts[1];
239 }
240 }
241 catch (e_1_1) { e_1 = { error: e_1_1 }; }
242 finally {
243 try {
244 if (queryParts_1_1 && !queryParts_1_1.done && (_a = queryParts_1.return)) _a.call(queryParts_1);
245 }
246 finally { if (e_1) throw e_1.error; }
247 }
248 if (!params.hasOwnProperty('access_token')) return [3 /*break*/, 2];
249 this.setSignature({
250 token: params['access_token'],
251 type: params['token_type'],
252 expiresIn: params['ttl'],
253 });
254 return [4 /*yield*/, this.getUser().toPromise()];
255 case 1:
256 user = _b.sent();
257 if (user) {
258 this.setUser(user);
259 }
260 observer.next(user);
261 return [3 /*break*/, 3];
262 case 2:
263 observer.next(null);
264 _b.label = 3;
265 case 3: return [2 /*return*/];
266 case 4:
267 observer.next(null);
268 return [3 /*break*/, 6];
269 case 5:
270 e_2 = _b.sent();
271 observer.next(null);
272 return [3 /*break*/, 6];
273 case 6: return [2 /*return*/];
274 }
275 });
276 }); }, false);
277 document.body.appendChild(iframe);
278 });
279 };
280 /**
281 * @param {?} scopes
282 * @param {?=} redirectUri
283 * @param {?=} needState
284 * @return {?}
285 */
286 NacoService.prototype.login = /**
287 * @param {?} scopes
288 * @param {?=} redirectUri
289 * @param {?=} needState
290 * @return {?}
291 */
292 function (scopes, redirectUri, needState) {
293 if (needState === void 0) { needState = true; }
294 if (!redirectUri) {
295 redirectUri = this.router.url;
296 }
297 var /** @type {?} */ params = {
298 response_type: 'token',
299 scopes: scopes,
300 client: this.config.clientId,
301 silent: true,
302 continue: encodeURIComponent(redirectUri),
303 };
304 if (needState) {
305 var /** @type {?} */ state = this.generateState();
306 this.storage.set('state', state);
307 params.state = state;
308 }
309 var /** @type {?} */ query = this.buildQueryString(params);
310 return this.config.endpoint + '/auth?' + query;
311 };
312 /**
313 * @param {?=} redirectUri
314 * @return {?}
315 */
316 NacoService.prototype.logout = /**
317 * @param {?=} redirectUri
318 * @return {?}
319 */
320 function (redirectUri) {
321 var _this = this;
322 this.signature = null;
323 this.user = null;
324 this.clientSecret = null;
325 this.refreshToken = null;
326 return new Promise(function (resolve) {
327 var /** @type {?} */ clear = [
328 _this.storage.remove('signature'),
329 _this.storage.remove('user'),
330 _this.storage.remove('refresh_token'),
331 _this.storage.remove('client_secret'),
332 ];
333 Promise.all(clear).then(function () {
334 var /** @type {?} */ endpoint = _this.config.endpoint + '/auth/logout';
335 if (redirectUri) {
336 endpoint += '?continue=' + encodeURIComponent(redirectUri);
337 }
338 resolve(endpoint);
339 });
340 });
341 };
342 /**
343 * @return {?}
344 */
345 NacoService.prototype.getState = /**
346 * @return {?}
347 */
348 function () {
349 return this.storage.get('state');
350 };
351 /**
352 * @param {?} route
353 * @return {?}
354 */
355 NacoService.prototype.buildNestedUri = /**
356 * @param {?} route
357 * @return {?}
358 */
359 function (route) {
360 var _this = this;
361 var /** @type {?} */ uri = '';
362 if (route.routeConfig && route.routeConfig.path) {
363 var /** @type {?} */ routePath = route.routeConfig.path;
364 for (var /** @type {?} */ key in route.params) {
365 if (key) {
366 var /** @type {?} */ re = new RegExp(':' + key);
367 routePath = routePath.replace(re, route.params[key]);
368 }
369 }
370 uri += '/' + routePath;
371 }
372 if (route.children) {
373 route.children.forEach(function (item) {
374 uri += _this.buildNestedUri(item);
375 });
376 }
377 return uri;
378 };
379 /**
380 * @return {?}
381 */
382 NacoService.prototype.getRefreshToken = /**
383 * @return {?}
384 */
385 function () {
386 if (null !== this.refreshToken) {
387 return Promise.resolve(this.refreshToken);
388 }
389 return this.storage.get('refresh_token');
390 };
391 /**
392 * @return {?}
393 */
394 NacoService.prototype.getClientSecret = /**
395 * @return {?}
396 */
397 function () {
398 if (null !== this.clientSecret) {
399 return Promise.resolve(this.clientSecret);
400 }
401 return this.storage.get('client_secret');
402 };
403 /**
404 * @param {?} path
405 * @return {?}
406 */
407 NacoService.prototype.getUri = /**
408 * @param {?} path
409 * @return {?}
410 */
411 function (path) {
412 return this.config.endpoint + '/api/' + this.VERSION + path;
413 };
414 /**
415 * @param {?=} path
416 * @return {?}
417 */
418 NacoService.prototype.getCurrentOrigin = /**
419 * @param {?=} path
420 * @return {?}
421 */
422 function (path) {
423 return window.location.origin + this.location.prepareExternalUrl(path || '');
424 };
425 /**
426 * @return {?}
427 */
428 NacoService.prototype.generateState = /**
429 * @return {?}
430 */
431 function () {
432 var /** @type {?} */ possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
433 var /** @type {?} */ text = '';
434 for (var /** @type {?} */ i = 0; i < 5; i++) {
435 text += possible.charAt(Math.floor(Math.random() * possible.length));
436 }
437 return text;
438 };
439 /**
440 * @param {?} params
441 * @return {?}
442 */
443 NacoService.prototype.buildQueryString = /**
444 * @param {?} params
445 * @return {?}
446 */
447 function (params) {
448 var /** @type {?} */ queryParams = Object.keys(params).map(function (key) {
449 return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
450 });
451 return queryParams.join('&');
452 };
453 NacoService.decorators = [
454 { type: Injectable },
455 ];
456 /** @nocollapse */
457 NacoService.ctorParameters = function () { return [
458 { type: Config },
459 { type: Router },
460 { type: Storage },
461 { type: HttpClient },
462 { type: Location }
463 ]; };
464 return NacoService;
465}());
466export { NacoService };
467function NacoService_tsickle_Closure_declarations() {
468 /** @type {?} */
469 NacoService.prototype.VERSION;
470 /** @type {?} */
471 NacoService.prototype.signature;
472 /** @type {?} */
473 NacoService.prototype.user;
474 /** @type {?} */
475 NacoService.prototype.refreshToken;
476 /** @type {?} */
477 NacoService.prototype.clientSecret;
478 /** @type {?} */
479 NacoService.prototype.config;
480 /** @type {?} */
481 NacoService.prototype.router;
482 /** @type {?} */
483 NacoService.prototype.storage;
484 /** @type {?} */
485 NacoService.prototype.http;
486 /** @type {?} */
487 NacoService.prototype.location;
488}
489
490//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFjby5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5ha2VyL25hY28vIiwic291cmNlcyI6WyJkb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUEwQixNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQVksRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRTFELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUNuRSxPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDMUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxVQUFVLEVBQXFCLE1BQU0sc0JBQXNCLENBQUM7QUFDckUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDOzt5QkFZM0IsUUFDQSxRQUNBLFNBQ0EsTUFDQTtRQUpBLFdBQU0sR0FBTixNQUFNO1FBQ04sV0FBTSxHQUFOLE1BQU07UUFDTixZQUFPLEdBQVAsT0FBTztRQUNQLFNBQUksR0FBSixJQUFJO1FBQ0osYUFBUSxHQUFSLFFBQVE7dUJBWk0sSUFBSTt5QkFFUSxJQUFJO29CQUNkLElBQUk7NEJBQ1MsSUFBSTs0QkFDUCxJQUFJOzs7Ozs7SUFXbkMsNkJBQU87Ozs7Y0FBQyxJQUFpQjtRQUM1QixJQUFJLENBQUMsSUFBSSxH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QUMsT0FBTyxHQUFHLElBQUksQ0FBQzs7Ozs7O0lBR3pELHNDQUFnQjs7OztjQUFDLElBQWE7UUFDakMsT0FBTyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFrQixDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQzs7Ozs7SUFHekUsbUNBQWE7Ozs7UUFDakIscUJBQU0sUUFBUSxHQUFHLGdFQUFnRSxDQUFDO1FBQ2xGLHFCQUFJLElBQUksR0FBRyxFQUFFLENBQUM7UUFFZCxLQUFLLHFCQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN4QixJQUFJLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztTQUN4RTtRQUVELE9BQU8sSUFBSSxDQUFDOzs7Ozs7SUFHUixzQ0FBZ0I7Ozs7Y0FBQyxNQUFjO1FBQ25DLHFCQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFDLEdBQVc7WUFDcEQsT0FBTyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsa0JBQWtCLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7U0FDMUUsQ0FBQyxDQUFDO1FBRUgsT0FBTyxXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDOzs7Z0JBdFZwQyxVQUFVOzs7O2dCQVZGLE1BQU07Z0JBRmtCLE1BQU07Z0JBQzlCLE9BQU87Z0JBUVAsVUFBVTtnQkFDVixRQUFROztzQkFYakI7O1NBY2EsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlU25hcHNob3QsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBTdG9yYWdlIH0gZnJvbSAnQHVidWQvc3RvcmFnZSc7XG5pbXBvcnQgeyBDb25maWcgfSBmcm9tICcuLi92YWx1ZXMvY29uZmlnJztcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi9tb2RlbHMvdXNlcic7XG5pbXBvcnQgeyBmb3JrSm9pbiwgT2JzZXJ2YWJsZSwgT2JzZXJ2ZXIsIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBTaWduYXR1cmUgfSBmcm9tICcuLi92YWx1ZXMvc2lnbmF0dXJlJztcbmltcG9ydCB7IGZyb21Qcm9taXNlIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9vYnNlcnZhYmxlL2Zyb21Qcm9taXNlJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIG1hcCwgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzL2ludGVybmFsL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBwbGFpblRvQ2xhc3MgfSBmcm9tICdjbGFzcy10cmFuc2Zvcm1lcic7XG5pbXBvcnQgeyBIdHRwQ2xpZW50LCBIdHRwRXJyb3JSZXNwb25zZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IExvY2F0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5hY29TZXJ2aWNlIHtcbiAgICBwdWJsaWMgcmVhZG9ubHkgVkVSU0lPTiA9ICd2MSc7XG5cbiAgICBwcml2YXRlIHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSB1c2VyOiBVc2VyIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSByZWZyZXNoVG9rZW46IFNpZ25hdHVyZSB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgY2xpZW50U2VjcmV0OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSBjb25maWc6IENvbmZpZyxcbiAgICAgICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgICAgICAgcHJpdmF0ZSBzdG9yYWdlOiBTdG9yYWdlLFxuICAgICAgICBwcml2YXRlIGh0dHA6IEh0dHBDbGllbnQsXG4gICAgICAgIHByaXZhdGUgbG9jYXRpb246IExvY2F0aW9uLFxuICAgICkge1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRVc2VyKHVzZXI6IFVzZXIgfCBudWxsKTogdm9pZCB7XG4gICAgICAgIHRoaXMudXNlciA9IHVzZXI7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFVzZXIoKTogT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy51c2VyKSB7XG4gICAgICAgICAgICByZXR1cm4gb2YodGhpcy51c2VyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHVyaSA9IHRoaXMuZ2V0VXJpKCcvdXNlcnMvbWUnKTtcblxuICAgICAgICByZXR1cm4gZnJvbVByb21pc2UodGhpcy5nZXRTaWduYXR1cmUoKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoc2lnbmF0dXJlOiBTaWduYXR1cmUgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKG51bGwgPT09IHNpZ25hdHVyZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZWZyZXNoVXNlcigpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF1dGhvcml6YXRpb246IGAke3NpZ25hdHVyZS50eXBlfSAke3NpZ25hdHVyZS50b2tlbn1gLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5odHRwLmdldDxhbnk+KHVyaSwgb3B0aW9ucykucGlwZShcbiAgICAgICAgICAgICAgICAgICAgbWFwKChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcy5kYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcy5kYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZXJlIGFyZSBubyBib2R5IHRvIGJlIHRyYW5zZm9ybWVkJyk7XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICBtYXAoKGRhdGE6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYXV0aFVzZXI6IGFueSA9IHBsYWluVG9DbGFzcyhVc2VyLCBkYXRhKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRVc2VyKGF1dGhVc2VyKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGF1dGhVc2VyO1xuICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgY2F0Y2hFcnJvcigoZTogSHR0cEVycm9yUmVzcG9uc2UpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICg0MDEgPT09IGUuc3RhdHVzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFVzZXIoKS5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKHJlZnJlc2hVc2VyOiBVc2VyIHwgbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlZnJlc2hVc2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9mKHJlZnJlc2hVc2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9mKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0UHJvZmlsZVBpY3R1cmUodXNlcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmVuZHBvaW50ICsgJy91c2Vycy8nICsgdXNlciArICcvcGljdHVyZSc7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFNpZ25hdHVyZSgpOiBQcm9taXNlPFNpZ25hdHVyZSB8IG51bGw+IHtcbiAgICAgICAgaWYgKHRoaXMuc2lnbmF0dXJlKSB7XG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRoaXMuc2lnbmF0dXJlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnN0b3JhZ2UuZ2V0KCdzaWduYXR1cmUnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0U2lnbmF0dXJlKHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNpZ25hdHVyZSA9IHNpZ25hdHVyZTtcblxuICAgICAgICBpZiAobnVsbCA9PT0gc2lnbmF0dXJlKSB7XG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlKCdzaWduYXR1cmUnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3NpZ25hdHVyZScsIHNpZ25hdHVyZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0Q2xpZW50U2VjcmV0KHNlY3JldDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIHRoaXMuY2xpZW50U2VjcmV0ID0gc2VjcmV0O1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdjbGllbnRfc2VjcmV0Jywgc2VjcmV0KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc2V0UmVmcmVzaFRva2VuKHJlZnJlc2hUb2tlbjogU2lnbmF0dXJlKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVmcmVzaFRva2VuID0gcmVmcmVzaFRva2VuO1xuICAgICAgICB0aGlzLnN0b3JhZ2Uuc2V0KCdyZWZyZXNoX3Rva2VuJywgcmVmcmVzaFRva2VuKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaFVzZXIoc2NvcGVzPzogc3RyaW5nKTogT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4ge1xuICAgICAgICB0aGlzLnNldFVzZXIobnVsbCk7XG4gICAgICAgIHRoaXMuc2V0U2lnbmF0dXJlKG51bGwpO1xuXG4gICAgICAgIHJldHVybiBmb3JrSm9pbih0aGlzLmdldFJlZnJlc2hUb2tlbigpLCB0aGlzLmdldENsaWVudFNlY3JldCgpKS5waXBlKFxuICAgICAgICAgICAgc3dpdGNoTWFwKChyZXN1bHRzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWZyZXNoVG9rZW46IFNpZ25hdHVyZSA9IHJlc3VsdHNbMF07XG4gICAgICAgICAgICAgICAgY29uc3QgY2xpZW50U2VjcmV0OiBzdHJpbmcgPSByZXN1bHRzWzFdO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZnJlc2hUb2tlbiAmJiBjbGllbnRTZWNyZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFdpdGhSZWZyZXNoVG9rZW4oY2xpZW50U2VjcmV0LCByZWZyZXNoVG9rZW4udG9rZW4sIHNjb3Blcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmcmVzaFdpdGhTaWxlbnRBdXRoKCk7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVmcmVzaFdpdGhSZWZyZXNoVG9rZW4oY2xpZW50U2VjcmV0OiBzdHJpbmcsIHJlZnJlc2hUb2tlbjogc3RyaW5nLCBzY29wZXM/OiBzdHJpbmcpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIGNvbnN0IHJlcXVlc3QgPSB0aGlzLmh0dHAucG9zdCh0aGlzLmdldFVyaSgnL3Rva2VucycpLCB7XG4gICAgICAgICAgICBncmFudF90eXBlOiAncmVmcmVzaF90b2tlbicsXG4gICAgICAgICAgICBzY29wZXM6IHNjb3BlcyB8fCAnYmFzaWMgZW1haWwnLFxuICAgICAgICAgICAgY2xpZW50X2lkOiB0aGlzLmNvbmZpZy5jbGllbnRJZCxcbiAgICAgICAgICAgIGNsaWVudF9zZWNyZXQ6IGNsaWVudFNlY3JldCxcbiAgICAgICAgICAgIHJlZnJlc2hfdG9rZW46IHJlZnJlc2hUb2tlbixcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHJlcXVlc3QucGlwZShcbiAgICAgICAgICAgIHRhcCgodG9rZW5zOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodG9rZW5zICYmIHRva2Vucy5kYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U2lnbmF0dXJlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGlyZXNJbjogdG9rZW5zLmRhdGEuZXhwaXJlc19pbixcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IHRva2Vucy5kYXRhLnRva2VuX3R5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogdG9rZW5zLmRhdGEuYWNjZXNzX3Rva2VuLFxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFJlZnJlc2hUb2tlbih7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiB0b2tlbnMuZGF0YS50b2tlbl90eXBlLFxuICAgICAgICAgICAgICAgICAgICAgICAgdG9rZW46IHRva2Vucy5kYXRhLnJlZnJlc2hfdG9rZW4sXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgbWFwKCh0b2tlbnM6IGFueSkgPT4gdG9rZW5zICYmIHRva2Vucy5kYXRhKSxcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoaGFzVG9rZW46IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzVG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VXNlcigpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBvZihudWxsKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWZyZXNoV2l0aFNpbGVudEF1dGgoKTogT2JzZXJ2YWJsZTxVc2VyIHwgbnVsbD4ge1xuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8VXNlciB8IG51bGw+KChvYnNlcnZlcjogT2JzZXJ2ZXI8VXNlciB8IG51bGw+KSA9PiB7XG4gICAgICAgICAgICBjb25zdCByZWRpcmVjdFVyaSA9IHRoaXMuZ2V0Q3VycmVudE9yaWdpbignYXV0aC9zaWxlbnQnKTtcbiAgICAgICAgICAgIGNvbnN0IHVyaSA9IHRoaXMubG9naW4oJ2Jhc2ljIGVtYWlsJywgcmVkaXJlY3RVcmksIGZhbHNlKTtcblxuICAgICAgICAgICAgY29uc3QgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG4gICAgICAgICAgICBpZnJhbWUuc2V0QXR0cmlidXRlKCdzcmMnLCB1cmkpO1xuICAgICAgICAgICAgaWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG5cbiAgICAgICAgICAgIGlmcmFtZS5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICAgICAgICdsb2FkJyxcbiAgICAgICAgICAgICAgICBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBxdWVyeVN0cmluZyA9IGlmcmFtZS5jb250ZW50V2luZG93LmxvY2F0aW9uLnNlYXJjaC5zdWJzdHJpbmcoMSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmcmFtZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGlmcmFtZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChxdWVyeVN0cmluZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHF1ZXJ5UGFydHMgPSBxdWVyeVN0cmluZy5zcGxpdCgnJicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHt9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHF1ZXJ5UGFydHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaXRlbVBhcnRzID0gaXRlbS5zcGxpdCgnPScpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtc1tpdGVtUGFydHNbMF1dID0gaXRlbVBhcnRzWzFdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwYXJhbXMuaGFzT3duUHJvcGVydHkoJ2FjY2Vzc190b2tlbicpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0U2lnbmF0dXJlKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRva2VuOiBwYXJhbXNbJ2FjY2Vzc190b2tlbiddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogcGFyYW1zWyd0b2tlbl90eXBlJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHBpcmVzSW46IHBhcmFtc1sndHRsJ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLmdldFVzZXIoKS50b1Byb21pc2UoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXNlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRVc2VyKHVzZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCh1c2VyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGlmcmFtZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBsb2dpbihzY29wZXM6IHN0cmluZywgcmVkaXJlY3RVcmk/OiBzdHJpbmcsIG5lZWRTdGF0ZTogYm9vbGVhbiA9IHRydWUpOiBzdHJpbmcge1xuICAgICAgICBpZiAoIXJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICByZWRpcmVjdFVyaSA9IHRoaXMucm91dGVyLnVybDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBhcmFtczogYW55ID0ge1xuICAgICAgICAgICAgcmVzcG9uc2VfdHlwZTogJ3Rva2VuJyxcbiAgICAgICAgICAgIHNjb3Blczogc2NvcGVzLFxuICAgICAgICAgICAgY2xpZW50OiB0aGlzLmNvbmZpZy5jbGllbnRJZCxcbiAgICAgICAgICAgIHNpbGVudDogdHJ1ZSxcbiAgICAgICAgICAgIGNvbnRpbnVlOiBlbmNvZGVVUklDb21wb25lbnQocmVkaXJlY3RVcmkpLFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChuZWVkU3RhdGUpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5nZW5lcmF0ZVN0YXRlKCk7XG5cbiAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3N0YXRlJywgc3RhdGUpO1xuICAgICAgICAgICAgcGFyYW1zLnN0YXRlID0gc3RhdGU7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBxdWVyeTogc3RyaW5nID0gdGhpcy5idWlsZFF1ZXJ5U3RyaW5nKHBhcmFtcyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLmVuZHBvaW50ICsgJy9hdXRoPycgKyBxdWVyeTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbG9nb3V0KHJlZGlyZWN0VXJpPzogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgdGhpcy5zaWduYXR1cmUgPSBudWxsO1xuICAgICAgICB0aGlzLnVzZXIgPSBudWxsO1xuICAgICAgICB0aGlzLmNsaWVudFNlY3JldCA9IG51bGw7XG4gICAgICAgIHRoaXMucmVmcmVzaFRva2VuID0gbnVsbDtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjbGVhciA9IFtcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlKCdzaWduYXR1cmUnKSxcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3JhZ2UucmVtb3ZlKCd1c2VyJyksXG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnJlbW92ZSgncmVmcmVzaF90b2tlbicpLFxuICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5yZW1vdmUoJ2NsaWVudF9zZWNyZXQnKSxcbiAgICAgICAgICAgIF07XG5cbiAgICAgICAgICAgIFByb21pc2UuYWxsKGNsZWFyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgZW5kcG9pbnQgPSB0aGlzLmNvbmZpZy5lbmRwb2ludCArICcvYXV0aC9sb2dvdXQnO1xuXG4gICAgICAgICAgICAgICAgaWYgKHJlZGlyZWN0VXJpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVuZHBvaW50ICs9ICc/Y29udGludWU9JyArIGVuY29kZVVSSUNvbXBvbmVudChyZWRpcmVjdFVyaSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShlbmRwb2ludCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFN0YXRlKCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgnc3RhdGUnKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYnVpbGROZXN0ZWRVcmkocm91dGU6IEFjdGl2YXRlZFJvdXRlU25hcHNob3QpOiBzdHJpbmcge1xuICAgICAgICBsZXQgdXJpID0gJyc7XG5cbiAgICAgICAgaWYgKHJvdXRlLnJvdXRlQ29uZmlnICYmIHJvdXRlLnJvdXRlQ29uZmlnLnBhdGgpIHtcbiAgICAgICAgICAgIGxldCByb3V0ZVBhdGggPSByb3V0ZS5yb3V0ZUNvbmZpZy5wYXRoO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiByb3V0ZS5wYXJhbXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlID0gbmV3IFJlZ0V4cCgnOicgKyBrZXkpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJvdXRlUGF0aCA9IHJvdXRlUGF0aC5yZXBsYWNlKHJlLCByb3V0ZS5wYXJhbXNba2V5XSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB1cmkgKz0gJy8nICsgcm91dGVQYXRoO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJvdXRlLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICByb3V0ZS5jaGlsZHJlbi5mb3JFYWNoKChpdGVtOiBBY3RpdmF0ZWRSb3V0ZVNuYXBzaG90KSA9PiB7XG4gICAgICAgICAgICAgICAgdXJpICs9IHRoaXMuYnVpbGROZXN0ZWRVcmkoaXRlbSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB1cmk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRSZWZyZXNoVG9rZW4oKTogUHJvbWlzZTxTaWduYXR1cmUgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnJlZnJlc2hUb2tlbikge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLnJlZnJlc2hUb2tlbik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgncmVmcmVzaF90b2tlbicpO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0Q2xpZW50U2VjcmV0KCk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICBpZiAobnVsbCAhPT0gdGhpcy5jbGllbnRTZWNyZXQpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodGhpcy5jbGllbnRTZWNyZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ2NsaWVudF9zZWNyZXQnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFVyaShwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2FwaS8nICsgdGhpcy5WRVJTSU9OICsgcGF0aDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0Q3VycmVudE9yaWdpbihwYXRoPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHdpbmRvdy5sb2NhdGlvbi5vcmlnaW4gKyB0aGlzLmxvY2F0aW9uLnByZXBhcmVFeHRlcm5hbFVybChwYXRoIHx8ICcnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdlbmVyYXRlU3RhdGUoKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3QgcG9zc2libGUgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODknO1xuICAgICAgICBsZXQgdGV4dCA9ICcnO1xuXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICAgICAgICB0ZXh0ICs9IHBvc3NpYmxlLmNoYXJBdChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiBwb3NzaWJsZS5sZW5ndGgpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cblxuICAgIHByaXZhdGUgYnVpbGRRdWVyeVN0cmluZyhwYXJhbXM6IG9iamVjdCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHF1ZXJ5UGFyYW1zID0gT2JqZWN0LmtleXMocGFyYW1zKS5tYXAoKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQocGFyYW1zW2tleV0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcXVlcnlQYXJhbXMuam9pbignJicpO1xuICAgIH1cbn1cbiJdfQ==
\No newline at end of file