http-request-manager 18.2.0 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/http-request-manager.module.mjs +5 -5
- package/esm2022/lib/http-request-services-demo/database-data-demo/database-data-demo.component.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/http-request-services-demo.component.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/local-storage-demo/local-storage-demo.component.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/local-storage-signals-demo/local-storage-signals-demo.component.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/download-file/download-file.component.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/file-download.module.mjs +4 -4
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/file-downloader.component.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/request-manager-demo/file-downloader/spinner/spinner.component.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/request-manager-demo/request-manager-demo.component.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/request-manager-state-demo/request-manager-state-demo.component.mjs +4 -4
- package/esm2022/lib/http-request-services-demo/request-manager-state-demo/services/state-manager-demo.service.mjs +3 -3
- package/esm2022/lib/http-request-services-demo/request-signals-manager-demo/request-signals-manager-demo.component.mjs +3 -3
- package/esm2022/lib/interceptors/credentials.interceptor.mjs +3 -3
- package/esm2022/lib/interceptors/proxy-debugger.interceptor.mjs +3 -3
- package/esm2022/lib/interceptors/request-error.interceptor.mjs +3 -3
- package/esm2022/lib/interceptors/request-header.interceptor.mjs +3 -3
- package/esm2022/lib/services/database-manager-services/database.manager.service.mjs +6 -6
- package/esm2022/lib/services/database-manager-services/db.storage.service.mjs +8 -8
- package/esm2022/lib/services/local-storage-manager-service/local-storage-manager.service.mjs +3 -3
- package/esm2022/lib/services/local-storage-manager-service/local-storage-signals-manager.service.mjs +3 -3
- package/esm2022/lib/services/request-manager-services/http-manager-signals.service.mjs +3 -3
- package/esm2022/lib/services/request-manager-services/http-manager.service.mjs +3 -3
- package/esm2022/lib/services/request-manager-services/request-signals.service.mjs +3 -3
- package/esm2022/lib/services/request-manager-services/request.service.mjs +7 -5
- package/esm2022/lib/services/request-manager-state-service/http-manager-state.store.mjs +100 -7
- package/esm2022/lib/services/request-manager-state-service/models/api-request.model.mjs +4 -3
- package/esm2022/lib/services/request-manager-state-service/models/ws-options.model.mjs +12 -0
- package/esm2022/lib/services/utils/app.service.mjs +3 -3
- package/esm2022/lib/services/utils/encryption/asymmetrical-encryption.service.mjs +3 -3
- package/esm2022/lib/services/utils/encryption/encryption-test.service.mjs +3 -3
- package/esm2022/lib/services/utils/encryption/symmetrical-encryption.service.mjs +3 -3
- package/esm2022/lib/services/utils/headers.service.mjs +3 -3
- package/esm2022/lib/services/utils/object-merger.service.mjs +3 -3
- package/esm2022/lib/services/utils/path-query.service.mjs +3 -3
- package/esm2022/lib/services/utils/utils.service.mjs +3 -3
- package/esm2022/lib/services/ws-manager-service/models/assortment-data.model.mjs +10 -0
- package/esm2022/lib/services/ws-manager-service/websocket.service.mjs +133 -0
- package/fesm2022/http-request-manager.mjs +341 -116
- package/fesm2022/http-request-manager.mjs.map +1 -1
- package/http-request-manager-19.0.0.tgz +0 -0
- package/lib/services/database-manager-services/database.manager.service.d.ts +1 -1
- package/lib/services/database-manager-services/db.storage.service.d.ts +2 -2
- package/lib/services/request-manager-services/request.service.d.ts +2 -1
- package/lib/services/request-manager-state-service/http-manager-state.store.d.ts +21 -8
- package/lib/services/request-manager-state-service/models/api-request.model.d.ts +4 -1
- package/lib/services/request-manager-state-service/models/ws-options.model.d.ts +14 -0
- package/lib/services/ws-manager-service/models/assortment-data.model.d.ts +10 -0
- package/lib/services/ws-manager-service/websocket.service.d.ts +21 -0
- package/package.json +1 -1
- package/http-request-manager-18.2.0.tgz +0 -0
|
@@ -9,10 +9,10 @@ export class HeadersService {
|
|
|
9
9
|
const allHeaders = headers ? { ...this.headers, ...headers } : {};
|
|
10
10
|
return { headers: new HttpHeaders(allHeaders) };
|
|
11
11
|
}
|
|
12
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.
|
|
13
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.
|
|
12
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HeadersService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
13
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HeadersService, providedIn: 'root' }); }
|
|
14
14
|
}
|
|
15
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.
|
|
15
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: HeadersService, decorators: [{
|
|
16
16
|
type: Injectable,
|
|
17
17
|
args: [{
|
|
18
18
|
providedIn: 'root'
|
|
@@ -53,10 +53,10 @@ export class ObjectMergerService {
|
|
|
53
53
|
mergedOptions.encrypted = (options && (typeof options.encrypted !== 'undefined')) ? options.encrypted : (configForRootOptions?.encrypted || false);
|
|
54
54
|
return mergedOptions;
|
|
55
55
|
}
|
|
56
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.
|
|
57
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.
|
|
56
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ObjectMergerService, deps: [{ token: CONFIG_SETTINGS_TOKEN, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
57
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ObjectMergerService, providedIn: 'root' }); }
|
|
58
58
|
}
|
|
59
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.
|
|
59
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ObjectMergerService, decorators: [{
|
|
60
60
|
type: Injectable,
|
|
61
61
|
args: [{
|
|
62
62
|
providedIn: 'root'
|
|
@@ -42,10 +42,10 @@ export class PathQueryService {
|
|
|
42
42
|
isObject(val) {
|
|
43
43
|
return (val === null) ? false : ((typeof val === 'function') || (typeof val === 'object'));
|
|
44
44
|
}
|
|
45
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.
|
|
46
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.
|
|
45
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PathQueryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
46
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PathQueryService, providedIn: 'root' }); }
|
|
47
47
|
}
|
|
48
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.
|
|
48
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PathQueryService, decorators: [{
|
|
49
49
|
type: Injectable,
|
|
50
50
|
args: [{
|
|
51
51
|
providedIn: 'root'
|
|
@@ -143,10 +143,10 @@ export class UtilsService {
|
|
|
143
143
|
}
|
|
144
144
|
return result.join(', ');
|
|
145
145
|
}
|
|
146
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.
|
|
147
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.
|
|
146
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
147
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UtilsService, providedIn: 'root' }); }
|
|
148
148
|
}
|
|
149
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.
|
|
149
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UtilsService, decorators: [{
|
|
150
150
|
type: Injectable,
|
|
151
151
|
args: [{
|
|
152
152
|
providedIn: 'root'
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export class ChannelInfo {
|
|
2
|
+
constructor(name = '', canSubscribe = false) {
|
|
3
|
+
this.name = name;
|
|
4
|
+
this.canSubscribe = canSubscribe;
|
|
5
|
+
}
|
|
6
|
+
static adapt(item) {
|
|
7
|
+
return new ChannelInfo(item?.name, item?.canSubscribe);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzb3J0bWVudC1kYXRhLm1vZGVsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaHR0cC1yZXF1ZXN0LW1hbmFnZXIvc3JjL2xpYi9zZXJ2aWNlcy93cy1tYW5hZ2VyLXNlcnZpY2UvbW9kZWxzL2Fzc29ydG1lbnQtZGF0YS5tb2RlbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxNQUFNLE9BQU8sV0FBVztJQUV0QixZQUNTLE9BQU8sRUFBRSxFQUNULGVBQWUsS0FBSztRQURwQixTQUFJLEdBQUosSUFBSSxDQUFLO1FBQ1QsaUJBQVksR0FBWixZQUFZLENBQVE7SUFDMUIsQ0FBQztJQUVKLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBVTtRQUVyQixPQUFPLElBQUksV0FBVyxDQUNwQixJQUFJLEVBQUUsSUFBSSxFQUNWLElBQUksRUFBRSxZQUFZLENBQ25CLENBQUE7SUFFSCxDQUFDO0NBRUYiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgaW50ZXJmYWNlIENoYW5uZWxJbmZvSW50ZXJmYWNlIHtcbiAgbmFtZTogc3RyaW5nXG4gIGNhblN1YnNjcmliZTogYm9vbGVhblxufVxuXG5leHBvcnQgY2xhc3MgQ2hhbm5lbEluZm8gaW1wbGVtZW50cyBDaGFubmVsSW5mb0ludGVyZmFjZSB7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIG5hbWUgPSAnJyxcbiAgICBwdWJsaWMgY2FuU3Vic2NyaWJlID0gZmFsc2UsXG4gICkge31cblxuICBzdGF0aWMgYWRhcHQoaXRlbT86IGFueSk6IENoYW5uZWxJbmZvIHtcblxuICAgIHJldHVybiBuZXcgQ2hhbm5lbEluZm8oXG4gICAgICBpdGVtPy5uYW1lLFxuICAgICAgaXRlbT8uY2FuU3Vic2NyaWJlLFxuICAgIClcblxuICB9XG5cbn1cblxuXG4iXX0=
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export class WebsocketService {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.socket = null;
|
|
7
|
+
this.messages = new BehaviorSubject(null);
|
|
8
|
+
this.messages$ = this.messages.asObservable();
|
|
9
|
+
this.connectionStatus = new BehaviorSubject(false);
|
|
10
|
+
this.connectionStatus$ = this.connectionStatus.asObservable();
|
|
11
|
+
}
|
|
12
|
+
connect(url, jwtToken) {
|
|
13
|
+
if (this.socket)
|
|
14
|
+
return;
|
|
15
|
+
const URL = (jwtToken) ? `${url}?token=${jwtToken}` : url;
|
|
16
|
+
this.socket = new WebSocket(URL);
|
|
17
|
+
this.socket.onopen = () => {
|
|
18
|
+
console.log(`📡 Connected to WebSocket`);
|
|
19
|
+
this.connectionStatus.next(true);
|
|
20
|
+
};
|
|
21
|
+
this.socket.onmessage = (event) => {
|
|
22
|
+
try {
|
|
23
|
+
const data = JSON.parse(event.data);
|
|
24
|
+
if (data.error && data.error === 'JWT_INVALID') {
|
|
25
|
+
console.error('JWT validation failed. Authentication error!');
|
|
26
|
+
this.connectionStatus.next(false);
|
|
27
|
+
this.socket?.close();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.messages.next(data);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
console.error('Error parsing WebSocket message:', event.data);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
this.socket.onclose = () => {
|
|
37
|
+
console.log('WebSocket connection closed');
|
|
38
|
+
this.connectionStatus.next(false);
|
|
39
|
+
this.socket = null;
|
|
40
|
+
};
|
|
41
|
+
this.socket.onerror = (error) => {
|
|
42
|
+
console.error('WebSocket error:', error);
|
|
43
|
+
this.connectionStatus.next(false);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
disconnect() {
|
|
47
|
+
if (this.socket) {
|
|
48
|
+
this.socket.close();
|
|
49
|
+
this.socket = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
subscribeToChannel(channel) {
|
|
53
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
54
|
+
this.socket.send(JSON.stringify({ type: 'subscribe', subscribedChannel: channel }));
|
|
55
|
+
console.log(`💬 Subscribed to channel: ${channel}`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
console.error('WebSocket is not open. Cannot subscribe to channel.');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
unsubscribeToChannel(channel) {
|
|
62
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
63
|
+
this.socket.send(JSON.stringify({ type: 'unsubscribe', subscribedChannel: channel }));
|
|
64
|
+
console.log(`💬 Unsubscribed to channel: ${channel}`);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.error('WebSocket is not open. Cannot unsubscribed to channel.');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
sendMessage(channel, content) {
|
|
71
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
72
|
+
this.socket.send(JSON.stringify({ type: 'message', subscribedChannel: channel, content }));
|
|
73
|
+
console.log(`💬 Send message: ${content}`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
console.error('WebSocket is not open. Cannot send message.');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
sendBroadcast(content) {
|
|
80
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
81
|
+
this.socket.send(JSON.stringify({ type: 'broadcast', content }));
|
|
82
|
+
console.log(`📢 Send broadcast: ${content}`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
console.error('WebSocket is not open. Cannot send broadcast.');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
getAllChannels() {
|
|
89
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
90
|
+
this.socket.send(JSON.stringify({ type: 'getChannels' }));
|
|
91
|
+
console.log('🗂️ List of all channels');
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.error('WebSocket is not open. Cannot request channels.');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
createChannel(channel) {
|
|
98
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
99
|
+
this.socket.send(JSON.stringify({ type: 'createChannel', content: channel }));
|
|
100
|
+
console.log('🗂️ Created channel:', channel);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
console.error('WebSocket is not open. Cannot request channels.');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
deleteChannel(channel) {
|
|
107
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
108
|
+
this.socket.send(JSON.stringify({ type: 'deleteChannel', content: channel }));
|
|
109
|
+
console.log('🗂️ Delete channel:', channel);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
console.error('WebSocket is not open. Cannot request channels.');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
getUsersInChannel(channel) {
|
|
116
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
117
|
+
this.socket.send(JSON.stringify({ type: 'getUsers', subscribedChannel: channel }));
|
|
118
|
+
console.log(`👥 List all users in channel: ${channel}`);
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
console.error('WebSocket is not open. Cannot request users.');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WebsocketService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
125
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WebsocketService, providedIn: 'root' }); }
|
|
126
|
+
}
|
|
127
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: WebsocketService, decorators: [{
|
|
128
|
+
type: Injectable,
|
|
129
|
+
args: [{
|
|
130
|
+
providedIn: 'root',
|
|
131
|
+
}]
|
|
132
|
+
}] });
|
|
133
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vic29ja2V0LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9odHRwLXJlcXVlc3QtbWFuYWdlci9zcmMvbGliL3NlcnZpY2VzL3dzLW1hbmFnZXItc2VydmljZS93ZWJzb2NrZXQuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBRSxlQUFlLEVBQWMsTUFBTSxNQUFNLENBQUM7O0FBS25ELE1BQU0sT0FBTyxnQkFBZ0I7SUFIN0I7UUFLVSxXQUFNLEdBQXFCLElBQUksQ0FBQztRQUVoQyxhQUFRLEdBQUcsSUFBSSxlQUFlLENBQU0sSUFBSSxDQUFDLENBQUM7UUFDM0MsY0FBUyxHQUFvQixJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBRXpELHFCQUFnQixHQUFHLElBQUksZUFBZSxDQUFVLEtBQUssQ0FBQyxDQUFDO1FBQ3hELHNCQUFpQixHQUF3QixJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLENBQUM7S0E2SHRGO0lBM0hDLE9BQU8sQ0FBQyxHQUFXLEVBQUUsUUFBaUI7UUFFcEMsSUFBSSxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU87UUFFeEIsTUFBTSxHQUFHLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLFVBQVUsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztRQUUxRCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBRWpDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxHQUFHLEdBQUcsRUFBRTtZQUN4QixPQUFPLENBQUMsR0FBRyxDQUFDLDJCQUEyQixDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuQyxDQUFDLENBQUM7UUFFRixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ2hDLElBQUksQ0FBQztnQkFDSCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFcEMsSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssYUFBYSxFQUFFLENBQUM7b0JBQy9DLE9BQU8sQ0FBQyxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztvQkFDOUQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDbEMsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQztvQkFDckIsT0FBTztnQkFDVCxDQUFDO2dCQUVELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRTNCLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsa0NBQWtDLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hFLENBQUM7UUFFSCxDQUFDLENBQUM7UUFFRixJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sR0FBRyxHQUFHLEVBQUU7WUFDekIsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1lBQzNDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDbEMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDckIsQ0FBQyxDQUFDO1FBRUYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUM5QixPQUFPLENBQUMsS0FBSyxDQUFDLGtCQUFrQixFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3pDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVELFVBQVU7UUFDUixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0lBRUQsa0JBQWtCLENBQUMsT0FBZTtRQUNoQyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsVUFBVSxLQUFLLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUMvQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDcEYsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUN0RCxDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sQ0FBQyxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQztRQUN2RSxDQUFDO0lBQ0gsQ0FBQztJQUVELG9CQUFvQixDQUFDLE9BQWU7UUFDbEMsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLFVBQVUsS0FBSyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsaUJBQWlCLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RGLE9BQU8sQ0FBQyxHQUFHLENBQUMsK0JBQStCLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDeEQsQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLENBQUMsS0FBSyxDQUFDLHdEQUF3RCxDQUFDLENBQUM7UUFDMUUsQ0FBQztJQUNILENBQUM7SUFFRCxXQUFXLENBQUMsT0FBZSxFQUFFLE9BQVk7UUFDdkMsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLFVBQVUsS0FBSyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN6RixPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQy9DLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1FBQy9ELENBQUM7SUFDSCxDQUFDO0lBRUQsYUFBYSxDQUFDLE9BQWU7UUFDM0IsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLFVBQVUsS0FBSyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ2pFLE9BQU8sQ0FBQyxHQUFHLENBQUMsc0JBQXNCLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFDL0MsQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLENBQUMsS0FBSyxDQUFDLCtDQUErQyxDQUFDLENBQUM7UUFDakUsQ0FBQztJQUNILENBQUM7SUFFRCxjQUFjO1FBQ1osSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLFVBQVUsS0FBSyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDMUQsT0FBTyxDQUFDLEdBQUcsQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1FBQzFDLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLEtBQUssQ0FBQyxpREFBaUQsQ0FBQyxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDO0lBRUQsYUFBYSxDQUFDLE9BQWU7UUFDM0IsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLFVBQVUsS0FBSyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM5RSxPQUFPLENBQUMsR0FBRyxDQUFDLHNCQUFzQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQy9DLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLEtBQUssQ0FBQyxpREFBaUQsQ0FBQyxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDO0lBRUQsYUFBYSxDQUFDLE9BQWU7UUFDM0IsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLFVBQVUsS0FBSyxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxlQUFlLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQztZQUM5RSxPQUFPLENBQUMsR0FBRyxDQUFDLHFCQUFxQixFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzlDLENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTyxDQUFDLEtBQUssQ0FBQyxpREFBaUQsQ0FBQyxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDO0lBRUQsaUJBQWlCLENBQUMsT0FBZTtRQUMvQixJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsVUFBVSxLQUFLLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUMvQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbkYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQ0FBaUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUMxRCxDQUFDO2FBQU0sQ0FBQztZQUNOLE9BQU8sQ0FBQyxLQUFLLENBQUMsOENBQThDLENBQUMsQ0FBQztRQUNoRSxDQUFDO0lBQ0gsQ0FBQzsrR0FuSVUsZ0JBQWdCO21IQUFoQixnQkFBZ0IsY0FGZixNQUFNOzs0RkFFUCxnQkFBZ0I7a0JBSDVCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxufSlcbmV4cG9ydCBjbGFzcyBXZWJzb2NrZXRTZXJ2aWNlIHtcblxuICBwcml2YXRlIHNvY2tldDogV2ViU29ja2V0IHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBtZXNzYWdlcyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55PihudWxsKTtcbiAgcHVibGljIG1lc3NhZ2VzJDogT2JzZXJ2YWJsZTxhbnk+ID0gdGhpcy5tZXNzYWdlcy5hc09ic2VydmFibGUoKTtcblxuICBwcml2YXRlIGNvbm5lY3Rpb25TdGF0dXMgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgcHVibGljIGNvbm5lY3Rpb25TdGF0dXMkOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gdGhpcy5jb25uZWN0aW9uU3RhdHVzLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIGNvbm5lY3QodXJsOiBzdHJpbmcsIGp3dFRva2VuPzogc3RyaW5nKSB7XG5cbiAgICBpZiAodGhpcy5zb2NrZXQpIHJldHVybjtcblxuICAgIGNvbnN0IFVSTCA9IChqd3RUb2tlbikgPyBgJHt1cmx9P3Rva2VuPSR7and0VG9rZW59YCA6IHVybDtcblxuICAgIHRoaXMuc29ja2V0ID0gbmV3IFdlYlNvY2tldChVUkwpO1xuXG4gICAgdGhpcy5zb2NrZXQub25vcGVuID0gKCkgPT4ge1xuICAgICAgY29uc29sZS5sb2coYPCfk6EgQ29ubmVjdGVkIHRvIFdlYlNvY2tldGApO1xuICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdHVzLm5leHQodHJ1ZSk7XG4gICAgfTtcblxuICAgIHRoaXMuc29ja2V0Lm9ubWVzc2FnZSA9IChldmVudCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgZGF0YSA9IEpTT04ucGFyc2UoZXZlbnQuZGF0YSk7XG5cbiAgICAgICAgaWYgKGRhdGEuZXJyb3IgJiYgZGF0YS5lcnJvciA9PT0gJ0pXVF9JTlZBTElEJykge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0pXVCB2YWxpZGF0aW9uIGZhaWxlZC4gQXV0aGVudGljYXRpb24gZXJyb3IhJyk7XG4gICAgICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdHVzLm5leHQoZmFsc2UpO1xuICAgICAgICAgIHRoaXMuc29ja2V0Py5jbG9zZSgpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubWVzc2FnZXMubmV4dChkYXRhKTtcblxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgcGFyc2luZyBXZWJTb2NrZXQgbWVzc2FnZTonLCBldmVudC5kYXRhKTtcbiAgICAgIH1cblxuICAgIH07XG5cbiAgICB0aGlzLnNvY2tldC5vbmNsb3NlID0gKCkgPT4ge1xuICAgICAgY29uc29sZS5sb2coJ1dlYlNvY2tldCBjb25uZWN0aW9uIGNsb3NlZCcpO1xuICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdHVzLm5leHQoZmFsc2UpO1xuICAgICAgdGhpcy5zb2NrZXQgPSBudWxsO1xuICAgIH07XG5cbiAgICB0aGlzLnNvY2tldC5vbmVycm9yID0gKGVycm9yKSA9PiB7XG4gICAgICBjb25zb2xlLmVycm9yKCdXZWJTb2NrZXQgZXJyb3I6JywgZXJyb3IpO1xuICAgICAgdGhpcy5jb25uZWN0aW9uU3RhdHVzLm5leHQoZmFsc2UpO1xuICAgIH07XG4gIH1cblxuICBkaXNjb25uZWN0KCkge1xuICAgIGlmICh0aGlzLnNvY2tldCkge1xuICAgICAgdGhpcy5zb2NrZXQuY2xvc2UoKTtcbiAgICAgIHRoaXMuc29ja2V0ID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBzdWJzY3JpYmVUb0NoYW5uZWwoY2hhbm5lbDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuc29ja2V0Py5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTikge1xuICAgICAgdGhpcy5zb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdzdWJzY3JpYmUnLCBzdWJzY3JpYmVkQ2hhbm5lbDogY2hhbm5lbCB9KSk7XG4gICAgICBjb25zb2xlLmxvZyhg8J+SrCBTdWJzY3JpYmVkIHRvIGNoYW5uZWw6ICR7Y2hhbm5lbH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcignV2ViU29ja2V0IGlzIG5vdCBvcGVuLiBDYW5ub3Qgc3Vic2NyaWJlIHRvIGNoYW5uZWwuJyk7XG4gICAgfVxuICB9XG5cbiAgdW5zdWJzY3JpYmVUb0NoYW5uZWwoY2hhbm5lbDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuc29ja2V0Py5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTikge1xuICAgICAgdGhpcy5zb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICd1bnN1YnNjcmliZScsIHN1YnNjcmliZWRDaGFubmVsOiBjaGFubmVsIH0pKTtcbiAgICAgIGNvbnNvbGUubG9nKGDwn5KsIFVuc3Vic2NyaWJlZCB0byBjaGFubmVsOiAke2NoYW5uZWx9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1dlYlNvY2tldCBpcyBub3Qgb3Blbi4gQ2Fubm90IHVuc3Vic2NyaWJlZCB0byBjaGFubmVsLicpO1xuICAgIH1cbiAgfVxuXG4gIHNlbmRNZXNzYWdlKGNoYW5uZWw6IHN0cmluZywgY29udGVudDogYW55KSB7XG4gICAgaWYgKHRoaXMuc29ja2V0Py5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTikge1xuICAgICAgdGhpcy5zb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdtZXNzYWdlJywgc3Vic2NyaWJlZENoYW5uZWw6IGNoYW5uZWwsIGNvbnRlbnQgfSkpO1xuICAgICAgICBjb25zb2xlLmxvZyhg8J+SrCBTZW5kIG1lc3NhZ2U6ICR7Y29udGVudH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcignV2ViU29ja2V0IGlzIG5vdCBvcGVuLiBDYW5ub3Qgc2VuZCBtZXNzYWdlLicpO1xuICAgIH1cbiAgfVxuXG4gIHNlbmRCcm9hZGNhc3QoY29udGVudDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuc29ja2V0Py5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTikge1xuICAgICAgdGhpcy5zb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdicm9hZGNhc3QnLCBjb250ZW50IH0pKTtcbiAgICAgIGNvbnNvbGUubG9nKGDwn5OiIFNlbmQgYnJvYWRjYXN0OiAke2NvbnRlbnR9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1dlYlNvY2tldCBpcyBub3Qgb3Blbi4gQ2Fubm90IHNlbmQgYnJvYWRjYXN0LicpO1xuICAgIH1cbiAgfVxuXG4gIGdldEFsbENoYW5uZWxzKCkge1xuICAgIGlmICh0aGlzLnNvY2tldD8ucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0Lk9QRU4pIHtcbiAgICAgIHRoaXMuc29ja2V0LnNlbmQoSlNPTi5zdHJpbmdpZnkoeyB0eXBlOiAnZ2V0Q2hhbm5lbHMnIH0pKTtcbiAgICAgIGNvbnNvbGUubG9nKCfwn5eC77iPIExpc3Qgb2YgYWxsIGNoYW5uZWxzJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1dlYlNvY2tldCBpcyBub3Qgb3Blbi4gQ2Fubm90IHJlcXVlc3QgY2hhbm5lbHMuJyk7XG4gICAgfVxuICB9XG5cbiAgY3JlYXRlQ2hhbm5lbChjaGFubmVsOiBzdHJpbmcpIHtcbiAgICBpZiAodGhpcy5zb2NrZXQ/LnJlYWR5U3RhdGUgPT09IFdlYlNvY2tldC5PUEVOKSB7XG4gICAgICB0aGlzLnNvY2tldC5zZW5kKEpTT04uc3RyaW5naWZ5KHsgdHlwZTogJ2NyZWF0ZUNoYW5uZWwnLCBjb250ZW50OiBjaGFubmVsIH0pKTtcbiAgICAgIGNvbnNvbGUubG9nKCfwn5eC77iPIENyZWF0ZWQgY2hhbm5lbDonLCBjaGFubmVsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcignV2ViU29ja2V0IGlzIG5vdCBvcGVuLiBDYW5ub3QgcmVxdWVzdCBjaGFubmVscy4nKTtcbiAgICB9XG4gIH1cblxuICBkZWxldGVDaGFubmVsKGNoYW5uZWw6IHN0cmluZykge1xuICAgIGlmICh0aGlzLnNvY2tldD8ucmVhZHlTdGF0ZSA9PT0gV2ViU29ja2V0Lk9QRU4pIHtcbiAgICAgIHRoaXMuc29ja2V0LnNlbmQoSlNPTi5zdHJpbmdpZnkoeyB0eXBlOiAnZGVsZXRlQ2hhbm5lbCcsIGNvbnRlbnQ6IGNoYW5uZWwgfSkpO1xuICAgICAgY29uc29sZS5sb2coJ/Cfl4LvuI8gRGVsZXRlIGNoYW5uZWw6JywgY2hhbm5lbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1dlYlNvY2tldCBpcyBub3Qgb3Blbi4gQ2Fubm90IHJlcXVlc3QgY2hhbm5lbHMuJyk7XG4gICAgfVxuICB9XG5cbiAgZ2V0VXNlcnNJbkNoYW5uZWwoY2hhbm5lbDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuc29ja2V0Py5yZWFkeVN0YXRlID09PSBXZWJTb2NrZXQuT1BFTikge1xuICAgICAgdGhpcy5zb2NrZXQuc2VuZChKU09OLnN0cmluZ2lmeSh7IHR5cGU6ICdnZXRVc2VycycsIHN1YnNjcmliZWRDaGFubmVsOiBjaGFubmVsIH0pKTtcbiAgICAgIGNvbnNvbGUubG9nKGDwn5GlIExpc3QgYWxsIHVzZXJzIGluIGNoYW5uZWw6ICR7Y2hhbm5lbH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc29sZS5lcnJvcignV2ViU29ja2V0IGlzIG5vdCBvcGVuLiBDYW5ub3QgcmVxdWVzdCB1c2Vycy4nKTtcbiAgICB9XG4gIH1cblxufVxuIl19
|