@idea-ionic/uncommon 8.5.13 → 8.6.0-beta.1
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/fesm2022/idea-ionic-uncommon.mjs +85 -85
- package/fesm2022/idea-ionic-uncommon.mjs.map +1 -1
- package/index.d.ts +1405 -3
- package/package.json +12 -13
- package/esm2022/idea-ionic-uncommon.mjs +0 -5
- package/esm2022/public-api.mjs +0 -26
- package/esm2022/src/AWSAPI.service.mjs +0 -431
- package/esm2022/src/AWSAPISocket.service.mjs +0 -188
- package/esm2022/src/address/address.component.mjs +0 -409
- package/esm2022/src/announcement/announcement.component.mjs +0 -72
- package/esm2022/src/cachedResources.service.mjs +0 -55
- package/esm2022/src/colors/colorPicker.component.mjs +0 -191
- package/esm2022/src/contacts/contacts.component.mjs +0 -188
- package/esm2022/src/dateTime/calendarPicker.component.mjs +0 -213
- package/esm2022/src/dateTime/dateTime.component.mjs +0 -217
- package/esm2022/src/duration/duration.component.mjs +0 -195
- package/esm2022/src/echo/echo.page.mjs +0 -233
- package/esm2022/src/echo/echo.routes.mjs +0 -6
- package/esm2022/src/errorReporting.service.mjs +0 -69
- package/esm2022/src/mde/mde.component.mjs +0 -143
- package/esm2022/src/mde/mdeToolbar.component.mjs +0 -25
- package/esm2022/src/offline/cacheableResource.component.mjs +0 -56
- package/esm2022/src/offline/offline.service.mjs +0 -63
- package/esm2022/src/offline/offlineData.service.mjs +0 -480
- package/esm2022/src/offline/offlineIndicator.component.mjs +0 -105
- package/esm2022/src/offline/offlineManager.component.mjs +0 -101
- package/esm2022/src/pushNotifications.service.mjs +0 -57
- package/esm2022/src/sentiment/sentiment.component.mjs +0 -112
- package/esm2022/src/timeInterval/fromTimeToTime.component.mjs +0 -171
- package/esm2022/src/timeInterval/timeInterval.component.mjs +0 -206
- package/esm2022/src/tinCan.service.mjs +0 -49
- package/public-api.d.ts +0 -25
- package/src/AWSAPI.service.d.ts +0 -178
- package/src/AWSAPISocket.service.d.ts +0 -129
- package/src/address/address.component.d.ts +0 -64
- package/src/announcement/announcement.component.d.ts +0 -23
- package/src/cachedResources.service.d.ts +0 -34
- package/src/colors/colorPicker.component.d.ts +0 -78
- package/src/contacts/contacts.component.d.ts +0 -31
- package/src/dateTime/calendarPicker.component.d.ts +0 -45
- package/src/dateTime/dateTime.component.d.ts +0 -81
- package/src/duration/duration.component.d.ts +0 -68
- package/src/echo/echo.page.d.ts +0 -34
- package/src/echo/echo.routes.d.ts +0 -2
- package/src/errorReporting.service.d.ts +0 -26
- package/src/mde/mde.component.d.ts +0 -39
- package/src/mde/mdeToolbar.component.d.ts +0 -5
- package/src/offline/cacheableResource.component.d.ts +0 -11
- package/src/offline/offline.service.d.ts +0 -39
- package/src/offline/offlineData.service.d.ts +0 -281
- package/src/offline/offlineIndicator.component.d.ts +0 -25
- package/src/offline/offlineManager.component.d.ts +0 -17
- package/src/pushNotifications.service.d.ts +0 -26
- package/src/sentiment/sentiment.component.d.ts +0 -35
- package/src/timeInterval/fromTimeToTime.component.d.ts +0 -61
- package/src/timeInterval/timeInterval.component.d.ts +0 -84
- package/src/tinCan.service.d.ts +0 -31
|
@@ -1,480 +0,0 @@
|
|
|
1
|
-
import { Injectable, inject } from '@angular/core';
|
|
2
|
-
import { IDEAStorageService, IDEATranslationsService } from '@idea-ionic/common';
|
|
3
|
-
import { IDEAAWSAPIService } from '../AWSAPI.service';
|
|
4
|
-
import { IDEAOfflineService } from './offline.service';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
/**
|
|
7
|
-
* After how much time we need to request a synchronisation to keep the contents up-to-date.
|
|
8
|
-
*/
|
|
9
|
-
export const SYNC_EXPIRATION_INTERVAL = 1000 * 60 * 60 * 24; // a day
|
|
10
|
-
/**
|
|
11
|
-
* Prefix for the key of the API requests queue info in the local storage.
|
|
12
|
-
*/
|
|
13
|
-
export const QUEUE_API_REQUESTS_KEY = 'IDEAOfflineService.queueAPIrequests';
|
|
14
|
-
/**
|
|
15
|
-
* Prefix for the key of the last sync time info in the local storage.
|
|
16
|
-
*/
|
|
17
|
-
export const LAST_SYNC_KEY = 'IDEAOfflineService.lastSyncAt';
|
|
18
|
-
/**
|
|
19
|
-
* The max number of elements per resource to synchronize during the first analysis of a synchronisation.
|
|
20
|
-
* If the number of elements exceeds (there is more data after the 1st page), the operation require manual confirmation.
|
|
21
|
-
*/
|
|
22
|
-
export const NUM_ELEMENTS_WITHOUT_MANUAL_SYNC = 100;
|
|
23
|
-
/**
|
|
24
|
-
* The max number of elements per resource to request at the same time during a normal synchronisation.
|
|
25
|
-
*/
|
|
26
|
-
export const NUM_ELEMENTS_WITH_MANUAL_SYNC = 300;
|
|
27
|
-
/**
|
|
28
|
-
* Manage the offline functioning of the app's data (upload/download/synchronization).
|
|
29
|
-
* Note: it includes all the methods of IDEAOfflineService.
|
|
30
|
-
*
|
|
31
|
-
* Download: it works through the **Delta** mechanism on back-end resources.
|
|
32
|
-
* Practically, the service prepares each possible API GET requests for each of the involved resources.
|
|
33
|
-
* In this way, if offline, the API service can hit an element by URL in the cache (storage offline).
|
|
34
|
-
*
|
|
35
|
-
* **How to use it**. Configure the sync mechanism in the main app.component as it follows:
|
|
36
|
-
*
|
|
37
|
-
* 1. Implement a CacheableResource class for each DeltaResource you want to cache offline.
|
|
38
|
-
* 2. Set up the service (`setUpOfflineData`).
|
|
39
|
-
* 3. Run a synchronization.
|
|
40
|
-
* 4. Add the navigation to the Offline Manager (UI).
|
|
41
|
-
* 5. Optionally, push offline API requests to the queue when offline.
|
|
42
|
-
*
|
|
43
|
-
* e.g. of CacheableResource classes:
|
|
44
|
-
* ```
|
|
45
|
-
* class CustomerCR extends CacheableResource {
|
|
46
|
-
* constructor(description: string) {
|
|
47
|
-
* super(DeltaResources.CUSTOMERS, description);
|
|
48
|
-
* }
|
|
49
|
-
* public listURL(element: any): string {
|
|
50
|
-
* return `teams/${element.teamId}/customers`;
|
|
51
|
-
* }
|
|
52
|
-
* public elementURL(element: any): string {
|
|
53
|
-
* return `teams/${element.teamId}/customers/${element.customerId}`;
|
|
54
|
-
* }
|
|
55
|
-
* public findIndexInList(list: Array<any>, element: any): number {
|
|
56
|
-
* return list.findIndex(x => x.customerId === element.customerId);
|
|
57
|
-
* }
|
|
58
|
-
* public sort(a: any, b: any): number {
|
|
59
|
-
* return a.name.localeCompare(b.name);
|
|
60
|
-
* }
|
|
61
|
-
* }
|
|
62
|
-
*/
|
|
63
|
-
export class IDEAOfflineDataService {
|
|
64
|
-
constructor() {
|
|
65
|
-
this._storage = inject(IDEAStorageService);
|
|
66
|
-
this._translate = inject(IDEATranslationsService);
|
|
67
|
-
this._offline = inject(IDEAOfflineService);
|
|
68
|
-
this._API = inject(IDEAAWSAPIService);
|
|
69
|
-
this.queueAPIRequests = new Array();
|
|
70
|
-
this.resources = new Array();
|
|
71
|
-
this.cacheableResources = {};
|
|
72
|
-
// subscribe to network changes
|
|
73
|
-
this._offline.subscribe(isOnline => {
|
|
74
|
-
if (isOnline) {
|
|
75
|
-
// try a synchronization if needed or if the last one failed
|
|
76
|
-
if (this.errorInLastSync)
|
|
77
|
-
this.synchronize();
|
|
78
|
-
else
|
|
79
|
-
this.synchronizeIfNeeded();
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
//
|
|
84
|
-
// NETWORK STATUS from IDEAOfflineService
|
|
85
|
-
//
|
|
86
|
-
/**
|
|
87
|
-
* Quickly check the connection status.
|
|
88
|
-
*/
|
|
89
|
-
isOnline() {
|
|
90
|
-
return this._offline.isOnline();
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Quickly check the connection status.
|
|
94
|
-
*/
|
|
95
|
-
isOffline() {
|
|
96
|
-
return this._offline.isOffline();
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Subscribe to the service to be notified when the connection status changes.
|
|
100
|
-
*/
|
|
101
|
-
subscribe(callback) {
|
|
102
|
-
return this._offline.subscribe(callback);
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Quickly check for online connection.
|
|
106
|
-
*/
|
|
107
|
-
check() {
|
|
108
|
-
return this._offline.check();
|
|
109
|
-
}
|
|
110
|
-
//
|
|
111
|
-
// CONFIGURATION
|
|
112
|
-
//
|
|
113
|
-
/**
|
|
114
|
-
* Whether the offline mode is allowed. You can customize this function, if needed.
|
|
115
|
-
*/
|
|
116
|
-
isAllowed() {
|
|
117
|
-
return !!this.resources.length;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Set up the service to use and sync offline data.
|
|
121
|
-
*/
|
|
122
|
-
setUpOfflineData(teamId, useQueueAPIRequests, cacheableResources) {
|
|
123
|
-
// set the team
|
|
124
|
-
this.teamId = teamId;
|
|
125
|
-
// decide if to allow certain API request while offline
|
|
126
|
-
this.useQueueAPIRequests = useQueueAPIRequests;
|
|
127
|
-
// load the API request pending queue, if any
|
|
128
|
-
this.queueAPIRequestKey = this.teamId ? `${QUEUE_API_REQUESTS_KEY}_${this.teamId}` : QUEUE_API_REQUESTS_KEY;
|
|
129
|
-
this.loadQueueAPIRequest();
|
|
130
|
-
// load the lastSyncAt information for the team
|
|
131
|
-
this.lastSyncKey = this.teamId ? `${LAST_SYNC_KEY}_${this.teamId}` : LAST_SYNC_KEY;
|
|
132
|
-
this.loadLastSyncAt();
|
|
133
|
-
// load the cacheable resources
|
|
134
|
-
this.resources = new Array();
|
|
135
|
-
this.cacheableResources = {};
|
|
136
|
-
cacheableResources.forEach(r => this.addCacheableResource(r));
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Load from the local storage the last sync at information.
|
|
140
|
-
*/
|
|
141
|
-
loadLastSyncAt() {
|
|
142
|
-
return new Promise(resolve => {
|
|
143
|
-
this._storage.get(this.lastSyncKey).then((lastSyncAt) => {
|
|
144
|
-
this.lastSyncAt = lastSyncAt ? Number(lastSyncAt) : null;
|
|
145
|
-
resolve(this.lastSyncAt);
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Update last sync at info in the local storage.
|
|
151
|
-
*/
|
|
152
|
-
saveLastSyncAt(lastSyncAt) {
|
|
153
|
-
this.lastSyncAt = lastSyncAt;
|
|
154
|
-
return this._storage.set(this.lastSyncKey, lastSyncAt);
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Add a CacheableResource.
|
|
158
|
-
*/
|
|
159
|
-
addCacheableResource(cacheableResource) {
|
|
160
|
-
if (this.teamId)
|
|
161
|
-
cacheableResource.teamId = this.teamId;
|
|
162
|
-
this.cacheableResources[cacheableResource.resource] = cacheableResource;
|
|
163
|
-
this.resources.push(cacheableResource.resource);
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Remove a CacheableResource by its DeltaResource.
|
|
167
|
-
*/
|
|
168
|
-
removeCacheableResource(resource) {
|
|
169
|
-
delete this.cacheableResources[resource];
|
|
170
|
-
this.resources.splice(this.resources.indexOf(resource), 1);
|
|
171
|
-
}
|
|
172
|
-
/**
|
|
173
|
-
* Get the the DeltaResourced configured.
|
|
174
|
-
*/
|
|
175
|
-
getResources() {
|
|
176
|
-
return this.resources;
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Get a CacheableResource by its DeltaResource.
|
|
180
|
-
*/
|
|
181
|
-
getCacheableResource(resource) {
|
|
182
|
-
return this.cacheableResources[resource];
|
|
183
|
-
}
|
|
184
|
-
//
|
|
185
|
-
// UPLOAD
|
|
186
|
-
//
|
|
187
|
-
/**
|
|
188
|
-
* Execute all the API requests in the queue; the requests terminated with an error will remain in the queue.
|
|
189
|
-
*/
|
|
190
|
-
runQueueAPIRequests() {
|
|
191
|
-
return new Promise((resolve, reject) => {
|
|
192
|
-
if (!this.useQueueAPIRequests || this.isOffline() || !this.queueAPIRequests.length)
|
|
193
|
-
return resolve();
|
|
194
|
-
this.queueAPIRequests.forEach(async (request) => {
|
|
195
|
-
const options = {};
|
|
196
|
-
if (request.resourceId)
|
|
197
|
-
options.resourceId = request.resourceId;
|
|
198
|
-
if (request.body)
|
|
199
|
-
options.body = request.body;
|
|
200
|
-
let promise;
|
|
201
|
-
try {
|
|
202
|
-
switch (request.method.toUpperCase()) {
|
|
203
|
-
case 'POST':
|
|
204
|
-
promise = await this._API.postResource(request.resource, options);
|
|
205
|
-
break;
|
|
206
|
-
case 'PUT':
|
|
207
|
-
promise = await this._API.putResource(request.resource, options);
|
|
208
|
-
break;
|
|
209
|
-
case 'PATCH':
|
|
210
|
-
promise = await this._API.patchResource(request.resource, options);
|
|
211
|
-
break;
|
|
212
|
-
}
|
|
213
|
-
if (!promise)
|
|
214
|
-
request.error = 'INVALID_METHOD';
|
|
215
|
-
else
|
|
216
|
-
request.error = null;
|
|
217
|
-
}
|
|
218
|
-
catch (err) {
|
|
219
|
-
request.error = err.message || 'UNKNOWN_ERROR';
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
// keep the requests NOT successfully executed
|
|
223
|
-
this.saveQueueAPIRequest(this.queueAPIRequests.filter(x => x.error)).then(() => {
|
|
224
|
-
// if the queue is empty, the entire operation was successful
|
|
225
|
-
if (this.queueAPIRequests.length)
|
|
226
|
-
reject();
|
|
227
|
-
else
|
|
228
|
-
resolve();
|
|
229
|
-
});
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Load from the local storage the API requests queue.
|
|
234
|
-
*/
|
|
235
|
-
loadQueueAPIRequest() {
|
|
236
|
-
return new Promise(resolve => {
|
|
237
|
-
if (!this.useQueueAPIRequests)
|
|
238
|
-
return resolve([]);
|
|
239
|
-
this._storage.get(this.queueAPIRequestKey).then((queue) => {
|
|
240
|
-
this.queueAPIRequests = queue || [];
|
|
241
|
-
resolve(this.queueAPIRequests);
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Update the queue in memory and also save the copy in the local storage.
|
|
247
|
-
*/
|
|
248
|
-
saveQueueAPIRequest(queue) {
|
|
249
|
-
if (!this.isAllowed())
|
|
250
|
-
return Promise.reject();
|
|
251
|
-
this.queueAPIRequests = queue || this.queueAPIRequests;
|
|
252
|
-
return this._storage.set(this.queueAPIRequestKey, this.queueAPIRequests);
|
|
253
|
-
}
|
|
254
|
-
/**
|
|
255
|
-
* Delete a request stuck in an error.
|
|
256
|
-
*/
|
|
257
|
-
deleteRequest(request) {
|
|
258
|
-
if (!this.isAllowed())
|
|
259
|
-
return Promise.reject();
|
|
260
|
-
if (request) {
|
|
261
|
-
this.queueAPIRequests.splice(this.queueAPIRequests.indexOf(request), 1);
|
|
262
|
-
this.saveQueueAPIRequest();
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
//
|
|
266
|
-
// DOWNLOAD
|
|
267
|
-
//
|
|
268
|
-
/**
|
|
269
|
-
* Save the records of a delta and, if the latter has more pages, go recursive.
|
|
270
|
-
*/
|
|
271
|
-
async syncDeltaRecords(delta, done) {
|
|
272
|
-
// for each resource, we reset the status; if a resource still need to be synchronized, it will be flagged below
|
|
273
|
-
this.resources.forEach(resource => {
|
|
274
|
-
this.cacheableResources[resource].error = false;
|
|
275
|
-
this.cacheableResources[resource].synchronizing = false;
|
|
276
|
-
});
|
|
277
|
-
try {
|
|
278
|
-
// synchronze each of the resources included in the delta; this execution can go in parallel
|
|
279
|
-
await Promise.all(delta.resources.map(async (resource) => {
|
|
280
|
-
const cr = this.cacheableResources[resource];
|
|
281
|
-
if (cr) {
|
|
282
|
-
// synchronize the delta records; note: the executuion inside a resource must go in series
|
|
283
|
-
cr.synchronizing = true;
|
|
284
|
-
const success = await this.syncResourceDeltaRecords(resource, delta.records[resource]);
|
|
285
|
-
if (!success)
|
|
286
|
-
this.errorInLastSync = true;
|
|
287
|
-
}
|
|
288
|
-
}));
|
|
289
|
-
// if there were error of if there is nothing left to sync, we are done
|
|
290
|
-
if (this.errorInLastSync || !delta.next)
|
|
291
|
-
return done();
|
|
292
|
-
// otherwise, get the next page of the delta and go recursive until we are done
|
|
293
|
-
const params = { next: delta.next, limit: NUM_ELEMENTS_WITH_MANUAL_SYNC };
|
|
294
|
-
if (this.lastSyncAt)
|
|
295
|
-
params.since = this.lastSyncAt;
|
|
296
|
-
const newDelta = await this._API.getResource(this.teamId ? `teams/${this.teamId}/delta` : 'delta', { params });
|
|
297
|
-
this.syncDeltaRecords(newDelta, done);
|
|
298
|
-
}
|
|
299
|
-
catch (err) {
|
|
300
|
-
// if something went wrong, stops the operation, since we need to make sure the entire flow is consistent
|
|
301
|
-
this.errorInLastSync = true;
|
|
302
|
-
return done();
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Save offline a list of DeltaRecords for this resource, creating a map of all the corresponding API GET requests.
|
|
307
|
-
*/
|
|
308
|
-
async syncResourceDeltaRecords(resource, records) {
|
|
309
|
-
// acquire the info an a cacheable resource
|
|
310
|
-
const cr = this.cacheableResources[resource];
|
|
311
|
-
if (!cr)
|
|
312
|
-
return Promise.resolve(true);
|
|
313
|
-
try {
|
|
314
|
-
// prepare helpers to group executions of elements of the same list
|
|
315
|
-
let list = null, oldListURL = null;
|
|
316
|
-
for (const r of records) {
|
|
317
|
-
// calculate the URL to access the API request key for this element
|
|
318
|
-
const elementURL = cr.elementURL(r.element);
|
|
319
|
-
// if the element was deleted (based on delta), delete its corresponding API GET request
|
|
320
|
-
if (r.deleted)
|
|
321
|
-
await this._API.deleteFromCache(elementURL);
|
|
322
|
-
// otherwise, update it
|
|
323
|
-
else
|
|
324
|
-
await this._API.putInCache(elementURL, r.element);
|
|
325
|
-
// calculate the URLs to access the API request key for this element's list
|
|
326
|
-
const listURL = cr.listURL(r.element);
|
|
327
|
-
// to improve the performance, get/sort/save the list only when it changes from the previous element's one.
|
|
328
|
-
if (listURL !== oldListURL) {
|
|
329
|
-
// skip first cycle (oldListURL === null)
|
|
330
|
-
if (oldListURL) {
|
|
331
|
-
// re-sort the list; note: it should be sorted from the last time, so we only manage the new element
|
|
332
|
-
list = list.sort(cr.sort);
|
|
333
|
-
// save the updated list
|
|
334
|
-
await this._API.putInCache(oldListURL, list);
|
|
335
|
-
}
|
|
336
|
-
// get the list of elements from the local storage by the calculated URL
|
|
337
|
-
list = await this._API.getFromCache(listURL);
|
|
338
|
-
// save the reference to the list for the next cycle
|
|
339
|
-
oldListURL = listURL;
|
|
340
|
-
}
|
|
341
|
-
// find in the list the element we want to manage
|
|
342
|
-
const index = cr.findIndexInList(list, r.element);
|
|
343
|
-
// delete the element from the list
|
|
344
|
-
if (index !== -1)
|
|
345
|
-
list.splice(index, 1);
|
|
346
|
-
// if the element wasn't deleted (following the delta record information), insert the new version
|
|
347
|
-
if (!r.deleted)
|
|
348
|
-
list.push(r.element);
|
|
349
|
-
}
|
|
350
|
-
// in case there were elements, save the last element's list
|
|
351
|
-
if (oldListURL) {
|
|
352
|
-
// re-sort the list; note: it should be sorted from the last time, so we only manage the new element
|
|
353
|
-
list = list.sort(cr.sort);
|
|
354
|
-
// save the updated list
|
|
355
|
-
await this._API.putInCache(oldListURL, list);
|
|
356
|
-
}
|
|
357
|
-
return Promise.resolve(true);
|
|
358
|
-
}
|
|
359
|
-
catch (err) {
|
|
360
|
-
// if something went wrong, stops the operation, since we need to make sure the entire flow is consistent
|
|
361
|
-
cr.error = true;
|
|
362
|
-
return Promise.resolve(false);
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
//
|
|
366
|
-
// SYNCHRONISATION (UPLOAD+DOWNLOAD)
|
|
367
|
-
//
|
|
368
|
-
/**
|
|
369
|
-
* Run a sync, but only if needed, i.e. the cached content expired or we have pending API requests in the queue.
|
|
370
|
-
*/
|
|
371
|
-
synchronizeIfNeeded() {
|
|
372
|
-
return new Promise((resolve, reject) => {
|
|
373
|
-
if (!this.isAllowed())
|
|
374
|
-
return;
|
|
375
|
-
this.loadLastSyncAt().then(() => this.loadQueueAPIRequest()
|
|
376
|
-
.then(() => {
|
|
377
|
-
if (this.queueAPIRequests.length || Date.now() > this.lastSyncAt + SYNC_EXPIRATION_INTERVAL)
|
|
378
|
-
this.synchronize();
|
|
379
|
-
resolve();
|
|
380
|
-
})
|
|
381
|
-
.catch(err => reject(err)));
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
/**
|
|
385
|
-
* Synchronization of the whole set of resources (upload+download).
|
|
386
|
-
* @param manualConfirmation if true, the request comes directly from a user action (not automatic procedures).
|
|
387
|
-
*/
|
|
388
|
-
synchronize(manualConfirmation) {
|
|
389
|
-
return new Promise((resolve, reject) => {
|
|
390
|
-
if (!this.isAllowed() || this.synchronizing)
|
|
391
|
-
return resolve();
|
|
392
|
-
this.synchronizing = true;
|
|
393
|
-
this.errorInLastSync = false;
|
|
394
|
-
this.requiresManualConfirmation = false;
|
|
395
|
-
// load the lastSyncAt information
|
|
396
|
-
this.loadLastSyncAt().then(() =>
|
|
397
|
-
// try to run all the pending API requests in the queue, i.e. uploading the offline resources changed
|
|
398
|
-
this.runQueueAPIRequests()
|
|
399
|
-
.then(() => {
|
|
400
|
-
// set this moment in time: if anything happened before the end of the sync, we don't lose fresh data
|
|
401
|
-
const now = Date.now();
|
|
402
|
-
// prepare a first "short" Delta request, to see if there is a lot of data to process
|
|
403
|
-
const params = { limit: NUM_ELEMENTS_WITHOUT_MANUAL_SYNC };
|
|
404
|
-
if (this.lastSyncAt)
|
|
405
|
-
params.since = this.lastSyncAt;
|
|
406
|
-
this._API
|
|
407
|
-
.getResource(this.teamId ? `teams/${this.teamId}/delta` : 'delta', { params })
|
|
408
|
-
.then((delta) => {
|
|
409
|
-
// decide if to proceed with the sync: in case there is another page, it requires a manual confirmation
|
|
410
|
-
if (delta.next && !manualConfirmation) {
|
|
411
|
-
this.requiresManualConfirmation = true;
|
|
412
|
-
this.synchronizing = false;
|
|
413
|
-
return resolve();
|
|
414
|
-
}
|
|
415
|
-
// save the records in the delta and request possible new pages
|
|
416
|
-
this.syncDeltaRecords(delta, () => {
|
|
417
|
-
if (this.errorInLastSync) {
|
|
418
|
-
this.synchronizing = false;
|
|
419
|
-
resolve();
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
// all the resources are succesfully in sync
|
|
423
|
-
this.resources.forEach(resource => (this.cacheableResources[resource].synchronizing = false));
|
|
424
|
-
// update the timestamp of last sync
|
|
425
|
-
this.saveLastSyncAt(now)
|
|
426
|
-
.then(() => {
|
|
427
|
-
this.synchronizing = false;
|
|
428
|
-
resolve();
|
|
429
|
-
})
|
|
430
|
-
.catch(() => {
|
|
431
|
-
// we couldn't save the last sync info
|
|
432
|
-
this.errorInLastSync = true;
|
|
433
|
-
this.synchronizing = false;
|
|
434
|
-
reject();
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
})
|
|
439
|
-
.catch(() => {
|
|
440
|
-
// we couldn't acquire new information (Delta)
|
|
441
|
-
this.errorInLastSync = true;
|
|
442
|
-
this.synchronizing = false;
|
|
443
|
-
reject();
|
|
444
|
-
});
|
|
445
|
-
})
|
|
446
|
-
.catch(() => {
|
|
447
|
-
// we stop, since we don't want backend data to override local info not yet uploaded
|
|
448
|
-
this.errorInLastSync = true;
|
|
449
|
-
this.synchronizing = false;
|
|
450
|
-
reject();
|
|
451
|
-
}));
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
/**
|
|
455
|
-
* Force a full synchronisation.
|
|
456
|
-
*/
|
|
457
|
-
forceFullSync() {
|
|
458
|
-
this._storage.clear().then(() => this.synchronize(true));
|
|
459
|
-
}
|
|
460
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: IDEAOfflineDataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
461
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: IDEAOfflineDataService, providedIn: 'root' }); }
|
|
462
|
-
}
|
|
463
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.9", ngImport: i0, type: IDEAOfflineDataService, decorators: [{
|
|
464
|
-
type: Injectable,
|
|
465
|
-
args: [{ providedIn: 'root' }]
|
|
466
|
-
}], ctorParameters: () => [] });
|
|
467
|
-
/**
|
|
468
|
-
* The abstract class to implement for each resource to cache offline from the back-end (DOWNLOAD).
|
|
469
|
-
*/
|
|
470
|
-
export class CacheableResource {
|
|
471
|
-
constructor(resource, description) {
|
|
472
|
-
this.resource = resource;
|
|
473
|
-
this.description = description;
|
|
474
|
-
this.synchronizing = false;
|
|
475
|
-
this.error = false;
|
|
476
|
-
// loaded at runtime
|
|
477
|
-
this.teamId = null;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2ZmbGluZURhdGEuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL21vZHVsZXMvdW5jb21tb24vc3JjL29mZmxpbmUvb2ZmbGluZURhdGEuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUduRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVqRixPQUFPLEVBQUUsaUJBQWlCLEVBQW9CLE1BQU0sbUJBQW1CLENBQUM7QUFDeEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7O0FBRXZEOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsSUFBSSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsUUFBUTtBQUNyRTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLHFDQUFxQyxDQUFDO0FBQzVFOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLCtCQUErQixDQUFDO0FBQzdEOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLEdBQUcsQ0FBQztBQUNwRDs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUFHLEdBQUcsQ0FBQztBQUVqRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQ0c7QUFFSCxNQUFNLE9BQU8sc0JBQXNCO0lBcURqQztRQXBEVSxhQUFRLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDdEMsZUFBVSxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQzdDLGFBQVEsR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUN0QyxTQUFJLEdBQUcsTUFB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QURULE1BQU07OzJGQUNuQixzQkFBc0I7a0JBRGxDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOztBQXFkbEM7O0dBRUc7QUFDSCxNQUFNLE9BQWdCLGlCQUFpQjtJQXVCckMsWUFBWSxRQUFnQixFQUFFLFdBQW1CO1FBQy9DLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzNCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztJQUNyQixDQUFDO0NBc0JGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IERlbHRhLCBEZWx0YVJlY29yZCwgRGVsdGFSZXNvdXJjZXMsIGVwb2NoRGF0ZVRpbWUgfSBmcm9tICdpZGVhLXRvb2xib3gnO1xuaW1wb3J0IHsgSURFQVN0b3JhZ2VTZXJ2aWNlLCBJREVBVHJhbnNsYXRpb25zU2VydmljZSB9IGZyb20gJ0BpZGVhLWlvbmljL2NvbW1vbic7XG5cbmltcG9ydCB7IElERUFBV1NBUElTZXJ2aWNlLCBBUElSZXF1ZXN0T3B0aW9uIH0gZnJvbSAnLi4vQVdTQVBJLnNlcnZpY2UnO1xuaW1wb3J0IHsgSURFQU9mZmxpbmVTZXJ2aWNlIH0gZnJvbSAnLi9vZmZsaW5lLnNlcnZpY2UnO1xuXG4vKipcbiAqIEFmdGVyIGhvdyBtdWNoIHRpbWUgd2UgbmVlZCB0byByZXF1ZXN0IGEgc3luY2hyb25pc2F0aW9uIHRvIGtlZXAgdGhlIGNvbnRlbnRzIHVwLXRvLWRhdGUuXG4gKi9cbmV4cG9ydCBjb25zdCBTWU5DX0VYUElSQVRJT05fSU5URVJWQUwgPSAxMDAwICogNjAgKiA2MCAqIDI0OyAvLyBhIGRheVxuLyoqXG4gKiBQcmVmaXggZm9yIHRoZSBrZXkgb2YgdGhlIEFQSSByZXF1ZXN0cyBxdWV1ZSBpbmZvIGluIHRoZSBsb2NhbCBzdG9yYWdlLlxuICovXG5leHBvcnQgY29uc3QgUVVFVUVfQVBJX1JFUVVFU1RTX0tFWSA9ICdJREVBT2ZmbGluZVNlcnZpY2UucXVldWVBUElyZXF1ZXN0cyc7XG4vKipcbiAqIFByZWZpeCBmb3IgdGhlIGtleSBvZiB0aGUgbGFzdCBzeW5jIHRpbWUgaW5mbyBpbiB0aGUgbG9jYWwgc3RvcmFnZS5cbiAqL1xuZXhwb3J0IGNvbnN0IExBU1RfU1lOQ19LRVkgPSAnSURFQU9mZmxpbmVTZXJ2aWNlLmxhc3RTeW5jQXQnO1xuLyoqXG4gKiBUaGUgbWF4IG51bWJlciBvZiBlbGVtZW50cyBwZXIgcmVzb3VyY2UgdG8gc3luY2hyb25pemUgZHVyaW5nIHRoZSBmaXJzdCBhbmFseXNpcyBvZiBhIHN5bmNocm9uaXNhdGlvbi5cbiAqIElmIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgZXhjZWVkcyAodGhlcmUgaXMgbW9yZSBkYXRhIGFmdGVyIHRoZSAxc3QgcGFnZSksIHRoZSBvcGVyYXRpb24gcmVxdWlyZSBtYW51YWwgY29uZmlybWF0aW9uLlxuICovXG5leHBvcnQgY29uc3QgTlVNX0VMRU1FTlRTX1dJVEhPVVRfTUFOVUFMX1NZTkMgPSAxMDA7XG4vKipcbiAqIFRoZSBtYXggbnVtYmVyIG9mIGVsZW1lbnRzIHBlciByZXNvdXJjZSB0byByZXF1ZXN0IGF0IHRoZSBzYW1lIHRpbWUgZHVyaW5nIGEgbm9ybWFsIHN5bmNocm9uaXNhdGlvbi5cbiAqL1xuZXhwb3J0IGNvbnN0IE5VTV9FTEVNRU5UU19XSVRIX01BTlVBTF9TWU5DID0gMzAwO1xuXG4vKipcbiAqIE1hbmFnZSB0aGUgb2ZmbGluZSBmdW5jdGlvbmluZyBvZiB0aGUgYXBwJ3MgZGF0YSAodXBsb2FkL2Rvd25sb2FkL3N5bmNocm9uaXphdGlvbikuXG4gKiBOb3RlOiBpdCBpbmNsdWRlcyBhbGwgdGhlIG1ldGhvZHMgb2YgSURFQU9mZmxpbmVTZXJ2aWNlLlxuICpcbiAqIERvd25sb2FkOiBpdCB3b3JrcyB0aHJvdWdoIHRoZSAqKkRlbHRhKiogbWVjaGFuaXNtIG9uIGJhY2stZW5kIHJlc291cmNlcy5cbiAqIFByYWN0aWNhbGx5LCB0aGUgc2VydmljZSBwcmVwYXJlcyBlYWNoIHBvc3NpYmxlIEFQSSBHRVQgcmVxdWVzdHMgZm9yIGVhY2ggb2YgdGhlIGludm9sdmVkIHJlc291cmNlcy5cbiAqIEluIHRoaXMgd2F5LCBpZiBvZmZsaW5lLCB0aGUgQVBJIHNlcnZpY2UgY2FuIGhpdCBhbiBlbGVtZW50IGJ5IFVSTCBpbiB0aGUgY2FjaGUgKHN0b3JhZ2Ugb2ZmbGluZSkuXG4gKlxuICogKipIb3cgdG8gdXNlIGl0KiouIENvbmZpZ3VyZSB0aGUgc3luYyBtZWNoYW5pc20gaW4gdGhlIG1haW4gYXBwLmNvbXBvbmVudCBhcyBpdCBmb2xsb3dzOlxuICpcbiAqICAgIDEuIEltcGxlbWVudCBhIENhY2hlYWJsZVJlc291cmNlIGNsYXNzIGZvciBlYWNoIERlbHRhUmVzb3VyY2UgeW91IHdhbnQgdG8gY2FjaGUgb2ZmbGluZS5cbiAqICAgIDIuIFNldCB1cCB0aGUgc2VydmljZSAoYHNldFVwT2ZmbGluZURhdGFgKS5cbiAqICAgIDMuIFJ1biBhIHN5bmNocm9uaXphdGlvbi5cbiAqICAgIDQuIEFkZCB0aGUgbmF2aWdhdGlvbiB0byB0aGUgT2ZmbGluZSBNYW5hZ2VyIChVSSkuXG4gKiAgICA1LiBPcHRpb25hbGx5LCBwdXNoIG9mZmxpbmUgQVBJIHJlcXVlc3RzIHRvIHRoZSBxdWV1ZSB3aGVuIG9mZmxpbmUuXG4gKlxuICogZS5nLiBvZiBDYWNoZWFibGVSZXNvdXJjZSBjbGFzc2VzOlxuICogYGBgXG4gKiBjbGFzcyBDdXN0b21lckNSIGV4dGVuZHMgQ2FjaGVhYmxlUmVzb3VyY2Uge1xuICogICBjb25zdHJ1Y3RvcihkZXNjcmlwdGlvbjogc3RyaW5nKSB7XG4gKiAgICAgc3VwZXIoRGVsdGFSZXNvdXJjZXMuQ1VTVE9NRVJTLCBkZXNjcmlwdGlvbik7XG4gKiAgIH1cbiAqICAgcHVibGljIGxpc3RVUkwoZWxlbWVudDogYW55KTogc3RyaW5nIHtcbiAqICAgICByZXR1cm4gYHRlYW1zLyR7ZWxlbWVudC50ZWFtSWR9L2N1c3RvbWVyc2A7XG4gKiAgIH1cbiAqICAgcHVibGljIGVsZW1lbnRVUkwoZWxlbWVudDogYW55KTogc3RyaW5nIHtcbiAqICAgICByZXR1cm4gYHRlYW1zLyR7ZWxlbWVudC50ZWFtSWR9L2N1c3RvbWVycy8ke2VsZW1lbnQuY3VzdG9tZXJJZH1gO1xuICogICB9XG4gKiAgIHB1YmxpYyBmaW5kSW5kZXhJbkxpc3QobGlzdDogQXJyYXk8YW55PiwgZWxlbWVudDogYW55KTogbnVtYmVyIHtcbiAqICAgICByZXR1cm4gbGlzdC5maW5kSW5kZXgoeCA9PiB4LmN1c3RvbWVySWQgPT09IGVsZW1lbnQuY3VzdG9tZXJJZCk7XG4gKiAgIH1cbiAqICAgcHVibGljIHNvcnQoYTogYW55LCBiOiBhbnkpOiBudW1iZXIge1xuICogICAgIHJldHVybiBhLm5hbWUubG9jYWxlQ29tcGFyZShiLm5hbWUpO1xuICogICB9XG4gKiB9XG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgSURFQU9mZmxpbmVEYXRhU2VydmljZSB7XG4gIHByb3RlY3RlZCBfc3RvcmFnZSA9IGluamVjdChJREVBU3RvcmFnZVNlcnZpY2UpO1xuICBwcm90ZWN0ZWQgX3RyYW5zbGF0ZSA9IGluamVjdChJREVBVHJhbnNsYXRpb25zU2VydmljZSk7XG4gIHByb3RlY3RlZCBfb2ZmbGluZSA9IGluamVjdChJREVBT2ZmbGluZVNlcnZpY2UpO1xuICBwcm90ZWN0ZWQgX0FQSSA9IGluamVjdChJREVBQVdTQVBJU2VydmljZSk7XG5cbiAgLyoqXG4gICAqIFRydWUgd2hlbiBydW5uaW5nIGEgc3luY2hyb25pemF0aW9uLlxuICAgKi9cbiAgc3luY2hyb25pemluZzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSB0aW1lc3RhbXAgb2YgdGhlIGxhc3Qgc3luY2hyb25pemF0aW9uLlxuICAgKi9cbiAgbGFzdFN5bmNBdDogZXBvY2hEYXRlVGltZTtcbiAgLyoqXG4gICAqIFRydWUgaWYgYW4gZXJyb3IgaGFwcGVuZWQgaW4gdGhlIGxhc3Qgc3luY2hyb25pemF0aW9uLlxuICAgKi9cbiAgZXJyb3JJbkxhc3RTeW5jOiBib29sZWFuO1xuICAvKipcbiAgICogVHJ1ZSBpZiB0aGUgc3luY2hyb25pc2F0aW9uIGlzIHRvbyB2YXN0IGFuZCBzbyByZXF1aXJlIGEgbWFudWFsIGFjdGlvbiBvZiB0aGUgdXNlci5cbiAgICovXG4gIHJlcXVpcmVzTWFudWFsQ29uZmlybWF0aW9uOiBib29sZWFuO1xuICAvKipcbiAgICogSWYgZmFsc2UsIGlnbm9yZSB0aGUgZW50aXJlIHVwbG9hZCBzY2VuYXJpby5cbiAgICovXG4gIHVzZVF1ZXVlQVBJUmVxdWVzdHM6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUaGUgYXJyYXkgb2YgdGhlIHJlcXVlc3RzIG5vdCBleGVjdXRlZCBiZWNhdXNlIHdlIGFyZS93ZXJlIG9mZmxpbmU7IHRoZXkgbmVlZCB0byBydW4gb25jZSBvbmxpbmUuXG4gICAqL1xuICBxdWV1ZUFQSVJlcXVlc3RzOiBBUElSZXF1ZXN0W107XG5cbiAgLyoqXG4gICAqIFRoZSBpZCBvZiB0aGUgdGVhbSBvZiB3aGljaCB0byBtYW5hZ2UgZGF0YSBvZmZsaW5lLlxuICAgKiBJZiBudWxsLCB0aGUgcHJvamVjdCBpc24ndCB0ZWFtcy1iYXNlZC5cbiAgICovXG4gIHByb3RlY3RlZCB0ZWFtSWQ6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBhcnJheSBvZiBEZWx0YVJlc291cmNlcyB0byBjYWNoZSBvZmZsaW5lLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlc291cmNlczogKERlbHRhUmVzb3VyY2VzIHwgc3RyaW5nKVtdO1xuICAvKipcbiAgICogSGVscGVyIHN0cnVjdHVyZSB0byBtYW5hZ2UgdGhlIENhY2hlYWJsZVJlc291cmNlIGZvciBlYWNoIERlbHRhUmVzb3VyY2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgY2FjaGVhYmxlUmVzb3VyY2VzOiB7IFtyZXNvdXJjZTogc3RyaW5nXTogQ2FjaGVhYmxlUmVzb3VyY2UgfTtcbiAgLyoqXG4gICAqIEtleSB0byBhY3F1aXJlIGZyb20gdGhlIHN0b3JhZ2UgdGhlIGxhc3RTeW5jQXQgaW5mb3JtYXRpb24gb2YgdGhlIHRlYW0uXG4gICAqL1xuICBwcm90ZWN0ZWQgbGFzdFN5bmNLZXk6IHN0cmluZztcbiAgLyoqXG4gICAqIEtleSB0byBhY3F1aXJlIGZyb20gdGhlIHN0b3JhZ2UgdGhlIGxhc3RTeW5jQXQgaW5mb3JtYXRpb24gb2YgdGhlIHRlYW0uXG4gICAqL1xuICBwcm90ZWN0ZWQgcXVldWVBUElSZXF1ZXN0S2V5OiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzID0gbmV3IEFycmF5PEFQSVJlcXVlc3Q+KCk7XG4gICAgdGhpcy5yZXNvdXJjZXMgPSBuZXcgQXJyYXk8c3RyaW5nPigpO1xuICAgIHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzID0ge307XG4gICAgLy8gc3Vic2NyaWJlIHRvIG5ldHdvcmsgY2hhbmdlc1xuICAgIHRoaXMuX29mZmxpbmUuc3Vic2NyaWJlKGlzT25saW5lID0+IHtcbiAgICAgIGlmIChpc09ubGluZSkge1xuICAgICAgICAvLyB0cnkgYSBzeW5jaHJvbml6YXRpb24gaWYgbmVlZGVkIG9yIGlmIHRoZSBsYXN0IG9uZSBmYWlsZWRcbiAgICAgICAgaWYgKHRoaXMuZXJyb3JJbkxhc3RTeW5jKSB0aGlzLnN5bmNocm9uaXplKCk7XG4gICAgICAgIGVsc2UgdGhpcy5zeW5jaHJvbml6ZUlmTmVlZGVkKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvL1xuICAvLyBORVRXT1JLIFNUQVRVUyBmcm9tIElERUFPZmZsaW5lU2VydmljZVxuICAvL1xuXG4gIC8qKlxuICAgKiBRdWlja2x5IGNoZWNrIHRoZSBjb25uZWN0aW9uIHN0YXR1cy5cbiAgICovXG4gIGlzT25saW5lKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9vZmZsaW5lLmlzT25saW5lKCk7XG4gIH1cbiAgLyoqXG4gICAqIFF1aWNrbHkgY2hlY2sgdGhlIGNvbm5lY3Rpb24gc3RhdHVzLlxuICAgKi9cbiAgaXNPZmZsaW5lKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9vZmZsaW5lLmlzT2ZmbGluZSgpO1xuICB9XG4gIC8qKlxuICAgKiBTdWJzY3JpYmUgdG8gdGhlIHNlcnZpY2UgdG8gYmUgbm90aWZpZWQgd2hlbiB0aGUgY29ubmVjdGlvbiBzdGF0dXMgY2hhbmdlcy5cbiAgICovXG4gIHN1YnNjcmliZShjYWxsYmFjazogKGlzT25saW5lOiBib29sZWFuKSA9PiB2b2lkKTogU3Vic2NyaXB0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5fb2ZmbGluZS5zdWJzY3JpYmUoY2FsbGJhY2spO1xuICB9XG4gIC8qKlxuICAgKiBRdWlja2x5IGNoZWNrIGZvciBvbmxpbmUgY29ubmVjdGlvbi5cbiAgICovXG4gIHB1YmxpYyBjaGVjaygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5fb2ZmbGluZS5jaGVjaygpO1xuICB9XG5cbiAgLy9cbiAgLy8gQ09ORklHVVJBVElPTlxuICAvL1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBvZmZsaW5lIG1vZGUgaXMgYWxsb3dlZC4gWW91IGNhbiBjdXN0b21pemUgdGhpcyBmdW5jdGlvbiwgaWYgbmVlZGVkLlxuICAgKi9cbiAgaXNBbGxvd2VkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMucmVzb3VyY2VzLmxlbmd0aDtcbiAgfVxuICAvKipcbiAgICogU2V0IHVwIHRoZSBzZXJ2aWNlIHRvIHVzZSBhbmQgc3luYyBvZmZsaW5lIGRhdGEuXG4gICAqL1xuICBzZXRVcE9mZmxpbmVEYXRhKHRlYW1JZDogc3RyaW5nLCB1c2VRdWV1ZUFQSVJlcXVlc3RzOiBib29sZWFuLCBjYWNoZWFibGVSZXNvdXJjZXM6IENhY2hlYWJsZVJlc291cmNlW10pOiB2b2lkIHtcbiAgICAvLyBzZXQgdGhlIHRlYW1cbiAgICB0aGlzLnRlYW1JZCA9IHRlYW1JZDtcbiAgICAvLyBkZWNpZGUgaWYgdG8gYWxsb3cgY2VydGFpbiBBUEkgcmVxdWVzdCB3aGlsZSBvZmZsaW5lXG4gICAgdGhpcy51c2VRdWV1ZUFQSVJlcXVlc3RzID0gdXNlUXVldWVBUElSZXF1ZXN0cztcbiAgICAvLyBsb2FkIHRoZSBBUEkgcmVxdWVzdCBwZW5kaW5nIHF1ZXVlLCBpZiBhbnlcbiAgICB0aGlzLnF1ZXVlQVBJUmVxdWVzdEtleSA9IHRoaXMudGVhbUlkID8gYCR7UVVFVUVfQVBJX1JFUVVFU1RTX0tFWX1fJHt0aGlzLnRlYW1JZH1gIDogUVVFVUVfQVBJX1JFUVVFU1RTX0tFWTtcbiAgICB0aGlzLmxvYWRRdWV1ZUFQSVJlcXVlc3QoKTtcbiAgICAvLyBsb2FkIHRoZSBsYXN0U3luY0F0IGluZm9ybWF0aW9uIGZvciB0aGUgdGVhbVxuICAgIHRoaXMubGFzdFN5bmNLZXkgPSB0aGlzLnRlYW1JZCA/IGAke0xBU1RfU1lOQ19LRVl9XyR7dGhpcy50ZWFtSWR9YCA6IExBU1RfU1lOQ19LRVk7XG4gICAgdGhpcy5sb2FkTGFzdFN5bmNBdCgpO1xuICAgIC8vIGxvYWQgdGhlIGNhY2hlYWJsZSByZXNvdXJjZXNcbiAgICB0aGlzLnJlc291cmNlcyA9IG5ldyBBcnJheTxEZWx0YVJlc291cmNlcyB8IHN0cmluZz4oKTtcbiAgICB0aGlzLmNhY2hlYWJsZVJlc291cmNlcyA9IHt9O1xuICAgIGNhY2hlYWJsZVJlc291cmNlcy5mb3JFYWNoKHIgPT4gdGhpcy5hZGRDYWNoZWFibGVSZXNvdXJjZShyKSk7XG4gIH1cbiAgLyoqXG4gICAqIExvYWQgZnJvbSB0aGUgbG9jYWwgc3RvcmFnZSB0aGUgbGFzdCBzeW5jIGF0IGluZm9ybWF0aW9uLlxuICAgKi9cbiAgcHJvdGVjdGVkIGxvYWRMYXN0U3luY0F0KCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5fc3RvcmFnZS5nZXQodGhpcy5sYXN0U3luY0tleSkudGhlbigobGFzdFN5bmNBdDogbnVtYmVyKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMubGFzdFN5bmNBdCA9IGxhc3RTeW5jQXQgPyBOdW1iZXIobGFzdFN5bmNBdCkgOiBudWxsO1xuICAgICAgICByZXNvbHZlKHRoaXMubGFzdFN5bmNBdCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogVXBkYXRlIGxhc3Qgc3luYyBhdCBpbmZvIGluIHRoZSBsb2NhbCBzdG9yYWdlLlxuICAgKi9cbiAgcHJvdGVjdGVkIHNhdmVMYXN0U3luY0F0KGxhc3RTeW5jQXQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMubGFzdFN5bmNBdCA9IGxhc3RTeW5jQXQ7XG4gICAgcmV0dXJuIHRoaXMuX3N0b3JhZ2Uuc2V0KHRoaXMubGFzdFN5bmNLZXksIGxhc3RTeW5jQXQpO1xuICB9XG4gIC8qKlxuICAgKiBBZGQgYSBDYWNoZWFibGVSZXNvdXJjZS5cbiAgICovXG4gIHByb3RlY3RlZCBhZGRDYWNoZWFibGVSZXNvdXJjZShjYWNoZWFibGVSZXNvdXJjZTogQ2FjaGVhYmxlUmVzb3VyY2UpOiB2b2lkIHtcbiAgICBpZiAodGhpcy50ZWFtSWQpIGNhY2hlYWJsZVJlc291cmNlLnRlYW1JZCA9IHRoaXMudGVhbUlkO1xuICAgIHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzW2NhY2hlYWJsZVJlc291cmNlLnJlc291cmNlXSA9IGNhY2hlYWJsZVJlc291cmNlO1xuICAgIHRoaXMucmVzb3VyY2VzLnB1c2goY2FjaGVhYmxlUmVzb3VyY2UucmVzb3VyY2UpO1xuICB9XG4gIC8qKlxuICAgKiBSZW1vdmUgYSBDYWNoZWFibGVSZXNvdXJjZSBieSBpdHMgRGVsdGFSZXNvdXJjZS5cbiAgICovXG4gIHByb3RlY3RlZCByZW1vdmVDYWNoZWFibGVSZXNvdXJjZShyZXNvdXJjZTogRGVsdGFSZXNvdXJjZXMgfCBzdHJpbmcpOiB2b2lkIHtcbiAgICBkZWxldGUgdGhpcy5jYWNoZWFibGVSZXNvdXJjZXNbcmVzb3VyY2VdO1xuICAgIHRoaXMucmVzb3VyY2VzLnNwbGljZSh0aGlzLnJlc291cmNlcy5pbmRleE9mKHJlc291cmNlKSwgMSk7XG4gIH1cbiAgLyoqXG4gICAqIEdldCB0aGUgdGhlIERlbHRhUmVzb3VyY2VkIGNvbmZpZ3VyZWQuXG4gICAqL1xuICBnZXRSZXNvdXJjZXMoKTogKERlbHRhUmVzb3VyY2VzIHwgc3RyaW5nKVtdIHtcbiAgICByZXR1cm4gdGhpcy5yZXNvdXJjZXM7XG4gIH1cbiAgLyoqXG4gICAqIEdldCBhIENhY2hlYWJsZVJlc291cmNlIGJ5IGl0cyBEZWx0YVJlc291cmNlLlxuICAgKi9cbiAgZ2V0Q2FjaGVhYmxlUmVzb3VyY2UocmVzb3VyY2U6IERlbHRhUmVzb3VyY2VzIHwgc3RyaW5nKTogQ2FjaGVhYmxlUmVzb3VyY2Uge1xuICAgIHJldHVybiB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV07XG4gIH1cblxuICAvL1xuICAvLyBVUExPQURcbiAgLy9cblxuICAvKipcbiAgICogRXhlY3V0ZSBhbGwgdGhlIEFQSSByZXF1ZXN0cyBpbiB0aGUgcXVldWU7IHRoZSByZXF1ZXN0cyB0ZXJtaW5hdGVkIHdpdGggYW4gZXJyb3Igd2lsbCByZW1haW4gaW4gdGhlIHF1ZXVlLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJ1blF1ZXVlQVBJUmVxdWVzdHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGlmICghdGhpcy51c2VRdWV1ZUFQSVJlcXVlc3RzIHx8IHRoaXMuaXNPZmZsaW5lKCkgfHwgIXRoaXMucXVldWVBUElSZXF1ZXN0cy5sZW5ndGgpIHJldHVybiByZXNvbHZlKCk7XG4gICAgICB0aGlzLnF1ZXVlQVBJUmVxdWVzdHMuZm9yRWFjaChhc3luYyByZXF1ZXN0ID0+IHtcbiAgICAgICAgY29uc3Qgb3B0aW9uczogQVBJUmVxdWVzdE9wdGlvbiA9IHt9O1xuICAgICAgICBpZiAocmVxdWVzdC5yZXNvdXJjZUlkKSBvcHRpb25zLnJlc291cmNlSWQgPSByZXF1ZXN0LnJlc291cmNlSWQ7XG4gICAgICAgIGlmIChyZXF1ZXN0LmJvZHkpIG9wdGlvbnMuYm9keSA9IHJlcXVlc3QuYm9keTtcbiAgICAgICAgbGV0IHByb21pc2U6IFByb21pc2U8YW55PjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBzd2l0Y2ggKHJlcXVlc3QubWV0aG9kLnRvVXBwZXJDYXNlKCkpIHtcbiAgICAgICAgICAgIGNhc2UgJ1BPU1QnOlxuICAgICAgICAgICAgICBwcm9taXNlID0gYXdhaXQgdGhpcy5fQVBJLnBvc3RSZXNvdXJjZShyZXF1ZXN0LnJlc291cmNlLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdQVVQnOlxuICAgICAgICAgICAgICBwcm9taXNlID0gYXdhaXQgdGhpcy5fQVBJLnB1dFJlc291cmNlKHJlcXVlc3QucmVzb3VyY2UsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ1BBVENIJzpcbiAgICAgICAgICAgICAgcHJvbWlzZSA9IGF3YWl0IHRoaXMuX0FQSS5wYXRjaFJlc291cmNlKHJlcXVlc3QucmVzb3VyY2UsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFwcm9taXNlKSByZXF1ZXN0LmVycm9yID0gJ0lOVkFMSURfTUVUSE9EJztcbiAgICAgICAgICBlbHNlIHJlcXVlc3QuZXJyb3IgPSBudWxsO1xuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICByZXF1ZXN0LmVycm9yID0gKGVyciBhcyBFcnJvcikubWVzc2FnZSB8fCAnVU5LTk9XTl9FUlJPUic7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgLy8ga2VlcCB0aGUgcmVxdWVzdHMgTk9UIHN1Y2Nlc3NmdWxseSBleGVjdXRlZFxuICAgICAgdGhpcy5zYXZlUXVldWVBUElSZXF1ZXN0KHRoaXMucXVldWVBUElSZXF1ZXN0cy5maWx0ZXIoeCA9PiB4LmVycm9yKSkudGhlbigoKTogdm9pZCA9PiB7XG4gICAgICAgIC8vIGlmIHRoZSBxdWV1ZSBpcyBlbXB0eSwgdGhlIGVudGlyZSBvcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWxcbiAgICAgICAgaWYgKHRoaXMucXVldWVBUElSZXF1ZXN0cy5sZW5ndGgpIHJlamVjdCgpO1xuICAgICAgICBlbHNlIHJlc29sdmUoKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBMb2FkIGZyb20gdGhlIGxvY2FsIHN0b3JhZ2UgdGhlIEFQSSByZXF1ZXN0cyBxdWV1ZS5cbiAgICovXG4gIHByb3RlY3RlZCBsb2FkUXVldWVBUElSZXF1ZXN0KCk6IFByb21pc2U8QVBJUmVxdWVzdFtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgaWYgKCF0aGlzLnVzZVF1ZXVlQVBJUmVxdWVzdHMpIHJldHVybiByZXNvbHZlKFtdKTtcbiAgICAgIHRoaXMuX3N0b3JhZ2UuZ2V0KHRoaXMucXVldWVBUElSZXF1ZXN0S2V5KS50aGVuKChxdWV1ZTogQVBJUmVxdWVzdFtdKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMucXVldWVBUElSZXF1ZXN0cyA9IHF1ZXVlIHx8IFtdO1xuICAgICAgICByZXNvbHZlKHRoaXMucXVldWVBUElSZXF1ZXN0cyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogVXBkYXRlIHRoZSBxdWV1ZSBpbiBtZW1vcnkgYW5kIGFsc28gc2F2ZSB0aGUgY29weSBpbiB0aGUgbG9jYWwgc3RvcmFnZS5cbiAgICovXG4gIHNhdmVRdWV1ZUFQSVJlcXVlc3QocXVldWU/OiBBUElSZXF1ZXN0W10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMuaXNBbGxvd2VkKCkpIHJldHVybiBQcm9taXNlLnJlamVjdCgpO1xuICAgIHRoaXMucXVldWVBUElSZXF1ZXN0cyA9IHF1ZXVlIHx8IHRoaXMucXVldWVBUElSZXF1ZXN0cztcbiAgICByZXR1cm4gdGhpcy5fc3RvcmFnZS5zZXQodGhpcy5xdWV1ZUFQSVJlcXVlc3RLZXksIHRoaXMucXVldWVBUElSZXF1ZXN0cyk7XG4gIH1cbiAgLyoqXG4gICAqIERlbGV0ZSBhIHJlcXVlc3Qgc3R1Y2sgaW4gYW4gZXJyb3IuXG4gICAqL1xuICBkZWxldGVSZXF1ZXN0KHJlcXVlc3Q6IEFQSVJlcXVlc3QpIHtcbiAgICBpZiAoIXRoaXMuaXNBbGxvd2VkKCkpIHJldHVybiBQcm9taXNlLnJlamVjdCgpO1xuICAgIGlmIChyZXF1ZXN0KSB7XG4gICAgICB0aGlzLnF1ZXVlQVBJUmVxdWVzdHMuc3BsaWNlKHRoaXMucXVldWVBUElSZXF1ZXN0cy5pbmRleE9mKHJlcXVlc3QpLCAxKTtcbiAgICAgIHRoaXMuc2F2ZVF1ZXVlQVBJUmVxdWVzdCgpO1xuICAgIH1cbiAgfVxuXG4gIC8vXG4gIC8vIERPV05MT0FEXG4gIC8vXG5cbiAgLyoqXG4gICAqIFNhdmUgdGhlIHJlY29yZHMgb2YgYSBkZWx0YSBhbmQsIGlmIHRoZSBsYXR0ZXIgaGFzIG1vcmUgcGFnZXMsIGdvIHJlY3Vyc2l2ZS5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBzeW5jRGVsdGFSZWNvcmRzKGRlbHRhOiBEZWx0YSwgZG9uZT86IGFueSk6IFByb21pc2U8YW55PiB7XG4gICAgLy8gZm9yIGVhY2ggcmVzb3VyY2UsIHdlIHJlc2V0IHRoZSBzdGF0dXM7IGlmIGEgcmVzb3VyY2Ugc3RpbGwgbmVlZCB0byBiZSBzeW5jaHJvbml6ZWQsIGl0IHdpbGwgYmUgZmxhZ2dlZCBiZWxvd1xuICAgIHRoaXMucmVzb3VyY2VzLmZvckVhY2gocmVzb3VyY2UgPT4ge1xuICAgICAgdGhpcy5jYWNoZWFibGVSZXNvdXJjZXNbcmVzb3VyY2VdLmVycm9yID0gZmFsc2U7XG4gICAgICB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV0uc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgIH0pO1xuICAgIHRyeSB7XG4gICAgICAvLyBzeW5jaHJvbnplIGVhY2ggb2YgdGhlIHJlc291cmNlcyBpbmNsdWRlZCBpbiB0aGUgZGVsdGE7IHRoaXMgZXhlY3V0aW9uIGNhbiBnbyBpbiBwYXJhbGxlbFxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICAgIGRlbHRhLnJlc291cmNlcy5tYXAoYXN5bmMgcmVzb3VyY2UgPT4ge1xuICAgICAgICAgIGNvbnN0IGNyID0gdGhpcy5jYWNoZWFibGVSZXNvdXJjZXNbcmVzb3VyY2VdO1xuICAgICAgICAgIGlmIChjcikge1xuICAgICAgICAgICAgLy8gc3luY2hyb25pemUgdGhlIGRlbHRhIHJlY29yZHM7IG5vdGU6IHRoZSBleGVjdXR1aW9uIGluc2lkZSBhIHJlc291cmNlIG11c3QgZ28gaW4gc2VyaWVzXG4gICAgICAgICAgICBjci5zeW5jaHJvbml6aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbnN0IHN1Y2Nlc3MgPSBhd2FpdCB0aGlzLnN5bmNSZXNvdXJjZURlbHRhUmVjb3JkcyhyZXNvdXJjZSwgZGVsdGEucmVjb3Jkc1tyZXNvdXJjZV0pO1xuICAgICAgICAgICAgaWYgKCFzdWNjZXNzKSB0aGlzLmVycm9ySW5MYXN0U3luYyA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgKTtcbiAgICAgIC8vIGlmIHRoZXJlIHdlcmUgZXJyb3Igb2YgaWYgdGhlcmUgaXMgbm90aGluZyBsZWZ0IHRvIHN5bmMsIHdlIGFyZSBkb25lXG4gICAgICBpZiAodGhpcy5lcnJvckluTGFzdFN5bmMgfHwgIWRlbHRhLm5leHQpIHJldHVybiBkb25lKCk7XG4gICAgICAvLyBvdGhlcndpc2UsIGdldCB0aGUgbmV4dCBwYWdlIG9mIHRoZSBkZWx0YSBhbmQgZ28gcmVjdXJzaXZlIHVudGlsIHdlIGFyZSBkb25lXG4gICAgICBjb25zdCBwYXJhbXM6IGFueSA9IHsgbmV4dDogZGVsdGEubmV4dCwgbGltaXQ6IE5VTV9FTEVNRU5UU19XSVRIX01BTlVBTF9TWU5DIH07XG4gICAgICBpZiAodGhpcy5sYXN0U3luY0F0KSBwYXJhbXMuc2luY2UgPSB0aGlzLmxhc3RTeW5jQXQ7XG4gICAgICBjb25zdCBuZXdEZWx0YSA9IGF3YWl0IHRoaXMuX0FQSS5nZXRSZXNvdXJjZSh0aGlzLnRlYW1JZCA/IGB0ZWFtcy8ke3RoaXMudGVhbUlkfS9kZWx0YWAgOiAnZGVsdGEnLCB7IHBhcmFtcyB9KTtcbiAgICAgIHRoaXMuc3luY0RlbHRhUmVjb3JkcyhuZXdEZWx0YSwgZG9uZSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBpZiBzb21ldGhpbmcgd2VudCB3cm9uZywgc3RvcHMgdGhlIG9wZXJhdGlvbiwgc2luY2Ugd2UgbmVlZCB0byBtYWtlIHN1cmUgdGhlIGVudGlyZSBmbG93IGlzIGNvbnNpc3RlbnRcbiAgICAgIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgIHJldHVybiBkb25lKCk7XG4gICAgfVxuICB9XG4gIC8qKlxuICAgKiBTYXZlIG9mZmxpbmUgYSBsaXN0IG9mIERlbHRhUmVjb3JkcyBmb3IgdGhpcyByZXNvdXJjZSwgY3JlYXRpbmcgYSBtYXAgb2YgYWxsIHRoZSBjb3JyZXNwb25kaW5nIEFQSSBHRVQgcmVxdWVzdHMuXG4gICAqL1xuICBwcm90ZWN0ZWQgYXN5bmMgc3luY1Jlc291cmNlRGVsdGFSZWNvcmRzKHJlc291cmNlOiBzdHJpbmcsIHJlY29yZHM6IERlbHRhUmVjb3JkW10pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAvLyBhY3F1aXJlIHRoZSBpbmZvIGFuIGEgY2FjaGVhYmxlIHJlc291cmNlXG4gICAgY29uc3QgY3IgPSB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV07XG4gICAgaWYgKCFjcikgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcbiAgICB0cnkge1xuICAgICAgLy8gcHJlcGFyZSBoZWxwZXJzIHRvIGdyb3VwIGV4ZWN1dGlvbnMgb2YgZWxlbWVudHMgb2YgdGhlIHNhbWUgbGlzdFxuICAgICAgbGV0IGxpc3Q6IGFueVtdID0gbnVsbCxcbiAgICAgICAgb2xkTGlzdFVSTDogc3RyaW5nID0gbnVsbDtcbiAgICAgIGZvciAoY29uc3QgciBvZiByZWNvcmRzKSB7XG4gICAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgVVJMIHRvIGFjY2VzcyB0aGUgQVBJIHJlcXVlc3Qga2V5IGZvciB0aGlzIGVsZW1lbnRcbiAgICAgICAgY29uc3QgZWxlbWVudFVSTCA9IGNyLmVsZW1lbnRVUkwoci5lbGVtZW50KTtcbiAgICAgICAgLy8gaWYgdGhlIGVsZW1lbnQgd2FzIGRlbGV0ZWQgKGJhc2VkIG9uIGRlbHRhKSwgZGVsZXRlIGl0cyBjb3JyZXNwb25kaW5nIEFQSSBHRVQgcmVxdWVzdFxuICAgICAgICBpZiAoci5kZWxldGVkKSBhd2FpdCB0aGlzLl9BUEkuZGVsZXRlRnJvbUNhY2hlKGVsZW1lbnRVUkwpO1xuICAgICAgICAvLyBvdGhlcndpc2UsIHVwZGF0ZSBpdFxuICAgICAgICBlbHNlIGF3YWl0IHRoaXMuX0FQSS5wdXRJbkNhY2hlKGVsZW1lbnRVUkwsIHIuZWxlbWVudCk7XG4gICAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgVVJMcyB0byBhY2Nlc3MgdGhlIEFQSSByZXF1ZXN0IGtleSBmb3IgdGhpcyBlbGVtZW50J3MgbGlzdFxuICAgICAgICBjb25zdCBsaXN0VVJMID0gY3IubGlzdFVSTChyLmVsZW1lbnQpO1xuICAgICAgICAvLyB0byBpbXByb3ZlIHRoZSBwZXJmb3JtYW5jZSwgZ2V0L3NvcnQvc2F2ZSB0aGUgbGlzdCBvbmx5IHdoZW4gaXQgY2hhbmdlcyBmcm9tIHRoZSBwcmV2aW91cyBlbGVtZW50J3Mgb25lLlxuICAgICAgICBpZiAobGlzdFVSTCAhPT0gb2xkTGlzdFVSTCkge1xuICAgICAgICAgIC8vIHNraXAgZmlyc3QgY3ljbGUgKG9sZExpc3RVUkwgPT09IG51bGwpXG4gICAgICAgICAgaWYgKG9sZExpc3RVUkwpIHtcbiAgICAgICAgICAgIC8vIHJlLXNvcnQgdGhlIGxpc3Q7IG5vdGU6IGl0IHNob3VsZCBiZSBzb3J0ZWQgZnJvbSB0aGUgbGFzdCB0aW1lLCBzbyB3ZSBvbmx5IG1hbmFnZSB0aGUgbmV3IGVsZW1lbnRcbiAgICAgICAgICAgIGxpc3QgPSBsaXN0LnNvcnQoY3Iuc29ydCk7XG4gICAgICAgICAgICAvLyBzYXZlIHRoZSB1cGRhdGVkIGxpc3RcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuX0FQSS5wdXRJbkNhY2hlKG9sZExpc3RVUkwsIGxpc3QpO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBnZXQgdGhlIGxpc3Qgb2YgZWxlbWVudHMgZnJvbSB0aGUgbG9jYWwgc3RvcmFnZSBieSB0aGUgY2FsY3VsYXRlZCBVUkxcbiAgICAgICAgICBsaXN0ID0gYXdhaXQgdGhpcy5fQVBJLmdldEZyb21DYWNoZShsaXN0VVJMKTtcbiAgICAgICAgICAvLyBzYXZlIHRoZSByZWZlcmVuY2UgdG8gdGhlIGxpc3QgZm9yIHRoZSBuZXh0IGN5Y2xlXG4gICAgICAgICAgb2xkTGlzdFVSTCA9IGxpc3RVUkw7XG4gICAgICAgIH1cbiAgICAgICAgLy8gZmluZCBpbiB0aGUgbGlzdCB0aGUgZWxlbWVudCB3ZSB3YW50IHRvIG1hbmFnZVxuICAgICAgICBjb25zdCBpbmRleCA9IGNyLmZpbmRJbmRleEluTGlzdChsaXN0LCByLmVsZW1lbnQpO1xuICAgICAgICAvLyBkZWxldGUgdGhlIGVsZW1lbnQgZnJvbSB0aGUgbGlzdFxuICAgICAgICBpZiAoaW5kZXggIT09IC0xKSBsaXN0LnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIC8vIGlmIHRoZSBlbGVtZW50IHdhc24ndCBkZWxldGVkIChmb2xsb3dpbmcgdGhlIGRlbHRhIHJlY29yZCBpbmZvcm1hdGlvbiksIGluc2VydCB0aGUgbmV3IHZlcnNpb25cbiAgICAgICAgaWYgKCFyLmRlbGV0ZWQpIGxpc3QucHVzaChyLmVsZW1lbnQpO1xuICAgICAgfVxuICAgICAgLy8gaW4gY2FzZSB0aGVyZSB3ZXJlIGVsZW1lbnRzLCBzYXZlIHRoZSBsYXN0IGVsZW1lbnQncyBsaXN0XG4gICAgICBpZiAob2xkTGlzdFVSTCkge1xuICAgICAgICAvLyByZS1zb3J0IHRoZSBsaXN0OyBub3RlOiBpdCBzaG91bGQgYmUgc29ydGVkIGZyb20gdGhlIGxhc3QgdGltZSwgc28gd2Ugb25seSBtYW5hZ2UgdGhlIG5ldyBlbGVtZW50XG4gICAgICAgIGxpc3QgPSBsaXN0LnNvcnQoY3Iuc29ydCk7XG4gICAgICAgIC8vIHNhdmUgdGhlIHVwZGF0ZWQgbGlzdFxuICAgICAgICBhd2FpdCB0aGlzLl9BUEkucHV0SW5DYWNoZShvbGRMaXN0VVJMLCBsaXN0KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUodHJ1ZSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBpZiBzb21ldGhpbmcgd2VudCB3cm9uZywgc3RvcHMgdGhlIG9wZXJhdGlvbiwgc2luY2Ugd2UgbmVlZCB0byBtYWtlIHN1cmUgdGhlIGVudGlyZSBmbG93IGlzIGNvbnNpc3RlbnRcbiAgICAgIGNyLmVycm9yID0gdHJ1ZTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIC8vXG4gIC8vIFNZTkNIUk9OSVNBVElPTiAoVVBMT0FEK0RPV05MT0FEKVxuICAvL1xuXG4gIC8qKlxuICAgKiBSdW4gYSBzeW5jLCBidXQgb25seSBpZiBuZWVkZWQsIGkuZS4gdGhlIGNhY2hlZCBjb250ZW50IGV4cGlyZWQgb3Igd2UgaGF2ZSBwZW5kaW5nIEFQSSByZXF1ZXN0cyBpbiB0aGUgcXVldWUuXG4gICAqL1xuICBzeW5jaHJvbml6ZUlmTmVlZGVkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KTogdm9pZCA9PiB7XG4gICAgICBpZiAoIXRoaXMuaXNBbGxvd2VkKCkpIHJldHVybjtcbiAgICAgIHRoaXMubG9hZExhc3RTeW5jQXQoKS50aGVuKFxuICAgICAgICAoKTogUHJvbWlzZTx2b2lkPiA9PlxuICAgICAgICAgIHRoaXMubG9hZFF1ZXVlQVBJUmVxdWVzdCgpXG4gICAgICAgICAgICAudGhlbigoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgIGlmICh0aGlzLnF1ZXVlQVBJUmVxdWVzdHMubGVuZ3RoIHx8IERhdGUubm93KCkgPiB0aGlzLmxhc3RTeW5jQXQgKyBTWU5DX0VYUElSQVRJT05fSU5URVJWQUwpXG4gICAgICAgICAgICAgICAgdGhpcy5zeW5jaHJvbml6ZSgpO1xuICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVyciA9PiByZWplY3QoZXJyKSlcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIFN5bmNocm9uaXphdGlvbiBvZiB0aGUgd2hvbGUgc2V0IG9mIHJlc291cmNlcyAodXBsb2FkK2Rvd25sb2FkKS5cbiAgICogQHBhcmFtIG1hbnVhbENvbmZpcm1hdGlvbiBpZiB0cnVlLCB0aGUgcmVxdWVzdCBjb21lcyBkaXJlY3RseSBmcm9tIGEgdXNlciBhY3Rpb24gKG5vdCBhdXRvbWF0aWMgcHJvY2VkdXJlcykuXG4gICAqL1xuICBzeW5jaHJvbml6ZShtYW51YWxDb25maXJtYXRpb24/OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGlmICghdGhpcy5pc0FsbG93ZWQoKSB8fCB0aGlzLnN5bmNocm9uaXppbmcpIHJldHVybiByZXNvbHZlKCk7XG4gICAgICB0aGlzLnN5bmNocm9uaXppbmcgPSB0cnVlO1xuICAgICAgdGhpcy5lcnJvckluTGFzdFN5bmMgPSBmYWxzZTtcbiAgICAgIHRoaXMucmVxdWlyZXNNYW51YWxDb25maXJtYXRpb24gPSBmYWxzZTtcbiAgICAgIC8vIGxvYWQgdGhlIGxhc3RTeW5jQXQgaW5mb3JtYXRpb25cbiAgICAgIHRoaXMubG9hZExhc3RTeW5jQXQoKS50aGVuKFxuICAgICAgICAoKTogUHJvbWlzZTx2b2lkPiA9PlxuICAgICAgICAgIC8vIHRyeSB0byBydW4gYWxsIHRoZSBwZW5kaW5nIEFQSSByZXF1ZXN0cyBpbiB0aGUgcXVldWUsIGkuZS4gdXBsb2FkaW5nIHRoZSBvZmZsaW5lIHJlc291cmNlcyBjaGFuZ2VkXG4gICAgICAgICAgdGhpcy5ydW5RdWV1ZUFQSVJlcXVlc3RzKClcbiAgICAgICAgICAgIC50aGVuKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgLy8gc2V0IHRoaXMgbW9tZW50IGluIHRpbWU6IGlmIGFueXRoaW5nIGhhcHBlbmVkIGJlZm9yZSB0aGUgZW5kIG9mIHRoZSBzeW5jLCB3ZSBkb24ndCBsb3NlIGZyZXNoIGRhdGFcbiAgICAgICAgICAgICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgICAgICAgICAgLy8gcHJlcGFyZSBhIGZpcnN0IFwic2hvcnRcIiBEZWx0YSByZXF1ZXN0LCB0byBzZWUgaWYgdGhlcmUgaXMgYSBsb3Qgb2YgZGF0YSB0byBwcm9jZXNzXG4gICAgICAgICAgICAgIGNvbnN0IHBhcmFtczogYW55ID0geyBsaW1pdDogTlVNX0VMRU1FTlRTX1dJVEhPVVRfTUFOVUFMX1NZTkMgfTtcbiAgICAgICAgICAgICAgaWYgKHRoaXMubGFzdFN5bmNBdCkgcGFyYW1zLnNpbmNlID0gdGhpcy5sYXN0U3luY0F0O1xuICAgICAgICAgICAgICB0aGlzLl9BUElcbiAgICAgICAgICAgICAgICAuZ2V0UmVzb3VyY2UodGhpcy50ZWFtSWQgPyBgdGVhbXMvJHt0aGlzLnRlYW1JZH0vZGVsdGFgIDogJ2RlbHRhJywgeyBwYXJhbXMgfSlcbiAgICAgICAgICAgICAgICAudGhlbigoZGVsdGE6IERlbHRhKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgICAvLyBkZWNpZGUgaWYgdG8gcHJvY2VlZCB3aXRoIHRoZSBzeW5jOiBpbiBjYXNlIHRoZXJlIGlzIGFub3RoZXIgcGFnZSwgaXQgcmVxdWlyZXMgYSBtYW51YWwgY29uZmlybWF0aW9uXG4gICAgICAgICAgICAgICAgICBpZiAoZGVsdGEubmV4dCAmJiAhbWFudWFsQ29uZmlybWF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWlyZXNNYW51YWxDb25maXJtYXRpb24gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnN5bmNocm9uaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIC8vIHNhdmUgdGhlIHJlY29yZHMgaW4gdGhlIGRlbHRhIGFuZCByZXF1ZXN0IHBvc3NpYmxlIG5ldyBwYWdlc1xuICAgICAgICAgICAgICAgICAgdGhpcy5zeW5jRGVsdGFSZWNvcmRzKGRlbHRhLCAoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmVycm9ySW5MYXN0U3luYykge1xuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAvLyBhbGwgdGhlIHJlc291cmNlcyBhcmUgc3VjY2VzZnVsbHkgaW4gc3luY1xuICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzb3VyY2VzLmZvckVhY2gocmVzb3VyY2UgPT4gKHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzW3Jlc291cmNlXS5zeW5jaHJvbml6aW5nID0gZmFsc2UpKTtcbiAgICAgICAgICAgICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHRpbWVzdGFtcCBvZiBsYXN0IHN5bmNcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNhdmVMYXN0U3luY0F0KG5vdylcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBjb3VsZG4ndCBzYXZlIHRoZSBsYXN0IHN5bmMgaW5mb1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9ySW5MYXN0U3luYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIC5jYXRjaCgoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgICAvLyB3ZSBjb3VsZG4ndCBhY3F1aXJlIG5ldyBpbmZvcm1hdGlvbiAoRGVsdGEpXG4gICAgICAgICAgICAgICAgICB0aGlzLmVycm9ySW5MYXN0U3luYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICB0aGlzLnN5bmNocm9uaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgIC8vIHdlIHN0b3AsIHNpbmNlIHdlIGRvbid0IHdhbnQgYmFja2VuZCBkYXRhIHRvIG92ZXJyaWRlIGxvY2FsIGluZm8gbm90IHlldCB1cGxvYWRlZFxuICAgICAgICAgICAgICB0aGlzLmVycm9ySW5MYXN0U3luYyA9IHRydWU7XG4gICAgICAgICAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICByZWplY3QoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICApO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBGb3JjZSBhIGZ1bGwgc3luY2hyb25pc2F0aW9uLlxuICAgKi9cbiAgZm9yY2VGdWxsU3luYygpOiB2b2lkIHtcbiAgICB0aGlzLl9zdG9yYWdlLmNsZWFyKCkudGhlbigoKTogUHJvbWlzZTx2b2lkPiA9PiB0aGlzLnN5bmNocm9uaXplKHRydWUpKTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBkZXNjcmlwdGlvbiBvZiBhbiBBUEkgcmVxdWVzdCB0byBhIHJlc291cmNlLCB0byB1c2Ugd2l0aCBgSURFQUFXU0FQSWAuXG4gKiBVc2VkIGZvciBxdWV1ZXMgb2YgcmVxdWVzdHMgKFVQTE9BRCkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQVBJUmVxdWVzdCB7XG4gIC8qKlxuICAgKiBSZXNvdXJjZSBwYXRoIChlLmcuIGB1c2Vyc2Agb3IgYHRlYW1zLyR7dGVhbUlkfS91c2Vyc2ApLlxuICAgKi9cbiAgcmVzb3VyY2U6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBpZCB0byBpZGVudGlmeSBhIHNwZWNpZmljIGVsZW1lbnQgb2YgdGhlIHJlc291cmNlLlxuICAgKi9cbiAgcmVzb3VyY2VJZDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIEFQSSByZXF1ZXN0IG1ldGhvZCAoZS5nLiBQT1NULCBQVVQsIFBBVENIKS5cbiAgICovXG4gIG1ldGhvZDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGJvZHkgb2YgdGhlIHJlcXVlc3QuXG4gICAqL1xuICBib2R5OiBhbnk7XG4gIC8qKlxuICAgKiBBIGRlc2NyaXB0aW9uIHRvIHNob3cgZm9yIHRoZSByZXF1ZXN0LlxuICAgKi9cbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBJZiBub3QgbnVsbCwgdGhlIHJlcXVlc3QgdHJpZWQgdG8gcnVuIGJ1dCBpdCBlbmNvdW50ZXJlZCB0aGUgZXJyb3IuXG4gICAqL1xuICBlcnJvcj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGUgYWJzdHJhY3QgY2xhc3MgdG8gaW1wbGVtZW50IGZvciBlYWNoIHJlc291cmNlIHRvIGNhY2hlIG9mZmxpbmUgZnJvbSB0aGUgYmFjay1lbmQgKERPV05MT0FEKS5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIENhY2hlYWJsZVJlc291cmNlIHtcbiAgLyoqXG4gICAqIFRoZSB0ZWFtIG93bmluZyB0aGUgcmVzb3VyY2UuXG4gICAqIElmIG51bGwsIHRoZSBwcm9qZWN0IGlzbid0IHRlYW1zLWJhc2VkLlxuICAgKi9cbiAgdGVhbUlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgaWRlbnRpZmllciBvZiB0aGUgcmVzb3VyY2UuXG4gICAqL1xuICByZXNvdXJjZTogRGVsdGFSZXNvdXJjZXMgfCBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgcmVzb3VyY2UgZGVzY3JpcHRpb24gKHRyYW5zbGF0ZWQpIGZvciB0aGUgVUkuXG4gICAqL1xuICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICAvKipcbiAgICogUnVudGltZSBhdHRyaWJ1dGUgdG8ga25vdyBpZiB0aGUgcmVzb3VyY2UgaXMgc3luY2hyb25pemluZy5cbiAgICovXG4gIHN5bmNocm9uaXppbmc6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUcnVlIGlmIG9uZSBvZiB0aGUgZWxlbWVudHMgZmFpbGVkIHRoZSBleGVjdXRpb24uXG4gICAqL1xuICBlcnJvcjogYm9vbGVhbjtcblxuICBjb25zdHJ1Y3RvcihyZXNvdXJjZTogc3RyaW5nLCBkZXNjcmlwdGlvbjogc3RyaW5nKSB7XG4gICAgdGhpcy5yZXNvdXJjZSA9IHJlc291cmNlO1xuICAgIHRoaXMuZGVzY3JpcHRpb24gPSBkZXNjcmlwdGlvbjtcbiAgICB0aGlzLnN5bmNocm9uaXppbmcgPSBmYWxzZTtcbiAgICB0aGlzLmVycm9yID0gZmFsc2U7XG4gICAgLy8gbG9hZGVkIGF0IHJ1bnRpbWVcbiAgICB0aGlzLnRlYW1JZCA9IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogSG93IHRvIGJ1aWxkIHRoZSByZWxhdGl2ZSBVUkwgdG8gdGhlIHJlc291cmNlIChsaXN0KS5cbiAgICogRS5nLiBgdGVhbXMvJHtlbGVtZW50LnRlYW1JZH0vY3VzdG9tZXJzYCBvciBgY3VzdG9tZXJzYC5cbiAgICovXG4gIGFic3RyYWN0IGxpc3RVUkwoZWxlbWVudDogYW55KTogc3RyaW5nO1xuICAvKipcbiAgICogSG93IHRvIGJ1aWxkIHRoZSByZWxhdGl2ZSBVUkwgdG8gdGhlIHJlc291cmNlIGVsZW1lbnQgKGRldGFpbCkuXG4gICAqIEUuZy4gYHRlYW1zLyR7ZWxlbWVudC50ZWFtSWR9L2N1c3RvbWVycy8ke2VsZW1lbnQuY3VzdG9tZXJJZH1gIG9yIGBjdXN0b21lcnMvJHtlbGVtZW50LmN1c3RvbWVySWR9YC5cbiAgICovXG4gIGFic3RyYWN0IGVsZW1lbnRVUkwoZWxlbWVudDogYW55KTogc3RyaW5nO1xuICAvKipcbiAgICogSG93IHRvIHVuaXF1ZWx5IGlkZW50aWZ5IGFuIGVsZW1lbnQgaW4gdGhlIGxpc3QgKGJ5IGl0cyBpZHMpLlxuICAgKiBFLmcuIGByZXR1cm4gbGlzdC5maW5kSW5kZXgoeCA9PiB4LmN1c3RvbWVySWQgPT09IGVsZW1lbnQuY3VzdG9tZXJJZCk7YFxuICAgKi9cbiAgYWJzdHJhY3QgZmluZEluZGV4SW5MaXN0KGxpc3Q6IGFueVtdLCBlbGVtZW50OiBhbnkpOiBudW1iZXI7XG4gIC8qKlxuICAgKiBIb3cgdG8ga2VlcCB0aGUgbGlzdCBzb3J0ZWQuXG4gICAqIEUuZy4gYHJldHVybiBhLm5hbWUubG9jYWxlQ29tcGFyZShiLm5hbWUpO2BcbiAgICovXG4gIGFic3RyYWN0IHNvcnQoYTogYW55LCBiOiBhbnkpOiBudW1iZXI7XG59XG4iXX0=
|