UNPKG

37.5 kBJavaScriptView Raw
1import { __assign, __decorate, __metadata } 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 { of } from 'rxjs';
7import { fromPromise } from 'rxjs/internal/observable/fromPromise';
8import { map, switchMap, first, catchError } from 'rxjs/internal/operators';
9import { HttpClient } from '@angular/common/http';
10import { ErrorObservable } from 'rxjs-compat/observable/ErrorObservable';
11
12/**
13 * @fileoverview added by tsickle
14 * @suppress {checkTypes} checked by tsc
15 */
16var Config = /** @class */ (function () {
17 function Config(data) {
18 this.endpoint = 'https://account.kemnaker.go.id';
19 Object.assign(this, data);
20 }
21 return Config;
22}());
23
24/**
25 * @fileoverview added by tsickle
26 * @suppress {checkTypes} checked by tsc
27 */
28var User = /** @class */ (function () {
29 function User() {
30 }
31 __decorate([
32 Type(/** @type {?} */ (forwardRef(function () { return Date; }))),
33 __metadata("design:type", Date)
34 ], User.prototype, "updatedAt", void 0);
35 return User;
36}());
37
38/**
39 * @fileoverview added by tsickle
40 * @suppress {checkTypes} checked by tsc
41 */
42var NacoService = /** @class */ (function () {
43 function NacoService(config, router, storage, http) {
44 this.config = config;
45 this.router = router;
46 this.storage = storage;
47 this.http = http;
48 this.VERSION = 'v1';
49 this.signature = null;
50 this.user = null;
51 }
52 /**
53 * @return {?}
54 */
55 NacoService.prototype.getUser = /**
56 * @return {?}
57 */
58 function () {
59 var _this = this;
60 if (null !== this.user) {
61 return of(this.user);
62 }
63 return fromPromise(this.storage.get('user')).pipe(switchMap(function (user) {
64 if (null !== user) {
65 return of(user);
66 }
67 var /** @type {?} */ uri = _this.config.endpoint + '/api/' + _this.VERSION + '/users/me';
68 return fromPromise(_this.getSignature()).pipe(switchMap(function (signature) {
69 if (null === signature) {
70 return of(null);
71 }
72 var /** @type {?} */ options = {
73 headers: {
74 Authorization: signature.type + " " + signature.token,
75 },
76 };
77 return _this.http.get(uri, options).pipe(map(function (res) {
78 if (res.data) {
79 return res.data;
80 }
81 throw new Error('There are no body to be transformed');
82 }), map(function (data) {
83 return plainToClass(User, data);
84 }));
85 }));
86 }));
87 };
88 /**
89 * @return {?}
90 */
91 NacoService.prototype.getSignature = /**
92 * @return {?}
93 */
94 function () {
95 if (null !== this.signature) {
96 return Promise.resolve(this.signature);
97 }
98 return this.storage.get('signature');
99 };
100 /**
101 * @param {?} signature
102 * @return {?}
103 */
104 NacoService.prototype.setSignature = /**
105 * @param {?} signature
106 * @return {?}
107 */
108 function (signature) {
109 this.signature = signature;
110 this.storage.set('signature', signature);
111 };
112 /**
113 * @param {?} scopes
114 * @param {?=} redirectUri
115 * @return {?}
116 */
117 NacoService.prototype.login = /**
118 * @param {?} scopes
119 * @param {?=} redirectUri
120 * @return {?}
121 */
122 function (scopes, redirectUri) {
123 if (!redirectUri) {
124 redirectUri = this.router.url;
125 }
126 var /** @type {?} */ state = this.generateState();
127 this.storage.set('state', state);
128 var /** @type {?} */ query = this.buildQueryString({
129 'response_type': 'token',
130 'scopes': scopes,
131 'client': this.config.clientId,
132 'state': state,
133 'continue': redirectUri,
134 });
135 return this.config.endpoint + '/auth?' + query;
136 };
137 /**
138 * @return {?}
139 */
140 NacoService.prototype.getState = /**
141 * @return {?}
142 */
143 function () {
144 return this.storage.get('state');
145 };
146 /**
147 * @return {?}
148 */
149 NacoService.prototype.generateState = /**
150 * @return {?}
151 */
152 function () {
153 var /** @type {?} */ possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
154 var /** @type {?} */ text = '';
155 for (var /** @type {?} */ i = 0; i < 5; i++) {
156 text += possible.charAt(Math.floor(Math.random() * possible.length));
157 }
158 return text;
159 };
160 /**
161 * @param {?} params
162 * @return {?}
163 */
164 NacoService.prototype.buildQueryString = /**
165 * @param {?} params
166 * @return {?}
167 */
168 function (params) {
169 var /** @type {?} */ queryParams = Object.keys(params).map(function (key) {
170 return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
171 });
172 return queryParams.join('&');
173 };
174 NacoService.decorators = [
175 { type: Injectable },
176 ];
177 /** @nocollapse */
178 NacoService.ctorParameters = function () { return [
179 { type: Config },
180 { type: Router },
181 { type: Storage },
182 { type: HttpClient }
183 ]; };
184 return NacoService;
185}());
186
187/**
188 * @fileoverview added by tsickle
189 * @suppress {checkTypes} checked by tsc
190 */
191var Signature = /** @class */ (function () {
192 function Signature() {
193 }
194 return Signature;
195}());
196
197/**
198 * @fileoverview added by tsickle
199 * @suppress {checkTypes} checked by tsc
200 */
201var AuthenticatedGuard = /** @class */ (function () {
202 function AuthenticatedGuard(service) {
203 this.service = service;
204 }
205 /**
206 * @return {?}
207 */
208 AuthenticatedGuard.prototype.canActivate = /**
209 * @return {?}
210 */
211 function () {
212 var _this = this;
213 return this.service.getUser().pipe(first(), map(function (user) {
214 if (null === user) {
215 var /** @type {?} */ redirectUri = document.location.protocol + '//' + document.location.hostname;
216 if (document.location.port) {
217 redirectUri += ':' + document.location.port;
218 }
219 window.location.href = _this.service.login('basic email', redirectUri + '/auth');
220 }
221 return null !== user;
222 }));
223 };
224 /**
225 * @return {?}
226 */
227 AuthenticatedGuard.prototype.canActivateChild = /**
228 * @return {?}
229 */
230 function () {
231 return this.canActivate();
232 };
233 AuthenticatedGuard.decorators = [
234 { type: Injectable },
235 ];
236 /** @nocollapse */
237 AuthenticatedGuard.ctorParameters = function () { return [
238 { type: NacoService }
239 ]; };
240 return AuthenticatedGuard;
241}());
242
243/**
244 * @fileoverview added by tsickle
245 * @suppress {checkTypes} checked by tsc
246 */
247var AuthInterceptor = /** @class */ (function () {
248 function AuthInterceptor(naco) {
249 this.naco = naco;
250 }
251 /**
252 * @param {?} req
253 * @param {?} next
254 * @return {?}
255 */
256 AuthInterceptor.prototype.intercept = /**
257 * @param {?} req
258 * @param {?} next
259 * @return {?}
260 */
261 function (req, next) {
262 return fromPromise(this.naco.getSignature()).pipe(switchMap(function (signature) {
263 if (!signature) {
264 return next.handle(req);
265 }
266 return next
267 .handle(req.clone({
268 setHeaders: {
269 Authorization: signature.type + " " + signature.token,
270 },
271 }))
272 .pipe(catchError(function (error) {
273 if (error.status === 401) ;
274 return ErrorObservable.create(error);
275 }));
276 }));
277 };
278 AuthInterceptor.decorators = [
279 { type: Injectable },
280 ];
281 /** @nocollapse */
282 AuthInterceptor.ctorParameters = function () { return [
283 { type: NacoService }
284 ]; };
285 return AuthInterceptor;
286}());
287
288/**
289 * @fileoverview added by tsickle
290 * @suppress {checkTypes} checked by tsc
291 */
292/**
293 * @param {?} config
294 * @param {?} router
295 * @param {?} storage
296 * @param {?} http
297 * @return {?}
298 */
299function nacoFactory(config, router, storage, http) {
300 return new NacoService(new Config(__assign({}, config)), router, storage, http);
301}
302var /** @type {?} */ NACO_CONFIG = new InjectionToken('NACO_CONFIG');
303
304/**
305 * @fileoverview added by tsickle
306 * @suppress {checkTypes} checked by tsc
307 */
308var AuthPage = /** @class */ (function () {
309 function AuthPage(route, router, naco) {
310 var _this = this;
311 this.route = route;
312 this.router = router;
313 this.naco = naco;
314 this.message = 'Authenticating...';
315 this.route.queryParams.subscribe(function (params) { return _this.handle(params); });
316 }
317 /**
318 * @param {?} params
319 * @return {?}
320 */
321 AuthPage.prototype.handle = /**
322 * @param {?} params
323 * @return {?}
324 */
325 function (params) {
326 var _this = this;
327 if (params["state"]) {
328 this.naco.getState().then(function (state) {
329 if (state !== params["state"]) {
330 _this.message = 'Invalid CSRF';
331 return;
332 }
333 _this.authenticate(params);
334 });
335 }
336 else {
337 this.authenticate(params);
338 }
339 };
340 /**
341 * @param {?} params
342 * @return {?}
343 */
344 AuthPage.prototype.authenticate = /**
345 * @param {?} params
346 * @return {?}
347 */
348 function (params) {
349 var _this = this;
350 var /** @type {?} */ signature = {
351 expiresIn: params["expires_in"],
352 type: params["token_type"],
353 token: params["access_token"],
354 };
355 this.naco.setSignature(signature);
356 this.naco.getUser().subscribe(function (user) {
357 if (null !== user) {
358 _this.router.navigate(['/']);
359 return;
360 }
361 _this.message = 'Unauthenticated!';
362 });
363 };
364 AuthPage.decorators = [
365 { type: Component, args: [{
366 selector: 'naker-auth-page',
367 template: '{{ message }}',
368 },] },
369 ];
370 /** @nocollapse */
371 AuthPage.ctorParameters = function () { return [
372 { type: ActivatedRoute },
373 { type: Router },
374 { type: NacoService }
375 ]; };
376 return AuthPage;
377}());
378
379/**
380 * @fileoverview added by tsickle
381 * @suppress {checkTypes} checked by tsc
382 */
383var /** @type {?} */ routes = [
384 {
385 path: 'auth',
386 component: AuthPage
387 },
388];
389var /** @type {?} */ AUTH_ROUTING = RouterModule.forChild(routes);
390
391/**
392 * @fileoverview added by tsickle
393 * @suppress {checkTypes} checked by tsc
394 */
395var NacoViewModule = /** @class */ (function () {
396 function NacoViewModule() {
397 }
398 NacoViewModule.decorators = [
399 { type: NgModule, args: [{
400 imports: [
401 AUTH_ROUTING,
402 ],
403 declarations: [
404 AuthPage,
405 ],
406 },] },
407 ];
408 return NacoViewModule;
409}());
410
411/**
412 * @fileoverview added by tsickle
413 * @suppress {checkTypes} checked by tsc
414 */
415var NacoModule = /** @class */ (function () {
416 function NacoModule() {
417 }
418 /**
419 * @param {?} config
420 * @return {?}
421 */
422 NacoModule.forRoot = /**
423 * @param {?} config
424 * @return {?}
425 */
426 function (config) {
427 return {
428 ngModule: NacoModule,
429 providers: [
430 {
431 provide: NACO_CONFIG,
432 useValue: config,
433 },
434 {
435 provide: NacoService,
436 useFactory: nacoFactory,
437 deps: [NACO_CONFIG, Router, Storage, HttpClient],
438 },
439 AuthenticatedGuard,
440 ],
441 };
442 };
443 NacoModule.decorators = [
444 { type: NgModule, args: [{
445 imports: [
446 UbudStorageModule,
447 NacoViewModule,
448 ],
449 },] },
450 ];
451 return NacoModule;
452}());
453
454/**
455 * @fileoverview added by tsickle
456 * @suppress {checkTypes} checked by tsc
457 */
458
459/**
460 * @fileoverview added by tsickle
461 * @suppress {checkTypes} checked by tsc
462 */
463
464export { NacoService, User, Signature, Config, AuthenticatedGuard, AuthInterceptor, NacoModule, NACO_CONFIG as ɵe, nacoFactory as ɵd, NacoViewModule as ɵa, AuthPage as ɵc, AUTH_ROUTING as ɵb };
465
466//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFrZXItbmFjby5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vQG5ha2VyL25hY28vZG9tYWlucy92YWx1ZXMvY29uZmlnLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9kb21haW5zL21vZGVscy91c2VyLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZS50cyIsIm5nOi8vQG5ha2VyL25hY28vZG9tYWlucy92YWx1ZXMvc2lnbmF0dXJlLnRzIiwibmc6Ly9AbmFrZXIvbmFjby9ndWFyZHMvYXV0aGVudGljYXRlZC5ndWFyZC50cyIsIm5nOi8vQG5ha2VyL25hY28vaW50ZXJjZXB0b3JzL2F1dGguaW50ZXJjZXB0b3IudHMiLCJuZzovL0BuYWtlci9uYWNvL2ZhY3Rvcmllcy9uYWNvLWZhY3RvcnkudHMiLCJuZzovL0BuYWtlci9uYWNvL3ZpZXdzL3BhZ2VzL2F1dGgucGFnZS50cyIsIm5nOi8vQG5ha2VyL25hY28vdmlld3Mvcm91dGVzLnRzIiwibmc6Ly9AbmFrZXIvbmFjby92aWV3cy9tb2R1bGUudHMiLCJuZzovL0BuYWtlci9uYWNvL25hY28ubW9kdWxlLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBjbGFzcyBDb25maWcge1xuICAgIHB1YmxpYyBlbmRwb2ludDogc3RyaW5nID0gJ2h0dHBzOi8vYWNjb3VudC5rZW1uYWtlci5nby5pZCc7XG4gICAgcHVibGljIGNsaWVudElkOiBzdHJpbmc7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoZGF0YT86IFBhcnRpYWw8Q29uZmlnPikge1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMsIGRhdGEpO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IGZvcndhcmRSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFR5cGUgfSBmcm9tICdjbGFzcy10cmFuc2Zvcm1lcic7XG5cbmV4cG9ydCBjbGFzcyBVc2VyIHtcbiAgICBwdWJsaWMgaWQ6IHN0cmluZztcbiAgICBwdWJsaWMgdXNlcm5hbWU6IHN0cmluZztcbiAgICBwdWJsaWMgZW1haWw/OiBzdHJpbmc7XG4gICAgcHVibGljIG5hbWU6IHN0cmluZztcbiAgICBwdWJsaWMgc3RhdHVzOiBudW1iZXI7XG5cbiAgICBAVHlwZShmb3J3YXJkUmVmKCgpID0+IERhdGUpIGFzIGFueSlcbiAgICBwdWJsaWMgdXBkYXRlZEF0OiBEYXRlO1xufVxuIiwiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IFN0b3JhZ2UgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJy4uL3ZhbHVlcy9jb25maWcnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uL21vZGVscy91c2VyJztcbmltcG9ydCB7IE9ic2VydmFibGUsIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBTaWduYXR1cmUgfSBmcm9tICcuLi92YWx1ZXMvc2lnbmF0dXJlJztcbmltcG9ydCB7IGZyb21Qcm9taXNlIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9vYnNlcnZhYmxlL2Zyb21Qcm9taXNlJztcbmltcG9ydCB7IG1hcCwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9pbnRlcm5hbC9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgcGxhaW5Ub0NsYXNzIH0gZnJvbSAnY2xhc3MtdHJhbnNmb3JtZXInO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIE5hY29TZXJ2aWNlIHtcbiAgICBwdWJsaWMgcmVhZG9ubHkgVkVSU0lPTiA9ICd2MSc7XG5cbiAgICBwcml2YXRlIHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSB1c2VyOiBVc2VyIHwgbnVsbCA9IG51bGw7XG5cbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSBjb25maWc6IENvbmZpZywgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlciwgcHJpdmF0ZSBzdG9yYWdlOiBTdG9yYWdlLCBwcml2YXRlIGh0dHA6IEh0dHBDbGllbnQpIHtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0VXNlcigpOiBPYnNlcnZhYmxlPFVzZXIgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnVzZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBvZih0aGlzLnVzZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZyb21Qcm9taXNlKHRoaXMuc3RvcmFnZS5nZXQoJ3VzZXInKSkucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgodXNlcjogVXNlciB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAobnVsbCAhPT0gdXNlcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2YodXNlcik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY29uc3QgdXJpID0gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2FwaS8nICsgdGhpcy5WRVJTSU9OICsgJy91c2Vycy9tZSc7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZnJvbVByb21pc2UodGhpcy5nZXRTaWduYXR1cmUoKSkucGlwZShcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoTWFwKChzaWduYXR1cmU6IFNpZ25hdHVyZSB8IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChudWxsID09PSBzaWduYXR1cmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgJHtzaWduYXR1cmUudHlwZX0gJHtzaWduYXR1cmUudG9rZW59YCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8YW55Pih1cmksIG9wdGlvbnMpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKChyZXM6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXMuZGF0YTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlcmUgYXJlIG5vIGJvZHkgdG8gYmUgdHJhbnNmb3JtZWQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAoKGRhdGE6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGxhaW5Ub0NsYXNzKFVzZXIsIGRhdGEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTaWduYXR1cmUoKTogUHJvbWlzZTxTaWduYXR1cmUgfCBudWxsPiB7XG4gICAgICAgIGlmIChudWxsICE9PSB0aGlzLnNpZ25hdHVyZSkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0aGlzLnNpZ25hdHVyZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5zdG9yYWdlLmdldCgnc2lnbmF0dXJlJyk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldFNpZ25hdHVyZShzaWduYXR1cmU6IFNpZ25hdHVyZSk6IHZvaWQge1xuICAgICAgICB0aGlzLnNpZ25hdHVyZSA9IHNpZ25hdHVyZTtcbiAgICAgICAgdGhpcy5zdG9yYWdlLnNldCgnc2lnbmF0dXJlJywgc2lnbmF0dXJlKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbG9naW4oc2NvcGVzOiBzdHJpbmcsIHJlZGlyZWN0VXJpPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKCFyZWRpcmVjdFVyaSkge1xuICAgICAgICAgICAgcmVkaXJlY3RVcmkgPSB0aGlzLnJvdXRlci51cmw7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzdGF0ZSA9IHRoaXMuZ2VuZXJhdGVTdGF0ZSgpO1xuXG4gICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoJ3N0YXRlJywgc3RhdGUpO1xuXG4gICAgICAgIGNvbnN0IHF1ZXJ5OiBzdHJpbmcgPSB0aGlzLmJ1aWxkUXVlcnlTdHJpbmcoXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgJ3Jlc3BvbnNlX3R5cGUnOiAndG9rZW4nLFxuICAgICAgICAgICAgICAgICdzY29wZXMnOiBzY29wZXMsXG4gICAgICAgICAgICAgICAgJ2NsaWVudCc6IHRoaXMuY29uZmlnLmNsaWVudElkLFxuICAgICAgICAgICAgICAgICdzdGF0ZSc6IHN0YXRlLFxuICAgICAgICAgICAgICAgICdjb250aW51ZSc6IHJlZGlyZWN0VXJpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgKTtcblxuICAgICAgICByZXR1cm4gdGhpcy5jb25maWcuZW5kcG9pbnQgKyAnL2F1dGg/JyArIHF1ZXJ5O1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRTdGF0ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5nZXQoJ3N0YXRlJyk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZW5lcmF0ZVN0YXRlKCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHBvc3NpYmxlID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5JztcbiAgICAgICAgbGV0IHRleHQgPSAnJztcblxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDU7IGkrKykge1xuICAgICAgICAgICAgdGV4dCArPSBwb3NzaWJsZS5jaGFyQXQoTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogcG9zc2libGUubGVuZ3RoKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGV4dDtcbiAgICB9XG5cbiAgICBwcml2YXRlIGJ1aWxkUXVlcnlTdHJpbmcocGFyYW1zOiBvYmplY3QpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCBxdWVyeVBhcmFtcyA9IE9iamVjdC5rZXlzKHBhcmFtcykubWFwKChrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChrZXkpICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHBhcmFtc1trZXldKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHF1ZXJ5UGFyYW1zLmpvaW4oJyYnKTtcbiAgICB9XG59XG4iLCJleHBvcnQgY2xhc3MgU2lnbmF0dXJlIHtcbiAgICBwdWJsaWMgZXhwaXJlc0luOiBudW1iZXI7XG4gICAgcHVibGljIHRva2VuOiBzdHJpbmc7XG4gICAgcHVibGljIHR5cGU6IHN0cmluZztcbn1cbiIsImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENhbkFjdGl2YXRlLCBDYW5BY3RpdmF0ZUNoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IE5hY29TZXJ2aWNlIH0gZnJvbSAnLi4vZG9tYWlucy9zZXJ2aWNlcy9uYWNvLnNlcnZpY2UnO1xuaW1wb3J0IHsgZmlyc3QsIG1hcCB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb3BlcmF0b3JzJztcbmltcG9ydCB7IFVzZXIgfSBmcm9tICcuLi9kb21haW5zL21vZGVscy91c2VyJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEF1dGhlbnRpY2F0ZWRHdWFyZCBpbXBsZW1lbnRzIENhbkFjdGl2YXRlLCBDYW5BY3RpdmF0ZUNoaWxkIHtcbiAgICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSBzZXJ2aWNlOiBOYWNvU2VydmljZSkge1xuICAgIH1cblxuICAgIHB1YmxpYyBjYW5BY3RpdmF0ZSgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VydmljZS5nZXRVc2VyKCkucGlwZShcbiAgICAgICAgICAgIGZpcnN0KCksXG4gICAgICAgICAgICBtYXAoKHVzZXI6IFVzZXIgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKG51bGwgPT09IHVzZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJlZGlyZWN0VXJpID0gZG9jdW1lbnQubG9jYXRpb24ucHJvdG9jb2wgKyAnLy8nICsgZG9jdW1lbnQubG9jYXRpb24uaG9zdG5hbWU7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmxvY2F0aW9uLnBvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlZGlyZWN0VXJpICs9ICc6JyArIGRvY3VtZW50LmxvY2F0aW9uLnBvcnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHRoaXMuc2VydmljZS5sb2dpbihcbiAgICAgICAgICAgICAgICAgICAgICAgICdiYXNpYyBlbWFpbCcsXG4gICAgICAgICAgICAgICAgICAgICAgICByZWRpcmVjdFVyaSArICcvYXV0aCcsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGwgIT09IHVzZXI7XG4gICAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY2FuQWN0aXZhdGVDaGlsZCgpOiBPYnNlcnZhYmxlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FuQWN0aXZhdGUoKTtcbiAgICB9XG59XG4iLCJpbXBvcnQgeyBIdHRwRXJyb3JSZXNwb25zZSwgSHR0cEV2ZW50LCBIdHRwSGFuZGxlciwgSHR0cEludGVyY2VwdG9yLCBIdHRwUmVxdWVzdCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE5hY29TZXJ2aWNlIH0gZnJvbSAnLi4vZG9tYWlucy9zZXJ2aWNlcy9uYWNvLnNlcnZpY2UnO1xuaW1wb3J0IHsgZnJvbVByb21pc2UgfSBmcm9tICdyeGpzL2ludGVybmFsL29ic2VydmFibGUvZnJvbVByb21pc2UnO1xuaW1wb3J0IHsgU2lnbmF0dXJlIH0gZnJvbSAnLi4vZG9tYWlucy92YWx1ZXMvc2lnbmF0dXJlJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIHN3aXRjaE1hcCB9IGZyb20gJ3J4anMvaW50ZXJuYWwvb3BlcmF0b3JzJztcbmltcG9ydCB7IEVycm9yT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMtY29tcGF0L29ic2VydmFibGUvRXJyb3JPYnNlcnZhYmxlJztcbmltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIEF1dGhJbnRlcmNlcHRvciBpbXBsZW1lbnRzIEh0dHBJbnRlcmNlcHRvciB7XG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgbmFjbzogTmFjb1NlcnZpY2UpIHtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW50ZXJjZXB0KHJlcTogSHR0cFJlcXVlc3Q8YW55PiwgbmV4dDogSHR0cEhhbmRsZXIpOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxhbnk+PiB7XG4gICAgICAgIHJldHVybiBmcm9tUHJvbWlzZSh0aGlzLm5hY28uZ2V0U2lnbmF0dXJlKCkpLnBpcGUoXG4gICAgICAgICAgICBzd2l0Y2hNYXAoKHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghc2lnbmF0dXJlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXh0LmhhbmRsZShyZXEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXh0XG4gICAgICAgICAgICAgICAgICAgIC5oYW5kbGUoXG4gICAgICAgICAgICAgICAgICAgICAgICByZXEuY2xvbmUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNldEhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0aG9yaXphdGlvbjogYCR7c2lnbmF0dXJlLnR5cGV9ICR7c2lnbmF0dXJlLnRva2VufWAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yLnN0YXR1cyA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IFJlZnJlc2ggdG9rZW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gRXJyb3JPYnNlcnZhYmxlLmNyZWF0ZShlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICApO1xuICAgIH1cbn1cbiIsImltcG9ydCB7IE5hY29TZXJ2aWNlIH0gZnJvbSAnLi4vZG9tYWlucy9zZXJ2aWNlcy9uYWNvLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ29uZmlnIH0gZnJvbSAnLi4vZG9tYWlucy92YWx1ZXMvY29uZmlnJztcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBTdG9yYWdlIH0gZnJvbSAnQHVidWQvc3RvcmFnZSc7XG5pbXBvcnQgeyBJbmplY3Rpb25Ub2tlbiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcblxuZXhwb3J0IGZ1bmN0aW9uIG5hY29GYWN0b3J5KGNvbmZpZzogb2JqZWN0LCByb3V0ZXI6IFJvdXRlciwgc3RvcmFnZTogU3RvcmFnZSwgaHR0cDogSHR0cENsaWVudCkge1xuICAgIHJldHVybiBuZXcgTmFjb1NlcnZpY2UoXG4gICAgICAgIG5ldyBDb25maWcoeyAuLi5jb25maWcgfSksXG4gICAgICAgIHJvdXRlcixcbiAgICAgICAgc3RvcmFnZSxcbiAgICAgICAgaHR0cFxuICAgICk7XG59XG5cbmV4cG9ydCBjb25zdCBOQUNPX0NPTkZJRyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxvYmplY3Q+KCdOQUNPX0NPTkZJRycpO1xuIiwiaW1wb3J0IHsgQ29tcG9uZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUGFyYW1zLCBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgTmFjb1NlcnZpY2UgfSBmcm9tICcuLi8uLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBTaWduYXR1cmUgfSBmcm9tICcuLi8uLi9kb21haW5zL3ZhbHVlcy9zaWduYXR1cmUnO1xuaW1wb3J0IHsgVXNlciB9IGZyb20gJy4uLy4uL2RvbWFpbnMvbW9kZWxzL3VzZXInO1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ25ha2VyLWF1dGgtcGFnZScsXG4gICAgdGVtcGxhdGU6ICd7eyBtZXNzYWdlIH19Jyxcbn0pXG5leHBvcnQgY2xhc3MgQXV0aFBhZ2Uge1xuICAgIHB1YmxpYyBtZXNzYWdlOiBzdHJpbmcgPSAnQXV0aGVudGljYXRpbmcuLi4nO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLCBwcml2YXRlIHJvdXRlcjogUm91dGVyLCBwcml2YXRlIG5hY286IE5hY29TZXJ2aWNlKSB7XG4gICAgICAgIHRoaXMucm91dGUucXVlcnlQYXJhbXMuc3Vic2NyaWJlKChwYXJhbXM6IFBhcmFtcykgPT4gdGhpcy5oYW5kbGUocGFyYW1zKSk7XG4gICAgfVxuXG4gICAgcHVibGljIGhhbmRsZShwYXJhbXM6IFBhcmFtcyk6IHZvaWQge1xuICAgICAgICBpZiAocGFyYW1zLnN0YXRlKSB7XG4gICAgICAgICAgICB0aGlzLm5hY28uZ2V0U3RhdGUoKS50aGVuKChzdGF0ZTogc3RyaW5nIHwgbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChzdGF0ZSAhPT0gcGFyYW1zLnN0YXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWVzc2FnZSA9ICdJbnZhbGlkIENTUkYnO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmF1dGhlbnRpY2F0ZShwYXJhbXMpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmF1dGhlbnRpY2F0ZShwYXJhbXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhdXRoZW50aWNhdGUocGFyYW1zOiBQYXJhbXMpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc2lnbmF0dXJlOiBTaWduYXR1cmUgPSB7XG4gICAgICAgICAgICBleHBpcmVzSW46IHBhcmFtcy5leHBpcmVzX2luLFxuICAgICAgICAgICAgdHlwZTogcGFyYW1zLnRva2VuX3R5cGUsXG4gICAgICAgICAgICB0b2tlbjogcGFyYW1zLmFjY2Vzc190b2tlbixcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLm5hY28uc2V0U2lnbmF0dXJlKHNpZ25hdHVyZSk7XG5cbiAgICAgICAgdGhpcy5uYWNvLmdldFVzZXIoKS5zdWJzY3JpYmUoKHVzZXI6IFVzZXIgfCBudWxsKSA9PiB7XG4gICAgICAgICAgICBpZiAobnVsbCAhPT0gdXNlcikge1xuICAgICAgICAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnLyddKTtcblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlID0gJ1VuYXV0aGVudGljYXRlZCEnO1xuICAgICAgICB9KTtcbiAgICB9XG59XG5cbiIsImltcG9ydCB7IE1vZHVsZVdpdGhQcm92aWRlcnMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJvdXRlck1vZHVsZSwgUm91dGVzIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEF1dGhQYWdlIH0gZnJvbSAnLi9wYWdlcy9hdXRoLnBhZ2UnO1xuXG5jb25zdCByb3V0ZXM6IFJvdXRlcyA9IFtcbiAgICB7XG4gICAgICAgIHBhdGg6ICdhdXRoJyxcbiAgICAgICAgY29tcG9uZW50OiBBdXRoUGFnZVxuICAgIH0sXG5dO1xuXG5leHBvcnQgY29uc3QgQVVUSF9ST1VUSU5HOiBNb2R1bGVXaXRoUHJvdmlkZXJzID0gUm91dGVyTW9kdWxlLmZvckNoaWxkKHJvdXRlcyk7XG4iLCJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQVVUSF9ST1VUSU5HIH0gZnJvbSAnLi9yb3V0ZXMnO1xuaW1wb3J0IHsgQXV0aFBhZ2UgfSBmcm9tICcuL3BhZ2VzL2F1dGgucGFnZSc7XG5cbkBOZ01vZHVsZSh7XG4gICAgaW1wb3J0czogW1xuICAgICAgICBBVVRIX1JPVVRJTkcsXG4gICAgXSxcbiAgICBkZWNsYXJhdGlvbnM6IFtcbiAgICAgICAgQXV0aFBhZ2UsXG4gICAgXSxcbn0pXG5leHBvcnQgY2xhc3MgTmFjb1ZpZXdNb2R1bGUge1xufVxuIiwiaW1wb3J0IHsgTW9kdWxlV2l0aFByb3ZpZGVycywgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5hY29TZXJ2aWNlIH0gZnJvbSAnLi9kb21haW5zL3NlcnZpY2VzL25hY28uc2VydmljZSc7XG5pbXBvcnQgeyBBdXRoZW50aWNhdGVkR3VhcmQgfSBmcm9tICcuL2d1YXJkcy9hdXRoZW50aWNhdGVkLmd1YXJkJztcbmltcG9ydCB7IE5BQ09fQ09ORklHLCBuYWNvRmFjdG9yeSB9IGZyb20gJy4vZmFjdG9yaWVzL25hY28tZmFjdG9yeSc7XG5pbXBvcnQgeyBSb3V0ZXIgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgU3RvcmFnZSwgVWJ1ZFN0b3JhZ2VNb2R1bGUgfSBmcm9tICdAdWJ1ZC9zdG9yYWdlJztcbmltcG9ydCB7IE5hY29WaWV3TW9kdWxlIH0gZnJvbSAnLi92aWV3cy9tb2R1bGUnO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcblxuQE5nTW9kdWxlKHtcbiAgICBpbXBvcnRzOiBbXG4gICAgICAgIFVidWRTdG9yYWdlTW9kdWxlLFxuICAgICAgICBOYWNvVmlld01vZHVsZSxcbiAgICBdLFxufSlcbmV4cG9ydCBjbGFzcyBOYWNvTW9kdWxlIHtcbiAgICBwdWJsaWMgc3RhdGljIGZvclJvb3QoY29uZmlnOiB7IGNsaWVudElkOiBzdHJpbmcsIGVuZHBvaW50Pzogc3RyaW5nIH0pOiBNb2R1bGVXaXRoUHJvdmlkZXJzIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG5nTW9kdWxlOiBOYWNvTW9kdWxlLFxuICAgICAgICAgICAgcHJvdmlkZXJzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBwcm92aWRlOiBOQUNPX0NPTkZJRyxcbiAgICAgICAgICAgICAgICAgICAgdXNlVmFsdWU6IGNvbmZpZyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvdmlkZTogTmFjb1NlcnZpY2UsXG4gICAgICAgICAgICAgICAgICAgIHVzZUZhY3Rvcnk6IG5hY29GYWN0b3J5LFxuICAgICAgICAgICAgICAgICAgICBkZXBzOiBbTkFDT19DT05GSUcsIFJvdXRlciwgU3RvcmFnZSwgSHR0cENsaWVudF0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBBdXRoZW50aWNhdGVkR3VhcmQsXG4gICAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7QUFBQSxJQUFBO29CQUl1QixJQUFzQjt3QkFIZixnQ0FBZ0M7UUFJdEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7O2lCQUxsQztJQU9DOzs7Ozs7Ozs7O1FDR0ksSUFBSSxtQkFBQyxVQUFVLENBQUMsY0FBTSxPQUFBLElBQUksR0FBQSxDQUFRLEVBQUM7a0NBQ2xCLElBQUk7O2VBWDFCOzs7Ozs7O0FDQUE7eUJBbUIrQixNQUFjLEVBQVUsTUFBYyxFQUFVLE9BQWdCLEVBQVUsSUFBZ0I7UUFBMUYsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUFVLFdBQU0sR0FBTixNQUFNLENBQVE7UUFBVSxZQUFPLEdBQVAsT0FBTyxDQUFTO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBWTt1QkFMM0YsSUFBSTt5QkFFUSxJQUFJO29CQUNkLElBQUk7Ozs7O0lBS3pCLDZCQUFPOzs7OztRQUNWLElBQUksSUFBSSxLQUFLLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDcEIsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3hCO1FBRUQsT0FBTyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQzdDLFNBQVMsQ0FBQyxVQUFDLElBQWlCO1lBQ3hCLElBQUksSUFBSSxLQUFLLElBQUksRUFBRTtnQkFDZixPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUNuQjtZQUVELHFCQUFNLEdBQUcsR0FBRyxLQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsR0FBRyxPQUFPLEdBQUcsS0FBSSxDQUFDLE9BQU8sR0FBRyxXQUFXLENBQUM7WUFFeEUsT0FBTyxXQUFXLENBQUMsS0FBSSxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUN4QyxTQUFTLENBQUMsVUFBQyxTQUEyQjtnQkFDbEMsSUFBSSxJQUFJLEtBQUssU0FBUyxFQUFFO29CQUNwQixPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztpQkFDbkI7Z0JBRUQscUJBQU0sT0FBTyxHQUFHO29CQUNaLE9BQU8sRUFBRTt3QkFDTCxhQUFhLEVBQUssU0FBUyxDQUFDLElBQUksU0FBSSxTQUFTLENBQUMsS0FBTztxQkFDeEQ7aUJBQ0osQ0FBQztnQkFFRixPQUFPLEtBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFNLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQ3hDLEdBQUcsQ0FBQyxVQUFDLEdBQVE7b0JBQ1QsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFO3dCQUNWLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQztxQkFDbkI7b0JBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFDO2lCQUMxRCxDQUFDLEVBQ0YsR0FBRyxDQUFDLFVBQUMsSUFBUztvQkFDVixPQUFPLFlBQVksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7aUJBQ25DLENBQUMsQ0FDTCxDQUFDO2FBQ0wsQ0FBQyxDQUNMLENBQUM7U0FDTCxDQUFDLENBQ0wsQ0FBQzs7Ozs7SUFHQyxrQ0FBWTs7OztRQUNmLElBQUksSUFBSSxLQUFLLElBQUksQ0FBQyxTQUFTLEVBQUU7WUFDekIsT0FBTyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztTQUMxQztRQUVELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7Ozs7OztJQUdsQyxrQ0FBWTs7OztjQUFDLFNBQW9CO1FBQ3BDLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBQzNCLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQzs7Ozs7OztJQUd0QywyQkFBSzs7Ozs7Y0FBQyxNQUFjLEVBQUUsV0FBb0I7UUFDN0MsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNkLFdBQVcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztTQUNqQztRQUVELHFCQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFFbkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRWpDLHFCQUFNLEtBQUssR0FBVyxJQUFJLENBQUMsZ0JBQWdCLENBQ3ZDO1lBQ0ksZUFBZSxFQUFFLE9BQU87WUFDeEIsUUFBUSxFQUFFLE1BQU07WUFDaEIsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUTtZQUM5QixPQUFPLEVBQUUsS0FBSztZQUNkLFVBQVUsRUFBRSxXQUFXO1NBQzFCLENBQ0osQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEdBQUcsUUFBUSxHQUFHLEtBQUssQ0FBQzs7Ozs7SUFHNUMsOEJBQVE7Ozs7UUFDWCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDOzs7OztJQUc3QixtQ0FBYTs7OztRQUNqQixxQkFBTSxRQUFRLEdBQUcsZ0VBQWdFLENBQUM7UUFDbEYscUJBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUVkLEtBQUsscUJBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3hCLElBQUksSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1NBQ3hFO1FBRUQsT0FBTyxJQUFJLENBQUM7Ozs7OztJQUdSLHNDQUFnQjs7OztjQUFDLE1BQWM7UUFDbkMscUJBQU0sV0FBVyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQUMsR0FBVztZQUNwRCxPQUFPLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztTQUMxRSxDQUFDLENBQUM7UUFFSCxPQUFPLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7OztnQkE1R3BDLFVBQVU7Ozs7Z0JBVEYsTUFBTTtnQkFGTixNQUFNO2dCQUNOLE9BQU87Z0JBUVAsVUFBVTs7c0JBVm5COzs7Ozs7O0FDQUEsSUFBQTs7O29CQUFBO0lBSUM7Ozs7OztBQ0pEO2dDQVMrQixPQUFvQjtRQUFwQixZQUFPLEdBQVAsT0FBTyxDQUFhOzs7OztJQUd4Qyx3Q0FBVzs7Ozs7UUFDZCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUM5QixLQUFLLEVBQUUsRUFDUCxHQUFHLENBQUMsVUFBQyxJQUFpQjtZQUNsQixJQUFJLElBQUksS0FBSyxJQUFJLEVBQUU7Z0JBQ2YscUJBQUksV0FBVyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsUUFBUSxHQUFHLElBQUksR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztnQkFFakYsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRTtvQkFDeEIsV0FBVyxJQUFJLEdBQUcsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztpQkFDL0M7Z0JBRUQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEdBQUcsS0FBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQ3JDLGFBQWEsRUFDYixXQUFXLEdBQUcsT0FBTyxDQUN4QixDQUFDO2FBQ0w7WUFFRCxPQUFPLElBQUksS0FBSyxJQUFJLENBQUM7U0FDeEIsQ0FBQyxDQUNMLENBQUM7Ozs7O0lBR0MsNkNBQWdCOzs7O1FBQ25CLE9BQU8sSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDOzs7Z0JBNUJqQyxVQUFVOzs7O2dCQUxGLFdBQVc7OzZCQUZwQjs7Ozs7OztBQ0VBOzZCQVMrQixJQUFpQjtRQUFqQixTQUFJLEdBQUosSUFBSSxDQUFhOzs7Ozs7O0lBR3JDLG1DQUFTOzs7OztjQUFDLEdBQXFCLEVBQUUsSUFBaUI7UUFDckQsT0FBTyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FDN0MsU0FBUyxDQUFDLFVBQUMsU0FBMkI7WUFDbEMsSUFBSSxDQUFDLFNBQVMsRUFBRTtnQkFDWixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7YUFDM0I7WUFFRCxPQUFPLElBQUk7aUJBQ04sTUFBTSxDQUNILEdBQUcsQ0FBQyxLQUFLLENBQUM7Z0JBQ04sVUFBVSxFQUFFO29CQUNSLGFBQWEsRUFBSyxTQUFTLENBQUMsSUFBSSxTQUFJLFNBQVMsQ0FBQyxLQUFPO2lCQUN4RDthQUNKLENBQUMsQ0FDTDtpQkFDQSxJQUFJLENBQ0QsVUFBVSxDQUFDLFVBQUMsS0FBd0I7Z0JBQ2hDLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxHQUFHLEVBQUUsQ0FFekI7Z0JBRUQsT0FBTyxlQUFlLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQ3hDLENBQUMsQ0FDTCxDQUFDO1NBQ1QsQ0FBQyxDQUNMLENBQUM7OztnQkE5QlQsVUFBVTs7OztnQkFQRixXQUFXOzswQkFGcEI7Ozs7Ozs7Ozs7Ozs7O0FDT0EscUJBQTRCLE1BQWMsRUFBRSxNQUFjLEVBQUUsT0FBZ0IsRUFBRSxJQUFnQjtJQUMxRixPQUFPLElBQUksV0FBVyxDQUNsQixJQUFJLE1BQU0sY0FBTSxNQUFNLEVBQUcsRUFDekIsTUFBTSxFQUNOLE9BQU8sRUFDUCxJQUFJLENBQ1AsQ0FBQztDQUNMO0FBRUQscUJBQWEsV0FBVyxHQUFHLElBQUksY0FBYyxDQUFTLGFBQWEsQ0FBQzs7Ozs7O0FDaEJwRTtzQkFhK0IsS0FBcUIsRUFBVSxNQUFjLEVBQVUsSUFBaUI7O1FBQXhFLFVBQUssR0FBTCxLQUFLLENBQWdCO1FBQVUsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUFVLFNBQUksR0FBSixJQUFJLENBQWE7dUJBRjFFLG1CQUFtQjtRQUd4QyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsVUFBQyxNQUFjLElBQUssT0FBQSxLQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFBLENBQUMsQ0FBQzs7Ozs7O0lBR3ZFLHlCQUFNOzs7O2NBQUMsTUFBYzs7UUFDeEIsSUFBSSxNQUFNLFdBQVE7WUFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFDLEtBQW9CO2dCQUMzQyxJQUFJLEtBQUssS0FBSyxNQUFNLFNBQU0sRUFBRTtvQkFDeEIsS0FBSSxDQUFDLE9BQU8sR0FBRyxjQUFjLENBQUM7b0JBRTlCLE9BQU87aUJBQ1Y7Z0JBRUQsS0FBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQzthQUM3QixDQUFDLENBQUM7U0FDTjthQUFNO1lBQ0gsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUM3Qjs7Ozs7O0lBR0csK0JBQVk7Ozs7Y0FBQyxNQUFjOztRQUMvQixxQkFBTSxTQUFTLEdBQWM7WUFDekIsU0FBUyxFQUFFLE1BQU0sY0FBVztZQUM1QixJQUFJLEVBQUUsTUFBTSxjQUFXO1lBQ3ZCLEtBQUssRUFBRSxNQUFNLGdCQUFhO1NBQzdCLENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUVsQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLFNBQVMsQ0FBQyxVQUFDLElBQWlCO1lBQzVDLElBQUksSUFBSSxLQUFLLElBQUksRUFBRTtnQkFDZixLQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBRTVCLE9BQU87YUFDVjtZQUVELEtBQUksQ0FBQyxPQUFPLEdBQUcsa0JBQWtCLENBQUM7U0FDckMsQ0FBQyxDQUFDOzs7Z0JBNUNWLFNBQVMsU0FBQztvQkFDUCxRQUFRLEVBQUUsaUJBQWlCO29CQUMzQixRQUFRLEVBQUUsZUFBZTtpQkFDNUI7Ozs7Z0JBUlEsY0FBYztnQkFBVSxNQUFNO2dCQUM5QixXQUFXOzttQkFGcEI7Ozs7Ozs7QUNDQSxBQUdBLHFCQUFNLE1BQU0sR0FBVztJQUNuQjtRQUNJLElBQUksRUFBRSxNQUFNO1FBQ1osU0FBUyxFQUFFLFFBQVE7S0FDdEI7Q0FDSixDQUFDO0FBRUYscUJBQWEsWUFBWSxHQUF3QixZQUFZLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQzs7Ozs7O0FDWDlFOzs7O2dCQUlDLFFBQVEsU0FBQztvQkFDTixPQUFPLEVBQUU7d0JBQ0wsWUFBWTtxQkFDZjtvQkFDRCxZQUFZLEVBQUU7d0JBQ1YsUUFBUTtxQkFDWDtpQkFDSjs7eUJBWEQ7Ozs7Ozs7QUNBQTs7Ozs7OztJQWdCa0Isa0JBQU87Ozs7Y0FBQyxNQUErQztRQUNqRSxPQUFPO1lBQ0gsUUFBUSxFQUFFLFVBQVU7WUFDcEIsU0FBUyxFQUFFO2dCQUNQO29CQUNJLE9BQU8sRUFBRSxXQUFXO29CQUNwQixRQUFRLEVBQUUsTUFBTTtpQkFDbkI7Z0JBQ0Q7b0JBQ0ksT0FBTyxFQUFFLFdBQVc7b0JBQ3BCLFVBQVUsRUFBRSxXQUFXO29CQUN2QixJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUM7aUJBQ25EO2dCQUNELGtCQUFrQjthQUNyQjtTQUNKLENBQUM7OztnQkF0QlQsUUFBUSxTQUFDO29CQUNOLE9BQU8sRUFBRTt3QkFDTCxpQkFBaUI7d0JBQ2pCLGNBQWM7cUJBQ2pCO2lCQUNKOztxQkFkRDs7Ozs7Ozs7Ozs7Ozs7OyJ9
\No newline at end of file