@gnwebsoft/ui 4.0.0 → 4.0.2

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.
Files changed (56) hide show
  1. package/dist/chunk-BXF3QEBN.js +2181 -0
  2. package/dist/chunk-DS524L7W.cjs +467 -0
  3. package/dist/chunk-FYU2OIMD.js +15 -0
  4. package/dist/chunk-GHW77WIM.cjs +72 -0
  5. package/dist/chunk-GLN5JSFF.cjs +2181 -0
  6. package/dist/chunk-GVWCGJ3F.js +140 -0
  7. package/dist/chunk-LUW7V5GI.cjs +15 -0
  8. package/dist/chunk-M526GQZS.js +2490 -0
  9. package/dist/chunk-MULSVYFT.js +72 -0
  10. package/dist/chunk-MVPLBJRK.cjs +1 -1
  11. package/dist/chunk-PUQIPRL2.js +467 -0
  12. package/dist/chunk-QLQ6OH25.cjs +2490 -0
  13. package/dist/chunk-Y3QTSDLJ.cjs +140 -0
  14. package/dist/core/index.cjs +121 -0
  15. package/dist/core/index.js +121 -0
  16. package/dist/hooks/index.cjs +3 -3
  17. package/dist/hooks/index.js +1 -1
  18. package/dist/index.cjs +85 -7
  19. package/dist/index.js +147 -69
  20. package/dist/types/index.cjs +3 -3
  21. package/dist/types/index.js +1 -1
  22. package/dist/utils/index.cjs +4 -24
  23. package/dist/utils/index.js +6 -26
  24. package/dist/wrappers/index.cjs +7 -4
  25. package/dist/wrappers/index.js +21 -18
  26. package/package.json +22 -17
  27. package/dist/AsyncSelectPayload-B9-6l33R.d.cts +0 -10
  28. package/dist/AsyncSelectPayload-B9-6l33R.d.ts +0 -10
  29. package/dist/chunk-3OPVOWQK.js +0 -140
  30. package/dist/chunk-AEOF2TUF.cjs +0 -2273
  31. package/dist/chunk-ALHC7RLK.js +0 -575
  32. package/dist/chunk-BRRLB22L.js +0 -72
  33. package/dist/chunk-CHZU4PZB.js +0 -2273
  34. package/dist/chunk-EBRUE2WR.cjs +0 -493
  35. package/dist/chunk-HEHPKM4B.cjs +0 -140
  36. package/dist/chunk-K2EJ4YKO.cjs +0 -72
  37. package/dist/chunk-U6SDYCWF.js +0 -493
  38. package/dist/chunk-XY4U6A77.cjs +0 -575
  39. package/dist/components/index.cjs +0 -25
  40. package/dist/components/index.d.cts +0 -752
  41. package/dist/components/index.d.ts +0 -752
  42. package/dist/components/index.js +0 -25
  43. package/dist/enhanced-CDTkKUlj.d.ts +0 -134
  44. package/dist/enhanced-ZQoS03Cd.d.cts +0 -134
  45. package/dist/events-BcHVCLBz.d.cts +0 -77
  46. package/dist/events-BcHVCLBz.d.ts +0 -77
  47. package/dist/hooks/index.d.cts +0 -96
  48. package/dist/hooks/index.d.ts +0 -96
  49. package/dist/index.d.cts +0 -16
  50. package/dist/index.d.ts +0 -16
  51. package/dist/types/index.d.cts +0 -820
  52. package/dist/types/index.d.ts +0 -820
  53. package/dist/utils/index.d.cts +0 -683
  54. package/dist/utils/index.d.ts +0 -683
  55. package/dist/wrappers/index.d.cts +0 -1753
  56. package/dist/wrappers/index.d.ts +0 -1753
@@ -0,0 +1,2490 @@
1
+ // src/core/api/CorrelationIdGenerator.ts
2
+ function generateUUID() {
3
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
4
+ return crypto.randomUUID();
5
+ }
6
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
7
+ const r = Math.random() * 16 | 0;
8
+ const v = c === "x" ? r : r & 3 | 8;
9
+ return v.toString(16);
10
+ });
11
+ }
12
+ function generateCorrelationId(prefix) {
13
+ const uuid = generateUUID();
14
+ return prefix ? `${prefix}-${uuid}` : uuid;
15
+ }
16
+
17
+ // src/core/api/Errors/ErrorNormalizer.ts
18
+ var ErrorNormalizer = class {
19
+ /**
20
+ * Maps an HTTP status code to a standardized error type category.
21
+ *
22
+ * This categorization helps consumers handle different error classes appropriately:
23
+ * - `validation_error` (400): Client sent invalid data
24
+ * - `client_error` (401-499): Client-side issues (auth, permissions, not found, etc.)
25
+ * - `server_error` (500-599): Server-side failures
26
+ * - `unknown_error`: Unrecognized status codes
27
+ *
28
+ * @param status - HTTP status code from the response
29
+ * @returns The error type category as a string
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * normalizer.getErrorType(400); // => 'validation_error'
34
+ * normalizer.getErrorType(404); // => 'client_error'
35
+ * normalizer.getErrorType(500); // => 'server_error'
36
+ * normalizer.getErrorType(0); // => 'unknown_error'
37
+ * ```
38
+ */
39
+ getErrorType(status) {
40
+ if (status >= 400 && status < 500) {
41
+ return status === 400 ? "validation_error" : "client_error";
42
+ } else if (status >= 500) {
43
+ return "server_error";
44
+ }
45
+ return "unknown_error";
46
+ }
47
+ /**
48
+ * Maps an HTTP status code to a human-readable error title.
49
+ *
50
+ * Provides user-friendly error messages for common HTTP status codes.
51
+ * Falls back to a generic "HTTP Error {status}" format for unmapped codes.
52
+ *
53
+ * @param status - HTTP status code from the response
54
+ * @returns A human-readable error title
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * normalizer.getErrorTitle(404); // => 'Not Found'
59
+ * normalizer.getErrorTitle(500); // => 'Internal Server Error'
60
+ * normalizer.getErrorTitle(999); // => 'HTTP Error 999'
61
+ * ```
62
+ */
63
+ getErrorTitle(status) {
64
+ const titles = {
65
+ 400: "Bad Request",
66
+ 401: "Unauthorized",
67
+ 403: "Forbidden",
68
+ 404: "Not Found",
69
+ 405: "Method Not Allowed",
70
+ 408: "Request Timeout",
71
+ 409: "Conflict",
72
+ 422: "Unprocessable Entity",
73
+ 429: "Too Many Requests",
74
+ 500: "Internal Server Error",
75
+ 502: "Bad Gateway",
76
+ 503: "Service Unavailable",
77
+ 504: "Gateway Timeout"
78
+ };
79
+ return titles[status] || `HTTP Error ${status}`;
80
+ }
81
+ /**
82
+ * Normalizes any error into a consistent, structured ApiError format.
83
+ *
84
+ * This method handles various error scenarios and ensures they all conform to
85
+ * the {@link ApiError} interface with appropriate categorization and metadata:
86
+ *
87
+ * - **Existing ApiErrors**: Enhances with missing fields (traceId, config)
88
+ * - **AbortErrors**: Marks as `request_cancelled` with isAborted flag
89
+ * - **Timeout Errors**: Categorizes as `timeout_error` with 408 status
90
+ * - **Network Errors**: Categorizes as `network_error` with 0 status
91
+ * - **Unknown Errors**: Fallback category for unexpected error types
92
+ *
93
+ * All normalized errors include:
94
+ * - `type`: Error category for programmatic handling
95
+ * - `title`: Human-readable error title
96
+ * - `status`: HTTP status code (or 0 for non-HTTP errors)
97
+ * - `traceId`: Correlation ID for distributed tracing
98
+ * - `isAborted`: Boolean flag indicating if request was cancelled
99
+ * - `config`: Original request configuration for debugging
100
+ *
101
+ * @param error - The error to normalize (can be any type)
102
+ * @param config - The request configuration that led to this error
103
+ * @param correlationId - Optional correlation ID for tracing
104
+ * @returns A fully structured ApiError instance
105
+ *
106
+ * @example
107
+ * Normalizing a fetch AbortError:
108
+ * ```typescript
109
+ * try {
110
+ * await fetch(url, { signal });
111
+ * } catch (error) {
112
+ * const apiError = normalizer.normalizeError(error, config, 'req-123');
113
+ * // apiError.type === 'request_cancelled'
114
+ * // apiError.isAborted === true
115
+ * }
116
+ * ```
117
+ *
118
+ * @example
119
+ * Normalizing a timeout:
120
+ * ```typescript
121
+ * const timeoutError = new Error('Request timeout after 30000ms');
122
+ * const apiError = normalizer.normalizeError(timeoutError, config);
123
+ * // apiError.type === 'timeout_error'
124
+ * // apiError.status === 408
125
+ * ```
126
+ */
127
+ normalizeError(error, config, correlationId) {
128
+ const err = error;
129
+ if (err.type || err.title || err.errors) {
130
+ return Object.assign(
131
+ err instanceof Error ? err : new Error(err.message || "Unknown error"),
132
+ {
133
+ type: err.type,
134
+ title: err.title,
135
+ status: err.status,
136
+ traceId: err.traceId || correlationId,
137
+ errors: err.errors,
138
+ isAborted: err.isAborted || false,
139
+ config
140
+ }
141
+ );
142
+ }
143
+ if (err.name === "AbortError" || err.isAborted) {
144
+ return Object.assign(new Error(err.message || "Request was aborted"), {
145
+ type: "request_cancelled",
146
+ title: "Request was cancelled",
147
+ status: 0,
148
+ traceId: correlationId,
149
+ isAborted: true,
150
+ config
151
+ });
152
+ }
153
+ if (err.message?.includes("timeout")) {
154
+ return Object.assign(new Error(err.message), {
155
+ type: "timeout_error",
156
+ title: "Request Timeout",
157
+ status: 408,
158
+ traceId: correlationId,
159
+ isAborted: true,
160
+ config
161
+ });
162
+ }
163
+ if (err.message?.includes("network")) {
164
+ return Object.assign(new Error(err.message || "Network request failed"), {
165
+ type: "network_error",
166
+ title: "Network Error",
167
+ status: 0,
168
+ traceId: correlationId,
169
+ isAborted: false,
170
+ config
171
+ });
172
+ }
173
+ return Object.assign(
174
+ new Error(err.message || "An unknown error occurred"),
175
+ {
176
+ type: "unknown_error",
177
+ title: "Unknown Error",
178
+ status: 0,
179
+ traceId: correlationId,
180
+ isAborted: false,
181
+ config
182
+ }
183
+ );
184
+ }
185
+ };
186
+
187
+ // src/core/api/Interceptors/InterceptorManager.ts
188
+ var InterceptorManager = class {
189
+ /**
190
+ * Array of registered request interceptors
191
+ * @private
192
+ */
193
+ requestInterceptors = [];
194
+ /**
195
+ * Array of registered response interceptors
196
+ * @private
197
+ */
198
+ responseInterceptors = [];
199
+ /**
200
+ * Array of registered error interceptors
201
+ * @private
202
+ */
203
+ errorInterceptors = [];
204
+ /**
205
+ * Registers a request interceptor to modify requests before they are sent.
206
+ *
207
+ * Request interceptors can:
208
+ * - Add or modify headers
209
+ * - Transform request bodies
210
+ * - Add query parameters
211
+ * - Implement request signing
212
+ * - Log outgoing requests
213
+ *
214
+ * @param interceptor - Async function that receives and returns RequestConfig
215
+ * @returns Cleanup function to unregister this interceptor
216
+ *
217
+ * @example
218
+ * ```typescript
219
+ * // Add authentication header
220
+ * const unregister = manager.addRequestInterceptor(async (config) => {
221
+ * const token = await getAuthToken();
222
+ * config.headers = config.headers || new Headers();
223
+ * config.headers.set('Authorization', `Bearer ${token}`);
224
+ * return config;
225
+ * });
226
+ *
227
+ * // Later, remove the interceptor
228
+ * unregister();
229
+ * ```
230
+ */
231
+ addRequestInterceptor(interceptor) {
232
+ this.requestInterceptors.push(interceptor);
233
+ return () => {
234
+ const index = this.requestInterceptors.indexOf(interceptor);
235
+ if (index > -1) this.requestInterceptors.splice(index, 1);
236
+ };
237
+ }
238
+ /**
239
+ * Registers a response interceptor to transform responses before they are returned.
240
+ *
241
+ * Response interceptors can:
242
+ * - Transform response data format
243
+ * - Extract nested data structures
244
+ * - Add computed properties
245
+ * - Cache responses
246
+ * - Log successful responses
247
+ *
248
+ * @param interceptor - Async function that receives and returns ApiResponse
249
+ * @returns Cleanup function to unregister this interceptor
250
+ *
251
+ * @example
252
+ * ```typescript
253
+ * // Extract data from envelope
254
+ * manager.addResponseInterceptor(async (response) => {
255
+ * if (response.data?.result) {
256
+ * response.data = response.data.result;
257
+ * }
258
+ * return response;
259
+ * });
260
+ *
261
+ * // Add timestamps
262
+ * manager.addResponseInterceptor(async (response) => {
263
+ * return {
264
+ * ...response,
265
+ * receivedAt: new Date().toISOString()
266
+ * };
267
+ * });
268
+ * ```
269
+ */
270
+ addResponseInterceptor(interceptor) {
271
+ this.responseInterceptors.push(interceptor);
272
+ return () => {
273
+ const index = this.responseInterceptors.indexOf(interceptor);
274
+ if (index > -1) this.responseInterceptors.splice(index, 1);
275
+ };
276
+ }
277
+ /**
278
+ * Registers an error interceptor to handle or transform errors before they are thrown.
279
+ *
280
+ * Error interceptors can:
281
+ * - Log errors to monitoring services
282
+ * - Transform error formats
283
+ * - Implement retry logic
284
+ * - Show user notifications
285
+ * - Extract validation errors
286
+ *
287
+ * **Note:** Error interceptors should re-throw the error (or a transformed version)
288
+ * to maintain the error flow. The final error is always thrown.
289
+ *
290
+ * @param interceptor - Async function that receives and returns (or throws) ApiError
291
+ * @returns Cleanup function to unregister this interceptor
292
+ *
293
+ * @example
294
+ * ```typescript
295
+ * // Log to monitoring service
296
+ * manager.addErrorInterceptor(async (error) => {
297
+ * if (error.status >= 500) {
298
+ * await Sentry.captureException(error, {
299
+ * extra: { traceId: error.traceId }
300
+ * });
301
+ * }
302
+ * throw error; // Re-throw to continue error flow
303
+ * });
304
+ *
305
+ * // Transform error messages
306
+ * manager.addErrorInterceptor(async (error) => {
307
+ * if (error.status === 404) {
308
+ * error.title = 'Resource not found';
309
+ * }
310
+ * throw error;
311
+ * });
312
+ * ```
313
+ */
314
+ addErrorInterceptor(interceptor) {
315
+ this.errorInterceptors.push(interceptor);
316
+ return () => {
317
+ const index = this.errorInterceptors.indexOf(interceptor);
318
+ if (index > -1) this.errorInterceptors.splice(index, 1);
319
+ };
320
+ }
321
+ /**
322
+ * Applies all registered request interceptors in sequential order.
323
+ *
324
+ * Each interceptor receives the config modified by the previous interceptor,
325
+ * forming a processing pipeline. If any interceptor throws an error,
326
+ * the pipeline stops and the error propagates.
327
+ *
328
+ * @param config - The initial request configuration
329
+ * @returns The modified request configuration after all interceptors
330
+ *
331
+ * @example
332
+ * ```typescript
333
+ * const config = { method: 'GET', url: '/users' };
334
+ * const finalConfig = await manager.applyRequestInterceptors(config);
335
+ * // finalConfig has been processed by all registered interceptors
336
+ * ```
337
+ */
338
+ async applyRequestInterceptors(config) {
339
+ let modifiedConfig = { ...config };
340
+ for (const interceptor of this.requestInterceptors) {
341
+ modifiedConfig = await interceptor(modifiedConfig);
342
+ }
343
+ return modifiedConfig;
344
+ }
345
+ /**
346
+ * Applies all registered response interceptors in sequential order.
347
+ *
348
+ * Each interceptor receives the response modified by the previous interceptor,
349
+ * forming a processing pipeline. If any interceptor throws an error,
350
+ * the pipeline stops and the error propagates.
351
+ *
352
+ * @template T - The type of the response data
353
+ * @param response - The initial API response
354
+ * @returns The modified response after all interceptors
355
+ *
356
+ * @example
357
+ * ```typescript
358
+ * const response = { data: { id: 1, name: 'John' } };
359
+ * const finalResponse = await manager.applyResponseInterceptors(response);
360
+ * // finalResponse has been processed by all registered interceptors
361
+ * ```
362
+ */
363
+ async applyResponseInterceptors(response) {
364
+ let modifiedResponse = response;
365
+ for (const interceptor of this.responseInterceptors) {
366
+ modifiedResponse = await interceptor(modifiedResponse);
367
+ }
368
+ return modifiedResponse;
369
+ }
370
+ /**
371
+ * Applies all registered error interceptors in sequential order and re-throws.
372
+ *
373
+ * Each interceptor receives the error (potentially modified by previous interceptors).
374
+ * Interceptors can transform the error before re-throwing it. The final error
375
+ * is always thrown to maintain error flow.
376
+ *
377
+ * If an interceptor itself throws an error, that becomes the new error to process
378
+ * by subsequent interceptors.
379
+ *
380
+ * @param error - The initial API error
381
+ * @returns Never returns (always throws)
382
+ * @throws The final error after all interceptors have processed it
383
+ *
384
+ * @example
385
+ * ```typescript
386
+ * try {
387
+ * await manager.applyErrorInterceptors(error);
388
+ * } catch (finalError) {
389
+ * // finalError has been processed by all registered error interceptors
390
+ * }
391
+ * ```
392
+ */
393
+ async applyErrorInterceptors(error) {
394
+ let modifiedError = error;
395
+ for (const interceptor of this.errorInterceptors) {
396
+ try {
397
+ modifiedError = await interceptor(modifiedError);
398
+ } catch (e) {
399
+ modifiedError = e;
400
+ }
401
+ }
402
+ throw modifiedError;
403
+ }
404
+ };
405
+
406
+ // src/core/api/RequestManager.ts
407
+ var RequestManager = class {
408
+ /**
409
+ * Map of active request keys to their abort controllers
410
+ * @private
411
+ */
412
+ activeRequests = /* @__PURE__ */ new Map();
413
+ /**
414
+ * Map of request keys to their correlation IDs for tracing
415
+ * @private
416
+ */
417
+ correlationMap = /* @__PURE__ */ new Map();
418
+ /**
419
+ * Registers a new request for tracking and cancellation management.
420
+ *
421
+ * If a request with the same key already exists, it will be automatically
422
+ * cancelled before the new one is registered (request deduplication).
423
+ *
424
+ * @param key - Unique identifier for the request (typically method + URL + timestamp)
425
+ * @param controller - AbortController for cancelling the request
426
+ * @param correlationId - Correlation ID for distributed tracing
427
+ *
428
+ * @example
429
+ * ```typescript
430
+ * const controller = new AbortController();
431
+ * manager.add('GET_/api/users_1699999999', controller, 'api-abc123');
432
+ * ```
433
+ */
434
+ add(key, controller, correlationId) {
435
+ this.cancel(key);
436
+ this.activeRequests.set(key, controller);
437
+ this.correlationMap.set(key, correlationId);
438
+ }
439
+ /**
440
+ * Removes a request from tracking without cancelling it.
441
+ *
442
+ * This is typically called when a request completes successfully or fails.
443
+ * Use {@link cancel} instead if you need to abort the request.
444
+ *
445
+ * @param key - Unique identifier for the request to remove
446
+ *
447
+ * @example
448
+ * ```typescript
449
+ * // Called automatically after request completes
450
+ * manager.remove('GET_/api/users_1699999999');
451
+ * ```
452
+ */
453
+ remove(key) {
454
+ this.activeRequests.delete(key);
455
+ this.correlationMap.delete(key);
456
+ }
457
+ /**
458
+ * Cancels a specific request and removes it from tracking.
459
+ *
460
+ * If the request doesn't exist or was already cancelled, this operation is a no-op.
461
+ * The associated AbortController's signal will be triggered, causing any active
462
+ * fetch operations to abort.
463
+ *
464
+ * @param key - Unique identifier for the request to cancel
465
+ *
466
+ * @example
467
+ * ```typescript
468
+ * // User navigates away, cancel the pending request
469
+ * manager.cancel('GET_/api/users_1699999999');
470
+ * ```
471
+ */
472
+ cancel(key) {
473
+ const controller = this.activeRequests.get(key);
474
+ if (controller) {
475
+ controller.abort();
476
+ this.activeRequests.delete(key);
477
+ this.correlationMap.delete(key);
478
+ }
479
+ }
480
+ /**
481
+ * Cancels all active requests and clears all tracking data.
482
+ *
483
+ * This is useful for cleanup scenarios such as:
484
+ * - User logout
485
+ * - Component unmount
486
+ * - Navigation to a different part of the application
487
+ * - Error recovery that requires a clean slate
488
+ *
489
+ * @example
490
+ * ```typescript
491
+ * // Cancel all pending requests on logout
492
+ * function handleLogout() {
493
+ * apiClient.cancelAllRequests();
494
+ * // ... rest of logout logic
495
+ * }
496
+ * ```
497
+ */
498
+ cancelAll() {
499
+ this.activeRequests.forEach((controller) => controller.abort());
500
+ this.activeRequests.clear();
501
+ this.correlationMap.clear();
502
+ }
503
+ /**
504
+ * Checks if a request with the given key is currently being tracked.
505
+ *
506
+ * @param key - Unique identifier for the request
507
+ * @returns `true` if the request is active, `false` otherwise
508
+ *
509
+ * @example
510
+ * ```typescript
511
+ * if (manager.has('GET_/api/users_1699999999')) {
512
+ * console.log('Request is still pending');
513
+ * }
514
+ * ```
515
+ */
516
+ has(key) {
517
+ return this.activeRequests.has(key);
518
+ }
519
+ /**
520
+ * Retrieves the correlation ID for a given request key.
521
+ *
522
+ * Correlation IDs are used for distributed tracing and request tracking
523
+ * across services and logs.
524
+ *
525
+ * @param key - Unique identifier for the request
526
+ * @returns The correlation ID if found, `undefined` otherwise
527
+ *
528
+ * @example
529
+ * ```typescript
530
+ * const correlationId = manager.getCorrelationId('GET_/api/users_1699999999');
531
+ * if (correlationId) {
532
+ * console.log('Trace request with ID:', correlationId);
533
+ * }
534
+ * ```
535
+ */
536
+ getCorrelationId(key) {
537
+ return this.correlationMap.get(key);
538
+ }
539
+ };
540
+
541
+ // src/core/api/Retry/RetryHandler.ts
542
+ var RetryHandler = class {
543
+ /**
544
+ * Retries a failed request with exponential backoff strategy.
545
+ *
546
+ * The retry logic works as follows:
547
+ * 1. Attempts the request immediately
548
+ * 2. On failure, checks if the error is retryable
549
+ * 3. If retryable and retries remain, waits for the current delay
550
+ * 4. Doubles the delay for the next attempt
551
+ * 5. Repeats until success or retries exhausted
552
+ *
553
+ * **Non-Retryable Errors:**
554
+ * - Validation errors (400) - Client sent bad data
555
+ * - AbortErrors - Request was explicitly cancelled
556
+ * - Requests with aborted signals
557
+ *
558
+ * **Abort Handling:**
559
+ * If the signal is aborted during a retry delay, the retry is immediately
560
+ * cancelled and an AbortError is thrown.
561
+ *
562
+ * @template T - The return type of the function being retried
563
+ * @param fn - Async function to retry on failure
564
+ * @param retries - Number of retry attempts remaining (decrements each retry)
565
+ * @param delay - Current delay in milliseconds before next retry
566
+ * @param signal - Optional AbortSignal to cancel retries
567
+ * @returns Promise resolving to the function's result on success
568
+ * @throws The last error encountered if all retries are exhausted
569
+ * @throws AbortError if the signal is aborted during execution or delay
570
+ *
571
+ * @example
572
+ * Basic retry usage:
573
+ * ```typescript
574
+ * const handler = new RetryHandler();
575
+ * const fetchUser = () => fetch('/api/users/123').then(r => r.json());
576
+ *
577
+ * try {
578
+ * const user = await handler.retryRequest(
579
+ * fetchUser,
580
+ * 3, // 3 retries
581
+ * 1000 // Start with 1s delay
582
+ * );
583
+ * console.log('User:', user);
584
+ * } catch (error) {
585
+ * console.error('Failed after all retries:', error);
586
+ * }
587
+ * ```
588
+ *
589
+ * @example
590
+ * With cancellation support:
591
+ * ```typescript
592
+ * const controller = new AbortController();
593
+ * const signal = controller.signal;
594
+ *
595
+ * // Cancel after 5 seconds
596
+ * setTimeout(() => controller.abort(), 5000);
597
+ *
598
+ * try {
599
+ * await handler.retryRequest(fetchUser, 5, 1000, signal);
600
+ * } catch (error) {
601
+ * if (error.name === 'AbortError') {
602
+ * console.log('Retry cancelled');
603
+ * }
604
+ * }
605
+ * ```
606
+ */
607
+ async retryRequest(fn, retries, delay, signal) {
608
+ try {
609
+ if (signal?.aborted) {
610
+ throw new Error(signal.reason || "Request aborted");
611
+ }
612
+ return await fn();
613
+ } catch (error) {
614
+ const err = error;
615
+ if (err.name === "AbortError" || signal?.aborted) {
616
+ throw error;
617
+ }
618
+ if (err.type === "validation_error" || err.status === 400) {
619
+ throw error;
620
+ }
621
+ if (retries === 0) throw error;
622
+ await new Promise((resolve, reject) => {
623
+ const timeoutId = setTimeout(resolve, delay);
624
+ if (signal) {
625
+ signal.addEventListener(
626
+ "abort",
627
+ () => {
628
+ clearTimeout(timeoutId);
629
+ reject(new Error(signal.reason || "Request aborted"));
630
+ },
631
+ { once: true }
632
+ );
633
+ }
634
+ });
635
+ return this.retryRequest(fn, retries - 1, delay * 2, signal);
636
+ }
637
+ }
638
+ };
639
+
640
+ // src/core/api/Signals/SignalManager.ts
641
+ var SignalManager = class {
642
+ /**
643
+ * Creates a combined AbortController that aborts when any source signal aborts.
644
+ *
645
+ * This method implements the "any" pattern for cancellation: the combined signal
646
+ * will abort as soon as ANY of the source signals abort. This is useful for
647
+ * coordinating multiple cancellation conditions:
648
+ * - User clicks cancel button
649
+ * - Request timeout expires
650
+ * - Component unmounts
651
+ * - Parent request is cancelled
652
+ *
653
+ * **Early Abort Optimization:**
654
+ * If any source signal is already aborted when this method is called,
655
+ * the returned controller is immediately aborted without setting up listeners.
656
+ *
657
+ * **Memory Management:**
658
+ * Event listeners are registered with `{ once: true }` to prevent memory leaks,
659
+ * as they automatically clean up after firing.
660
+ *
661
+ * @param signals - Array of AbortSignals to combine (undefined values are ignored)
662
+ * @returns A new AbortController that aborts when any source signal aborts
663
+ *
664
+ * @example
665
+ * User cancellation + timeout:
666
+ * ```typescript
667
+ * const userController = new AbortController();
668
+ * const timeout = manager.createTimeoutSignal(30000);
669
+ *
670
+ * const combined = manager.createCombinedSignal([
671
+ * userController.signal,
672
+ * timeout.signal
673
+ * ]);
674
+ *
675
+ * // Request will be cancelled after 30s OR when user clicks cancel
676
+ * fetch('/api/data', { signal: combined.signal });
677
+ * ```
678
+ *
679
+ * @example
680
+ * React component with cleanup:
681
+ * ```typescript
682
+ * useEffect(() => {
683
+ * const controller = new AbortController();
684
+ *
685
+ * const combined = manager.createCombinedSignal([
686
+ * controller.signal,
687
+ * unmountSignal // From component lifecycle
688
+ * ]);
689
+ *
690
+ * fetchData(combined.signal);
691
+ *
692
+ * return () => controller.abort(); // Cleanup
693
+ * }, []);
694
+ * ```
695
+ */
696
+ createCombinedSignal(signals) {
697
+ const controller = new AbortController();
698
+ for (const signal of signals) {
699
+ if (signal) {
700
+ if (signal.aborted) {
701
+ controller.abort(signal.reason);
702
+ break;
703
+ }
704
+ signal.addEventListener(
705
+ "abort",
706
+ () => {
707
+ controller.abort(signal.reason);
708
+ },
709
+ { once: true }
710
+ );
711
+ }
712
+ }
713
+ return controller;
714
+ }
715
+ /**
716
+ * Creates an AbortController that automatically aborts after a specified timeout.
717
+ *
718
+ * This method creates a time-based cancellation mechanism useful for implementing
719
+ * request timeouts and deadlines. The signal will automatically abort after the
720
+ * specified duration, providing a consistent timeout experience.
721
+ *
722
+ * **Automatic Cleanup:**
723
+ * If the signal is aborted by other means before the timeout expires, the internal
724
+ * setTimeout is automatically cleared to prevent memory leaks.
725
+ *
726
+ * **Abort Reason:**
727
+ * The abort reason includes the timeout duration for debugging purposes:
728
+ * `"Request timeout after {timeout}ms"`
729
+ *
730
+ * @param timeout - Timeout duration in milliseconds
731
+ * @returns An AbortController that will abort after the timeout
732
+ *
733
+ * @example
734
+ * Simple request timeout:
735
+ * ```typescript
736
+ * const manager = new SignalManager();
737
+ * const timeout = manager.createTimeoutSignal(5000); // 5 seconds
738
+ *
739
+ * try {
740
+ * const response = await fetch('/api/slow-endpoint', {
741
+ * signal: timeout.signal
742
+ * });
743
+ * const data = await response.json();
744
+ * } catch (error) {
745
+ * if (error.name === 'AbortError') {
746
+ * console.error('Request timed out after 5 seconds');
747
+ * }
748
+ * }
749
+ * ```
750
+ *
751
+ * @example
752
+ * Different timeouts for different operations:
753
+ * ```typescript
754
+ * // Short timeout for quick operations
755
+ * const quickTimeout = manager.createTimeoutSignal(2000);
756
+ * await fetch('/api/health', { signal: quickTimeout.signal });
757
+ *
758
+ * // Long timeout for heavy operations
759
+ * const longTimeout = manager.createTimeoutSignal(60000);
760
+ * await fetch('/api/export', { signal: longTimeout.signal });
761
+ * ```
762
+ *
763
+ * @example
764
+ * Manual cancellation before timeout:
765
+ * ```typescript
766
+ * const timeout = manager.createTimeoutSignal(30000);
767
+ *
768
+ * // If user cancels, timeout is automatically cleaned up
769
+ * timeout.abort('User cancelled');
770
+ * // Internal setTimeout is cleared, no memory leak
771
+ * ```
772
+ */
773
+ createTimeoutSignal(timeout) {
774
+ const controller = new AbortController();
775
+ const timeoutId = setTimeout(() => {
776
+ controller.abort(`Request timeout after ${timeout}ms`);
777
+ }, timeout);
778
+ controller.signal.addEventListener(
779
+ "abort",
780
+ () => {
781
+ clearTimeout(timeoutId);
782
+ },
783
+ { once: true }
784
+ );
785
+ return controller;
786
+ }
787
+ };
788
+
789
+ // src/core/api/Utils/ResponseParser.ts
790
+ var ResponseParser = class {
791
+ /**
792
+ * Parses the HTTP response body into an appropriate JavaScript type.
793
+ *
794
+ * The parsing strategy is determined by the Content-Type header:
795
+ * 1. **JSON** (application/json): Calls `response.json()`
796
+ * 2. **Text** (text/*): Calls `response.text()`
797
+ * 3. **Binary** (application/octet-stream): Calls `response.blob()`
798
+ * 4. **Unknown**: Reads as text, attempts JSON parse, falls back to raw text
799
+ *
800
+ * **Fallback Behavior:**
801
+ * For responses without a Content-Type header or with unknown types, the parser
802
+ * attempts to parse as JSON first (common for APIs that don't set proper headers).
803
+ * If JSON parsing fails, it returns the raw text.
804
+ *
805
+ * @param response - The Fetch API Response object to parse
806
+ * @returns Promise resolving to the parsed response data
807
+ * @returns Can be: JSON object/array, string, or Blob depending on Content-Type
808
+ *
809
+ * @example
810
+ * API response parsing:
811
+ * ```typescript
812
+ * const response = await fetch('/api/users');
813
+ * const data = await parser.parseResponse(response);
814
+ *
815
+ * if (typeof data === 'string') {
816
+ * console.log('Text response:', data);
817
+ * } else if (data instanceof Blob) {
818
+ * console.log('Binary response:', data.size, 'bytes');
819
+ * } else {
820
+ * console.log('JSON response:', data);
821
+ * }
822
+ * ```
823
+ *
824
+ * @example
825
+ * Handling different content types:
826
+ * ```typescript
827
+ * // CSV file download
828
+ * const csvResponse = await fetch('/api/export.csv');
829
+ * const blob = await parser.parseResponse(csvResponse);
830
+ * // Returns Blob for download
831
+ *
832
+ * // JSON API
833
+ * const jsonResponse = await fetch('/api/users');
834
+ * const users = await parser.parseResponse(jsonResponse);
835
+ * // Returns parsed JSON array
836
+ *
837
+ * // Plain text logs
838
+ * const logResponse = await fetch('/api/logs');
839
+ * const logs = await parser.parseResponse(logResponse);
840
+ * // Returns string
841
+ * ```
842
+ */
843
+ async parseResponse(response) {
844
+ const contentType = response.headers.get("content-type");
845
+ if (contentType?.includes("application/json")) {
846
+ return response.json();
847
+ } else if (contentType?.includes("text/")) {
848
+ return response.text();
849
+ } else if (contentType?.includes("application/octet-stream")) {
850
+ return response.blob();
851
+ } else {
852
+ const text = await response.text();
853
+ try {
854
+ return JSON.parse(text);
855
+ } catch {
856
+ return text;
857
+ }
858
+ }
859
+ }
860
+ };
861
+
862
+ // src/core/api/Utils/UrlBuilder.ts
863
+ var UrlBuilder = class {
864
+ /**
865
+ * Builds a complete URL by combining base URL, endpoint, and query parameters.
866
+ *
867
+ * The URL construction process:
868
+ * 1. Combines `baseURL` and `endpoint` using URL API
869
+ * 2. Iterates through query parameters
870
+ * 3. Skips null/undefined values
871
+ * 4. Handles arrays by appending multiple values with same key
872
+ * 5. Converts all values to strings
873
+ * 6. Returns fully-qualified URL string
874
+ *
875
+ * **Path Handling:**
876
+ * The endpoint can be either relative or absolute:
877
+ * - Relative: `/users` → Combined with baseURL
878
+ * - Absolute: `https://other-api.com/users` → Uses absolute URL
879
+ *
880
+ * **Encoding:**
881
+ * All parameter values are automatically URL-encoded by the URL API,
882
+ * so special characters (spaces, &, =, etc.) are safely handled.
883
+ *
884
+ * @param baseURL - Base URL for the API (e.g., 'https://api.example.com')
885
+ * @param endpoint - API endpoint path relative to baseURL (e.g., '/users/123')
886
+ * @param params - Optional query parameters as key-value pairs
887
+ * @returns The fully-qualified URL string with encoded query parameters
888
+ *
889
+ * @example
890
+ * Basic URL construction:
891
+ * ```typescript
892
+ * const url = builder.buildURL(
893
+ * 'https://api.example.com',
894
+ * '/search',
895
+ * { q: 'hello world', limit: 10 }
896
+ * );
897
+ * // => "https://api.example.com/search?q=hello+world&limit=10"
898
+ * ```
899
+ *
900
+ * @example
901
+ * Array parameters:
902
+ * ```typescript
903
+ * const url = builder.buildURL(
904
+ * 'https://api.example.com',
905
+ * '/posts',
906
+ * { tags: ['javascript', 'typescript', 'react'] }
907
+ * );
908
+ * // => "https://api.example.com/posts?tags=javascript&tags=typescript&tags=react"
909
+ * ```
910
+ *
911
+ * @example
912
+ * Null/undefined handling:
913
+ * ```typescript
914
+ * const url = builder.buildURL(
915
+ * 'https://api.example.com',
916
+ * '/users',
917
+ * {
918
+ * name: 'John',
919
+ * age: null, // Skipped
920
+ * email: undefined // Skipped
921
+ * }
922
+ * );
923
+ * // => "https://api.example.com/users?name=John"
924
+ * ```
925
+ *
926
+ * @example
927
+ * Special characters encoding:
928
+ * ```typescript
929
+ * const url = builder.buildURL(
930
+ * 'https://api.example.com',
931
+ * '/search',
932
+ * { q: 'foo & bar', category: 'code/examples' }
933
+ * );
934
+ * // => "https://api.example.com/search?q=foo+%26+bar&category=code%2Fexamples"
935
+ * ```
936
+ */
937
+ buildURL(baseURL, endpoint, params) {
938
+ const url = new URL(endpoint, baseURL);
939
+ if (params) {
940
+ Object.keys(params).forEach((key) => {
941
+ const value = params[key];
942
+ if (value !== void 0 && value !== null) {
943
+ if (Array.isArray(value)) {
944
+ value.forEach((v) => url.searchParams.append(key, String(v)));
945
+ } else {
946
+ url.searchParams.append(key, String(value));
947
+ }
948
+ }
949
+ });
950
+ }
951
+ return url.toString();
952
+ }
953
+ };
954
+
955
+ // src/core/api/ApiClient.ts
956
+ var ApiClient = class {
957
+ baseURL;
958
+ defaultTimeout;
959
+ interceptorManager = new InterceptorManager();
960
+ signalManager = new SignalManager();
961
+ errorNormalizer = new ErrorNormalizer();
962
+ responseParser = new ResponseParser();
963
+ urlBuilder = new UrlBuilder();
964
+ retryHandler = new RetryHandler();
965
+ requestManager = new RequestManager();
966
+ authToken = null;
967
+ refreshTokenPromise = null;
968
+ correlationIdPrefix = "api";
969
+ includeCorrelationId = true;
970
+ /**
971
+ * Creates a new API client instance
972
+ * @param baseURL - Base URL for all API requests (default: empty string for relative URLs)
973
+ * @param defaultTimeout - Default request timeout in milliseconds (default: 30000)
974
+ */
975
+ constructor(baseURL = "", defaultTimeout = 3e4) {
976
+ this.baseURL = baseURL;
977
+ this.defaultTimeout = defaultTimeout;
978
+ }
979
+ /**
980
+ * Sets the prefix for auto-generated correlation IDs
981
+ * @param prefix - The prefix to use for correlation IDs (e.g., 'api', 'web', 'mobile')
982
+ */
983
+ setCorrelationIdPrefix(prefix) {
984
+ this.correlationIdPrefix = prefix;
985
+ }
986
+ /**
987
+ * Enables or disables automatic correlation ID generation
988
+ * @param include - Whether to include correlation IDs in requests
989
+ */
990
+ setIncludeCorrelationId(include) {
991
+ this.includeCorrelationId = include;
992
+ }
993
+ /**
994
+ * Registers a request interceptor to modify requests before they're sent
995
+ * @param interceptor - Function to intercept and potentially modify request config
996
+ * @returns Function to unregister this interceptor
997
+ *
998
+ * @example
999
+ * ```typescript
1000
+ * const unregister = client.addRequestInterceptor(async (config) => {
1001
+ * config.headers = config.headers || new Headers();
1002
+ * config.headers.set('X-Client-Version', '1.0.0');
1003
+ * return config;
1004
+ * });
1005
+ *
1006
+ * // Later, to remove the interceptor:
1007
+ * unregister();
1008
+ * ```
1009
+ */
1010
+ addRequestInterceptor(interceptor) {
1011
+ return this.interceptorManager.addRequestInterceptor(interceptor);
1012
+ }
1013
+ /**
1014
+ * Registers a response interceptor to modify responses before they're returned
1015
+ * @param interceptor - Function to intercept and potentially modify responses
1016
+ * @returns Function to unregister this interceptor
1017
+ *
1018
+ * @example
1019
+ * ```typescript
1020
+ * client.addResponseInterceptor(async (response) => {
1021
+ * // Transform data format
1022
+ * if (response.data) {
1023
+ * response.data = camelCaseKeys(response.data);
1024
+ * }
1025
+ * return response;
1026
+ * });
1027
+ * ```
1028
+ */
1029
+ addResponseInterceptor(interceptor) {
1030
+ return this.interceptorManager.addResponseInterceptor(interceptor);
1031
+ }
1032
+ /**
1033
+ * Registers an error interceptor to handle or transform errors
1034
+ * @param interceptor - Function to intercept and potentially modify errors
1035
+ * @returns Function to unregister this interceptor
1036
+ *
1037
+ * @example
1038
+ * ```typescript
1039
+ * client.addErrorInterceptor(async (error) => {
1040
+ * // Log errors to monitoring service
1041
+ * if (error.status >= 500) {
1042
+ * await monitoringService.logError(error);
1043
+ * }
1044
+ * return error; // Re-throw the error
1045
+ * });
1046
+ * ```
1047
+ */
1048
+ addErrorInterceptor(interceptor) {
1049
+ return this.interceptorManager.addErrorInterceptor(interceptor);
1050
+ }
1051
+ /**
1052
+ * Sets the authentication token for subsequent requests
1053
+ * @param token - JWT token or null to clear authentication
1054
+ *
1055
+ * @example
1056
+ * ```typescript
1057
+ * // Set token after login
1058
+ * client.setAuthToken(loginResponse.accessToken);
1059
+ *
1060
+ * // Clear token on logout
1061
+ * client.setAuthToken(null);
1062
+ * ```
1063
+ */
1064
+ setAuthToken(token) {
1065
+ this.authToken = token;
1066
+ }
1067
+ /**
1068
+ * Retrieves the current authentication token
1069
+ * @returns The current auth token or null if not set
1070
+ */
1071
+ getAuthToken() {
1072
+ return this.authToken;
1073
+ }
1074
+ /**
1075
+ * Cancels a specific request by its key
1076
+ * @param key - The unique key identifying the request to cancel
1077
+ */
1078
+ cancelRequest(key) {
1079
+ this.requestManager.cancel(key);
1080
+ }
1081
+ /**
1082
+ * Cancels all pending requests
1083
+ * Useful for cleanup on navigation or component unmount
1084
+ */
1085
+ cancelAllRequests() {
1086
+ this.requestManager.cancelAll();
1087
+ }
1088
+ /**
1089
+ * Core request method that handles all HTTP operations
1090
+ * @template T - The expected response data type
1091
+ * @param endpoint - API endpoint relative to baseURL
1092
+ * @param config - Request configuration options
1093
+ * @returns Promise resolving to ApiResponse with data or error
1094
+ *
1095
+ * @example
1096
+ * ```typescript
1097
+ * const response = await client.request<User>('/users/123', {
1098
+ * method: 'GET',
1099
+ * timeout: 5000,
1100
+ * throwErrors: false
1101
+ * });
1102
+ * ```
1103
+ */
1104
+ async request(endpoint, config = {}) {
1105
+ const correlationId = config.correlationId || (!config.skipCorrelationId && this.includeCorrelationId ? generateCorrelationId(this.correlationIdPrefix) : void 0);
1106
+ const requestKey = `${config.method || "GET"}_${endpoint}_${Date.now()}`;
1107
+ const masterController = new AbortController();
1108
+ try {
1109
+ const signals = [
1110
+ config.signal,
1111
+ config.cancelToken?.signal,
1112
+ masterController.signal
1113
+ ];
1114
+ const timeout = config.timeout || this.defaultTimeout;
1115
+ const timeoutController = this.signalManager.createTimeoutSignal(timeout);
1116
+ signals.push(timeoutController.signal);
1117
+ const combinedController = this.signalManager.createCombinedSignal(signals);
1118
+ if (correlationId) {
1119
+ this.requestManager.add(requestKey, masterController, correlationId);
1120
+ }
1121
+ const finalConfig = await this.interceptorManager.applyRequestInterceptors({
1122
+ ...config,
1123
+ signal: combinedController.signal,
1124
+ correlationId
1125
+ });
1126
+ const url = this.urlBuilder.buildURL(
1127
+ this.baseURL,
1128
+ endpoint,
1129
+ finalConfig.params
1130
+ );
1131
+ const headers = new Headers(finalConfig.headers);
1132
+ if (correlationId) {
1133
+ headers.set("X-Correlation-Id", correlationId);
1134
+ headers.set("X-Request-Id", correlationId);
1135
+ }
1136
+ if (this.authToken && !finalConfig.skipAuthRefresh) {
1137
+ headers.set("Authorization", `Bearer ${this.authToken}`);
1138
+ }
1139
+ if (finalConfig.body && typeof finalConfig.body === "object" && !(finalConfig.body instanceof FormData)) {
1140
+ headers.set("Content-Type", "application/json");
1141
+ finalConfig.body = JSON.stringify(finalConfig.body);
1142
+ }
1143
+ finalConfig.headers = headers;
1144
+ const fetchPromise = async () => {
1145
+ try {
1146
+ const response = await fetch(url, {
1147
+ ...finalConfig,
1148
+ signal: combinedController.signal
1149
+ });
1150
+ const responseData = await this.responseParser.parseResponse(response);
1151
+ if (!response.ok) {
1152
+ const error = Object.assign(
1153
+ new Error(
1154
+ responseData.title || `HTTP ${response.status}: ${response.statusText}`
1155
+ ),
1156
+ {
1157
+ type: responseData.type || this.errorNormalizer.getErrorType(response.status),
1158
+ title: responseData.title || this.errorNormalizer.getErrorTitle(response.status),
1159
+ status: response.status,
1160
+ traceId: responseData.traceId || correlationId,
1161
+ errors: responseData.errors,
1162
+ isAborted: false,
1163
+ config: finalConfig
1164
+ }
1165
+ );
1166
+ if (finalConfig.throwErrors !== false) {
1167
+ throw error;
1168
+ } else {
1169
+ return await this.interceptorManager.applyResponseInterceptors({
1170
+ error
1171
+ });
1172
+ }
1173
+ }
1174
+ const apiResponse = {
1175
+ data: responseData
1176
+ };
1177
+ return await this.interceptorManager.applyResponseInterceptors(
1178
+ apiResponse
1179
+ );
1180
+ } catch (error) {
1181
+ if (error.name === "AbortError") {
1182
+ const abortError = Object.assign(
1183
+ new Error(error.message || "Request aborted"),
1184
+ {
1185
+ type: "request_cancelled",
1186
+ title: "Request was cancelled",
1187
+ status: 0,
1188
+ traceId: correlationId,
1189
+ isAborted: true,
1190
+ config: finalConfig
1191
+ }
1192
+ );
1193
+ if (finalConfig.throwErrors !== false) {
1194
+ throw abortError;
1195
+ } else {
1196
+ return await this.interceptorManager.applyResponseInterceptors({
1197
+ error: abortError
1198
+ });
1199
+ }
1200
+ }
1201
+ throw error;
1202
+ }
1203
+ };
1204
+ if (finalConfig.retries && finalConfig.retries > 0) {
1205
+ return await this.retryHandler.retryRequest(
1206
+ fetchPromise,
1207
+ finalConfig.retries,
1208
+ finalConfig.retryDelay || 1e3,
1209
+ combinedController.signal
1210
+ );
1211
+ }
1212
+ return await fetchPromise();
1213
+ } catch (error) {
1214
+ const apiError = this.errorNormalizer.normalizeError(
1215
+ error,
1216
+ config,
1217
+ correlationId
1218
+ );
1219
+ if (config.throwErrors !== false) {
1220
+ await this.interceptorManager.applyErrorInterceptors(apiError);
1221
+ throw apiError;
1222
+ } else {
1223
+ return {
1224
+ error: apiError
1225
+ };
1226
+ }
1227
+ } finally {
1228
+ this.requestManager.remove(requestKey);
1229
+ }
1230
+ }
1231
+ /**
1232
+ * Performs a GET request
1233
+ * @template T - The expected response data type
1234
+ * @param endpoint - API endpoint
1235
+ * @param config - Optional request configuration
1236
+ * @returns Promise resolving to ApiResponse
1237
+ *
1238
+ * @example
1239
+ * ```typescript
1240
+ * const { data, error } = await client.get<User[]>('/users', {
1241
+ * params: { active: true },
1242
+ * timeout: 5000
1243
+ * });
1244
+ * ```
1245
+ */
1246
+ get(endpoint, config) {
1247
+ return this.request(endpoint, { ...config, method: "GET" });
1248
+ }
1249
+ /**
1250
+ * Performs a POST request
1251
+ * @template T - The expected response data type
1252
+ * @template TData - The request body data type
1253
+ * @param endpoint - API endpoint
1254
+ * @param data - Request body data
1255
+ * @param config - Optional request configuration
1256
+ * @returns Promise resolving to ApiResponse
1257
+ *
1258
+ * @example
1259
+ * ```typescript
1260
+ * const { data, error } = await client.post<User, CreateUserDto>('/users', {
1261
+ * name: 'John Doe',
1262
+ * email: 'john@example.com'
1263
+ * });
1264
+ * ```
1265
+ */
1266
+ post(endpoint, data, config) {
1267
+ return this.request(endpoint, { ...config, method: "POST", body: data });
1268
+ }
1269
+ /**
1270
+ * Performs a PUT request
1271
+ * @template T - The expected response data type
1272
+ * @template TData - The request body data type
1273
+ * @param endpoint - API endpoint
1274
+ * @param data - Request body data
1275
+ * @param config - Optional request configuration
1276
+ * @returns Promise resolving to ApiResponse
1277
+ *
1278
+ * @example
1279
+ * ```typescript
1280
+ * const { data, error } = await client.put<User, UpdateUserDto>(
1281
+ * '/users/123',
1282
+ * { name: 'Jane Doe' }
1283
+ * );
1284
+ * ```
1285
+ */
1286
+ put(endpoint, data, config) {
1287
+ return this.request(endpoint, { ...config, method: "PUT", body: data });
1288
+ }
1289
+ /**
1290
+ * Performs a PATCH request
1291
+ * @template T - The expected response data type
1292
+ * @template TData - The request body data type
1293
+ * @param endpoint - API endpoint
1294
+ * @param data - Request body data
1295
+ * @param config - Optional request configuration
1296
+ * @returns Promise resolving to ApiResponse
1297
+ *
1298
+ * @example
1299
+ * ```typescript
1300
+ * const { data, error } = await client.patch<User>(
1301
+ * '/users/123',
1302
+ * { status: 'active' }
1303
+ * );
1304
+ * ```
1305
+ */
1306
+ patch(endpoint, data, config) {
1307
+ return this.request(endpoint, {
1308
+ ...config,
1309
+ method: "PATCH",
1310
+ body: data
1311
+ });
1312
+ }
1313
+ /**
1314
+ * Performs a DELETE request
1315
+ * @template T - The expected response data type
1316
+ * @param endpoint - API endpoint
1317
+ * @param config - Optional request configuration
1318
+ * @returns Promise resolving to ApiResponse
1319
+ *
1320
+ * @example
1321
+ * ```typescript
1322
+ * const { error } = await client.delete('/users/123');
1323
+ * if (!error) {
1324
+ * console.log('User deleted successfully');
1325
+ * }
1326
+ * ```
1327
+ */
1328
+ delete(endpoint, config) {
1329
+ return this.request(endpoint, { ...config, method: "DELETE" });
1330
+ }
1331
+ /**
1332
+ * Performs a filtered list request with pagination and sorting
1333
+ * @template TListModel - The type of individual list items
1334
+ * @template TFilter - The filter criteria type
1335
+ * @param url - API endpoint
1336
+ * @param data - Pagination and filter data
1337
+ * @param config - Optional request configuration
1338
+ * @returns Promise resolving to paginated list response
1339
+ *
1340
+ * @example
1341
+ * ```typescript
1342
+ * const { data, error } = await client.filter<User, UserFilter>(
1343
+ * '/users/filter',
1344
+ * {
1345
+ * pageOffset: 0,
1346
+ * pageSize: 20,
1347
+ * sortField: 'createdAt',
1348
+ * sortOrder: 'desc',
1349
+ * filterModel: { status: 'active' }
1350
+ * }
1351
+ * );
1352
+ *
1353
+ * if (data) {
1354
+ * console.log(`Found ${data.Total} users`);
1355
+ * console.log('Users:', data.Data);
1356
+ * }
1357
+ * ```
1358
+ */
1359
+ filter(url, data, config) {
1360
+ const mergedData = { ...data, ...data.filterModel };
1361
+ return this.request(url, {
1362
+ ...config,
1363
+ method: "POST",
1364
+ body: mergedData
1365
+ });
1366
+ }
1367
+ };
1368
+
1369
+ // src/core/api/createApiClient.ts
1370
+ var globalApiClient = null;
1371
+ function createApiClient(config = {}) {
1372
+ const {
1373
+ baseURL = import.meta.env.VITE_API_URL,
1374
+ timeout = 3e4,
1375
+ correlationIdPrefix = "api",
1376
+ includeCorrelationId = true,
1377
+ requestInterceptors = [],
1378
+ responseInterceptors = [],
1379
+ errorInterceptors = []
1380
+ } = config;
1381
+ const client = new ApiClient(baseURL, timeout);
1382
+ client.addRequestInterceptor((config2) => {
1383
+ const token = localStorage.getItem("serviceToken");
1384
+ if (token && !config2.skipAuthRefresh) {
1385
+ config2.headers = {
1386
+ ...config2.headers,
1387
+ Authorization: `Bearer ${token}`
1388
+ };
1389
+ }
1390
+ return config2;
1391
+ });
1392
+ client.setCorrelationIdPrefix(correlationIdPrefix);
1393
+ client.setIncludeCorrelationId(includeCorrelationId);
1394
+ requestInterceptors.forEach((interceptor) => {
1395
+ client.addRequestInterceptor(interceptor);
1396
+ });
1397
+ responseInterceptors.forEach((interceptor) => {
1398
+ client.addResponseInterceptor(interceptor);
1399
+ });
1400
+ errorInterceptors.forEach((interceptor) => {
1401
+ client.addErrorInterceptor(interceptor);
1402
+ });
1403
+ return client;
1404
+ }
1405
+ function getGlobalApiClient(config) {
1406
+ if (!globalApiClient) {
1407
+ globalApiClient = createApiClient(config);
1408
+ }
1409
+ return globalApiClient;
1410
+ }
1411
+ function setGlobalApiClient(client) {
1412
+ globalApiClient = client;
1413
+ }
1414
+ function resetGlobalApiClient() {
1415
+ globalApiClient = null;
1416
+ }
1417
+
1418
+ // src/core/api/types/CancelToken.ts
1419
+ var CancelToken = class _CancelToken {
1420
+ abortController;
1421
+ cancelPromise;
1422
+ cancelResolve;
1423
+ constructor() {
1424
+ this.abortController = new AbortController();
1425
+ this.cancelPromise = new Promise((resolve) => {
1426
+ this.cancelResolve = resolve;
1427
+ });
1428
+ }
1429
+ get signal() {
1430
+ return this.abortController.signal;
1431
+ }
1432
+ cancel(reason) {
1433
+ this.abortController.abort(reason);
1434
+ this.cancelResolve?.();
1435
+ }
1436
+ get isCancelled() {
1437
+ return this.abortController.signal.aborted;
1438
+ }
1439
+ throwIfCancelled() {
1440
+ if (this.isCancelled) {
1441
+ throw new Error("Request cancelled");
1442
+ }
1443
+ }
1444
+ static source() {
1445
+ const token = new _CancelToken();
1446
+ return {
1447
+ token,
1448
+ cancel: (reason) => token.cancel(reason)
1449
+ };
1450
+ }
1451
+ };
1452
+
1453
+ // src/core/api/useValidationErrors.ts
1454
+ import { useCallback } from "react";
1455
+ function useValidationErrors(error) {
1456
+ const getFieldError = useCallback(
1457
+ (field) => {
1458
+ if (!error?.errors || !error.errors[field]) return null;
1459
+ const fieldError = error.errors[field];
1460
+ if (typeof fieldError === "string") return fieldError;
1461
+ if (Array.isArray(fieldError)) return fieldError[0];
1462
+ if (typeof fieldError === "object" && "message" in fieldError) {
1463
+ return fieldError.message;
1464
+ }
1465
+ return null;
1466
+ },
1467
+ [error]
1468
+ );
1469
+ const hasFieldError = useCallback(
1470
+ (field) => {
1471
+ return !!getFieldError(field);
1472
+ },
1473
+ [getFieldError]
1474
+ );
1475
+ const getAllErrors = useCallback(() => {
1476
+ if (!error?.errors) return {};
1477
+ const result = {};
1478
+ Object.entries(error.errors).forEach(([key, value]) => {
1479
+ if (typeof value === "string") {
1480
+ result[key] = value;
1481
+ } else if (Array.isArray(value)) {
1482
+ result[key] = value.join(", ");
1483
+ } else if (typeof value === "object" && value && "message" in value) {
1484
+ result[key] = value.message;
1485
+ }
1486
+ });
1487
+ return result;
1488
+ }, [error]);
1489
+ return {
1490
+ getFieldError,
1491
+ hasFieldError,
1492
+ getAllErrors,
1493
+ hasErrors: error?.errors
1494
+ };
1495
+ }
1496
+
1497
+ // src/core/components/AuthorizedView/AuthorizedView.tsx
1498
+ import { Fragment, jsx } from "react/jsx-runtime";
1499
+ var AuthorizedView = ({ children, show }) => {
1500
+ if (!show) return /* @__PURE__ */ jsx(Fragment, {});
1501
+ return /* @__PURE__ */ jsx(Fragment, { children });
1502
+ };
1503
+
1504
+ // src/core/components/CancelButton/CancelButton.tsx
1505
+ import { Button } from "@mui/material";
1506
+ import { jsx as jsx2 } from "react/jsx-runtime";
1507
+ var CancelButton = ({
1508
+ children = "Cancel",
1509
+ variant = "outlined",
1510
+ sx,
1511
+ ...rest
1512
+ }) => /* @__PURE__ */ jsx2(Button, { variant, sx: { width: "6rem", ...sx }, ...rest, children });
1513
+
1514
+ // src/core/components/ClearButton/ClearButton.tsx
1515
+ import { Button as Button2 } from "@mui/material";
1516
+ import { jsx as jsx3 } from "react/jsx-runtime";
1517
+ var ClearButton = ({
1518
+ isSubmitting,
1519
+ handleClear,
1520
+ sx,
1521
+ storeKey
1522
+ }) => {
1523
+ const onClick = () => {
1524
+ handleClear();
1525
+ if (storeKey != null) {
1526
+ localStorage.removeItem(storeKey);
1527
+ }
1528
+ };
1529
+ return /* @__PURE__ */ jsx3(
1530
+ Button2,
1531
+ {
1532
+ variant: "outlined",
1533
+ onClick,
1534
+ disabled: isSubmitting,
1535
+ sx,
1536
+ children: "Clear"
1537
+ }
1538
+ );
1539
+ };
1540
+
1541
+ // src/core/components/Containers/SimpleContainer.tsx
1542
+ import { Container } from "@mui/material";
1543
+ import { jsx as jsx4 } from "react/jsx-runtime";
1544
+ var SimpleContainer = ({
1545
+ children,
1546
+ className,
1547
+ sx
1548
+ }) => /* @__PURE__ */ jsx4(Container, { className, sx: { ...sx }, children });
1549
+
1550
+ // src/core/components/FilterButton/FilterButton.tsx
1551
+ import FilterAltIcon from "@mui/icons-material/FilterAlt";
1552
+ import { LoadingButton } from "@mui/lab";
1553
+ import { Badge } from "@mui/material";
1554
+ import { jsx as jsx5 } from "react/jsx-runtime";
1555
+ var FilterButton = ({
1556
+ isSubmitting,
1557
+ show,
1558
+ title,
1559
+ icon,
1560
+ sx,
1561
+ iconSx
1562
+ }) => {
1563
+ return /* @__PURE__ */ jsx5(
1564
+ LoadingButton,
1565
+ {
1566
+ type: "submit",
1567
+ variant: "contained",
1568
+ loading: isSubmitting,
1569
+ disabled: !show,
1570
+ disableRipple: true,
1571
+ color: "primary",
1572
+ sx: {
1573
+ display: "flex",
1574
+ alignItems: "center",
1575
+ ...sx
1576
+ },
1577
+ startIcon: /* @__PURE__ */ jsx5(Badge, { color: "error", variant: "standard", children: icon ? icon : /* @__PURE__ */ jsx5(FilterAltIcon, { width: "20", height: "20", sx: iconSx }) }),
1578
+ children: title?.trim() === "" || !title ? "Filter" : title
1579
+ }
1580
+ );
1581
+ };
1582
+
1583
+ // src/core/components/FilterDisplay/FilterChip.tsx
1584
+ import Chip from "@mui/material/Chip";
1585
+ import { memo } from "react";
1586
+ import { jsx as jsx6 } from "react/jsx-runtime";
1587
+ var FilterChip = memo(
1588
+ ({
1589
+ fieldKey,
1590
+ filter,
1591
+ onDelete
1592
+ }) => {
1593
+ const hasValue = filter.Value !== null && filter.Value !== void 0 && filter.Value !== "";
1594
+ const label = `${fieldKey.replace("PK", "")}: ${filter.Label}`;
1595
+ return /* @__PURE__ */ jsx6(
1596
+ Chip,
1597
+ {
1598
+ label,
1599
+ variant: hasValue ? "filled" : "outlined",
1600
+ size: "small",
1601
+ onDelete: hasValue ? onDelete : void 0
1602
+ },
1603
+ fieldKey
1604
+ );
1605
+ }
1606
+ );
1607
+ FilterChip.displayName = "FilterChip";
1608
+
1609
+ // src/core/components/FilterDisplay/FilterDisplay.tsx
1610
+ import { Card, CardContent, Typography, Box } from "@mui/material";
1611
+ import { memo as memo2, useMemo } from "react";
1612
+ import { jsx as jsx7, jsxs } from "react/jsx-runtime";
1613
+ var ProgramsFilterDisplay = memo2(
1614
+ (props) => {
1615
+ const { friendlyFilter, onFriendlyFilterChange } = props;
1616
+ const deleteHandlers = useMemo(() => {
1617
+ if (!onFriendlyFilterChange) return {};
1618
+ const handlers = {};
1619
+ for (const key of Object.keys(friendlyFilter)) {
1620
+ handlers[key] = () => onFriendlyFilterChange(key);
1621
+ }
1622
+ return handlers;
1623
+ }, [onFriendlyFilterChange, friendlyFilter]);
1624
+ const chipList = useMemo(() => {
1625
+ return Object.entries(friendlyFilter).map(([key, filter]) => /* @__PURE__ */ jsx7(
1626
+ FilterChip,
1627
+ {
1628
+ fieldKey: key,
1629
+ filter,
1630
+ onDelete: deleteHandlers[key]
1631
+ },
1632
+ key
1633
+ ));
1634
+ }, [friendlyFilter, deleteHandlers]);
1635
+ return /* @__PURE__ */ jsx7(Card, { sx: { mb: 2 }, children: /* @__PURE__ */ jsxs(CardContent, { children: [
1636
+ /* @__PURE__ */ jsx7(Typography, { variant: "h6", gutterBottom: true, children: "Active Filters" }),
1637
+ /* @__PURE__ */ jsx7(Box, { display: "flex", gap: 1, flexWrap: "wrap", children: chipList })
1638
+ ] }) });
1639
+ }
1640
+ );
1641
+ ProgramsFilterDisplay.displayName = "FilterDisplay";
1642
+
1643
+ // src/core/components/FilterWrapper/FilterWrapper.tsx
1644
+ import ManageSearchIcon from "@mui/icons-material/ManageSearch";
1645
+ import {
1646
+ Box as Box2,
1647
+ Card as Card2,
1648
+ CardContent as CardContent2,
1649
+ CardHeader,
1650
+ Divider,
1651
+ Grid,
1652
+ Typography as Typography2,
1653
+ useTheme
1654
+ } from "@mui/material";
1655
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
1656
+ var FilterWrapper = ({
1657
+ children,
1658
+ title,
1659
+ filterCount,
1660
+ cardSx,
1661
+ textSx,
1662
+ icon,
1663
+ iconSx,
1664
+ showCount
1665
+ }) => {
1666
+ const theme = useTheme();
1667
+ return /* @__PURE__ */ jsxs2(
1668
+ Card2,
1669
+ {
1670
+ sx: {
1671
+ position: "relative",
1672
+ borderRadius: "0px",
1673
+ mb: 2,
1674
+ ...cardSx
1675
+ },
1676
+ children: [
1677
+ /* @__PURE__ */ jsx8(
1678
+ CardHeader,
1679
+ {
1680
+ sx: {
1681
+ display: "flex",
1682
+ flexWrap: "wrap",
1683
+ p: "1rem",
1684
+ ".MuiCardHeader-action": {
1685
+ margin: 0,
1686
+ alignSelf: "center"
1687
+ },
1688
+ alignItems: "center"
1689
+ },
1690
+ title: /* @__PURE__ */ jsxs2(Box2, { sx: { display: "flex", alignItems: "center", gap: 0.5 }, children: [
1691
+ icon ? icon : /* @__PURE__ */ jsx8(
1692
+ ManageSearchIcon,
1693
+ {
1694
+ sx: {
1695
+ height: "2.5rem",
1696
+ color: theme.palette.primary.main,
1697
+ ...iconSx
1698
+ }
1699
+ }
1700
+ ),
1701
+ /* @__PURE__ */ jsxs2(
1702
+ Typography2,
1703
+ {
1704
+ variant: "h5",
1705
+ sx: {
1706
+ fontWeight: "bold",
1707
+ color: theme.palette.primary.main,
1708
+ ...textSx
1709
+ },
1710
+ children: [
1711
+ title ? title : "Filter",
1712
+ " ",
1713
+ showCount ? `(${filterCount ? filterCount : 0})` : /* @__PURE__ */ jsx8(Fragment2, {})
1714
+ ]
1715
+ }
1716
+ )
1717
+ ] })
1718
+ }
1719
+ ),
1720
+ /* @__PURE__ */ jsx8(Divider, {}),
1721
+ /* @__PURE__ */ jsx8(CardContent2, { sx: { py: 2 }, children: /* @__PURE__ */ jsx8(Grid, { container: true, spacing: 2, children }) })
1722
+ ]
1723
+ }
1724
+ );
1725
+ };
1726
+
1727
+ // src/core/components/Footer/Footer.tsx
1728
+ import { Box as Box3, Typography as Typography3 } from "@mui/material";
1729
+ import { jsx as jsx9 } from "react/jsx-runtime";
1730
+ var Footer = () => {
1731
+ const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
1732
+ return /* @__PURE__ */ jsx9(
1733
+ Box3,
1734
+ {
1735
+ component: "footer",
1736
+ sx: {
1737
+ py: 2,
1738
+ px: 4,
1739
+ mt: "auto",
1740
+ backgroundColor: (theme) => theme.palette.mode === "light" ? theme.palette.grey[200] : theme.palette.grey[800]
1741
+ },
1742
+ children: /* @__PURE__ */ jsx9(Typography3, { variant: "body2", color: "text.secondary", align: "center", children: `\xA9 Copyright ${currentYear} GN. All rights reserved by Parul University.` })
1743
+ }
1744
+ );
1745
+ };
1746
+
1747
+ // src/core/components/LabelText/LabelText.tsx
1748
+ import { Grid as Grid2, Tooltip, Typography as Typography4 } from "@mui/material";
1749
+ import { jsx as jsx10, jsxs as jsxs3 } from "react/jsx-runtime";
1750
+ var LabelText = ({
1751
+ label,
1752
+ value,
1753
+ gridSize,
1754
+ containerSize,
1755
+ labelSx,
1756
+ valueSx
1757
+ }) => {
1758
+ const defaultGridSize = {
1759
+ labelSize: { xs: 6, sm: 6, md: 6 },
1760
+ valueSize: { xs: 12, sm: 6, md: 6 }
1761
+ };
1762
+ const defaultContainerSize = { xs: 12, sm: 6, md: 6 };
1763
+ const size = gridSize || defaultGridSize;
1764
+ const container = containerSize || defaultContainerSize;
1765
+ return /* @__PURE__ */ jsxs3(
1766
+ Grid2,
1767
+ {
1768
+ size: container,
1769
+ sx: {
1770
+ display: "flex",
1771
+ flexDirection: { xs: "column", sm: "row", md: "row" },
1772
+ "&:hover": { bgcolor: "#efefef", overflow: "hidden" }
1773
+ },
1774
+ children: [
1775
+ /* @__PURE__ */ jsxs3(
1776
+ Grid2,
1777
+ {
1778
+ size: size.labelSize,
1779
+ sx: {
1780
+ padding: "5px",
1781
+ fontSize: "14px",
1782
+ textAlign: { xs: "left", sm: "right", md: "right" },
1783
+ ...labelSx
1784
+ },
1785
+ children: [
1786
+ label,
1787
+ " :"
1788
+ ]
1789
+ }
1790
+ ),
1791
+ /* @__PURE__ */ jsx10(
1792
+ Grid2,
1793
+ {
1794
+ size: size.valueSize,
1795
+ sx: { padding: "5px", display: "flex", flexWrap: "wrap" },
1796
+ children: /* @__PURE__ */ jsx10(Tooltip, { title: value, arrow: true, children: /* @__PURE__ */ jsx10(
1797
+ Typography4,
1798
+ {
1799
+ sx: {
1800
+ fontSize: "14px",
1801
+ wordBreak: "break-word",
1802
+ overflow: "hidden",
1803
+ display: "-webkit-box",
1804
+ textOverflow: "ellipsis",
1805
+ WebkitLineClamp: 2,
1806
+ WebkitBoxOrient: "vertical",
1807
+ ...valueSx,
1808
+ color: "#078dee"
1809
+ },
1810
+ children: value ? value : "-"
1811
+ }
1812
+ ) })
1813
+ }
1814
+ )
1815
+ ]
1816
+ }
1817
+ );
1818
+ };
1819
+
1820
+ // src/core/components/RenderIf/RenderIf.tsx
1821
+ import { Fragment as Fragment3, jsx as jsx11 } from "react/jsx-runtime";
1822
+ var RenderIf = ({
1823
+ show,
1824
+ children
1825
+ }) => {
1826
+ return show ? /* @__PURE__ */ jsx11(Fragment3, { children }) : null;
1827
+ };
1828
+
1829
+ // src/core/components/SectionBox/SectionBox.tsx
1830
+ import { Box as Box4, Divider as Divider2, Grid as Grid3, Stack, Typography as Typography5 } from "@mui/material";
1831
+ import { memo as memo3, useMemo as useMemo2 } from "react";
1832
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
1833
+ var getSectionTheme = (variant = "default") => {
1834
+ const themes = {
1835
+ default: {
1836
+ bgcolor: "#faebd7",
1837
+ color: "#925d21"
1838
+ },
1839
+ form: {
1840
+ bgcolor: "#cdced1",
1841
+ color: "black"
1842
+ },
1843
+ info: {
1844
+ bgcolor: "#e3f2fd",
1845
+ color: "#1976d2"
1846
+ },
1847
+ warning: {
1848
+ bgcolor: "#fff3e0",
1849
+ color: "#f57c00"
1850
+ },
1851
+ error: {
1852
+ bgcolor: "#ffebee",
1853
+ color: "#d32f2f"
1854
+ }
1855
+ };
1856
+ return themes[variant];
1857
+ };
1858
+ var SectionBox = memo3(
1859
+ ({
1860
+ title,
1861
+ children,
1862
+ spacing = 0,
1863
+ containerSx,
1864
+ titleSx,
1865
+ variant = "default",
1866
+ icon,
1867
+ actions
1868
+ }) => {
1869
+ const themeColors = useMemo2(() => getSectionTheme(variant), [variant]);
1870
+ const headerSx = useMemo2(
1871
+ () => ({
1872
+ px: 1.5,
1873
+ py: 0.1,
1874
+ width: "fit-content",
1875
+ ...themeColors,
1876
+ ...titleSx
1877
+ }),
1878
+ [themeColors, titleSx]
1879
+ );
1880
+ const contentSx = useMemo2(
1881
+ () => ({
1882
+ padding: "16px",
1883
+ ...containerSx
1884
+ }),
1885
+ [containerSx]
1886
+ );
1887
+ return /* @__PURE__ */ jsxs4(Fragment4, { children: [
1888
+ /* @__PURE__ */ jsxs4(Box4, { sx: { display: "flex", flexDirection: "column", width: "100%" }, children: [
1889
+ /* @__PURE__ */ jsxs4(
1890
+ Stack,
1891
+ {
1892
+ direction: "row",
1893
+ justifyContent: "space-between",
1894
+ alignItems: "center",
1895
+ sx: headerSx,
1896
+ children: [
1897
+ /* @__PURE__ */ jsxs4(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [
1898
+ icon,
1899
+ /* @__PURE__ */ jsx12(Typography5, { sx: { fontSize: "15px", fontWeight: 400 }, children: title })
1900
+ ] }),
1901
+ actions
1902
+ ]
1903
+ }
1904
+ ),
1905
+ /* @__PURE__ */ jsx12(Divider2, {})
1906
+ ] }),
1907
+ /* @__PURE__ */ jsx12(Grid3, { container: true, spacing, sx: contentSx, children })
1908
+ ] });
1909
+ }
1910
+ );
1911
+
1912
+ // src/core/components/SimpleTabs/SimpleTabs.tsx
1913
+ import { TabContext } from "@mui/lab";
1914
+ import { Box as Box5, Tab, Tabs } from "@mui/material";
1915
+ import { useState } from "react";
1916
+ import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
1917
+ var SimpleTabs = ({
1918
+ tabs,
1919
+ defaultValue = 1,
1920
+ onTabChange,
1921
+ children,
1922
+ tabSx,
1923
+ tabsSx
1924
+ }) => {
1925
+ const [value, setValue] = useState(defaultValue);
1926
+ const handleChange = (event, newValue) => {
1927
+ setValue(newValue);
1928
+ if (onTabChange) onTabChange(newValue);
1929
+ };
1930
+ return /* @__PURE__ */ jsxs5(TabContext, { value, children: [
1931
+ /* @__PURE__ */ jsx13(Box5, { sx: { borderBottom: 1, borderColor: "divider", width: "100%" }, children: /* @__PURE__ */ jsx13(
1932
+ Tabs,
1933
+ {
1934
+ value,
1935
+ onChange: handleChange,
1936
+ sx: { px: 2, py: 0, ...tabsSx },
1937
+ children: tabs.map((tab) => /* @__PURE__ */ jsx13(
1938
+ Tab,
1939
+ {
1940
+ label: tab.label,
1941
+ value: tab.value,
1942
+ disabled: tab.permission === false,
1943
+ sx: { fontSize: "1rem", ...tabSx }
1944
+ },
1945
+ tab.value
1946
+ ))
1947
+ }
1948
+ ) }),
1949
+ children
1950
+ ] });
1951
+ };
1952
+
1953
+ // src/core/components/SubmitButton/SubmitButton.tsx
1954
+ import { LoadingButton as LoadingButton2 } from "@mui/lab";
1955
+ import { jsx as jsx14 } from "react/jsx-runtime";
1956
+ var SubmitButton = ({
1957
+ loading = false,
1958
+ ...rest
1959
+ }) => /* @__PURE__ */ jsx14(
1960
+ LoadingButton2,
1961
+ {
1962
+ loading,
1963
+ variant: "contained",
1964
+ color: "primary",
1965
+ type: "submit",
1966
+ ...rest,
1967
+ sx: { fontWeight: 400 },
1968
+ children: "Submit"
1969
+ }
1970
+ );
1971
+
1972
+ // src/core/components/WithRef/WithRef.tsx
1973
+ import { forwardRef } from "react";
1974
+ function withDataModal(component) {
1975
+ return forwardRef(
1976
+ (props, ref) => component({ ...props, ref })
1977
+ );
1978
+ }
1979
+
1980
+ // src/core/config.ts
1981
+ var Config = {
1982
+ defaultPageSize: 20,
1983
+ apiBaseUrl: "http://localhost:5143"
1984
+ // apiBaseUrl: 'http://192.168.1.246:5143',
1985
+ };
1986
+ var dateTimePatterns = {
1987
+ dateTime: "DD MMM YYYY h:mm A",
1988
+ // 17 Apr 2022 12:00 am
1989
+ date: "DD MMM YYYY",
1990
+ // 17 Apr 2022
1991
+ month_year_short_format: "MMM YYYY",
1992
+ month_year_full_format: "MMMM YYYY",
1993
+ year: "YYYY",
1994
+ time: "h:mm a",
1995
+ // 12:00 am
1996
+ split: {
1997
+ dateTime: "DD/MM/YYYY h:mm A",
1998
+ // 17/04/2022 12:00 am
1999
+ date: "DD/MM/YYYY"
2000
+ // 17/04/2022
2001
+ },
2002
+ paramCase: {
2003
+ dateTime: "DD-MM-YYYY h:mm A",
2004
+ // 17-04-2022 12:00 am
2005
+ date: "DD-MM-YYYY",
2006
+ // 17-04-2022
2007
+ dateReverse: "YYYY-MM-DD",
2008
+ // 2022-04-17 for compare date
2009
+ MonthYear: "MMM-YYYY"
2010
+ }
2011
+ };
2012
+
2013
+ // src/core/hooks/useApiClient.ts
2014
+ import { useMemo as useMemo3 } from "react";
2015
+ function useApiClient(config = {}) {
2016
+ return useMemo3(
2017
+ () => createApiClient(config),
2018
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2019
+ [
2020
+ config.baseURL,
2021
+ config.timeout,
2022
+ config.correlationIdPrefix,
2023
+ config.includeCorrelationId,
2024
+ config.authToken,
2025
+ config.requestInterceptors,
2026
+ config.responseInterceptors,
2027
+ config.errorInterceptors
2028
+ ]
2029
+ );
2030
+ }
2031
+
2032
+ // src/core/hooks/useFormErrorHandler.ts
2033
+ import { useCallback as useCallback2 } from "react";
2034
+ import { toast } from "sonner";
2035
+ var useFormErrorHandler = ({
2036
+ setError,
2037
+ successMessage = {
2038
+ create: "Created successfully",
2039
+ update: "Updated successfully"
2040
+ },
2041
+ errorMessage = {
2042
+ noChanges: "No changes were made",
2043
+ general: "Failed to save. Please try again."
2044
+ }
2045
+ }) => {
2046
+ const getFieldError = useCallback2(
2047
+ (fields, fieldName) => {
2048
+ if (!fields || !fields[fieldName]) return void 0;
2049
+ const fieldError = fields[fieldName];
2050
+ if (typeof fieldError === "string") {
2051
+ return fieldError;
2052
+ }
2053
+ if (Array.isArray(fieldError)) {
2054
+ return fieldError.join(", ");
2055
+ }
2056
+ if (typeof fieldError === "object" && "message" in fieldError) {
2057
+ return fieldError.message;
2058
+ }
2059
+ return void 0;
2060
+ },
2061
+ []
2062
+ );
2063
+ const handleSuccess = useCallback2(
2064
+ (isEditing, rowsAffected) => {
2065
+ if (rowsAffected !== void 0 && rowsAffected > 0) {
2066
+ toast.success(
2067
+ isEditing ? successMessage.update : successMessage.create
2068
+ );
2069
+ return true;
2070
+ } else if (rowsAffected === 0) {
2071
+ toast.error(errorMessage.noChanges);
2072
+ return false;
2073
+ }
2074
+ toast.success(isEditing ? successMessage.update : successMessage.create);
2075
+ return true;
2076
+ },
2077
+ [successMessage, errorMessage]
2078
+ );
2079
+ const handleError = useCallback2(
2080
+ (processedError) => {
2081
+ if (processedError.type === "validation_error" && processedError.errors && setError) {
2082
+ Object.keys(processedError.errors).forEach((fieldName) => {
2083
+ const fieldError = getFieldError(processedError.errors, fieldName);
2084
+ if (fieldError) {
2085
+ setError(fieldName, {
2086
+ type: "server",
2087
+ message: fieldError
2088
+ });
2089
+ }
2090
+ });
2091
+ toast.error(
2092
+ processedError.title || "Please check the form for validation errors"
2093
+ );
2094
+ } else {
2095
+ toast.error(processedError.title || errorMessage.general);
2096
+ }
2097
+ },
2098
+ [errorMessage.general, getFieldError, setError]
2099
+ );
2100
+ return {
2101
+ handleSuccess,
2102
+ handleError
2103
+ };
2104
+ };
2105
+ var useDeleteHandler = ({
2106
+ successMessage = "Deleted successfully",
2107
+ errorMessage = "Failed to delete. Please try again."
2108
+ } = {}) => {
2109
+ return useFormErrorHandler({
2110
+ successMessage: {
2111
+ create: successMessage,
2112
+ // Not used for delete, but required for type
2113
+ update: successMessage
2114
+ },
2115
+ errorMessage: {
2116
+ noChanges: "No changes were made",
2117
+ // Not typically used for delete
2118
+ general: errorMessage
2119
+ }
2120
+ // setError is omitted (undefined) for delete operations
2121
+ });
2122
+ };
2123
+
2124
+ // src/core/utils/CacheUtility/index.ts
2125
+ import { useQueryClient } from "@tanstack/react-query";
2126
+ import { useMemo as useMemo4 } from "react";
2127
+ var CacheUtility = class {
2128
+ constructor(queryClient) {
2129
+ this.queryClient = queryClient;
2130
+ }
2131
+ /**
2132
+ * Get cached data using only the queryKey from query factory
2133
+ */
2134
+ getCachedData(queryKey) {
2135
+ return this.queryClient.getQueryData(queryKey);
2136
+ }
2137
+ /**
2138
+ * Get cached data with transformation using select function
2139
+ */
2140
+ getCachedDataWithSelect(queryKey, select) {
2141
+ const cachedData = this.queryClient.getQueryData(queryKey);
2142
+ if (cachedData === void 0) {
2143
+ return void 0;
2144
+ }
2145
+ return select(cachedData);
2146
+ }
2147
+ };
2148
+ function useCacheUtility() {
2149
+ const queryClient = useQueryClient();
2150
+ return useMemo4(() => new CacheUtility(queryClient), [queryClient]);
2151
+ }
2152
+
2153
+ // src/core/utils/watch/core.ts
2154
+ import { useWatch } from "react-hook-form";
2155
+ var useWatchForm = (control) => useWatch({ control });
2156
+ var useWatchField = (control, name) => useWatch({ control, name });
2157
+ var useWatchFields = (control, names) => useWatch({ control, name: names });
2158
+
2159
+ // src/core/utils/watch/utilities.ts
2160
+ import { useEffect, useMemo as useMemo5, useState as useState2 } from "react";
2161
+ import { useWatch as useWatch2 } from "react-hook-form";
2162
+ var useWatchTransform = (control, name, transform) => {
2163
+ const value = useWatch2({ control, name });
2164
+ return useMemo5(() => transform(value), [value, transform]);
2165
+ };
2166
+ var useWatchDefault = (control, name, defaultValue) => {
2167
+ const value = useWatch2({ control, name });
2168
+ return value ?? defaultValue;
2169
+ };
2170
+ var useWatchBoolean = (control, name, defaultValue = false) => {
2171
+ const value = useWatch2({ control, name });
2172
+ return Boolean(value ?? defaultValue);
2173
+ };
2174
+ var useWatchBatch = (control, fields) => {
2175
+ const values = useWatch2({ control, name: fields });
2176
+ return useMemo5(() => {
2177
+ const result = {};
2178
+ fields.forEach((field, index) => {
2179
+ result[field] = values[index];
2180
+ });
2181
+ return result;
2182
+ }, [values, fields]);
2183
+ };
2184
+ var useWatchConditional = (control, name, shouldWatch, fallback) => {
2185
+ const activeValue = useWatch2({
2186
+ control,
2187
+ name,
2188
+ disabled: !shouldWatch
2189
+ });
2190
+ return shouldWatch ? activeValue : fallback;
2191
+ };
2192
+ var useWatchDebounced = (control, name, delay = 300) => {
2193
+ const value = useWatch2({ control, name });
2194
+ const [debouncedValue, setDebouncedValue] = useState2(value);
2195
+ useEffect(() => {
2196
+ const timer = setTimeout(() => {
2197
+ setDebouncedValue(value);
2198
+ }, delay);
2199
+ return () => clearTimeout(timer);
2200
+ }, [value, delay]);
2201
+ return debouncedValue;
2202
+ };
2203
+ var useWatchSelector = (control, name, selector, deps = []) => {
2204
+ const value = useWatch2({ control, name });
2205
+ return useMemo5(
2206
+ () => selector(value),
2207
+ [value, selector, ...deps]
2208
+ // eslint-disable-line react-hooks/exhaustive-deps
2209
+ );
2210
+ };
2211
+
2212
+ // src/core/utils/watch/index.ts
2213
+ var typedWatch = {
2214
+ // === CORE FUNCTIONS ===
2215
+ /** Watch entire form */
2216
+ form: useWatchForm,
2217
+ /** Watch single field */
2218
+ field: useWatchField,
2219
+ /** Watch multiple fields */
2220
+ fields: useWatchFields,
2221
+ // === UTILITY FUNCTIONS ===
2222
+ /** Watch with transformation */
2223
+ transform: useWatchTransform,
2224
+ /** Watch with default value */
2225
+ withDefault: useWatchDefault,
2226
+ /** Watch as boolean */
2227
+ boolean: useWatchBoolean,
2228
+ /** Watch multiple with custom keys */
2229
+ batch: useWatchBatch,
2230
+ /** Watch conditionally */
2231
+ conditional: useWatchConditional,
2232
+ /** Watch with debouncing */
2233
+ debounced: useWatchDebounced,
2234
+ /** Watch with selector */
2235
+ selector: useWatchSelector
2236
+ };
2237
+
2238
+ // src/core/utils/calculateFilterCount.ts
2239
+ var calculateFilterCount = (model) => Object.values(model).filter(
2240
+ (v) => v !== null && v !== void 0 && String(v).trim() !== ""
2241
+ ).length;
2242
+
2243
+ // src/core/utils/format-time.ts
2244
+ import dayjs from "dayjs";
2245
+ import duration from "dayjs/plugin/duration";
2246
+ import relativeTime from "dayjs/plugin/relativeTime";
2247
+ dayjs.extend(duration);
2248
+ dayjs.extend(relativeTime);
2249
+ var formatPatterns = {
2250
+ dateTime: "DD MMM YYYY h:mm A",
2251
+ // 17 Apr 2022 12:00 am
2252
+ date: "DD MMM YYYY",
2253
+ // 17 Apr 2022
2254
+ month_year_short_format: "MMM YYYY",
2255
+ month_year_full_format: "MMMM YYYY",
2256
+ year: "YYYY",
2257
+ time: "h:mm a",
2258
+ // 12:00 am
2259
+ split: {
2260
+ dateTime: "DD/MM/YYYY h:mm A",
2261
+ // 17/04/2022 12:00 am
2262
+ date: "DD/MM/YYYY"
2263
+ // 17/04/2022
2264
+ },
2265
+ paramCase: {
2266
+ dateTime: "DD-MM-YYYY h:mm A",
2267
+ // 17-04-2022 12:00 am
2268
+ date: "DD-MM-YYYY",
2269
+ // 17-04-2022
2270
+ dateReverse: "YYYY-MM-DD",
2271
+ // 2022-04-17 for compare date
2272
+ MonthYear: "MMM-YYYY"
2273
+ }
2274
+ };
2275
+ var isValidDate = (date) => date !== null && date !== void 0 && dayjs(date).isValid();
2276
+ function today(template) {
2277
+ return dayjs(/* @__PURE__ */ new Date()).startOf("day").format(template);
2278
+ }
2279
+ function fDateTime(date, template) {
2280
+ if (!isValidDate(date)) {
2281
+ return "Invalid date";
2282
+ }
2283
+ return dayjs(date).format(template ?? formatPatterns.dateTime);
2284
+ }
2285
+ function fDate(date, template) {
2286
+ if (!isValidDate(date)) {
2287
+ return "Invalid date";
2288
+ }
2289
+ return dayjs(date).format(template ?? formatPatterns.date);
2290
+ }
2291
+ function fTime(date, template) {
2292
+ if (!isValidDate(date)) {
2293
+ return "Invalid date";
2294
+ }
2295
+ return dayjs(date).format(template ?? formatPatterns.time);
2296
+ }
2297
+ function fTimestamp(date) {
2298
+ if (!isValidDate(date)) {
2299
+ return "Invalid date";
2300
+ }
2301
+ return dayjs(date).valueOf();
2302
+ }
2303
+ function fToNow(date) {
2304
+ if (!isValidDate(date)) {
2305
+ return "Invalid date";
2306
+ }
2307
+ return dayjs(date).toNow(true);
2308
+ }
2309
+ function fIsBetween(inputDate, startDate, endDate) {
2310
+ if (!isValidDate(inputDate) || !isValidDate(startDate) || !isValidDate(endDate)) {
2311
+ return false;
2312
+ }
2313
+ const formattedInputDate = fTimestamp(inputDate);
2314
+ const formattedStartDate = fTimestamp(startDate);
2315
+ const formattedEndDate = fTimestamp(endDate);
2316
+ if (formattedInputDate === "Invalid date" || formattedStartDate === "Invalid date" || formattedEndDate === "Invalid date") {
2317
+ return false;
2318
+ }
2319
+ return formattedInputDate >= formattedStartDate && formattedInputDate <= formattedEndDate;
2320
+ }
2321
+ function fIsAfter(startDate, endDate) {
2322
+ if (!isValidDate(startDate) || !isValidDate(endDate)) {
2323
+ return false;
2324
+ }
2325
+ return dayjs(startDate).isAfter(endDate);
2326
+ }
2327
+ function fIsSame(startDate, endDate, unitToCompare) {
2328
+ if (!isValidDate(startDate) || !isValidDate(endDate)) {
2329
+ return false;
2330
+ }
2331
+ return dayjs(startDate).isSame(endDate, unitToCompare ?? "year");
2332
+ }
2333
+ function fDateRangeShortLabel(startDate, endDate, initial) {
2334
+ if (!isValidDate(startDate) || !isValidDate(endDate) || fIsAfter(startDate, endDate)) {
2335
+ return "Invalid date";
2336
+ }
2337
+ let label = `${fDate(startDate)} - ${fDate(endDate)}`;
2338
+ if (initial) {
2339
+ return label;
2340
+ }
2341
+ const isSameYear = fIsSame(startDate, endDate, "year");
2342
+ const isSameMonth = fIsSame(startDate, endDate, "month");
2343
+ const isSameDay = fIsSame(startDate, endDate, "day");
2344
+ if (isSameYear && !isSameMonth) {
2345
+ label = `${fDate(startDate, "DD MMM")} - ${fDate(endDate)}`;
2346
+ } else if (isSameYear && isSameMonth && !isSameDay) {
2347
+ label = `${fDate(startDate, "DD")} - ${fDate(endDate)}`;
2348
+ } else if (isSameYear && isSameMonth && isSameDay) {
2349
+ label = `${fDate(endDate)}`;
2350
+ }
2351
+ return label;
2352
+ }
2353
+ function fAdd({
2354
+ years = 0,
2355
+ months = 0,
2356
+ days = 0,
2357
+ hours = 0,
2358
+ minutes = 0,
2359
+ seconds = 0,
2360
+ milliseconds = 0
2361
+ }) {
2362
+ const result = dayjs().add(
2363
+ dayjs.duration({
2364
+ years,
2365
+ months,
2366
+ days,
2367
+ hours,
2368
+ minutes,
2369
+ seconds,
2370
+ milliseconds
2371
+ })
2372
+ ).format();
2373
+ return result;
2374
+ }
2375
+ function fSub({
2376
+ years = 0,
2377
+ months = 0,
2378
+ days = 0,
2379
+ hours = 0,
2380
+ minutes = 0,
2381
+ seconds = 0,
2382
+ milliseconds = 0
2383
+ }) {
2384
+ const result = dayjs().subtract(
2385
+ dayjs.duration({
2386
+ years,
2387
+ months,
2388
+ days,
2389
+ hours,
2390
+ minutes,
2391
+ seconds,
2392
+ milliseconds
2393
+ })
2394
+ ).format();
2395
+ return result;
2396
+ }
2397
+
2398
+ // src/core/utils/getEmptyObject.ts
2399
+ function getEmptyObject(data, defaultValues = {}) {
2400
+ const obj = {};
2401
+ for (const key of Object.keys(data)) {
2402
+ const value = data[key];
2403
+ const type = typeof value;
2404
+ if (type === "number") {
2405
+ obj[key] = 0;
2406
+ } else if (type === "string" || type === "boolean") {
2407
+ obj[key] = null;
2408
+ } else if (value instanceof Date) {
2409
+ obj[key] = null;
2410
+ } else {
2411
+ obj[key] = null;
2412
+ }
2413
+ }
2414
+ return { ...obj, ...defaultValues };
2415
+ }
2416
+
2417
+ // src/core/utils/useStableRowCount.ts
2418
+ import { useRef, useMemo as useMemo6 } from "react";
2419
+ function useStableRowCount(currentTotal) {
2420
+ const rowCountRef = useRef(currentTotal || 0);
2421
+ const stableRowCount = useMemo6(() => {
2422
+ if (currentTotal !== void 0) {
2423
+ rowCountRef.current = currentTotal;
2424
+ }
2425
+ return rowCountRef.current;
2426
+ }, [currentTotal]);
2427
+ return stableRowCount;
2428
+ }
2429
+
2430
+ export {
2431
+ generateCorrelationId,
2432
+ RequestManager,
2433
+ ApiClient,
2434
+ createApiClient,
2435
+ getGlobalApiClient,
2436
+ setGlobalApiClient,
2437
+ resetGlobalApiClient,
2438
+ CancelToken,
2439
+ useValidationErrors,
2440
+ AuthorizedView,
2441
+ CancelButton,
2442
+ ClearButton,
2443
+ SimpleContainer,
2444
+ FilterButton,
2445
+ FilterChip,
2446
+ ProgramsFilterDisplay,
2447
+ FilterWrapper,
2448
+ Footer,
2449
+ LabelText,
2450
+ RenderIf,
2451
+ SectionBox,
2452
+ SimpleTabs,
2453
+ SubmitButton,
2454
+ withDataModal,
2455
+ Config,
2456
+ dateTimePatterns,
2457
+ useApiClient,
2458
+ useFormErrorHandler,
2459
+ useDeleteHandler,
2460
+ CacheUtility,
2461
+ useCacheUtility,
2462
+ useWatchForm,
2463
+ useWatchField,
2464
+ useWatchFields,
2465
+ useWatchTransform,
2466
+ useWatchDefault,
2467
+ useWatchBoolean,
2468
+ useWatchBatch,
2469
+ useWatchConditional,
2470
+ useWatchDebounced,
2471
+ useWatchSelector,
2472
+ typedWatch,
2473
+ calculateFilterCount,
2474
+ formatPatterns,
2475
+ today,
2476
+ fDateTime,
2477
+ fDate,
2478
+ fTime,
2479
+ fTimestamp,
2480
+ fToNow,
2481
+ fIsBetween,
2482
+ fIsAfter,
2483
+ fIsSame,
2484
+ fDateRangeShortLabel,
2485
+ fAdd,
2486
+ fSub,
2487
+ getEmptyObject,
2488
+ useStableRowCount
2489
+ };
2490
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2NvcmUvYXBpL0NvcnJlbGF0aW9uSWRHZW5lcmF0b3IudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0Vycm9ycy9FcnJvck5vcm1hbGl6ZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0ludGVyY2VwdG9ycy9JbnRlcmNlcHRvck1hbmFnZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1JlcXVlc3RNYW5hZ2VyLnRzIiwgIi4uL3NyYy9jb3JlL2FwaS9SZXRyeS9SZXRyeUhhbmRsZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1NpZ25hbHMvU2lnbmFsTWFuYWdlci50cyIsICIuLi9zcmMvY29yZS9hcGkvVXRpbHMvUmVzcG9uc2VQYXJzZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL1V0aWxzL1VybEJ1aWxkZXIudHMiLCAiLi4vc3JjL2NvcmUvYXBpL0FwaUNsaWVudC50cyIsICIuLi9zcmMvY29yZS9hcGkvY3JlYXRlQXBpQ2xpZW50LnRzIiwgIi4uL3NyYy9jb3JlL2FwaS90eXBlcy9DYW5jZWxUb2tlbi50cyIsICIuLi9zcmMvY29yZS9hcGkvdXNlVmFsaWRhdGlvbkVycm9ycy50cyIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0F1dGhvcml6ZWRWaWV3L0F1dGhvcml6ZWRWaWV3LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0NhbmNlbEJ1dHRvbi9DYW5jZWxCdXR0b24udHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvQ2xlYXJCdXR0b24vQ2xlYXJCdXR0b24udHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvQ29udGFpbmVycy9TaW1wbGVDb250YWluZXIudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvRmlsdGVyQnV0dG9uL0ZpbHRlckJ1dHRvbi50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9GaWx0ZXJEaXNwbGF5L0ZpbHRlckNoaXAudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvRmlsdGVyRGlzcGxheS9GaWx0ZXJEaXNwbGF5LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0ZpbHRlcldyYXBwZXIvRmlsdGVyV3JhcHBlci50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9Gb290ZXIvRm9vdGVyLnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL0xhYmVsVGV4dC9MYWJlbFRleHQudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvUmVuZGVySWYvUmVuZGVySWYudHN4IiwgIi4uL3NyYy9jb3JlL2NvbXBvbmVudHMvU2VjdGlvbkJveC9TZWN0aW9uQm94LnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL1NpbXBsZVRhYnMvU2ltcGxlVGFicy50c3giLCAiLi4vc3JjL2NvcmUvY29tcG9uZW50cy9TdWJtaXRCdXR0b24vU3VibWl0QnV0dG9uLnRzeCIsICIuLi9zcmMvY29yZS9jb21wb25lbnRzL1dpdGhSZWYvV2l0aFJlZi50c3giLCAiLi4vc3JjL2NvcmUvY29uZmlnLnRzIiwgIi4uL3NyYy9jb3JlL2hvb2tzL3VzZUFwaUNsaWVudC50cyIsICIuLi9zcmMvY29yZS9ob29rcy91c2VGb3JtRXJyb3JIYW5kbGVyLnRzIiwgIi4uL3NyYy9jb3JlL3V0aWxzL0NhY2hlVXRpbGl0eS9pbmRleC50cyIsICIuLi9zcmMvY29yZS91dGlscy93YXRjaC9jb3JlLnRzIiwgIi4uL3NyYy9jb3JlL3V0aWxzL3dhdGNoL3V0aWxpdGllcy50cyIsICIuLi9zcmMvY29yZS91dGlscy93YXRjaC9pbmRleC50cyIsICIuLi9zcmMvY29yZS91dGlscy9jYWxjdWxhdGVGaWx0ZXJDb3VudC50cyIsICIuLi9zcmMvY29yZS91dGlscy9mb3JtYXQtdGltZS50cyIsICIuLi9zcmMvY29yZS91dGlscy9nZXRFbXB0eU9iamVjdC50cyIsICIuLi9zcmMvY29yZS91dGlscy91c2VTdGFibGVSb3dDb3VudC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZW92ZXJ2aWV3IFV0aWxpdGllcyBmb3IgZ2VuZXJhdGluZyBjb3JyZWxhdGlvbiBJRHMgZm9yIGRpc3RyaWJ1dGVkIHJlcXVlc3QgdHJhY2luZy5cbiAqXG4gKiBDb3JyZWxhdGlvbiBJRHMgYXJlIHVuaXF1ZSBpZGVudGlmaWVycyBhdHRhY2hlZCB0byBlYWNoIEFQSSByZXF1ZXN0IHRvIGVuYWJsZVxuICogdHJhY2tpbmcgYW5kIGRlYnVnZ2luZyBhY3Jvc3MgZGlzdHJpYnV0ZWQgc3lzdGVtcywgbWljcm9zZXJ2aWNlcywgYW5kIGxvZyBhZ2dyZWdhdGlvbi5cbiAqXG4gKiBAbW9kdWxlIENvcnJlbGF0aW9uSWRHZW5lcmF0b3JcbiAqL1xuXG4vKipcbiAqIEdlbmVyYXRlcyBhIGNyeXB0b2dyYXBoaWNhbGx5IHJhbmRvbSBVVUlEIHY0IHN0cmluZy5cbiAqXG4gKiBQcmVmZXJzIG5hdGl2ZSBgY3J5cHRvLnJhbmRvbVVVSUQoKWAgd2hlbiBhdmFpbGFibGUgKG1vZGVybiBicm93c2VycyBhbmQgTm9kZS5qcyAxOSspLFxuICogZmFsbGluZyBiYWNrIHRvIGEgY29tcGxpYW50IFVVSUQgdjQgaW1wbGVtZW50YXRpb24gdXNpbmcgYE1hdGgucmFuZG9tKClgLlxuICpcbiAqIEBpbnRlcm5hbCBUaGlzIGZ1bmN0aW9uIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXG4gKiBAcmV0dXJucyBBIFVVSUQgdjQgc3RyaW5nIGluIHRoZSBmb3JtYXQgYHh4eHh4eHh4LXh4eHgtNHh4eC15eHh4LXh4eHh4eHh4eHh4eGBcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgdXVpZCA9IGdlbmVyYXRlVVVJRCgpO1xuICogLy8gPT4gXCJhMWIyYzNkNC1lNWY2LTQ3ODktYTAxMi1iM2M0ZDVlNmY3YThcIlxuICogYGBgXG4gKi9cbmZ1bmN0aW9uIGdlbmVyYXRlVVVJRCgpOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIGNyeXB0byAhPT0gJ3VuZGVmaW5lZCcgJiYgY3J5cHRvLnJhbmRvbVVVSUQpIHtcbiAgICByZXR1cm4gY3J5cHRvLnJhbmRvbVVVSUQoKTtcbiAgfVxuXG4gIC8vIEZhbGxiYWNrIFVVSUQgdjQgZ2VuZXJhdG9yXG4gIHJldHVybiAneHh4eHh4eHgteHh4eC00eHh4LXl4eHgteHh4eHh4eHh4eHh4Jy5yZXBsYWNlKC9beHldL2csIGMgPT4ge1xuICAgIGNvbnN0IHIgPSAoTWF0aC5yYW5kb20oKSAqIDE2KSB8IDA7XG4gICAgY29uc3QgdiA9IGMgPT09ICd4JyA/IHIgOiAociAmIDB4MykgfCAweDg7XG5cbiAgICByZXR1cm4gdi50b1N0cmluZygxNik7XG4gIH0pO1xufVxuXG4vKipcbiAqIEdlbmVyYXRlcyBhIHVuaXF1ZSBjb3JyZWxhdGlvbiBJRCBmb3IgQVBJIHJlcXVlc3QgdHJhY2tpbmcgYW5kIGRpc3RyaWJ1dGVkIHRyYWNpbmcuXG4gKlxuICogQ29ycmVsYXRpb24gSURzIGhlbHAgdHJhY2sgcmVxdWVzdHMgYWNyb3NzIG11bHRpcGxlIHNlcnZpY2VzIGFuZCBzeXN0ZW1zLiBUaGV5IGFyZVxuICogYXV0b21hdGljYWxseSBhdHRhY2hlZCB0byBvdXRnb2luZyByZXF1ZXN0cyB2aWEgSFRUUCBoZWFkZXJzIChgWC1Db3JyZWxhdGlvbi1JZGAgYW5kXG4gKiBgWC1SZXF1ZXN0LUlkYCkgYW5kIGNhbiBiZSB1c2VkIHRvOlxuICogLSBDb3JyZWxhdGUgbG9ncyBhY3Jvc3MgZGlzdHJpYnV0ZWQgc3lzdGVtc1xuICogLSBUcmFjayByZXF1ZXN0IGZsb3dzIGluIG1pY3Jvc2VydmljZXMgYXJjaGl0ZWN0dXJlc1xuICogLSBEZWJ1ZyBpc3N1ZXMgYnkgdHJhY2luZyBhIHNwZWNpZmljIHJlcXVlc3QncyBqb3VybmV5XG4gKiAtIE1vbml0b3IgcGVyZm9ybWFuY2UgYWNyb3NzIHNlcnZpY2UgYm91bmRhcmllc1xuICpcbiAqIFRoZSBnZW5lcmF0ZWQgSUQgZm9sbG93cyB0aGUgZm9ybWF0OiBge3ByZWZpeH0te3V1aWR9YCBvciBqdXN0IGB7dXVpZH1gIGlmIG5vIHByZWZpeCBpcyBwcm92aWRlZC5cbiAqXG4gKiBAcGFyYW0gcHJlZml4IC0gT3B0aW9uYWwgcHJlZml4IHRvIG5hbWVzcGFjZSBjb3JyZWxhdGlvbiBJRHMgYnkgY29udGV4dCAoZS5nLiwgJ2FwaScsICd3ZWInLCAnbW9iaWxlJylcbiAqIEByZXR1cm5zIEEgY29ycmVsYXRpb24gSUQgc3RyaW5nLCBvcHRpb25hbGx5IHByZWZpeGVkXG4gKiBAcHVibGljXG4gKlxuICogQGV4YW1wbGVcbiAqIEJhc2ljIHVzYWdlOlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgaWQgPSBnZW5lcmF0ZUNvcnJlbGF0aW9uSWQoKTtcbiAqIC8vID0+IFwiYTFiMmMzZDQtZTVmNi00Nzg5LWEwMTItYjNjNGQ1ZTZmN2E4XCJcbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIHByZWZpeCBmb3IgY29udGV4dCBpZGVudGlmaWNhdGlvbjpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHdlYklkID0gZ2VuZXJhdGVDb3JyZWxhdGlvbklkKCd3ZWInKTtcbiAqIC8vID0+IFwid2ViLWExYjJjM2Q0LWU1ZjYtNDc4OS1hMDEyLWIzYzRkNWU2ZjdhOFwiXG4gKlxuICogY29uc3QgYXBpSWQgPSBnZW5lcmF0ZUNvcnJlbGF0aW9uSWQoJ2FwaScpO1xuICogLy8gPT4gXCJhcGktZjFlMmQzYzQtYjVhNi00OTg3LWEwMTItYjNjNGQ1ZTZmN2E4XCJcbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBDb25maWd1cmluZyBpbiBBcGlDbGllbnQ6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScpO1xuICogY2xpZW50LnNldENvcnJlbGF0aW9uSWRQcmVmaXgoJ21vYmlsZScpO1xuICogLy8gQWxsIHJlcXVlc3RzIHdpbGwgaGF2ZSBjb3JyZWxhdGlvbiBJRHMgbGlrZSBcIm1vYmlsZS17dXVpZH1cIlxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZUNvcnJlbGF0aW9uSWQocHJlZml4Pzogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgdXVpZCA9IGdlbmVyYXRlVVVJRCgpO1xuXG4gIHJldHVybiBwcmVmaXggPyBgJHtwcmVmaXh9LSR7dXVpZH1gIDogdXVpZDtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IEFwaUVycm9yIH0gZnJvbSAnLi4vdHlwZXMvQXBpRXJyb3InO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0Q29uZmlnIH0gZnJvbSAnLi4vdHlwZXMvUmVxdWVzdENvbmZpZyc7XG5cbi8qKlxuICogTm9ybWFsaXplcyB2YXJpb3VzIGVycm9yIHR5cGVzIGludG8gYSBjb25zaXN0ZW50LCBzdHJ1Y3R1cmVkIEFwaUVycm9yIGZvcm1hdC5cbiAqXG4gKiBUaGlzIGludGVybmFsIGNsYXNzIGhhbmRsZXMgdGhlIGNvbXBsZXggdGFzayBvZiBjb252ZXJ0aW5nIGFueSB0eXBlIG9mIGVycm9yXG4gKiAobmV0d29yayBlcnJvcnMsIEhUVFAgZXJyb3JzLCBhYm9ydCBlcnJvcnMsIHRpbWVvdXRzLCBldGMuKSBpbnRvIGEgc3RhbmRhcmRpemVkXG4gKiB7QGxpbmsgQXBpRXJyb3J9IHN0cnVjdHVyZSB3aXRoIHByb3BlciBjYXRlZ29yaXphdGlvbiBhbmQgbWV0YWRhdGEuXG4gKlxuICogS2V5IEZlYXR1cmVzOlxuICogLSAqKkVycm9yIENhdGVnb3JpemF0aW9uKio6IENsYXNzaWZpZXMgZXJyb3JzIGJ5IHR5cGUgKHZhbGlkYXRpb24sIGNsaWVudCwgc2VydmVyLCBuZXR3b3JrLCBldGMuKVxuICogLSAqKkhUVFAgU3RhdHVzIE1hcHBpbmcqKjogQ29udmVydHMgc3RhdHVzIGNvZGVzIHRvIGh1bWFuLXJlYWRhYmxlIHRpdGxlc1xuICogLSAqKkNvcnJlbGF0aW9uIElEIFRyYWNraW5nKio6IFByZXNlcnZlcyBvciBpbmplY3RzIGNvcnJlbGF0aW9uIElEcyBmb3IgdHJhY2luZ1xuICogLSAqKkFib3J0IERldGVjdGlvbioqOiBJZGVudGlmaWVzIGFuZCBwcm9wZXJseSBoYW5kbGVzIHJlcXVlc3QgY2FuY2VsbGF0aW9uc1xuICogLSAqKkNvbnNpc3RlbnQgU3RydWN0dXJlKio6IEVuc3VyZXMgYWxsIGVycm9ycyBjb25mb3JtIHRvIHRoZSBBcGlFcnJvciBpbnRlcmZhY2VcbiAqXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxuICovXG5leHBvcnQgY2xhc3MgRXJyb3JOb3JtYWxpemVyIHtcbiAgLyoqXG4gICAqIE1hcHMgYW4gSFRUUCBzdGF0dXMgY29kZSB0byBhIHN0YW5kYXJkaXplZCBlcnJvciB0eXBlIGNhdGVnb3J5LlxuICAgKlxuICAgKiBUaGlzIGNhdGVnb3JpemF0aW9uIGhlbHBzIGNvbnN1bWVycyBoYW5kbGUgZGlmZmVyZW50IGVycm9yIGNsYXNzZXMgYXBwcm9wcmlhdGVseTpcbiAgICogLSBgdmFsaWRhdGlvbl9lcnJvcmAgKDQwMCk6IENsaWVudCBzZW50IGludmFsaWQgZGF0YVxuICAgKiAtIGBjbGllbnRfZXJyb3JgICg0MDEtNDk5KTogQ2xpZW50LXNpZGUgaXNzdWVzIChhdXRoLCBwZXJtaXNzaW9ucywgbm90IGZvdW5kLCBldGMuKVxuICAgKiAtIGBzZXJ2ZXJfZXJyb3JgICg1MDAtNTk5KTogU2VydmVyLXNpZGUgZmFpbHVyZXNcbiAgICogLSBgdW5rbm93bl9lcnJvcmA6IFVucmVjb2duaXplZCBzdGF0dXMgY29kZXNcbiAgICpcbiAgICogQHBhcmFtIHN0YXR1cyAtIEhUVFAgc3RhdHVzIGNvZGUgZnJvbSB0aGUgcmVzcG9uc2VcbiAgICogQHJldHVybnMgVGhlIGVycm9yIHR5cGUgY2F0ZWdvcnkgYXMgYSBzdHJpbmdcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBub3JtYWxpemVyLmdldEVycm9yVHlwZSg0MDApOyAvLyA9PiAndmFsaWRhdGlvbl9lcnJvcidcbiAgICogbm9ybWFsaXplci5nZXRFcnJvclR5cGUoNDA0KTsgLy8gPT4gJ2NsaWVudF9lcnJvcidcbiAgICogbm9ybWFsaXplci5nZXRFcnJvclR5cGUoNTAwKTsgLy8gPT4gJ3NlcnZlcl9lcnJvcidcbiAgICogbm9ybWFsaXplci5nZXRFcnJvclR5cGUoMCk7ICAgLy8gPT4gJ3Vua25vd25fZXJyb3InXG4gICAqIGBgYFxuICAgKi9cbiAgZ2V0RXJyb3JUeXBlKHN0YXR1czogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBpZiAoc3RhdHVzID49IDQwMCAmJiBzdGF0dXMgPCA1MDApIHtcbiAgICAgIHJldHVybiBzdGF0dXMgPT09IDQwMCA/ICd2YWxpZGF0aW9uX2Vycm9yJyA6ICdjbGllbnRfZXJyb3InO1xuICAgIH0gZWxzZSBpZiAoc3RhdHVzID49IDUwMCkge1xuICAgICAgcmV0dXJuICdzZXJ2ZXJfZXJyb3InO1xuICAgIH1cblxuICAgIHJldHVybiAndW5rbm93bl9lcnJvcic7XG4gIH1cblxuICAvKipcbiAgICogTWFwcyBhbiBIVFRQIHN0YXR1cyBjb2RlIHRvIGEgaHVtYW4tcmVhZGFibGUgZXJyb3IgdGl0bGUuXG4gICAqXG4gICAqIFByb3ZpZGVzIHVzZXItZnJpZW5kbHkgZXJyb3IgbWVzc2FnZXMgZm9yIGNvbW1vbiBIVFRQIHN0YXR1cyBjb2Rlcy5cbiAgICogRmFsbHMgYmFjayB0byBhIGdlbmVyaWMgXCJIVFRQIEVycm9yIHtzdGF0dXN9XCIgZm9ybWF0IGZvciB1bm1hcHBlZCBjb2Rlcy5cbiAgICpcbiAgICogQHBhcmFtIHN0YXR1cyAtIEhUVFAgc3RhdHVzIGNvZGUgZnJvbSB0aGUgcmVzcG9uc2VcbiAgICogQHJldHVybnMgQSBodW1hbi1yZWFkYWJsZSBlcnJvciB0aXRsZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIG5vcm1hbGl6ZXIuZ2V0RXJyb3JUaXRsZSg0MDQpOyAvLyA9PiAnTm90IEZvdW5kJ1xuICAgKiBub3JtYWxpemVyLmdldEVycm9yVGl0bGUoNTAwKTsgLy8gPT4gJ0ludGVybmFsIFNlcnZlciBFcnJvcidcbiAgICogbm9ybWFsaXplci5nZXRFcnJvclRpdGxlKDk5OSk7IC8vID0+ICdIVFRQIEVycm9yIDk5OSdcbiAgICogYGBgXG4gICAqL1xuICBnZXRFcnJvclRpdGxlKHN0YXR1czogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBjb25zdCB0aXRsZXM6IFJlY29yZDxudW1iZXIsIHN0cmluZz4gPSB7XG4gICAgICA0MDA6ICdCYWQgUmVxdWVzdCcsXG4gICAgICA0MDE6ICdVbmF1dGhvcml6ZWQnLFxuICAgICAgNDAzOiAnRm9yYmlkZGVuJyxcbiAgICAgIDQwNDogJ05vdCBGb3VuZCcsXG4gICAgICA0MDU6ICdNZXRob2QgTm90IEFsbG93ZWQnLFxuICAgICAgNDA4OiAnUmVxdWVzdCBUaW1lb3V0JyxcbiAgICAgIDQwOTogJ0NvbmZsaWN0JyxcbiAgICAgIDQyMjogJ1VucHJvY2Vzc2FibGUgRW50aXR5JyxcbiAgICAgIDQyOTogJ1RvbyBNYW55IFJlcXVlc3RzJyxcbiAgICAgIDUwMDogJ0ludGVybmFsIFNlcnZlciBFcnJvcicsXG4gICAgICA1MDI6ICdCYWQgR2F0ZXdheScsXG4gICAgICA1MDM6ICdTZXJ2aWNlIFVuYXZhaWxhYmxlJyxcbiAgICAgIDUwNDogJ0dhdGV3YXkgVGltZW91dCcsXG4gICAgfTtcblxuICAgIHJldHVybiB0aXRsZXNbc3RhdHVzXSB8fCBgSFRUUCBFcnJvciAke3N0YXR1c31gO1xuICB9XG5cbiAgLyoqXG4gICAqIE5vcm1hbGl6ZXMgYW55IGVycm9yIGludG8gYSBjb25zaXN0ZW50LCBzdHJ1Y3R1cmVkIEFwaUVycm9yIGZvcm1hdC5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgaGFuZGxlcyB2YXJpb3VzIGVycm9yIHNjZW5hcmlvcyBhbmQgZW5zdXJlcyB0aGV5IGFsbCBjb25mb3JtIHRvXG4gICAqIHRoZSB7QGxpbmsgQXBpRXJyb3J9IGludGVyZmFjZSB3aXRoIGFwcHJvcHJpYXRlIGNhdGVnb3JpemF0aW9uIGFuZCBtZXRhZGF0YTpcbiAgICpcbiAgICogLSAqKkV4aXN0aW5nIEFwaUVycm9ycyoqOiBFbmhhbmNlcyB3aXRoIG1pc3NpbmcgZmllbGRzICh0cmFjZUlkLCBjb25maWcpXG4gICAqIC0gKipBYm9ydEVycm9ycyoqOiBNYXJrcyBhcyBgcmVxdWVzdF9jYW5jZWxsZWRgIHdpdGggaXNBYm9ydGVkIGZsYWdcbiAgICogLSAqKlRpbWVvdXQgRXJyb3JzKio6IENhdGVnb3JpemVzIGFzIGB0aW1lb3V0X2Vycm9yYCB3aXRoIDQwOCBzdGF0dXNcbiAgICogLSAqKk5ldHdvcmsgRXJyb3JzKio6IENhdGVnb3JpemVzIGFzIGBuZXR3b3JrX2Vycm9yYCB3aXRoIDAgc3RhdHVzXG4gICAqIC0gKipVbmtub3duIEVycm9ycyoqOiBGYWxsYmFjayBjYXRlZ29yeSBmb3IgdW5leHBlY3RlZCBlcnJvciB0eXBlc1xuICAgKlxuICAgKiBBbGwgbm9ybWFsaXplZCBlcnJvcnMgaW5jbHVkZTpcbiAgICogLSBgdHlwZWA6IEVycm9yIGNhdGVnb3J5IGZvciBwcm9ncmFtbWF0aWMgaGFuZGxpbmdcbiAgICogLSBgdGl0bGVgOiBIdW1hbi1yZWFkYWJsZSBlcnJvciB0aXRsZVxuICAgKiAtIGBzdGF0dXNgOiBIVFRQIHN0YXR1cyBjb2RlIChvciAwIGZvciBub24tSFRUUCBlcnJvcnMpXG4gICAqIC0gYHRyYWNlSWRgOiBDb3JyZWxhdGlvbiBJRCBmb3IgZGlzdHJpYnV0ZWQgdHJhY2luZ1xuICAgKiAtIGBpc0Fib3J0ZWRgOiBCb29sZWFuIGZsYWcgaW5kaWNhdGluZyBpZiByZXF1ZXN0IHdhcyBjYW5jZWxsZWRcbiAgICogLSBgY29uZmlnYDogT3JpZ2luYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uIGZvciBkZWJ1Z2dpbmdcbiAgICpcbiAgICogQHBhcmFtIGVycm9yIC0gVGhlIGVycm9yIHRvIG5vcm1hbGl6ZSAoY2FuIGJlIGFueSB0eXBlKVxuICAgKiBAcGFyYW0gY29uZmlnIC0gVGhlIHJlcXVlc3QgY29uZmlndXJhdGlvbiB0aGF0IGxlZCB0byB0aGlzIGVycm9yXG4gICAqIEBwYXJhbSBjb3JyZWxhdGlvbklkIC0gT3B0aW9uYWwgY29ycmVsYXRpb24gSUQgZm9yIHRyYWNpbmdcbiAgICogQHJldHVybnMgQSBmdWxseSBzdHJ1Y3R1cmVkIEFwaUVycm9yIGluc3RhbmNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIE5vcm1hbGl6aW5nIGEgZmV0Y2ggQWJvcnRFcnJvcjpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiB0cnkge1xuICAgKiAgIGF3YWl0IGZldGNoKHVybCwgeyBzaWduYWwgfSk7XG4gICAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAqICAgY29uc3QgYXBpRXJyb3IgPSBub3JtYWxpemVyLm5vcm1hbGl6ZUVycm9yKGVycm9yLCBjb25maWcsICdyZXEtMTIzJyk7XG4gICAqICAgLy8gYXBpRXJyb3IudHlwZSA9PT0gJ3JlcXVlc3RfY2FuY2VsbGVkJ1xuICAgKiAgIC8vIGFwaUVycm9yLmlzQWJvcnRlZCA9PT0gdHJ1ZVxuICAgKiB9XG4gICAqIGBgYFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBOb3JtYWxpemluZyBhIHRpbWVvdXQ6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdGltZW91dEVycm9yID0gbmV3IEVycm9yKCdSZXF1ZXN0IHRpbWVvdXQgYWZ0ZXIgMzAwMDBtcycpO1xuICAgKiBjb25zdCBhcGlFcnJvciA9IG5vcm1hbGl6ZXIubm9ybWFsaXplRXJyb3IodGltZW91dEVycm9yLCBjb25maWcpO1xuICAgKiAvLyBhcGlFcnJvci50eXBlID09PSAndGltZW91dF9lcnJvcidcbiAgICogLy8gYXBpRXJyb3Iuc3RhdHVzID09PSA0MDhcbiAgICogYGBgXG4gICAqL1xuICBub3JtYWxpemVFcnJvcihcbiAgICBlcnJvcjogdW5rbm93bixcbiAgICBjb25maWc6IFJlcXVlc3RDb25maWcsXG4gICAgY29ycmVsYXRpb25JZD86IHN0cmluZ1xuICApOiBBcGlFcnJvciB7XG4gICAgY29uc3QgZXJyID0gZXJyb3IgYXMgUGFydGlhbDxBcGlFcnJvcj4gJiBFcnJvcjtcblxuICAgIC8vIElmIGVycm9yIGFscmVhZHkgaGFzIEFwaUVycm9yIHN0cnVjdHVyZSwgZW5oYW5jZSBpdFxuICAgIGlmIChlcnIudHlwZSB8fCBlcnIudGl0bGUgfHwgZXJyLmVycm9ycykge1xuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oXG4gICAgICAgIGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyIDogbmV3IEVycm9yKGVyci5tZXNzYWdlIHx8ICdVbmtub3duIGVycm9yJyksXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBlcnIudHlwZSxcbiAgICAgICAgICB0aXRsZTogZXJyLnRpdGxlLFxuICAgICAgICAgIHN0YXR1czogZXJyLnN0YXR1cyxcbiAgICAgICAgICB0cmFjZUlkOiBlcnIudHJhY2VJZCB8fCBjb3JyZWxhdGlvbklkLFxuICAgICAgICAgIGVycm9yczogZXJyLmVycm9ycyxcbiAgICAgICAgICBpc0Fib3J0ZWQ6IGVyci5pc0Fib3J0ZWQgfHwgZmFsc2UsXG4gICAgICAgICAgY29uZmlnLFxuICAgICAgICB9XG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChlcnIubmFtZSA9PT0gJ0Fib3J0RXJyb3InIHx8IGVyci5pc0Fib3J0ZWQpIHtcbiAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKG5ldyBFcnJvcihlcnIubWVzc2FnZSB8fCAnUmVxdWVzdCB3YXMgYWJvcnRlZCcpLCB7XG4gICAgICAgIHR5cGU6ICdyZXF1ZXN0X2NhbmNlbGxlZCcsXG4gICAgICAgIHRpdGxlOiAnUmVxdWVzdCB3YXMgY2FuY2VsbGVkJyxcbiAgICAgICAgc3RhdHVzOiAwLFxuICAgICAgICB0cmFjZUlkOiBjb3JyZWxhdGlvbklkLFxuICAgICAgICBpc0Fib3J0ZWQ6IHRydWUsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgIH0gYXMgQXBpRXJyb3IpO1xuICAgIH1cblxuICAgIGlmIChlcnIubWVzc2FnZT8uaW5jbHVkZXMoJ3RpbWVvdXQnKSkge1xuICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24obmV3IEVycm9yKGVyci5tZXNzYWdlKSwge1xuICAgICAgICB0eXBlOiAndGltZW91dF9lcnJvcicsXG4gICAgICAgIHRpdGxlOiAnUmVxdWVzdCBUaW1lb3V0JyxcbiAgICAgICAgc3RhdHVzOiA0MDgsXG4gICAgICAgIHRyYWNlSWQ6IGNvcnJlbGF0aW9uSWQsXG4gICAgICAgIGlzQWJvcnRlZDogdHJ1ZSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgfSBhcyBBcGlFcnJvcik7XG4gICAgfVxuXG4gICAgaWYgKGVyci5tZXNzYWdlPy5pbmNsdWRlcygnbmV0d29yaycpKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihuZXcgRXJyb3IoZXJyLm1lc3NhZ2UgfHwgJ05ldHdvcmsgcmVxdWVzdCBmYWlsZWQnKSwge1xuICAgICAgICB0eXBlOiAnbmV0d29ya19lcnJvcicsXG4gICAgICAgIHRpdGxlOiAnTmV0d29yayBFcnJvcicsXG4gICAgICAgIHN0YXR1czogMCxcbiAgICAgICAgdHJhY2VJZDogY29ycmVsYXRpb25JZCxcbiAgICAgICAgaXNBYm9ydGVkOiBmYWxzZSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgfSBhcyBBcGlFcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oXG4gICAgICBuZXcgRXJyb3IoZXJyLm1lc3NhZ2UgfHwgJ0FuIHVua25vd24gZXJyb3Igb2NjdXJyZWQnKSxcbiAgICAgIHtcbiAgICAgICAgdHlwZTogJ3Vua25vd25fZXJyb3InLFxuICAgICAgICB0aXRsZTogJ1Vua25vd24gRXJyb3InLFxuICAgICAgICBzdGF0dXM6IDAsXG4gICAgICAgIHRyYWNlSWQ6IGNvcnJlbGF0aW9uSWQsXG4gICAgICAgIGlzQWJvcnRlZDogZmFsc2UsXG4gICAgICAgIGNvbmZpZyxcbiAgICAgIH0gYXMgQXBpRXJyb3JcbiAgICApO1xuICB9XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBBcGlFcnJvciB9IGZyb20gJy4uL3R5cGVzL0FwaUVycm9yJztcbmltcG9ydCB0eXBlIHsgRXJyb3JJbnRlcmNlcHRvciB9IGZyb20gJy4uL3R5cGVzL0Vycm9ySW50ZXJjZXB0b3InO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0Q29uZmlnIH0gZnJvbSAnLi4vdHlwZXMvUmVxdWVzdENvbmZpZyc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RJbnRlcmNlcHRvciB9IGZyb20gJy4uL3R5cGVzL1JlcXVlc3RJbnRlcmNlcHRvcic7XG5pbXBvcnQgdHlwZSB7IFJlc3BvbnNlSW50ZXJjZXB0b3IgfSBmcm9tICcuLi90eXBlcy9SZXNwb25zZUludGVyY2VwdG9yJztcblxuaW1wb3J0IHR5cGUgeyBBcGlSZXNwb25zZSB9IGZyb20gJ0AvdHlwZXMnO1xuXG4vKipcbiAqIE1hbmFnZXMgdGhlIHJlZ2lzdHJhdGlvbiBhbmQgZXhlY3V0aW9uIG9mIHJlcXVlc3QvcmVzcG9uc2UvZXJyb3IgaW50ZXJjZXB0b3JzLlxuICpcbiAqIFRoaXMgaW50ZXJuYWwgY2xhc3MgaW1wbGVtZW50cyB0aGUgaW50ZXJjZXB0b3IgcGF0dGVybiwgYWxsb3dpbmcgbWlkZGxld2FyZS1zdHlsZVxuICogZnVuY3Rpb25zIHRvIGJlIHJlZ2lzdGVyZWQgYW5kIGV4ZWN1dGVkIGF0IGRpZmZlcmVudCBwb2ludHMgaW4gdGhlIHJlcXVlc3QgbGlmZWN5Y2xlOlxuICogLSAqKlJlcXVlc3QgSW50ZXJjZXB0b3JzKio6IE1vZGlmeSByZXF1ZXN0cyBiZWZvcmUgdGhleSBhcmUgc2VudFxuICogLSAqKlJlc3BvbnNlIEludGVyY2VwdG9ycyoqOiBUcmFuc2Zvcm0gcmVzcG9uc2VzIGJlZm9yZSB0aGV5IGFyZSByZXR1cm5lZFxuICogLSAqKkVycm9yIEludGVyY2VwdG9ycyoqOiBIYW5kbGUgb3IgdHJhbnNmb3JtIGVycm9ycyBiZWZvcmUgdGhleSBhcmUgdGhyb3duXG4gKlxuICogSW50ZXJjZXB0b3JzIGFyZSBleGVjdXRlZCBzZXF1ZW50aWFsbHkgaW4gdGhlIG9yZGVyIHRoZXkgd2VyZSByZWdpc3RlcmVkLFxuICogZm9ybWluZyBhIHByb2Nlc3NpbmcgcGlwZWxpbmUuIEVhY2ggaW50ZXJjZXB0b3IgY2FuOlxuICogLSBJbnNwZWN0IHRoZSBkYXRhIHBhc3NpbmcgdGhyb3VnaFxuICogLSBUcmFuc2Zvcm0gb3IgZW5oYW5jZSB0aGUgZGF0YVxuICogLSBTaG9ydC1jaXJjdWl0IHRoZSBwaXBlbGluZSAoZm9yIGVycm9ycylcbiAqIC0gUGVyZm9ybSBzaWRlIGVmZmVjdHMgKGxvZ2dpbmcsIG1vbml0b3JpbmcsIGV0Yy4pXG4gKlxuICogS2V5IEZlYXR1cmVzOlxuICogLSAqKlNlcXVlbnRpYWwgRXhlY3V0aW9uKio6IEludGVyY2VwdG9ycyBydW4gaW4gcmVnaXN0cmF0aW9uIG9yZGVyXG4gKiAtICoqVW5yZWdpc3RyYXRpb24gU3VwcG9ydCoqOiBSZXR1cm5zIGNsZWFudXAgZnVuY3Rpb24gZm9yIGVhY2ggaW50ZXJjZXB0b3JcbiAqIC0gKipUeXBlIFNhZmV0eSoqOiBGdWxseSB0eXBlZCBpbnRlcmNlcHRvciBmdW5jdGlvbnMgd2l0aCBnZW5lcmljc1xuICogLSAqKkVycm9yIEhhbmRsaW5nKio6IEdyYWNlZnVsIGhhbmRsaW5nIG9mIGludGVyY2VwdG9yIGZhaWx1cmVzXG4gKlxuICogQGludGVybmFsIFRoaXMgY2xhc3MgaXMgbm90IGV4cG9ydGVkIGZyb20gdGhlIHB1YmxpYyBBUElcbiAqXG4gKiBAZXhhbXBsZVxuICogQ29tbW9uIGludGVyY2VwdG9yIHBhdHRlcm5zOlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgbWFuYWdlciA9IG5ldyBJbnRlcmNlcHRvck1hbmFnZXIoKTtcbiAqXG4gKiAvLyBSZXF1ZXN0IGxvZ2dpbmdcbiAqIG1hbmFnZXIuYWRkUmVxdWVzdEludGVyY2VwdG9yKGFzeW5jIChjb25maWcpID0+IHtcbiAqICAgY29uc29sZS5sb2coJ1JlcXVlc3Q6JywgY29uZmlnLm1ldGhvZCwgY29uZmlnLnVybCk7XG4gKiAgIHJldHVybiBjb25maWc7XG4gKiB9KTtcbiAqXG4gKiAvLyBSZXNwb25zZSB0cmFuc2Zvcm1hdGlvblxuICogbWFuYWdlci5hZGRSZXNwb25zZUludGVyY2VwdG9yKGFzeW5jIChyZXNwb25zZSkgPT4ge1xuICogICBpZiAocmVzcG9uc2UuZGF0YSkge1xuICogICAgIHJlc3BvbnNlLmRhdGEgPSBjYW1lbENhc2VLZXlzKHJlc3BvbnNlLmRhdGEpO1xuICogICB9XG4gKiAgIHJldHVybiByZXNwb25zZTtcbiAqIH0pO1xuICpcbiAqIC8vIEVycm9yIG1vbml0b3JpbmdcbiAqIG1hbmFnZXIuYWRkRXJyb3JJbnRlcmNlcHRvcihhc3luYyAoZXJyb3IpID0+IHtcbiAqICAgaWYgKGVycm9yLnN0YXR1cyA+PSA1MDApIHtcbiAqICAgICBhd2FpdCBsb2dUb01vbml0b3JpbmcoZXJyb3IpO1xuICogICB9XG4gKiAgIHRocm93IGVycm9yOyAvLyBSZS10aHJvdyB0byBtYWludGFpbiBlcnJvciBmbG93XG4gKiB9KTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgSW50ZXJjZXB0b3JNYW5hZ2VyIHtcbiAgLyoqXG4gICAqIEFycmF5IG9mIHJlZ2lzdGVyZWQgcmVxdWVzdCBpbnRlcmNlcHRvcnNcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVxdWVzdEludGVyY2VwdG9yczogUmVxdWVzdEludGVyY2VwdG9yW10gPSBbXTtcblxuICAvKipcbiAgICogQXJyYXkgb2YgcmVnaXN0ZXJlZCByZXNwb25zZSBpbnRlcmNlcHRvcnNcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVzcG9uc2VJbnRlcmNlcHRvcnM6IFJlc3BvbnNlSW50ZXJjZXB0b3JbXSA9IFtdO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiByZWdpc3RlcmVkIGVycm9yIGludGVyY2VwdG9yc1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBlcnJvckludGVyY2VwdG9yczogRXJyb3JJbnRlcmNlcHRvcltdID0gW107XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHJlcXVlc3QgaW50ZXJjZXB0b3IgdG8gbW9kaWZ5IHJlcXVlc3RzIGJlZm9yZSB0aGV5IGFyZSBzZW50LlxuICAgKlxuICAgKiBSZXF1ZXN0IGludGVyY2VwdG9ycyBjYW46XG4gICAqIC0gQWRkIG9yIG1vZGlmeSBoZWFkZXJzXG4gICAqIC0gVHJhbnNmb3JtIHJlcXVlc3QgYm9kaWVzXG4gICAqIC0gQWRkIHF1ZXJ5IHBhcmFtZXRlcnNcbiAgICogLSBJbXBsZW1lbnQgcmVxdWVzdCBzaWduaW5nXG4gICAqIC0gTG9nIG91dGdvaW5nIHJlcXVlc3RzXG4gICAqXG4gICAqIEBwYXJhbSBpbnRlcmNlcHRvciAtIEFzeW5jIGZ1bmN0aW9uIHRoYXQgcmVjZWl2ZXMgYW5kIHJldHVybnMgUmVxdWVzdENvbmZpZ1xuICAgKiBAcmV0dXJucyBDbGVhbnVwIGZ1bmN0aW9uIHRvIHVucmVnaXN0ZXIgdGhpcyBpbnRlcmNlcHRvclxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIEFkZCBhdXRoZW50aWNhdGlvbiBoZWFkZXJcbiAgICogY29uc3QgdW5yZWdpc3RlciA9IG1hbmFnZXIuYWRkUmVxdWVzdEludGVyY2VwdG9yKGFzeW5jIChjb25maWcpID0+IHtcbiAgICogICBjb25zdCB0b2tlbiA9IGF3YWl0IGdldEF1dGhUb2tlbigpO1xuICAgKiAgIGNvbmZpZy5oZWFkZXJzID0gY29uZmlnLmhlYWRlcnMgfHwgbmV3IEhlYWRlcnMoKTtcbiAgICogICBjb25maWcuaGVhZGVycy5zZXQoJ0F1dGhvcml6YXRpb24nLCBgQmVhcmVyICR7dG9rZW59YCk7XG4gICAqICAgcmV0dXJuIGNvbmZpZztcbiAgICogfSk7XG4gICAqXG4gICAqIC8vIExhdGVyLCByZW1vdmUgdGhlIGludGVyY2VwdG9yXG4gICAqIHVucmVnaXN0ZXIoKTtcbiAgICogYGBgXG4gICAqL1xuICBhZGRSZXF1ZXN0SW50ZXJjZXB0b3IoaW50ZXJjZXB0b3I6IFJlcXVlc3RJbnRlcmNlcHRvcik6ICgpID0+IHZvaWQge1xuICAgIHRoaXMucmVxdWVzdEludGVyY2VwdG9ycy5wdXNoKGludGVyY2VwdG9yKTtcblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMucmVxdWVzdEludGVyY2VwdG9ycy5pbmRleE9mKGludGVyY2VwdG9yKTtcblxuICAgICAgaWYgKGluZGV4ID4gLTEpIHRoaXMucmVxdWVzdEludGVyY2VwdG9ycy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXJzIGEgcmVzcG9uc2UgaW50ZXJjZXB0b3IgdG8gdHJhbnNmb3JtIHJlc3BvbnNlcyBiZWZvcmUgdGhleSBhcmUgcmV0dXJuZWQuXG4gICAqXG4gICAqIFJlc3BvbnNlIGludGVyY2VwdG9ycyBjYW46XG4gICAqIC0gVHJhbnNmb3JtIHJlc3BvbnNlIGRhdGEgZm9ybWF0XG4gICAqIC0gRXh0cmFjdCBuZXN0ZWQgZGF0YSBzdHJ1Y3R1cmVzXG4gICAqIC0gQWRkIGNvbXB1dGVkIHByb3BlcnRpZXNcbiAgICogLSBDYWNoZSByZXNwb25zZXNcbiAgICogLSBMb2cgc3VjY2Vzc2Z1bCByZXNwb25zZXNcbiAgICpcbiAgICogQHBhcmFtIGludGVyY2VwdG9yIC0gQXN5bmMgZnVuY3Rpb24gdGhhdCByZWNlaXZlcyBhbmQgcmV0dXJucyBBcGlSZXNwb25zZVxuICAgKiBAcmV0dXJucyBDbGVhbnVwIGZ1bmN0aW9uIHRvIHVucmVnaXN0ZXIgdGhpcyBpbnRlcmNlcHRvclxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIEV4dHJhY3QgZGF0YSBmcm9tIGVudmVsb3BlXG4gICAqIG1hbmFnZXIuYWRkUmVzcG9uc2VJbnRlcmNlcHRvcihhc3luYyAocmVzcG9uc2UpID0+IHtcbiAgICogICBpZiAocmVzcG9uc2UuZGF0YT8ucmVzdWx0KSB7XG4gICAqICAgICByZXNwb25zZS5kYXRhID0gcmVzcG9uc2UuZGF0YS5yZXN1bHQ7XG4gICAqICAgfVxuICAgKiAgIHJldHVybiByZXNwb25zZTtcbiAgICogfSk7XG4gICAqXG4gICAqIC8vIEFkZCB0aW1lc3RhbXBzXG4gICAqIG1hbmFnZXIuYWRkUmVzcG9uc2VJbnRlcmNlcHRvcihhc3luYyAocmVzcG9uc2UpID0+IHtcbiAgICogICByZXR1cm4ge1xuICAgKiAgICAgLi4ucmVzcG9uc2UsXG4gICAqICAgICByZWNlaXZlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKClcbiAgICogICB9O1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBhZGRSZXNwb25zZUludGVyY2VwdG9yKGludGVyY2VwdG9yOiBSZXNwb25zZUludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XG4gICAgdGhpcy5yZXNwb25zZUludGVyY2VwdG9ycy5wdXNoKGludGVyY2VwdG9yKTtcblxuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMucmVzcG9uc2VJbnRlcmNlcHRvcnMuaW5kZXhPZihpbnRlcmNlcHRvcik7XG5cbiAgICAgIGlmIChpbmRleCA+IC0xKSB0aGlzLnJlc3BvbnNlSW50ZXJjZXB0b3JzLnNwbGljZShpbmRleCwgMSk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYW4gZXJyb3IgaW50ZXJjZXB0b3IgdG8gaGFuZGxlIG9yIHRyYW5zZm9ybSBlcnJvcnMgYmVmb3JlIHRoZXkgYXJlIHRocm93bi5cbiAgICpcbiAgICogRXJyb3IgaW50ZXJjZXB0b3JzIGNhbjpcbiAgICogLSBMb2cgZXJyb3JzIHRvIG1vbml0b3Jpbmcgc2VydmljZXNcbiAgICogLSBUcmFuc2Zvcm0gZXJyb3IgZm9ybWF0c1xuICAgKiAtIEltcGxlbWVudCByZXRyeSBsb2dpY1xuICAgKiAtIFNob3cgdXNlciBub3RpZmljYXRpb25zXG4gICAqIC0gRXh0cmFjdCB2YWxpZGF0aW9uIGVycm9yc1xuICAgKlxuICAgKiAqKk5vdGU6KiogRXJyb3IgaW50ZXJjZXB0b3JzIHNob3VsZCByZS10aHJvdyB0aGUgZXJyb3IgKG9yIGEgdHJhbnNmb3JtZWQgdmVyc2lvbilcbiAgICogdG8gbWFpbnRhaW4gdGhlIGVycm9yIGZsb3cuIFRoZSBmaW5hbCBlcnJvciBpcyBhbHdheXMgdGhyb3duLlxuICAgKlxuICAgKiBAcGFyYW0gaW50ZXJjZXB0b3IgLSBBc3luYyBmdW5jdGlvbiB0aGF0IHJlY2VpdmVzIGFuZCByZXR1cm5zIChvciB0aHJvd3MpIEFwaUVycm9yXG4gICAqIEByZXR1cm5zIENsZWFudXAgZnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gTG9nIHRvIG1vbml0b3Jpbmcgc2VydmljZVxuICAgKiBtYW5hZ2VyLmFkZEVycm9ySW50ZXJjZXB0b3IoYXN5bmMgKGVycm9yKSA9PiB7XG4gICAqICAgaWYgKGVycm9yLnN0YXR1cyA+PSA1MDApIHtcbiAgICogICAgIGF3YWl0IFNlbnRyeS5jYXB0dXJlRXhjZXB0aW9uKGVycm9yLCB7XG4gICAqICAgICAgIGV4dHJhOiB7IHRyYWNlSWQ6IGVycm9yLnRyYWNlSWQgfVxuICAgKiAgICAgfSk7XG4gICAqICAgfVxuICAgKiAgIHRocm93IGVycm9yOyAvLyBSZS10aHJvdyB0byBjb250aW51ZSBlcnJvciBmbG93XG4gICAqIH0pO1xuICAgKlxuICAgKiAvLyBUcmFuc2Zvcm0gZXJyb3IgbWVzc2FnZXNcbiAgICogbWFuYWdlci5hZGRFcnJvckludGVyY2VwdG9yKGFzeW5jIChlcnJvcikgPT4ge1xuICAgKiAgIGlmIChlcnJvci5zdGF0dXMgPT09IDQwNCkge1xuICAgKiAgICAgZXJyb3IudGl0bGUgPSAnUmVzb3VyY2Ugbm90IGZvdW5kJztcbiAgICogICB9XG4gICAqICAgdGhyb3cgZXJyb3I7XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFkZEVycm9ySW50ZXJjZXB0b3IoaW50ZXJjZXB0b3I6IEVycm9ySW50ZXJjZXB0b3IpOiAoKSA9PiB2b2lkIHtcbiAgICB0aGlzLmVycm9ySW50ZXJjZXB0b3JzLnB1c2goaW50ZXJjZXB0b3IpO1xuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGNvbnN0IGluZGV4ID0gdGhpcy5lcnJvckludGVyY2VwdG9ycy5pbmRleE9mKGludGVyY2VwdG9yKTtcblxuICAgICAgaWYgKGluZGV4ID4gLTEpIHRoaXMuZXJyb3JJbnRlcmNlcHRvcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgYWxsIHJlZ2lzdGVyZWQgcmVxdWVzdCBpbnRlcmNlcHRvcnMgaW4gc2VxdWVudGlhbCBvcmRlci5cbiAgICpcbiAgICogRWFjaCBpbnRlcmNlcHRvciByZWNlaXZlcyB0aGUgY29uZmlnIG1vZGlmaWVkIGJ5IHRoZSBwcmV2aW91cyBpbnRlcmNlcHRvcixcbiAgICogZm9ybWluZyBhIHByb2Nlc3NpbmcgcGlwZWxpbmUuIElmIGFueSBpbnRlcmNlcHRvciB0aHJvd3MgYW4gZXJyb3IsXG4gICAqIHRoZSBwaXBlbGluZSBzdG9wcyBhbmQgdGhlIGVycm9yIHByb3BhZ2F0ZXMuXG4gICAqXG4gICAqIEBwYXJhbSBjb25maWcgLSBUaGUgaW5pdGlhbCByZXF1ZXN0IGNvbmZpZ3VyYXRpb25cbiAgICogQHJldHVybnMgVGhlIG1vZGlmaWVkIHJlcXVlc3QgY29uZmlndXJhdGlvbiBhZnRlciBhbGwgaW50ZXJjZXB0b3JzXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgY29uZmlnID0geyBtZXRob2Q6ICdHRVQnLCB1cmw6ICcvdXNlcnMnIH07XG4gICAqIGNvbnN0IGZpbmFsQ29uZmlnID0gYXdhaXQgbWFuYWdlci5hcHBseVJlcXVlc3RJbnRlcmNlcHRvcnMoY29uZmlnKTtcbiAgICogLy8gZmluYWxDb25maWcgaGFzIGJlZW4gcHJvY2Vzc2VkIGJ5IGFsbCByZWdpc3RlcmVkIGludGVyY2VwdG9yc1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGFwcGx5UmVxdWVzdEludGVyY2VwdG9ycyhcbiAgICBjb25maWc6IFJlcXVlc3RDb25maWdcbiAgKTogUHJvbWlzZTxSZXF1ZXN0Q29uZmlnPiB7XG4gICAgbGV0IG1vZGlmaWVkQ29uZmlnID0geyAuLi5jb25maWcgfTtcblxuICAgIGZvciAoY29uc3QgaW50ZXJjZXB0b3Igb2YgdGhpcy5yZXF1ZXN0SW50ZXJjZXB0b3JzKSB7XG4gICAgICBtb2RpZmllZENvbmZpZyA9IGF3YWl0IGludGVyY2VwdG9yKG1vZGlmaWVkQ29uZmlnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kaWZpZWRDb25maWc7XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhbGwgcmVnaXN0ZXJlZCByZXNwb25zZSBpbnRlcmNlcHRvcnMgaW4gc2VxdWVudGlhbCBvcmRlci5cbiAgICpcbiAgICogRWFjaCBpbnRlcmNlcHRvciByZWNlaXZlcyB0aGUgcmVzcG9uc2UgbW9kaWZpZWQgYnkgdGhlIHByZXZpb3VzIGludGVyY2VwdG9yLFxuICAgKiBmb3JtaW5nIGEgcHJvY2Vzc2luZyBwaXBlbGluZS4gSWYgYW55IGludGVyY2VwdG9yIHRocm93cyBhbiBlcnJvcixcbiAgICogdGhlIHBpcGVsaW5lIHN0b3BzIGFuZCB0aGUgZXJyb3IgcHJvcGFnYXRlcy5cbiAgICpcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiB0aGUgcmVzcG9uc2UgZGF0YVxuICAgKiBAcGFyYW0gcmVzcG9uc2UgLSBUaGUgaW5pdGlhbCBBUEkgcmVzcG9uc2VcbiAgICogQHJldHVybnMgVGhlIG1vZGlmaWVkIHJlc3BvbnNlIGFmdGVyIGFsbCBpbnRlcmNlcHRvcnNcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCByZXNwb25zZSA9IHsgZGF0YTogeyBpZDogMSwgbmFtZTogJ0pvaG4nIH0gfTtcbiAgICogY29uc3QgZmluYWxSZXNwb25zZSA9IGF3YWl0IG1hbmFnZXIuYXBwbHlSZXNwb25zZUludGVyY2VwdG9ycyhyZXNwb25zZSk7XG4gICAqIC8vIGZpbmFsUmVzcG9uc2UgaGFzIGJlZW4gcHJvY2Vzc2VkIGJ5IGFsbCByZWdpc3RlcmVkIGludGVyY2VwdG9yc1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGFwcGx5UmVzcG9uc2VJbnRlcmNlcHRvcnM8VD4oXG4gICAgcmVzcG9uc2U6IEFwaVJlc3BvbnNlPFQ+XG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8VD4+IHtcbiAgICBsZXQgbW9kaWZpZWRSZXNwb25zZSA9IHJlc3BvbnNlO1xuXG4gICAgZm9yIChjb25zdCBpbnRlcmNlcHRvciBvZiB0aGlzLnJlc3BvbnNlSW50ZXJjZXB0b3JzKSB7XG4gICAgICBtb2RpZmllZFJlc3BvbnNlID0gYXdhaXQgaW50ZXJjZXB0b3IobW9kaWZpZWRSZXNwb25zZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vZGlmaWVkUmVzcG9uc2U7XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhbGwgcmVnaXN0ZXJlZCBlcnJvciBpbnRlcmNlcHRvcnMgaW4gc2VxdWVudGlhbCBvcmRlciBhbmQgcmUtdGhyb3dzLlxuICAgKlxuICAgKiBFYWNoIGludGVyY2VwdG9yIHJlY2VpdmVzIHRoZSBlcnJvciAocG90ZW50aWFsbHkgbW9kaWZpZWQgYnkgcHJldmlvdXMgaW50ZXJjZXB0b3JzKS5cbiAgICogSW50ZXJjZXB0b3JzIGNhbiB0cmFuc2Zvcm0gdGhlIGVycm9yIGJlZm9yZSByZS10aHJvd2luZyBpdC4gVGhlIGZpbmFsIGVycm9yXG4gICAqIGlzIGFsd2F5cyB0aHJvd24gdG8gbWFpbnRhaW4gZXJyb3IgZmxvdy5cbiAgICpcbiAgICogSWYgYW4gaW50ZXJjZXB0b3IgaXRzZWxmIHRocm93cyBhbiBlcnJvciwgdGhhdCBiZWNvbWVzIHRoZSBuZXcgZXJyb3IgdG8gcHJvY2Vzc1xuICAgKiBieSBzdWJzZXF1ZW50IGludGVyY2VwdG9ycy5cbiAgICpcbiAgICogQHBhcmFtIGVycm9yIC0gVGhlIGluaXRpYWwgQVBJIGVycm9yXG4gICAqIEByZXR1cm5zIE5ldmVyIHJldHVybnMgKGFsd2F5cyB0aHJvd3MpXG4gICAqIEB0aHJvd3MgVGhlIGZpbmFsIGVycm9yIGFmdGVyIGFsbCBpbnRlcmNlcHRvcnMgaGF2ZSBwcm9jZXNzZWQgaXRcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiB0cnkge1xuICAgKiAgIGF3YWl0IG1hbmFnZXIuYXBwbHlFcnJvckludGVyY2VwdG9ycyhlcnJvcik7XG4gICAqIH0gY2F0Y2ggKGZpbmFsRXJyb3IpIHtcbiAgICogICAvLyBmaW5hbEVycm9yIGhhcyBiZWVuIHByb2Nlc3NlZCBieSBhbGwgcmVnaXN0ZXJlZCBlcnJvciBpbnRlcmNlcHRvcnNcbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGFwcGx5RXJyb3JJbnRlcmNlcHRvcnMoZXJyb3I6IEFwaUVycm9yKTogUHJvbWlzZTxuZXZlcj4ge1xuICAgIGxldCBtb2RpZmllZEVycm9yID0gZXJyb3I7XG5cbiAgICBmb3IgKGNvbnN0IGludGVyY2VwdG9yIG9mIHRoaXMuZXJyb3JJbnRlcmNlcHRvcnMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIG1vZGlmaWVkRXJyb3IgPSBhd2FpdCBpbnRlcmNlcHRvcihtb2RpZmllZEVycm9yKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgbW9kaWZpZWRFcnJvciA9IGUgYXMgQXBpRXJyb3I7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbW9kaWZpZWRFcnJvcjtcbiAgfVxufVxuIiwgIi8qKlxuICogTWFuYWdlcyBhY3RpdmUgSFRUUCByZXF1ZXN0cyB3aXRoIHN1cHBvcnQgZm9yIGNhbmNlbGxhdGlvbiBhbmQgY29ycmVsYXRpb24gdHJhY2tpbmcuXG4gKlxuICogVGhpcyBpbnRlcm5hbCBjbGFzcyBtYWludGFpbnMgYSByZWdpc3RyeSBvZiBpbi1mbGlnaHQgcmVxdWVzdHMsIGFsbG93aW5nIHRoZW0gdG8gYmVcbiAqIGNhbmNlbGxlZCBpbmRpdmlkdWFsbHkgb3IgaW4gYnVsay4gRWFjaCByZXF1ZXN0IGlzIHRyYWNrZWQgYnkgYSB1bmlxdWUga2V5IGFuZFxuICogYXNzb2NpYXRlZCB3aXRoIGEgY29ycmVsYXRpb24gSUQgZm9yIGRpc3RyaWJ1dGVkIHRyYWNpbmcuXG4gKlxuICogS2V5IEZlYXR1cmVzOlxuICogLSAqKlJlcXVlc3QgRGVkdXBsaWNhdGlvbioqOiBBdXRvbWF0aWNhbGx5IGNhbmNlbHMgZHVwbGljYXRlIHJlcXVlc3RzIHdpdGggdGhlIHNhbWUga2V5XG4gKiAtICoqQ29ycmVsYXRpb24gVHJhY2tpbmcqKjogTWFwcyByZXF1ZXN0IGtleXMgdG8gY29ycmVsYXRpb24gSURzIGZvciB0cmFjaW5nXG4gKiAtICoqQnVsayBDYW5jZWxsYXRpb24qKjogQ2FuY2VsIGFsbCBwZW5kaW5nIHJlcXVlc3RzIGF0IG9uY2UgKHVzZWZ1bCBmb3IgY2xlYW51cClcbiAqIC0gKipNZW1vcnkgTWFuYWdlbWVudCoqOiBBdXRvbWF0aWNhbGx5IGNsZWFucyB1cCB0cmFja2luZyBkYXRhIHdoZW4gcmVxdWVzdHMgY29tcGxldGVcbiAqXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBtYW5hZ2VyID0gbmV3IFJlcXVlc3RNYW5hZ2VyKCk7XG4gKiBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICpcbiAqIC8vIFRyYWNrIGEgcmVxdWVzdFxuICogbWFuYWdlci5hZGQoJ0dFVF8vdXNlcnMvMTIzJywgY29udHJvbGxlciwgJ2FwaS1hYmMxMjMnKTtcbiAqXG4gKiAvLyBDYW5jZWwgc3BlY2lmaWMgcmVxdWVzdFxuICogbWFuYWdlci5jYW5jZWwoJ0dFVF8vdXNlcnMvMTIzJyk7XG4gKlxuICogLy8gT3IgY2FuY2VsIGFsbCByZXF1ZXN0c1xuICogbWFuYWdlci5jYW5jZWxBbGwoKTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgUmVxdWVzdE1hbmFnZXIge1xuICAvKipcbiAgICogTWFwIG9mIGFjdGl2ZSByZXF1ZXN0IGtleXMgdG8gdGhlaXIgYWJvcnQgY29udHJvbGxlcnNcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgYWN0aXZlUmVxdWVzdHM6IE1hcDxzdHJpbmcsIEFib3J0Q29udHJvbGxlcj4gPSBuZXcgTWFwKCk7XG5cbiAgLyoqXG4gICAqIE1hcCBvZiByZXF1ZXN0IGtleXMgdG8gdGhlaXIgY29ycmVsYXRpb24gSURzIGZvciB0cmFjaW5nXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBwcml2YXRlIGNvcnJlbGF0aW9uTWFwOiBNYXA8c3RyaW5nLCBzdHJpbmc+ID0gbmV3IE1hcCgpO1xuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSBuZXcgcmVxdWVzdCBmb3IgdHJhY2tpbmcgYW5kIGNhbmNlbGxhdGlvbiBtYW5hZ2VtZW50LlxuICAgKlxuICAgKiBJZiBhIHJlcXVlc3Qgd2l0aCB0aGUgc2FtZSBrZXkgYWxyZWFkeSBleGlzdHMsIGl0IHdpbGwgYmUgYXV0b21hdGljYWxseVxuICAgKiBjYW5jZWxsZWQgYmVmb3JlIHRoZSBuZXcgb25lIGlzIHJlZ2lzdGVyZWQgKHJlcXVlc3QgZGVkdXBsaWNhdGlvbikuXG4gICAqXG4gICAqIEBwYXJhbSBrZXkgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHJlcXVlc3QgKHR5cGljYWxseSBtZXRob2QgKyBVUkwgKyB0aW1lc3RhbXApXG4gICAqIEBwYXJhbSBjb250cm9sbGVyIC0gQWJvcnRDb250cm9sbGVyIGZvciBjYW5jZWxsaW5nIHRoZSByZXF1ZXN0XG4gICAqIEBwYXJhbSBjb3JyZWxhdGlvbklkIC0gQ29ycmVsYXRpb24gSUQgZm9yIGRpc3RyaWJ1dGVkIHRyYWNpbmdcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgKiBtYW5hZ2VyLmFkZCgnR0VUXy9hcGkvdXNlcnNfMTY5OTk5OTk5OScsIGNvbnRyb2xsZXIsICdhcGktYWJjMTIzJyk7XG4gICAqIGBgYFxuICAgKi9cbiAgYWRkKGtleTogc3RyaW5nLCBjb250cm9sbGVyOiBBYm9ydENvbnRyb2xsZXIsIGNvcnJlbGF0aW9uSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIC8vIENhbmNlbCBleGlzdGluZyByZXF1ZXN0IHdpdGggc2FtZSBrZXkgaWYgZXhpc3RzXG4gICAgdGhpcy5jYW5jZWwoa2V5KTtcbiAgICB0aGlzLmFjdGl2ZVJlcXVlc3RzLnNldChrZXksIGNvbnRyb2xsZXIpO1xuICAgIHRoaXMuY29ycmVsYXRpb25NYXAuc2V0KGtleSwgY29ycmVsYXRpb25JZCk7XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhIHJlcXVlc3QgZnJvbSB0cmFja2luZyB3aXRob3V0IGNhbmNlbGxpbmcgaXQuXG4gICAqXG4gICAqIFRoaXMgaXMgdHlwaWNhbGx5IGNhbGxlZCB3aGVuIGEgcmVxdWVzdCBjb21wbGV0ZXMgc3VjY2Vzc2Z1bGx5IG9yIGZhaWxzLlxuICAgKiBVc2Uge0BsaW5rIGNhbmNlbH0gaW5zdGVhZCBpZiB5b3UgbmVlZCB0byBhYm9ydCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHBhcmFtIGtleSAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgcmVxdWVzdCB0byByZW1vdmVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiAvLyBDYWxsZWQgYXV0b21hdGljYWxseSBhZnRlciByZXF1ZXN0IGNvbXBsZXRlc1xuICAgKiBtYW5hZ2VyLnJlbW92ZSgnR0VUXy9hcGkvdXNlcnNfMTY5OTk5OTk5OScpO1xuICAgKiBgYGBcbiAgICovXG4gIHJlbW92ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuYWN0aXZlUmVxdWVzdHMuZGVsZXRlKGtleSk7XG4gICAgdGhpcy5jb3JyZWxhdGlvbk1hcC5kZWxldGUoa2V5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYW5jZWxzIGEgc3BlY2lmaWMgcmVxdWVzdCBhbmQgcmVtb3ZlcyBpdCBmcm9tIHRyYWNraW5nLlxuICAgKlxuICAgKiBJZiB0aGUgcmVxdWVzdCBkb2Vzbid0IGV4aXN0IG9yIHdhcyBhbHJlYWR5IGNhbmNlbGxlZCwgdGhpcyBvcGVyYXRpb24gaXMgYSBuby1vcC5cbiAgICogVGhlIGFzc29jaWF0ZWQgQWJvcnRDb250cm9sbGVyJ3Mgc2lnbmFsIHdpbGwgYmUgdHJpZ2dlcmVkLCBjYXVzaW5nIGFueSBhY3RpdmVcbiAgICogZmV0Y2ggb3BlcmF0aW9ucyB0byBhYm9ydC5cbiAgICpcbiAgICogQHBhcmFtIGtleSAtIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgcmVxdWVzdCB0byBjYW5jZWxcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiAvLyBVc2VyIG5hdmlnYXRlcyBhd2F5LCBjYW5jZWwgdGhlIHBlbmRpbmcgcmVxdWVzdFxuICAgKiBtYW5hZ2VyLmNhbmNlbCgnR0VUXy9hcGkvdXNlcnNfMTY5OTk5OTk5OScpO1xuICAgKiBgYGBcbiAgICovXG4gIGNhbmNlbChrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSB0aGlzLmFjdGl2ZVJlcXVlc3RzLmdldChrZXkpO1xuXG4gICAgaWYgKGNvbnRyb2xsZXIpIHtcbiAgICAgIGNvbnRyb2xsZXIuYWJvcnQoKTtcbiAgICAgIHRoaXMuYWN0aXZlUmVxdWVzdHMuZGVsZXRlKGtleSk7XG4gICAgICB0aGlzLmNvcnJlbGF0aW9uTWFwLmRlbGV0ZShrZXkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYW5jZWxzIGFsbCBhY3RpdmUgcmVxdWVzdHMgYW5kIGNsZWFycyBhbGwgdHJhY2tpbmcgZGF0YS5cbiAgICpcbiAgICogVGhpcyBpcyB1c2VmdWwgZm9yIGNsZWFudXAgc2NlbmFyaW9zIHN1Y2ggYXM6XG4gICAqIC0gVXNlciBsb2dvdXRcbiAgICogLSBDb21wb25lbnQgdW5tb3VudFxuICAgKiAtIE5hdmlnYXRpb24gdG8gYSBkaWZmZXJlbnQgcGFydCBvZiB0aGUgYXBwbGljYXRpb25cbiAgICogLSBFcnJvciByZWNvdmVyeSB0aGF0IHJlcXVpcmVzIGEgY2xlYW4gc2xhdGVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiAvLyBDYW5jZWwgYWxsIHBlbmRpbmcgcmVxdWVzdHMgb24gbG9nb3V0XG4gICAqIGZ1bmN0aW9uIGhhbmRsZUxvZ291dCgpIHtcbiAgICogICBhcGlDbGllbnQuY2FuY2VsQWxsUmVxdWVzdHMoKTtcbiAgICogICAvLyAuLi4gcmVzdCBvZiBsb2dvdXQgbG9naWNcbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIGNhbmNlbEFsbCgpOiB2b2lkIHtcbiAgICB0aGlzLmFjdGl2ZVJlcXVlc3RzLmZvckVhY2goY29udHJvbGxlciA9PiBjb250cm9sbGVyLmFib3J0KCkpO1xuICAgIHRoaXMuYWN0aXZlUmVxdWVzdHMuY2xlYXIoKTtcbiAgICB0aGlzLmNvcnJlbGF0aW9uTWFwLmNsZWFyKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2tzIGlmIGEgcmVxdWVzdCB3aXRoIHRoZSBnaXZlbiBrZXkgaXMgY3VycmVudGx5IGJlaW5nIHRyYWNrZWQuXG4gICAqXG4gICAqIEBwYXJhbSBrZXkgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHJlcXVlc3RcbiAgICogQHJldHVybnMgYHRydWVgIGlmIHRoZSByZXF1ZXN0IGlzIGFjdGl2ZSwgYGZhbHNlYCBvdGhlcndpc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBpZiAobWFuYWdlci5oYXMoJ0dFVF8vYXBpL3VzZXJzXzE2OTk5OTk5OTknKSkge1xuICAgKiAgIGNvbnNvbGUubG9nKCdSZXF1ZXN0IGlzIHN0aWxsIHBlbmRpbmcnKTtcbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIGhhcyhrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmFjdGl2ZVJlcXVlc3RzLmhhcyhrZXkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgY29ycmVsYXRpb24gSUQgZm9yIGEgZ2l2ZW4gcmVxdWVzdCBrZXkuXG4gICAqXG4gICAqIENvcnJlbGF0aW9uIElEcyBhcmUgdXNlZCBmb3IgZGlzdHJpYnV0ZWQgdHJhY2luZyBhbmQgcmVxdWVzdCB0cmFja2luZ1xuICAgKiBhY3Jvc3Mgc2VydmljZXMgYW5kIGxvZ3MuXG4gICAqXG4gICAqIEBwYXJhbSBrZXkgLSBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHJlcXVlc3RcbiAgICogQHJldHVybnMgVGhlIGNvcnJlbGF0aW9uIElEIGlmIGZvdW5kLCBgdW5kZWZpbmVkYCBvdGhlcndpc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBjb3JyZWxhdGlvbklkID0gbWFuYWdlci5nZXRDb3JyZWxhdGlvbklkKCdHRVRfL2FwaS91c2Vyc18xNjk5OTk5OTk5Jyk7XG4gICAqIGlmIChjb3JyZWxhdGlvbklkKSB7XG4gICAqICAgY29uc29sZS5sb2coJ1RyYWNlIHJlcXVlc3Qgd2l0aCBJRDonLCBjb3JyZWxhdGlvbklkKTtcbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIGdldENvcnJlbGF0aW9uSWQoa2V5OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmNvcnJlbGF0aW9uTWFwLmdldChrZXkpO1xuICB9XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBBcGlFcnJvciB9IGZyb20gJy4uL3R5cGVzL0FwaUVycm9yJztcblxuLyoqXG4gKiBJbXBsZW1lbnRzIGF1dG9tYXRpYyByZXRyeSBsb2dpYyB3aXRoIGV4cG9uZW50aWFsIGJhY2tvZmYgZm9yIGZhaWxlZCBIVFRQIHJlcXVlc3RzLlxuICpcbiAqIFRoaXMgaW50ZXJuYWwgY2xhc3MgaGFuZGxlcyB0cmFuc2llbnQgZmFpbHVyZXMgYnkgYXV0b21hdGljYWxseSByZXRyeWluZyByZXF1ZXN0c1xuICogd2l0aCBwcm9ncmVzc2l2ZWx5IGluY3JlYXNpbmcgZGVsYXlzIGJldHdlZW4gYXR0ZW1wdHMuIFRoZSBleHBvbmVudGlhbCBiYWNrb2ZmXG4gKiBzdHJhdGVneSBoZWxwcyBwcmV2ZW50IG92ZXJ3aGVsbWluZyBhIHN0cnVnZ2xpbmcgc2VydmVyIHdoaWxlIGdpdmluZyB0ZW1wb3JhcnlcbiAqIGlzc3VlcyB0aW1lIHRvIHJlc29sdmUuXG4gKlxuICogS2V5IEZlYXR1cmVzOlxuICogLSAqKkV4cG9uZW50aWFsIEJhY2tvZmYqKjogRG91YmxlcyBkZWxheSBiZXR3ZWVuIHJldHJpZXMgKGUuZy4sIDFzLCAycywgNHMsIDhzKVxuICogLSAqKlNtYXJ0IEVycm9yIERldGVjdGlvbioqOiBTa2lwcyByZXRyeSBmb3Igbm9uLXJldHJ5YWJsZSBlcnJvcnMgKHZhbGlkYXRpb24sIGFib3J0cylcbiAqIC0gKipBYm9ydCBTdXBwb3J0Kio6IFJlc3BlY3RzIGNhbmNlbGxhdGlvbiBzaWduYWxzIGR1cmluZyByZXRyeSBkZWxheXNcbiAqIC0gKipUeXBlIFNhZmV0eSoqOiBGdWxseSBnZW5lcmljIGltcGxlbWVudGF0aW9uIHByZXNlcnZpbmcgcmV0dXJuIHR5cGVzXG4gKlxuICogUmV0cnkgU3RyYXRlZ3k6XG4gKiAtICoqUmV0cnlhYmxlKio6IE5ldHdvcmsgZXJyb3JzLCA1eHggc2VydmVyIGVycm9ycywgdGltZW91dHNcbiAqIC0gKipOb24tUmV0cnlhYmxlKio6IFZhbGlkYXRpb24gZXJyb3JzICg0MDApLCBBYm9ydEVycm9ycywgY2FuY2VsbGVkIHJlcXVlc3RzXG4gKlxuICogQGludGVybmFsIFRoaXMgY2xhc3MgaXMgbm90IGV4cG9ydGVkIGZyb20gdGhlIHB1YmxpYyBBUElcbiAqXG4gKiBAZXhhbXBsZVxuICogUmV0cnkgY29uZmlndXJhdGlvbiBpbiBBcGlDbGllbnQ6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScpO1xuICpcbiAqIC8vIFJldHJ5IHVwIHRvIDMgdGltZXMgd2l0aCAxcyBpbml0aWFsIGRlbGF5XG4gKiBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IGNsaWVudC5nZXQoJy91c2VycycsIHtcbiAqICAgcmV0cmllczogMyxcbiAqICAgcmV0cnlEZWxheTogMTAwMCAgLy8gMXMsIDJzLCA0c1xuICogfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIFJldHJ5SGFuZGxlciB7XG4gIC8qKlxuICAgKiBSZXRyaWVzIGEgZmFpbGVkIHJlcXVlc3Qgd2l0aCBleHBvbmVudGlhbCBiYWNrb2ZmIHN0cmF0ZWd5LlxuICAgKlxuICAgKiBUaGUgcmV0cnkgbG9naWMgd29ya3MgYXMgZm9sbG93czpcbiAgICogMS4gQXR0ZW1wdHMgdGhlIHJlcXVlc3QgaW1tZWRpYXRlbHlcbiAgICogMi4gT24gZmFpbHVyZSwgY2hlY2tzIGlmIHRoZSBlcnJvciBpcyByZXRyeWFibGVcbiAgICogMy4gSWYgcmV0cnlhYmxlIGFuZCByZXRyaWVzIHJlbWFpbiwgd2FpdHMgZm9yIHRoZSBjdXJyZW50IGRlbGF5XG4gICAqIDQuIERvdWJsZXMgdGhlIGRlbGF5IGZvciB0aGUgbmV4dCBhdHRlbXB0XG4gICAqIDUuIFJlcGVhdHMgdW50aWwgc3VjY2VzcyBvciByZXRyaWVzIGV4aGF1c3RlZFxuICAgKlxuICAgKiAqKk5vbi1SZXRyeWFibGUgRXJyb3JzOioqXG4gICAqIC0gVmFsaWRhdGlvbiBlcnJvcnMgKDQwMCkgLSBDbGllbnQgc2VudCBiYWQgZGF0YVxuICAgKiAtIEFib3J0RXJyb3JzIC0gUmVxdWVzdCB3YXMgZXhwbGljaXRseSBjYW5jZWxsZWRcbiAgICogLSBSZXF1ZXN0cyB3aXRoIGFib3J0ZWQgc2lnbmFsc1xuICAgKlxuICAgKiAqKkFib3J0IEhhbmRsaW5nOioqXG4gICAqIElmIHRoZSBzaWduYWwgaXMgYWJvcnRlZCBkdXJpbmcgYSByZXRyeSBkZWxheSwgdGhlIHJldHJ5IGlzIGltbWVkaWF0ZWx5XG4gICAqIGNhbmNlbGxlZCBhbmQgYW4gQWJvcnRFcnJvciBpcyB0aHJvd24uXG4gICAqXG4gICAqIEB0ZW1wbGF0ZSBUIC0gVGhlIHJldHVybiB0eXBlIG9mIHRoZSBmdW5jdGlvbiBiZWluZyByZXRyaWVkXG4gICAqIEBwYXJhbSBmbiAtIEFzeW5jIGZ1bmN0aW9uIHRvIHJldHJ5IG9uIGZhaWx1cmVcbiAgICogQHBhcmFtIHJldHJpZXMgLSBOdW1iZXIgb2YgcmV0cnkgYXR0ZW1wdHMgcmVtYWluaW5nIChkZWNyZW1lbnRzIGVhY2ggcmV0cnkpXG4gICAqIEBwYXJhbSBkZWxheSAtIEN1cnJlbnQgZGVsYXkgaW4gbWlsbGlzZWNvbmRzIGJlZm9yZSBuZXh0IHJldHJ5XG4gICAqIEBwYXJhbSBzaWduYWwgLSBPcHRpb25hbCBBYm9ydFNpZ25hbCB0byBjYW5jZWwgcmV0cmllc1xuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgZnVuY3Rpb24ncyByZXN1bHQgb24gc3VjY2Vzc1xuICAgKiBAdGhyb3dzIFRoZSBsYXN0IGVycm9yIGVuY291bnRlcmVkIGlmIGFsbCByZXRyaWVzIGFyZSBleGhhdXN0ZWRcbiAgICogQHRocm93cyBBYm9ydEVycm9yIGlmIHRoZSBzaWduYWwgaXMgYWJvcnRlZCBkdXJpbmcgZXhlY3V0aW9uIG9yIGRlbGF5XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIEJhc2ljIHJldHJ5IHVzYWdlOlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IGhhbmRsZXIgPSBuZXcgUmV0cnlIYW5kbGVyKCk7XG4gICAqIGNvbnN0IGZldGNoVXNlciA9ICgpID0+IGZldGNoKCcvYXBpL3VzZXJzLzEyMycpLnRoZW4ociA9PiByLmpzb24oKSk7XG4gICAqXG4gICAqIHRyeSB7XG4gICAqICAgY29uc3QgdXNlciA9IGF3YWl0IGhhbmRsZXIucmV0cnlSZXF1ZXN0KFxuICAgKiAgICAgZmV0Y2hVc2VyLFxuICAgKiAgICAgMywgICAgICAvLyAzIHJldHJpZXNcbiAgICogICAgIDEwMDAgICAgLy8gU3RhcnQgd2l0aCAxcyBkZWxheVxuICAgKiAgICk7XG4gICAqICAgY29uc29sZS5sb2coJ1VzZXI6JywgdXNlcik7XG4gICAqIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAqICAgY29uc29sZS5lcnJvcignRmFpbGVkIGFmdGVyIGFsbCByZXRyaWVzOicsIGVycm9yKTtcbiAgICogfVxuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogV2l0aCBjYW5jZWxsYXRpb24gc3VwcG9ydDpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgKiBjb25zdCBzaWduYWwgPSBjb250cm9sbGVyLnNpZ25hbDtcbiAgICpcbiAgICogLy8gQ2FuY2VsIGFmdGVyIDUgc2Vjb25kc1xuICAgKiBzZXRUaW1lb3V0KCgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKSwgNTAwMCk7XG4gICAqXG4gICAqIHRyeSB7XG4gICAqICAgYXdhaXQgaGFuZGxlci5yZXRyeVJlcXVlc3QoZmV0Y2hVc2VyLCA1LCAxMDAwLCBzaWduYWwpO1xuICAgKiB9IGNhdGNoIChlcnJvcikge1xuICAgKiAgIGlmIChlcnJvci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHtcbiAgICogICAgIGNvbnNvbGUubG9nKCdSZXRyeSBjYW5jZWxsZWQnKTtcbiAgICogICB9XG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBhc3luYyByZXRyeVJlcXVlc3Q8VD4oXG4gICAgZm46ICgpID0+IFByb21pc2U8VD4sXG4gICAgcmV0cmllczogbnVtYmVyLFxuICAgIGRlbGF5OiBudW1iZXIsXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWxcbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIENoZWNrIGlmIGFscmVhZHkgYWJvcnRlZFxuICAgICAgaWYgKHNpZ25hbD8uYWJvcnRlZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3Ioc2lnbmFsLnJlYXNvbiB8fCAnUmVxdWVzdCBhYm9ydGVkJyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhd2FpdCBmbigpO1xuICAgIH0gY2F0Y2ggKGVycm9yOiB1bmtub3duKSB7XG4gICAgICBjb25zdCBlcnIgPSBlcnJvciBhcyBBcGlFcnJvcjtcblxuICAgICAgLy8gRG9uJ3QgcmV0cnkgaWYgYWJvcnRlZFxuICAgICAgaWYgKGVyci5uYW1lID09PSAnQWJvcnRFcnJvcicgfHwgc2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuXG4gICAgICAvLyBEb24ndCByZXRyeSB2YWxpZGF0aW9uIGVycm9yc1xuICAgICAgaWYgKGVyci50eXBlID09PSAndmFsaWRhdGlvbl9lcnJvcicgfHwgZXJyLnN0YXR1cyA9PT0gNDAwKSB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfVxuXG4gICAgICBpZiAocmV0cmllcyA9PT0gMCkgdGhyb3cgZXJyb3I7XG5cbiAgICAgIC8vIFdhaXQgd2l0aCBhYm9ydCBzdXBwb3J0XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIGNvbnN0IHRpbWVvdXRJZCA9IHNldFRpbWVvdXQocmVzb2x2ZSwgZGVsYXkpO1xuXG4gICAgICAgIGlmIChzaWduYWwpIHtcbiAgICAgICAgICBzaWduYWwuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICdhYm9ydCcsXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKHNpZ25hbC5yZWFzb24gfHwgJ1JlcXVlc3QgYWJvcnRlZCcpKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7IG9uY2U6IHRydWUgfVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdGhpcy5yZXRyeVJlcXVlc3QoZm4sIHJldHJpZXMgLSAxLCBkZWxheSAqIDIsIHNpZ25hbCk7XG4gICAgfVxuICB9XG59XG4iLCAiLyoqXG4gKiBNYW5hZ2VzIEFib3J0U2lnbmFsIGNyZWF0aW9uIGFuZCBjb21wb3NpdGlvbiBmb3IgcmVxdWVzdCBjYW5jZWxsYXRpb24gYW5kIHRpbWVvdXRzLlxuICpcbiAqIFRoaXMgaW50ZXJuYWwgY2xhc3MgcHJvdmlkZXMgdXRpbGl0aWVzIGZvciB3b3JraW5nIHdpdGggdGhlIEFib3J0U2lnbmFsIEFQSSxcbiAqIGVuYWJsaW5nIHNvcGhpc3RpY2F0ZWQgY2FuY2VsbGF0aW9uIHBhdHRlcm5zIGJ5IGNvbWJpbmluZyBtdWx0aXBsZSBjYW5jZWxsYXRpb25cbiAqIHNvdXJjZXMgYW5kIGNyZWF0aW5nIHRpbWVvdXQtYmFzZWQgc2lnbmFscy5cbiAqXG4gKiBLZXkgRmVhdHVyZXM6XG4gKiAtICoqU2lnbmFsIENvbXBvc2l0aW9uKio6IENvbWJpbmUgbXVsdGlwbGUgQWJvcnRTaWduYWxzIGludG8gb25lXG4gKiAtICoqVGltZW91dCBTaWduYWxzKio6IENyZWF0ZSBzaWduYWxzIHRoYXQgYXV0by1hYm9ydCBhZnRlciBhIGRlbGF5XG4gKiAtICoqRWFybHkgQWJvcnQgRGV0ZWN0aW9uKio6IEltbWVkaWF0ZWx5IGFib3J0IGlmIGFueSBzb3VyY2UgaXMgYWxyZWFkeSBhYm9ydGVkXG4gKiAtICoqUmVzb3VyY2UgQ2xlYW51cCoqOiBBdXRvbWF0aWMgdGltZW91dCBjbGVhbnVwIG9uIGFib3J0XG4gKlxuICogVXNlIENhc2VzOlxuICogLSBDb21iaW5lIHVzZXIgY2FuY2VsbGF0aW9uICsgdGltZW91dCArIGNvbXBvbmVudCB1bm1vdW50IHNpZ25hbHNcbiAqIC0gQ3JlYXRlIHJlcXVlc3QgZGVhZGxpbmVzXG4gKiAtIEltcGxlbWVudCBjYXNjYWRpbmcgY2FuY2VsbGF0aW9uXG4gKlxuICogQGludGVybmFsIFRoaXMgY2xhc3MgaXMgbm90IGV4cG9ydGVkIGZyb20gdGhlIHB1YmxpYyBBUElcbiAqXG4gKiBAZXhhbXBsZVxuICogQ29tYmluaW5nIG11bHRpcGxlIGNhbmNlbGxhdGlvbiBzb3VyY2VzOlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgbWFuYWdlciA9IG5ldyBTaWduYWxNYW5hZ2VyKCk7XG4gKiBjb25zdCB1c2VyQ2FuY2VsID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICogY29uc3QgdW5tb3VudFNpZ25hbCA9IGNvbXBvbmVudFVubW91bnRTaWduYWw7XG4gKlxuICogLy8gUmVxdWVzdCB3aWxsIGJlIGNhbmNlbGxlZCBpZiBlaXRoZXIgdXNlciBjbGlja3MgY2FuY2VsIE9SIGNvbXBvbmVudCB1bm1vdW50c1xuICogY29uc3QgY29tYmluZWQgPSBtYW5hZ2VyLmNyZWF0ZUNvbWJpbmVkU2lnbmFsKFtcbiAqICAgdXNlckNhbmNlbC5zaWduYWwsXG4gKiAgIHVubW91bnRTaWduYWxcbiAqIF0pO1xuICpcbiAqIGZldGNoKCcvYXBpL2RhdGEnLCB7IHNpZ25hbDogY29tYmluZWQuc2lnbmFsIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBTaWduYWxNYW5hZ2VyIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBjb21iaW5lZCBBYm9ydENvbnRyb2xsZXIgdGhhdCBhYm9ydHMgd2hlbiBhbnkgc291cmNlIHNpZ25hbCBhYm9ydHMuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGltcGxlbWVudHMgdGhlIFwiYW55XCIgcGF0dGVybiBmb3IgY2FuY2VsbGF0aW9uOiB0aGUgY29tYmluZWQgc2lnbmFsXG4gICAqIHdpbGwgYWJvcnQgYXMgc29vbiBhcyBBTlkgb2YgdGhlIHNvdXJjZSBzaWduYWxzIGFib3J0LiBUaGlzIGlzIHVzZWZ1bCBmb3JcbiAgICogY29vcmRpbmF0aW5nIG11bHRpcGxlIGNhbmNlbGxhdGlvbiBjb25kaXRpb25zOlxuICAgKiAtIFVzZXIgY2xpY2tzIGNhbmNlbCBidXR0b25cbiAgICogLSBSZXF1ZXN0IHRpbWVvdXQgZXhwaXJlc1xuICAgKiAtIENvbXBvbmVudCB1bm1vdW50c1xuICAgKiAtIFBhcmVudCByZXF1ZXN0IGlzIGNhbmNlbGxlZFxuICAgKlxuICAgKiAqKkVhcmx5IEFib3J0IE9wdGltaXphdGlvbjoqKlxuICAgKiBJZiBhbnkgc291cmNlIHNpZ25hbCBpcyBhbHJlYWR5IGFib3J0ZWQgd2hlbiB0aGlzIG1ldGhvZCBpcyBjYWxsZWQsXG4gICAqIHRoZSByZXR1cm5lZCBjb250cm9sbGVyIGlzIGltbWVkaWF0ZWx5IGFib3J0ZWQgd2l0aG91dCBzZXR0aW5nIHVwIGxpc3RlbmVycy5cbiAgICpcbiAgICogKipNZW1vcnkgTWFuYWdlbWVudDoqKlxuICAgKiBFdmVudCBsaXN0ZW5lcnMgYXJlIHJlZ2lzdGVyZWQgd2l0aCBgeyBvbmNlOiB0cnVlIH1gIHRvIHByZXZlbnQgbWVtb3J5IGxlYWtzLFxuICAgKiBhcyB0aGV5IGF1dG9tYXRpY2FsbHkgY2xlYW4gdXAgYWZ0ZXIgZmlyaW5nLlxuICAgKlxuICAgKiBAcGFyYW0gc2lnbmFscyAtIEFycmF5IG9mIEFib3J0U2lnbmFscyB0byBjb21iaW5lICh1bmRlZmluZWQgdmFsdWVzIGFyZSBpZ25vcmVkKVxuICAgKiBAcmV0dXJucyBBIG5ldyBBYm9ydENvbnRyb2xsZXIgdGhhdCBhYm9ydHMgd2hlbiBhbnkgc291cmNlIHNpZ25hbCBhYm9ydHNcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogVXNlciBjYW5jZWxsYXRpb24gKyB0aW1lb3V0OlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHVzZXJDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgKiBjb25zdCB0aW1lb3V0ID0gbWFuYWdlci5jcmVhdGVUaW1lb3V0U2lnbmFsKDMwMDAwKTtcbiAgICpcbiAgICogY29uc3QgY29tYmluZWQgPSBtYW5hZ2VyLmNyZWF0ZUNvbWJpbmVkU2lnbmFsKFtcbiAgICogICB1c2VyQ29udHJvbGxlci5zaWduYWwsXG4gICAqICAgdGltZW91dC5zaWduYWxcbiAgICogXSk7XG4gICAqXG4gICAqIC8vIFJlcXVlc3Qgd2lsbCBiZSBjYW5jZWxsZWQgYWZ0ZXIgMzBzIE9SIHdoZW4gdXNlciBjbGlja3MgY2FuY2VsXG4gICAqIGZldGNoKCcvYXBpL2RhdGEnLCB7IHNpZ25hbDogY29tYmluZWQuc2lnbmFsIH0pO1xuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogUmVhY3QgY29tcG9uZW50IHdpdGggY2xlYW51cDpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiB1c2VFZmZlY3QoKCkgPT4ge1xuICAgKiAgIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gICAqXG4gICAqICAgY29uc3QgY29tYmluZWQgPSBtYW5hZ2VyLmNyZWF0ZUNvbWJpbmVkU2lnbmFsKFtcbiAgICogICAgIGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgKiAgICAgdW5tb3VudFNpZ25hbCAgLy8gRnJvbSBjb21wb25lbnQgbGlmZWN5Y2xlXG4gICAqICAgXSk7XG4gICAqXG4gICAqICAgZmV0Y2hEYXRhKGNvbWJpbmVkLnNpZ25hbCk7XG4gICAqXG4gICAqICAgcmV0dXJuICgpID0+IGNvbnRyb2xsZXIuYWJvcnQoKTsgLy8gQ2xlYW51cFxuICAgKiB9LCBbXSk7XG4gICAqIGBgYFxuICAgKi9cbiAgY3JlYXRlQ29tYmluZWRTaWduYWwoXG4gICAgc2lnbmFsczogQXJyYXk8QWJvcnRTaWduYWwgfCB1bmRlZmluZWQ+XG4gICk6IEFib3J0Q29udHJvbGxlciB7XG4gICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICAgIGZvciAoY29uc3Qgc2lnbmFsIG9mIHNpZ25hbHMpIHtcbiAgICAgIGlmIChzaWduYWwpIHtcbiAgICAgICAgaWYgKHNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICAgICAgY29udHJvbGxlci5hYm9ydChzaWduYWwucmVhc29uKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICdhYm9ydCcsXG4gICAgICAgICAgKCkgPT4ge1xuICAgICAgICAgICAgY29udHJvbGxlci5hYm9ydChzaWduYWwucmVhc29uKTtcbiAgICAgICAgICB9LFxuICAgICAgICAgIHsgb25jZTogdHJ1ZSB9XG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnRyb2xsZXI7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhbiBBYm9ydENvbnRyb2xsZXIgdGhhdCBhdXRvbWF0aWNhbGx5IGFib3J0cyBhZnRlciBhIHNwZWNpZmllZCB0aW1lb3V0LlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjcmVhdGVzIGEgdGltZS1iYXNlZCBjYW5jZWxsYXRpb24gbWVjaGFuaXNtIHVzZWZ1bCBmb3IgaW1wbGVtZW50aW5nXG4gICAqIHJlcXVlc3QgdGltZW91dHMgYW5kIGRlYWRsaW5lcy4gVGhlIHNpZ25hbCB3aWxsIGF1dG9tYXRpY2FsbHkgYWJvcnQgYWZ0ZXIgdGhlXG4gICAqIHNwZWNpZmllZCBkdXJhdGlvbiwgcHJvdmlkaW5nIGEgY29uc2lzdGVudCB0aW1lb3V0IGV4cGVyaWVuY2UuXG4gICAqXG4gICAqICoqQXV0b21hdGljIENsZWFudXA6KipcbiAgICogSWYgdGhlIHNpZ25hbCBpcyBhYm9ydGVkIGJ5IG90aGVyIG1lYW5zIGJlZm9yZSB0aGUgdGltZW91dCBleHBpcmVzLCB0aGUgaW50ZXJuYWxcbiAgICogc2V0VGltZW91dCBpcyBhdXRvbWF0aWNhbGx5IGNsZWFyZWQgdG8gcHJldmVudCBtZW1vcnkgbGVha3MuXG4gICAqXG4gICAqICoqQWJvcnQgUmVhc29uOioqXG4gICAqIFRoZSBhYm9ydCByZWFzb24gaW5jbHVkZXMgdGhlIHRpbWVvdXQgZHVyYXRpb24gZm9yIGRlYnVnZ2luZyBwdXJwb3NlczpcbiAgICogYFwiUmVxdWVzdCB0aW1lb3V0IGFmdGVyIHt0aW1lb3V0fW1zXCJgXG4gICAqXG4gICAqIEBwYXJhbSB0aW1lb3V0IC0gVGltZW91dCBkdXJhdGlvbiBpbiBtaWxsaXNlY29uZHNcbiAgICogQHJldHVybnMgQW4gQWJvcnRDb250cm9sbGVyIHRoYXQgd2lsbCBhYm9ydCBhZnRlciB0aGUgdGltZW91dFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBTaW1wbGUgcmVxdWVzdCB0aW1lb3V0OlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IG1hbmFnZXIgPSBuZXcgU2lnbmFsTWFuYWdlcigpO1xuICAgKiBjb25zdCB0aW1lb3V0ID0gbWFuYWdlci5jcmVhdGVUaW1lb3V0U2lnbmFsKDUwMDApOyAvLyA1IHNlY29uZHNcbiAgICpcbiAgICogdHJ5IHtcbiAgICogICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKCcvYXBpL3Nsb3ctZW5kcG9pbnQnLCB7XG4gICAqICAgICBzaWduYWw6IHRpbWVvdXQuc2lnbmFsXG4gICAqICAgfSk7XG4gICAqICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICogfSBjYXRjaCAoZXJyb3IpIHtcbiAgICogICBpZiAoZXJyb3IubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XG4gICAqICAgICBjb25zb2xlLmVycm9yKCdSZXF1ZXN0IHRpbWVkIG91dCBhZnRlciA1IHNlY29uZHMnKTtcbiAgICogICB9XG4gICAqIH1cbiAgICogYGBgXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIERpZmZlcmVudCB0aW1lb3V0cyBmb3IgZGlmZmVyZW50IG9wZXJhdGlvbnM6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gU2hvcnQgdGltZW91dCBmb3IgcXVpY2sgb3BlcmF0aW9uc1xuICAgKiBjb25zdCBxdWlja1RpbWVvdXQgPSBtYW5hZ2VyLmNyZWF0ZVRpbWVvdXRTaWduYWwoMjAwMCk7XG4gICAqIGF3YWl0IGZldGNoKCcvYXBpL2hlYWx0aCcsIHsgc2lnbmFsOiBxdWlja1RpbWVvdXQuc2lnbmFsIH0pO1xuICAgKlxuICAgKiAvLyBMb25nIHRpbWVvdXQgZm9yIGhlYXZ5IG9wZXJhdGlvbnNcbiAgICogY29uc3QgbG9uZ1RpbWVvdXQgPSBtYW5hZ2VyLmNyZWF0ZVRpbWVvdXRTaWduYWwoNjAwMDApO1xuICAgKiBhd2FpdCBmZXRjaCgnL2FwaS9leHBvcnQnLCB7IHNpZ25hbDogbG9uZ1RpbWVvdXQuc2lnbmFsIH0pO1xuICAgKiBgYGBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogTWFudWFsIGNhbmNlbGxhdGlvbiBiZWZvcmUgdGltZW91dDpcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCB0aW1lb3V0ID0gbWFuYWdlci5jcmVhdGVUaW1lb3V0U2lnbmFsKDMwMDAwKTtcbiAgICpcbiAgICogLy8gSWYgdXNlciBjYW5jZWxzLCB0aW1lb3V0IGlzIGF1dG9tYXRpY2FsbHkgY2xlYW5lZCB1cFxuICAgKiB0aW1lb3V0LmFib3J0KCdVc2VyIGNhbmNlbGxlZCcpO1xuICAgKiAvLyBJbnRlcm5hbCBzZXRUaW1lb3V0IGlzIGNsZWFyZWQsIG5vIG1lbW9yeSBsZWFrXG4gICAqIGBgYFxuICAgKi9cbiAgY3JlYXRlVGltZW91dFNpZ25hbCh0aW1lb3V0OiBudW1iZXIpOiBBYm9ydENvbnRyb2xsZXIge1xuICAgIGNvbnN0IGNvbnRyb2xsZXIgPSBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG5cbiAgICBjb25zdCB0aW1lb3V0SWQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGNvbnRyb2xsZXIuYWJvcnQoYFJlcXVlc3QgdGltZW91dCBhZnRlciAke3RpbWVvdXR9bXNgKTtcbiAgICB9LCB0aW1lb3V0KTtcblxuICAgIC8vIENsZWFuIHVwIHRpbWVvdXQgd2hlbiBzaWduYWwgaXMgYWJvcnRlZFxuICAgIGNvbnRyb2xsZXIuc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAnYWJvcnQnLFxuICAgICAgKCkgPT4ge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dElkKTtcbiAgICAgIH0sXG4gICAgICB7IG9uY2U6IHRydWUgfVxuICAgICk7XG5cbiAgICByZXR1cm4gY29udHJvbGxlcjtcbiAgfVxufVxuIiwgImltcG9ydCB0eXBlIHsgUmVzcG9uc2VEYXRhIH0gZnJvbSAnLi4vTW9kZWxzJztcblxuLyoqXG4gKiBQYXJzZXMgSFRUUCByZXNwb25zZSBib2RpZXMgaW50byBhcHByb3ByaWF0ZSBKYXZhU2NyaXB0IHR5cGVzIGJhc2VkIG9uIENvbnRlbnQtVHlwZSBoZWFkZXJzLlxuICpcbiAqIFRoaXMgaW50ZXJuYWwgY2xhc3MgaGFuZGxlcyB0aGUgY29tcGxleGl0eSBvZiBjb252ZXJ0aW5nIHZhcmlvdXMgSFRUUCByZXNwb25zZSBmb3JtYXRzXG4gKiBpbnRvIHVzYWJsZSBKYXZhU2NyaXB0IGRhdGEgc3RydWN0dXJlcy4gSXQgaW50ZWxsaWdlbnRseSBkZXRlY3RzIHRoZSByZXNwb25zZSB0eXBlXG4gKiBhbmQgYXBwbGllcyB0aGUgYXBwcm9wcmlhdGUgcGFyc2luZyBzdHJhdGVneS5cbiAqXG4gKiBTdXBwb3J0ZWQgQ29udGVudCBUeXBlczpcbiAqIC0gKiphcHBsaWNhdGlvbi9qc29uKio6IFBhcnNlZCBhcyBKU09OIG9iamVjdHMvYXJyYXlzXG4gKiAtICoqdGV4dC8qKiogKHRleHQvcGxhaW4sIHRleHQvaHRtbCwgZXRjLik6IFJldHVybmVkIGFzIHN0cmluZ1xuICogLSAqKmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSoqOiBSZXR1cm5lZCBhcyBCbG9iIGZvciBiaW5hcnkgZGF0YVxuICogLSAqKlVua25vd24vTWlzc2luZyoqOiBBdHRlbXB0cyBKU09OIHBhcnNlLCBmYWxscyBiYWNrIHRvIHRleHRcbiAqXG4gKiBLZXkgRmVhdHVyZXM6XG4gKiAtICoqQXV0b21hdGljIERldGVjdGlvbioqOiBVc2VzIENvbnRlbnQtVHlwZSBoZWFkZXIgdG8gZGV0ZXJtaW5lIHBhcnNpbmcgc3RyYXRlZ3lcbiAqIC0gKipHcmFjZWZ1bCBGYWxsYmFjayoqOiBBdHRlbXB0cyBKU09OIHBhcnNpbmcgZm9yIHVua25vd24gdHlwZXMsIGZhbGxzIGJhY2sgdG8gdGV4dFxuICogLSAqKkJpbmFyeSBTdXBwb3J0Kio6IEhhbmRsZXMgYmluYXJ5IGRhdGEgdmlhIEJsb2JcbiAqIC0gKipUeXBlIFNhZmV0eSoqOiBSZXR1cm5zIHR5cGVkIFJlc3BvbnNlRGF0YSB1bmlvblxuICpcbiAqIEBpbnRlcm5hbCBUaGlzIGNsYXNzIGlzIG5vdCBleHBvcnRlZCBmcm9tIHRoZSBwdWJsaWMgQVBJXG4gKlxuICogQGV4YW1wbGVcbiAqIFBhcnNpbmcgZGlmZmVyZW50IHJlc3BvbnNlIHR5cGVzOlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcGFyc2VyID0gbmV3IFJlc3BvbnNlUGFyc2VyKCk7XG4gKlxuICogLy8gSlNPTiByZXNwb25zZVxuICogY29uc3QganNvblJlc3BvbnNlID0gbmV3IFJlc3BvbnNlKCd7XCJpZFwiOiAxfScsIHtcbiAqICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nIH1cbiAqIH0pO1xuICogY29uc3QgZGF0YSA9IGF3YWl0IHBhcnNlci5wYXJzZVJlc3BvbnNlKGpzb25SZXNwb25zZSk7XG4gKiAvLyA9PiB7IGlkOiAxIH1cbiAqXG4gKiAvLyBUZXh0IHJlc3BvbnNlXG4gKiBjb25zdCB0ZXh0UmVzcG9uc2UgPSBuZXcgUmVzcG9uc2UoJ0hlbGxvIFdvcmxkJywge1xuICogICBoZWFkZXJzOiB7ICdDb250ZW50LVR5cGUnOiAndGV4dC9wbGFpbicgfVxuICogfSk7XG4gKiBjb25zdCB0ZXh0ID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UodGV4dFJlc3BvbnNlKTtcbiAqIC8vID0+IFwiSGVsbG8gV29ybGRcIlxuICpcbiAqIC8vIEJpbmFyeSByZXNwb25zZVxuICogY29uc3QgYmxvYlJlc3BvbnNlID0gbmV3IFJlc3BvbnNlKGJpbmFyeURhdGEsIHtcbiAqICAgaGVhZGVyczogeyAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL29jdGV0LXN0cmVhbScgfVxuICogfSk7XG4gKiBjb25zdCBibG9iID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UoYmxvYlJlc3BvbnNlKTtcbiAqIC8vID0+IEJsb2IgeyAuLi4gfVxuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXNwb25zZVBhcnNlciB7XG4gIC8qKlxuICAgKiBQYXJzZXMgdGhlIEhUVFAgcmVzcG9uc2UgYm9keSBpbnRvIGFuIGFwcHJvcHJpYXRlIEphdmFTY3JpcHQgdHlwZS5cbiAgICpcbiAgICogVGhlIHBhcnNpbmcgc3RyYXRlZ3kgaXMgZGV0ZXJtaW5lZCBieSB0aGUgQ29udGVudC1UeXBlIGhlYWRlcjpcbiAgICogMS4gKipKU09OKiogKGFwcGxpY2F0aW9uL2pzb24pOiBDYWxscyBgcmVzcG9uc2UuanNvbigpYFxuICAgKiAyLiAqKlRleHQqKiAodGV4dC8qKTogQ2FsbHMgYHJlc3BvbnNlLnRleHQoKWBcbiAgICogMy4gKipCaW5hcnkqKiAoYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtKTogQ2FsbHMgYHJlc3BvbnNlLmJsb2IoKWBcbiAgICogNC4gKipVbmtub3duKio6IFJlYWRzIGFzIHRleHQsIGF0dGVtcHRzIEpTT04gcGFyc2UsIGZhbGxzIGJhY2sgdG8gcmF3IHRleHRcbiAgICpcbiAgICogKipGYWxsYmFjayBCZWhhdmlvcjoqKlxuICAgKiBGb3IgcmVzcG9uc2VzIHdpdGhvdXQgYSBDb250ZW50LVR5cGUgaGVhZGVyIG9yIHdpdGggdW5rbm93biB0eXBlcywgdGhlIHBhcnNlclxuICAgKiBhdHRlbXB0cyB0byBwYXJzZSBhcyBKU09OIGZpcnN0IChjb21tb24gZm9yIEFQSXMgdGhhdCBkb24ndCBzZXQgcHJvcGVyIGhlYWRlcnMpLlxuICAgKiBJZiBKU09OIHBhcnNpbmcgZmFpbHMsIGl0IHJldHVybnMgdGhlIHJhdyB0ZXh0LlxuICAgKlxuICAgKiBAcGFyYW0gcmVzcG9uc2UgLSBUaGUgRmV0Y2ggQVBJIFJlc3BvbnNlIG9iamVjdCB0byBwYXJzZVxuICAgKiBAcmV0dXJucyBQcm9taXNlIHJlc29sdmluZyB0byB0aGUgcGFyc2VkIHJlc3BvbnNlIGRhdGFcbiAgICogQHJldHVybnMgQ2FuIGJlOiBKU09OIG9iamVjdC9hcnJheSwgc3RyaW5nLCBvciBCbG9iIGRlcGVuZGluZyBvbiBDb250ZW50LVR5cGVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogQVBJIHJlc3BvbnNlIHBhcnNpbmc6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgnL2FwaS91c2VycycpO1xuICAgKiBjb25zdCBkYXRhID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UocmVzcG9uc2UpO1xuICAgKlxuICAgKiBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAqICAgY29uc29sZS5sb2coJ1RleHQgcmVzcG9uc2U6JywgZGF0YSk7XG4gICAqIH0gZWxzZSBpZiAoZGF0YSBpbnN0YW5jZW9mIEJsb2IpIHtcbiAgICogICBjb25zb2xlLmxvZygnQmluYXJ5IHJlc3BvbnNlOicsIGRhdGEuc2l6ZSwgJ2J5dGVzJyk7XG4gICAqIH0gZWxzZSB7XG4gICAqICAgY29uc29sZS5sb2coJ0pTT04gcmVzcG9uc2U6JywgZGF0YSk7XG4gICAqIH1cbiAgICogYGBgXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIEhhbmRsaW5nIGRpZmZlcmVudCBjb250ZW50IHR5cGVzOlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIENTViBmaWxlIGRvd25sb2FkXG4gICAqIGNvbnN0IGNzdlJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJy9hcGkvZXhwb3J0LmNzdicpO1xuICAgKiBjb25zdCBibG9iID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UoY3N2UmVzcG9uc2UpO1xuICAgKiAvLyBSZXR1cm5zIEJsb2IgZm9yIGRvd25sb2FkXG4gICAqXG4gICAqIC8vIEpTT04gQVBJXG4gICAqIGNvbnN0IGpzb25SZXNwb25zZSA9IGF3YWl0IGZldGNoKCcvYXBpL3VzZXJzJyk7XG4gICAqIGNvbnN0IHVzZXJzID0gYXdhaXQgcGFyc2VyLnBhcnNlUmVzcG9uc2UoanNvblJlc3BvbnNlKTtcbiAgICogLy8gUmV0dXJucyBwYXJzZWQgSlNPTiBhcnJheVxuICAgKlxuICAgKiAvLyBQbGFpbiB0ZXh0IGxvZ3NcbiAgICogY29uc3QgbG9nUmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgnL2FwaS9sb2dzJyk7XG4gICAqIGNvbnN0IGxvZ3MgPSBhd2FpdCBwYXJzZXIucGFyc2VSZXNwb25zZShsb2dSZXNwb25zZSk7XG4gICAqIC8vIFJldHVybnMgc3RyaW5nXG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgcGFyc2VSZXNwb25zZShyZXNwb25zZTogUmVzcG9uc2UpOiBQcm9taXNlPFJlc3BvbnNlRGF0YT4ge1xuICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gcmVzcG9uc2UuaGVhZGVycy5nZXQoJ2NvbnRlbnQtdHlwZScpO1xuXG4gICAgaWYgKGNvbnRlbnRUeXBlPy5pbmNsdWRlcygnYXBwbGljYXRpb24vanNvbicpKSB7XG4gICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGU/LmluY2x1ZGVzKCd0ZXh0LycpKSB7XG4gICAgICByZXR1cm4gcmVzcG9uc2UudGV4dCgpO1xuICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGU/LmluY2x1ZGVzKCdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nKSkge1xuICAgICAgcmV0dXJuIHJlc3BvbnNlLmJsb2IoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gVHJ5IEpTT04gZmlyc3QsIGZhbGxiYWNrIHRvIHRleHRcbiAgICAgIGNvbnN0IHRleHQgPSBhd2FpdCByZXNwb25zZS50ZXh0KCk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKHRleHQpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIiwgImltcG9ydCB0eXBlIHsgUXVlcnlQYXJhbXMgfSBmcm9tICcuLi9Nb2RlbHMnO1xuXG4vKipcbiAqIENvbnN0cnVjdHMgZnVsbHktcXVhbGlmaWVkIFVSTHMgd2l0aCBwcm9wZXIgcXVlcnkgcGFyYW1ldGVyIGVuY29kaW5nLlxuICpcbiAqIFRoaXMgaW50ZXJuYWwgY2xhc3MgaGFuZGxlcyB0aGUgY29tcGxleGl0eSBvZiBVUkwgY29uc3RydWN0aW9uLCBjb21iaW5pbmdcbiAqIGJhc2UgVVJMcywgZW5kcG9pbnRzLCBhbmQgcXVlcnkgcGFyYW1ldGVycyB3aXRoIHByb3BlciBlbmNvZGluZyBhbmQgYXJyYXlcbiAqIGhhbmRsaW5nLiBJdCB1c2VzIHRoZSBuYXRpdmUgVVJMIEFQSSBmb3IgcmVsaWFibGUgVVJMIGNvbXBvc2l0aW9uLlxuICpcbiAqIEtleSBGZWF0dXJlczpcbiAqIC0gKipVUkwgQ29tcG9zaXRpb24qKjogU2FmZWx5IGNvbWJpbmVzIGJhc2UgVVJMIGFuZCBlbmRwb2ludCBwYXRoc1xuICogLSAqKlF1ZXJ5IFBhcmFtZXRlciBFbmNvZGluZyoqOiBBdXRvbWF0aWMgZW5jb2Rpbmcgb2Ygc3BlY2lhbCBjaGFyYWN0ZXJzXG4gKiAtICoqQXJyYXkgU3VwcG9ydCoqOiBIYW5kbGVzIGFycmF5IHBhcmFtZXRlcnMgd2l0aCBtdWx0aXBsZSB2YWx1ZXNcbiAqIC0gKipOdWxsL1VuZGVmaW5lZCBGaWx0ZXJpbmcqKjogQXV0b21hdGljYWxseSBza2lwcyBudWxsL3VuZGVmaW5lZCB2YWx1ZXNcbiAqIC0gKipUeXBlIFNhZmV0eSoqOiBTdHJvbmdseSB0eXBlZCBxdWVyeSBwYXJhbWV0ZXIgdmFsdWVzXG4gKlxuICogQXJyYXkgSGFuZGxpbmc6XG4gKiBBcnJheSBwYXJhbWV0ZXJzIGFyZSBzZXJpYWxpemVkIGJ5IGFwcGVuZGluZyB0aGUgc2FtZSBrZXkgbXVsdGlwbGUgdGltZXM6XG4gKiBgP3RhZ3M9amF2YXNjcmlwdCZ0YWdzPXR5cGVzY3JpcHQmdGFncz1yZWFjdGBcbiAqXG4gKiBAaW50ZXJuYWwgVGhpcyBjbGFzcyBpcyBub3QgZXhwb3J0ZWQgZnJvbSB0aGUgcHVibGljIEFQSVxuICpcbiAqIEBleGFtcGxlXG4gKiBCdWlsZGluZyBVUkxzIHdpdGggcXVlcnkgcGFyYW1ldGVyczpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGJ1aWxkZXIgPSBuZXcgVXJsQnVpbGRlcigpO1xuICpcbiAqIGNvbnN0IHVybCA9IGJ1aWxkZXIuYnVpbGRVUkwoXG4gKiAgICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXG4gKiAgICcvdXNlcnMnLFxuICogICB7IGFjdGl2ZTogdHJ1ZSwgcm9sZTogJ2FkbWluJywgcGFnZTogMSB9XG4gKiApO1xuICogLy8gPT4gXCJodHRwczovL2FwaS5leGFtcGxlLmNvbS91c2Vycz9hY3RpdmU9dHJ1ZSZyb2xlPWFkbWluJnBhZ2U9MVwiXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGNsYXNzIFVybEJ1aWxkZXIge1xuICAvKipcbiAgICogQnVpbGRzIGEgY29tcGxldGUgVVJMIGJ5IGNvbWJpbmluZyBiYXNlIFVSTCwgZW5kcG9pbnQsIGFuZCBxdWVyeSBwYXJhbWV0ZXJzLlxuICAgKlxuICAgKiBUaGUgVVJMIGNvbnN0cnVjdGlvbiBwcm9jZXNzOlxuICAgKiAxLiBDb21iaW5lcyBgYmFzZVVSTGAgYW5kIGBlbmRwb2ludGAgdXNpbmcgVVJMIEFQSVxuICAgKiAyLiBJdGVyYXRlcyB0aHJvdWdoIHF1ZXJ5IHBhcmFtZXRlcnNcbiAgICogMy4gU2tpcHMgbnVsbC91bmRlZmluZWQgdmFsdWVzXG4gICAqIDQuIEhhbmRsZXMgYXJyYXlzIGJ5IGFwcGVuZGluZyBtdWx0aXBsZSB2YWx1ZXMgd2l0aCBzYW1lIGtleVxuICAgKiA1LiBDb252ZXJ0cyBhbGwgdmFsdWVzIHRvIHN0cmluZ3NcbiAgICogNi4gUmV0dXJucyBmdWxseS1xdWFsaWZpZWQgVVJMIHN0cmluZ1xuICAgKlxuICAgKiAqKlBhdGggSGFuZGxpbmc6KipcbiAgICogVGhlIGVuZHBvaW50IGNhbiBiZSBlaXRoZXIgcmVsYXRpdmUgb3IgYWJzb2x1dGU6XG4gICAqIC0gUmVsYXRpdmU6IGAvdXNlcnNgIFx1MjE5MiBDb21iaW5lZCB3aXRoIGJhc2VVUkxcbiAgICogLSBBYnNvbHV0ZTogYGh0dHBzOi8vb3RoZXItYXBpLmNvbS91c2Vyc2AgXHUyMTkyIFVzZXMgYWJzb2x1dGUgVVJMXG4gICAqXG4gICAqICoqRW5jb2Rpbmc6KipcbiAgICogQWxsIHBhcmFtZXRlciB2YWx1ZXMgYXJlIGF1dG9tYXRpY2FsbHkgVVJMLWVuY29kZWQgYnkgdGhlIFVSTCBBUEksXG4gICAqIHNvIHNwZWNpYWwgY2hhcmFjdGVycyAoc3BhY2VzLCAmLCA9LCBldGMuKSBhcmUgc2FmZWx5IGhhbmRsZWQuXG4gICAqXG4gICAqIEBwYXJhbSBiYXNlVVJMIC0gQmFzZSBVUkwgZm9yIHRoZSBBUEkgKGUuZy4sICdodHRwczovL2FwaS5leGFtcGxlLmNvbScpXG4gICAqIEBwYXJhbSBlbmRwb2ludCAtIEFQSSBlbmRwb2ludCBwYXRoIHJlbGF0aXZlIHRvIGJhc2VVUkwgKGUuZy4sICcvdXNlcnMvMTIzJylcbiAgICogQHBhcmFtIHBhcmFtcyAtIE9wdGlvbmFsIHF1ZXJ5IHBhcmFtZXRlcnMgYXMga2V5LXZhbHVlIHBhaXJzXG4gICAqIEByZXR1cm5zIFRoZSBmdWxseS1xdWFsaWZpZWQgVVJMIHN0cmluZyB3aXRoIGVuY29kZWQgcXVlcnkgcGFyYW1ldGVyc1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBCYXNpYyBVUkwgY29uc3RydWN0aW9uOlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHVybCA9IGJ1aWxkZXIuYnVpbGRVUkwoXG4gICAqICAgJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcbiAgICogICAnL3NlYXJjaCcsXG4gICAqICAgeyBxOiAnaGVsbG8gd29ybGQnLCBsaW1pdDogMTAgfVxuICAgKiApO1xuICAgKiAvLyA9PiBcImh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3NlYXJjaD9xPWhlbGxvK3dvcmxkJmxpbWl0PTEwXCJcbiAgICogYGBgXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIEFycmF5IHBhcmFtZXRlcnM6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdXJsID0gYnVpbGRlci5idWlsZFVSTChcbiAgICogICAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxuICAgKiAgICcvcG9zdHMnLFxuICAgKiAgIHsgdGFnczogWydqYXZhc2NyaXB0JywgJ3R5cGVzY3JpcHQnLCAncmVhY3QnXSB9XG4gICAqICk7XG4gICAqIC8vID0+IFwiaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20vcG9zdHM/dGFncz1qYXZhc2NyaXB0JnRhZ3M9dHlwZXNjcmlwdCZ0YWdzPXJlYWN0XCJcbiAgICogYGBgXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIE51bGwvdW5kZWZpbmVkIGhhbmRsaW5nOlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHVybCA9IGJ1aWxkZXIuYnVpbGRVUkwoXG4gICAqICAgJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcbiAgICogICAnL3VzZXJzJyxcbiAgICogICB7XG4gICAqICAgICBuYW1lOiAnSm9obicsXG4gICAqICAgICBhZ2U6IG51bGwsICAgICAgICAvLyBTa2lwcGVkXG4gICAqICAgICBlbWFpbDogdW5kZWZpbmVkICAvLyBTa2lwcGVkXG4gICAqICAgfVxuICAgKiApO1xuICAgKiAvLyA9PiBcImh0dHBzOi8vYXBpLmV4YW1wbGUuY29tL3VzZXJzP25hbWU9Sm9oblwiXG4gICAqIGBgYFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBTcGVjaWFsIGNoYXJhY3RlcnMgZW5jb2Rpbmc6XG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdXJsID0gYnVpbGRlci5idWlsZFVSTChcbiAgICogICAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxuICAgKiAgICcvc2VhcmNoJyxcbiAgICogICB7IHE6ICdmb28gJiBiYXInLCBjYXRlZ29yeTogJ2NvZGUvZXhhbXBsZXMnIH1cbiAgICogKTtcbiAgICogLy8gPT4gXCJodHRwczovL2FwaS5leGFtcGxlLmNvbS9zZWFyY2g/cT1mb28rJTI2K2JhciZjYXRlZ29yeT1jb2RlJTJGZXhhbXBsZXNcIlxuICAgKiBgYGBcbiAgICovXG4gIGJ1aWxkVVJMKGJhc2VVUkw6IHN0cmluZywgZW5kcG9pbnQ6IHN0cmluZywgcGFyYW1zPzogUXVlcnlQYXJhbXMpOiBzdHJpbmcge1xuICAgIGNvbnN0IHVybCA9IG5ldyBVUkwoZW5kcG9pbnQsIGJhc2VVUkwpO1xuXG4gICAgaWYgKHBhcmFtcykge1xuICAgICAgT2JqZWN0LmtleXMocGFyYW1zKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gcGFyYW1zW2tleV07XG5cbiAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwpIHtcbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHZhbHVlLmZvckVhY2godiA9PiB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChrZXksIFN0cmluZyh2KSkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB1cmwuc2VhcmNoUGFyYW1zLmFwcGVuZChrZXksIFN0cmluZyh2YWx1ZSkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHVybC50b1N0cmluZygpO1xuICB9XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBBcGlSZXNwb25zZSB9IGZyb20gJy4uLy4uL3R5cGVzJztcblxuaW1wb3J0IHsgZ2VuZXJhdGVDb3JyZWxhdGlvbklkIH0gZnJvbSAnLi9Db3JyZWxhdGlvbklkR2VuZXJhdG9yJztcbmltcG9ydCB7IEVycm9yTm9ybWFsaXplciB9IGZyb20gJy4vRXJyb3JzL0Vycm9yTm9ybWFsaXplcic7XG5pbXBvcnQgeyBJbnRlcmNlcHRvck1hbmFnZXIgfSBmcm9tICcuL0ludGVyY2VwdG9ycy9JbnRlcmNlcHRvck1hbmFnZXInO1xuaW1wb3J0IHR5cGUge1xuICBMaXN0UmVzcG9uc2UyLFxuICBQb3N0TW9kZWwsXG4gIFF1ZXJ5UGFyYW1zLFxuICBSZXNwb25zZURhdGEsXG59IGZyb20gJy4vTW9kZWxzJztcbmltcG9ydCB7IFJlcXVlc3RNYW5hZ2VyIH0gZnJvbSAnLi9SZXF1ZXN0TWFuYWdlcic7XG5pbXBvcnQgeyBSZXRyeUhhbmRsZXIgfSBmcm9tICcuL1JldHJ5L1JldHJ5SGFuZGxlcic7XG5pbXBvcnQgeyBTaWduYWxNYW5hZ2VyIH0gZnJvbSAnLi9TaWduYWxzL1NpZ25hbE1hbmFnZXInO1xuaW1wb3J0IHR5cGUgeyBBcGlFcnJvciB9IGZyb20gJy4vdHlwZXMvQXBpRXJyb3InO1xuaW1wb3J0IHR5cGUgeyBFcnJvckludGVyY2VwdG9yIH0gZnJvbSAnLi90eXBlcy9FcnJvckludGVyY2VwdG9yJztcbmltcG9ydCB0eXBlIHsgUmVxdWVzdENvbmZpZyB9IGZyb20gJy4vdHlwZXMvUmVxdWVzdENvbmZpZyc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvUmVxdWVzdEludGVyY2VwdG9yJztcbmltcG9ydCB0eXBlIHsgUmVzcG9uc2VJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvUmVzcG9uc2VJbnRlcmNlcHRvcic7XG5pbXBvcnQgeyBSZXNwb25zZVBhcnNlciB9IGZyb20gJy4vVXRpbHMvUmVzcG9uc2VQYXJzZXInO1xuaW1wb3J0IHsgVXJsQnVpbGRlciB9IGZyb20gJy4vVXRpbHMvVXJsQnVpbGRlcic7XG5cbi8qKlxuICogRW50ZXJwcmlzZS1ncmFkZSBBUEkgY2xpZW50IHdpdGggYWR2YW5jZWQgZmVhdHVyZXMgZm9yIHByb2R1Y3Rpb24gYXBwbGljYXRpb25zLlxuICpcbiAqIFRoaXMgY2xpZW50IHByb3ZpZGVzIGEgcm9idXN0LCB0eXBlLXNhZmUgYWJzdHJhY3Rpb24gb3ZlciB0aGUgRmV0Y2ggQVBJIHdpdGg6XG4gKiAtIENvbXByZWhlbnNpdmUgcmVxdWVzdC9yZXNwb25zZS9lcnJvciBpbnRlcmNlcHRvciBzeXN0ZW1cbiAqIC0gQXV0b21hdGljIHJldHJ5IGxvZ2ljIHdpdGggZXhwb25lbnRpYWwgYmFja29mZlxuICogLSBSZXF1ZXN0IGNvcnJlbGF0aW9uIElEIHRyYWNraW5nIGZvciBkaXN0cmlidXRlZCB0cmFjaW5nXG4gKiAtIFRva2VuLWJhc2VkIGF1dGhlbnRpY2F0aW9uIHdpdGggYXV0b21hdGljIGhlYWRlciBpbmplY3Rpb25cbiAqIC0gUmVxdWVzdCBjYW5jZWxsYXRpb24gYW5kIHRpbWVvdXQgbWFuYWdlbWVudFxuICogLSBUeXBlLXNhZmUgZXJyb3IgaGFuZGxpbmcgd2l0aCBzdHJ1Y3R1cmVkIGVycm9yIHJlc3BvbnNlc1xuICogLSBSZWFjdCBRdWVyeSBpbnRlZ3JhdGlvbiBzdXBwb3J0XG4gKlxuICogQXJjaGl0ZWN0dXJlIFByaW5jaXBsZXM6XG4gKiAtICoqVHlwZSBTYWZldHkqKjogRnVsbCBUeXBlU2NyaXB0IGluZmVyZW5jZSB3aXRoIG5vIGBhbnlgIHR5cGVzXG4gKiAtICoqRXh0ZW5zaWJpbGl0eSoqOiBJbnRlcmNlcHRvciBwYXR0ZXJuIGFsbG93cyBmb3IgZmxleGlibGUgbWlkZGxld2FyZVxuICogLSAqKk9ic2VydmFiaWxpdHkqKjogQnVpbHQtaW4gY29ycmVsYXRpb24gSURzIGZvciByZXF1ZXN0IHRyYWNpbmdcbiAqIC0gKipSZXNpbGllbmNlKio6IEF1dG9tYXRpYyByZXRyaWVzLCB0aW1lb3V0cywgYW5kIGdyYWNlZnVsIGVycm9yIGhhbmRsaW5nXG4gKiAtICoqUGVyZm9ybWFuY2UqKjogUmVxdWVzdCBkZWR1cGxpY2F0aW9uIGFuZCBjYW5jZWxsYXRpb24gc3VwcG9ydFxuICogLSAqKk1vZHVsYXJpdHkqKjogT3JnYW5pemVkIGludG8gZm9jdXNlZCwgc2luZ2xlLXJlc3BvbnNpYmlsaXR5IG1vZHVsZXNcbiAqXG4gKiBAZXhhbXBsZVxuICogQmFzaWMgdXNhZ2U6XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScsIDMwMDAwKTtcbiAqIGNsaWVudC5zZXRBdXRoVG9rZW4oJ3lvdXItand0LXRva2VuJyk7XG4gKlxuICogLy8gVHlwZS1zYWZlIEdFVCByZXF1ZXN0XG4gKiBjb25zdCB7IGRhdGEsIGVycm9yIH0gPSBhd2FpdCBjbGllbnQuZ2V0PFVzZXI+KCcvdXNlcnMvMTIzJyk7XG4gKiBpZiAoZXJyb3IpIHtcbiAqICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGZldGNoIHVzZXI6JywgZXJyb3IpO1xuICogfSBlbHNlIHtcbiAqICAgY29uc29sZS5sb2coJ1VzZXIgZGF0YTonLCBkYXRhKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIFJlYWN0IFF1ZXJ5OlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcXVlcnlDbGllbnQgPSBuZXcgUXVlcnlDbGllbnQoKTtcbiAqIGNvbnN0IGFwaUNsaWVudCA9IG5ldyBBcGlDbGllbnQocHJvY2Vzcy5lbnYuQVBJX0JBU0VfVVJMKTtcbiAqXG4gKiAvLyBBZGQgbG9nZ2luZyBpbnRlcmNlcHRvclxuICogYXBpQ2xpZW50LmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoYXN5bmMgKHJlc3BvbnNlKSA9PiB7XG4gKiAgIGNvbnNvbGUubG9nKCdSZXNwb25zZSByZWNlaXZlZDonLCByZXNwb25zZSk7XG4gKiAgIHJldHVybiByZXNwb25zZTtcbiAqIH0pO1xuICpcbiAqIC8vIFVzZSBpbiBxdWVyaWVzXG4gKiBjb25zdCB7IGRhdGEgfSA9IHVzZVF1ZXJ5KHtcbiAqICAgcXVlcnlLZXk6IFsndXNlcnMnLCB1c2VySWRdLFxuICogICBxdWVyeUZuOiAoKSA9PiBhcGlDbGllbnQuZ2V0PFVzZXI+KGAvdXNlcnMvJHt1c2VySWR9YClcbiAqIH0pO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIEFkdmFuY2VkIGVycm9yIGhhbmRsaW5nOlxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gT3B0aW9uIDE6IEVycm9ycyB0aHJvd24gKGRlZmF1bHQpXG4gKiB0cnkge1xuICogICBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcj4oJy91c2Vycy8xMjMnKTtcbiAqICAgY29uc29sZS5sb2coZGF0YSk7XG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICBpZiAoZXJyb3Iuc3RhdHVzID09PSA0MDQpIHtcbiAqICAgICBjb25zb2xlLmxvZygnVXNlciBub3QgZm91bmQnKTtcbiAqICAgfVxuICogfVxuICpcbiAqIC8vIE9wdGlvbiAyOiBFcnJvcnMgcmV0dXJuZWQgaW4gcmVzcG9uc2VcbiAqIGNvbnN0IHsgZGF0YSwgZXJyb3IgfSA9IGF3YWl0IGNsaWVudC5nZXQ8VXNlcj4oJy91c2Vycy8xMjMnLCB7XG4gKiAgIHRocm93RXJyb3JzOiBmYWxzZVxuICogfSk7XG4gKiBpZiAoZXJyb3IpIHtcbiAqICAgY29uc29sZS5lcnJvcignUmVxdWVzdCBmYWlsZWQ6JywgZXJyb3IpO1xuICogfVxuICogYGBgXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgQXBpQ2xpZW50IHtcbiAgcHJpdmF0ZSByZWFkb25seSBiYXNlVVJMOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdFRpbWVvdXQ6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlcmNlcHRvck1hbmFnZXI6IEludGVyY2VwdG9yTWFuYWdlciA9XG4gICAgbmV3IEludGVyY2VwdG9yTWFuYWdlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHNpZ25hbE1hbmFnZXI6IFNpZ25hbE1hbmFnZXIgPSBuZXcgU2lnbmFsTWFuYWdlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGVycm9yTm9ybWFsaXplcjogRXJyb3JOb3JtYWxpemVyID0gbmV3IEVycm9yTm9ybWFsaXplcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc3BvbnNlUGFyc2VyOiBSZXNwb25zZVBhcnNlciA9IG5ldyBSZXNwb25zZVBhcnNlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHVybEJ1aWxkZXI6IFVybEJ1aWxkZXIgPSBuZXcgVXJsQnVpbGRlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJldHJ5SGFuZGxlcjogUmV0cnlIYW5kbGVyID0gbmV3IFJldHJ5SGFuZGxlcigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJlcXVlc3RNYW5hZ2VyOiBSZXF1ZXN0TWFuYWdlciA9IG5ldyBSZXF1ZXN0TWFuYWdlcigpO1xuICBwcml2YXRlIGF1dGhUb2tlbjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVmcmVzaFRva2VuUHJvbWlzZTogUHJvbWlzZTxzdHJpbmc+IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgY29ycmVsYXRpb25JZFByZWZpeDogc3RyaW5nID0gJ2FwaSc7XG4gIHByaXZhdGUgaW5jbHVkZUNvcnJlbGF0aW9uSWQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IEFQSSBjbGllbnQgaW5zdGFuY2VcbiAgICogQHBhcmFtIGJhc2VVUkwgLSBCYXNlIFVSTCBmb3IgYWxsIEFQSSByZXF1ZXN0cyAoZGVmYXVsdDogZW1wdHkgc3RyaW5nIGZvciByZWxhdGl2ZSBVUkxzKVxuICAgKiBAcGFyYW0gZGVmYXVsdFRpbWVvdXQgLSBEZWZhdWx0IHJlcXVlc3QgdGltZW91dCBpbiBtaWxsaXNlY29uZHMgKGRlZmF1bHQ6IDMwMDAwKVxuICAgKi9cbiAgY29uc3RydWN0b3IoYmFzZVVSTDogc3RyaW5nID0gJycsIGRlZmF1bHRUaW1lb3V0OiBudW1iZXIgPSAzMDAwMCkge1xuICAgIHRoaXMuYmFzZVVSTCA9IGJhc2VVUkw7XG4gICAgdGhpcy5kZWZhdWx0VGltZW91dCA9IGRlZmF1bHRUaW1lb3V0O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHByZWZpeCBmb3IgYXV0by1nZW5lcmF0ZWQgY29ycmVsYXRpb24gSURzXG4gICAqIEBwYXJhbSBwcmVmaXggLSBUaGUgcHJlZml4IHRvIHVzZSBmb3IgY29ycmVsYXRpb24gSURzIChlLmcuLCAnYXBpJywgJ3dlYicsICdtb2JpbGUnKVxuICAgKi9cbiAgc2V0Q29ycmVsYXRpb25JZFByZWZpeChwcmVmaXg6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuY29ycmVsYXRpb25JZFByZWZpeCA9IHByZWZpeDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIG9yIGRpc2FibGVzIGF1dG9tYXRpYyBjb3JyZWxhdGlvbiBJRCBnZW5lcmF0aW9uXG4gICAqIEBwYXJhbSBpbmNsdWRlIC0gV2hldGhlciB0byBpbmNsdWRlIGNvcnJlbGF0aW9uIElEcyBpbiByZXF1ZXN0c1xuICAgKi9cbiAgc2V0SW5jbHVkZUNvcnJlbGF0aW9uSWQoaW5jbHVkZTogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuaW5jbHVkZUNvcnJlbGF0aW9uSWQgPSBpbmNsdWRlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHJlcXVlc3QgaW50ZXJjZXB0b3IgdG8gbW9kaWZ5IHJlcXVlc3RzIGJlZm9yZSB0aGV5J3JlIHNlbnRcbiAgICogQHBhcmFtIGludGVyY2VwdG9yIC0gRnVuY3Rpb24gdG8gaW50ZXJjZXB0IGFuZCBwb3RlbnRpYWxseSBtb2RpZnkgcmVxdWVzdCBjb25maWdcbiAgICogQHJldHVybnMgRnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdW5yZWdpc3RlciA9IGNsaWVudC5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoYXN5bmMgKGNvbmZpZykgPT4ge1xuICAgKiAgIGNvbmZpZy5oZWFkZXJzID0gY29uZmlnLmhlYWRlcnMgfHwgbmV3IEhlYWRlcnMoKTtcbiAgICogICBjb25maWcuaGVhZGVycy5zZXQoJ1gtQ2xpZW50LVZlcnNpb24nLCAnMS4wLjAnKTtcbiAgICogICByZXR1cm4gY29uZmlnO1xuICAgKiB9KTtcbiAgICpcbiAgICogLy8gTGF0ZXIsIHRvIHJlbW92ZSB0aGUgaW50ZXJjZXB0b3I6XG4gICAqIHVucmVnaXN0ZXIoKTtcbiAgICogYGBgXG4gICAqL1xuICBhZGRSZXF1ZXN0SW50ZXJjZXB0b3IoaW50ZXJjZXB0b3I6IFJlcXVlc3RJbnRlcmNlcHRvcik6ICgpID0+IHZvaWQge1xuICAgIHJldHVybiB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHJlc3BvbnNlIGludGVyY2VwdG9yIHRvIG1vZGlmeSByZXNwb25zZXMgYmVmb3JlIHRoZXkncmUgcmV0dXJuZWRcbiAgICogQHBhcmFtIGludGVyY2VwdG9yIC0gRnVuY3Rpb24gdG8gaW50ZXJjZXB0IGFuZCBwb3RlbnRpYWxseSBtb2RpZnkgcmVzcG9uc2VzXG4gICAqIEByZXR1cm5zIEZ1bmN0aW9uIHRvIHVucmVnaXN0ZXIgdGhpcyBpbnRlcmNlcHRvclxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNsaWVudC5hZGRSZXNwb25zZUludGVyY2VwdG9yKGFzeW5jIChyZXNwb25zZSkgPT4ge1xuICAgKiAgIC8vIFRyYW5zZm9ybSBkYXRhIGZvcm1hdFxuICAgKiAgIGlmIChyZXNwb25zZS5kYXRhKSB7XG4gICAqICAgICByZXNwb25zZS5kYXRhID0gY2FtZWxDYXNlS2V5cyhyZXNwb25zZS5kYXRhKTtcbiAgICogICB9XG4gICAqICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBhZGRSZXNwb25zZUludGVyY2VwdG9yKGludGVyY2VwdG9yOiBSZXNwb25zZUludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMuaW50ZXJjZXB0b3JNYW5hZ2VyLmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhbiBlcnJvciBpbnRlcmNlcHRvciB0byBoYW5kbGUgb3IgdHJhbnNmb3JtIGVycm9yc1xuICAgKiBAcGFyYW0gaW50ZXJjZXB0b3IgLSBGdW5jdGlvbiB0byBpbnRlcmNlcHQgYW5kIHBvdGVudGlhbGx5IG1vZGlmeSBlcnJvcnNcbiAgICogQHJldHVybnMgRnVuY3Rpb24gdG8gdW5yZWdpc3RlciB0aGlzIGludGVyY2VwdG9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY2xpZW50LmFkZEVycm9ySW50ZXJjZXB0b3IoYXN5bmMgKGVycm9yKSA9PiB7XG4gICAqICAgLy8gTG9nIGVycm9ycyB0byBtb25pdG9yaW5nIHNlcnZpY2VcbiAgICogICBpZiAoZXJyb3Iuc3RhdHVzID49IDUwMCkge1xuICAgKiAgICAgYXdhaXQgbW9uaXRvcmluZ1NlcnZpY2UubG9nRXJyb3IoZXJyb3IpO1xuICAgKiAgIH1cbiAgICogICByZXR1cm4gZXJyb3I7IC8vIFJlLXRocm93IHRoZSBlcnJvclxuICAgKiB9KTtcbiAgICogYGBgXG4gICAqL1xuICBhZGRFcnJvckludGVyY2VwdG9yKGludGVyY2VwdG9yOiBFcnJvckludGVyY2VwdG9yKTogKCkgPT4gdm9pZCB7XG4gICAgcmV0dXJuIHRoaXMuaW50ZXJjZXB0b3JNYW5hZ2VyLmFkZEVycm9ySW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGF1dGhlbnRpY2F0aW9uIHRva2VuIGZvciBzdWJzZXF1ZW50IHJlcXVlc3RzXG4gICAqIEBwYXJhbSB0b2tlbiAtIEpXVCB0b2tlbiBvciBudWxsIHRvIGNsZWFyIGF1dGhlbnRpY2F0aW9uXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gU2V0IHRva2VuIGFmdGVyIGxvZ2luXG4gICAqIGNsaWVudC5zZXRBdXRoVG9rZW4obG9naW5SZXNwb25zZS5hY2Nlc3NUb2tlbik7XG4gICAqXG4gICAqIC8vIENsZWFyIHRva2VuIG9uIGxvZ291dFxuICAgKiBjbGllbnQuc2V0QXV0aFRva2VuKG51bGwpO1xuICAgKiBgYGBcbiAgICovXG4gIHNldEF1dGhUb2tlbih0b2tlbjogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuYXV0aFRva2VuID0gdG9rZW47XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIHRoZSBjdXJyZW50IGF1dGhlbnRpY2F0aW9uIHRva2VuXG4gICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IGF1dGggdG9rZW4gb3IgbnVsbCBpZiBub3Qgc2V0XG4gICAqL1xuICBnZXRBdXRoVG9rZW4oKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aFRva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbmNlbHMgYSBzcGVjaWZpYyByZXF1ZXN0IGJ5IGl0cyBrZXlcbiAgICogQHBhcmFtIGtleSAtIFRoZSB1bmlxdWUga2V5IGlkZW50aWZ5aW5nIHRoZSByZXF1ZXN0IHRvIGNhbmNlbFxuICAgKi9cbiAgY2FuY2VsUmVxdWVzdChrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMucmVxdWVzdE1hbmFnZXIuY2FuY2VsKGtleSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FuY2VscyBhbGwgcGVuZGluZyByZXF1ZXN0c1xuICAgKiBVc2VmdWwgZm9yIGNsZWFudXAgb24gbmF2aWdhdGlvbiBvciBjb21wb25lbnQgdW5tb3VudFxuICAgKi9cbiAgY2FuY2VsQWxsUmVxdWVzdHMoKTogdm9pZCB7XG4gICAgdGhpcy5yZXF1ZXN0TWFuYWdlci5jYW5jZWxBbGwoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb3JlIHJlcXVlc3QgbWV0aG9kIHRoYXQgaGFuZGxlcyBhbGwgSFRUUCBvcGVyYXRpb25zXG4gICAqIEB0ZW1wbGF0ZSBUIC0gVGhlIGV4cGVjdGVkIHJlc3BvbnNlIGRhdGEgdHlwZVxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnQgcmVsYXRpdmUgdG8gYmFzZVVSTFxuICAgKiBAcGFyYW0gY29uZmlnIC0gUmVxdWVzdCBjb25maWd1cmF0aW9uIG9wdGlvbnNcbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gQXBpUmVzcG9uc2Ugd2l0aCBkYXRhIG9yIGVycm9yXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucmVxdWVzdDxVc2VyPignL3VzZXJzLzEyMycsIHtcbiAgICogICBtZXRob2Q6ICdHRVQnLFxuICAgKiAgIHRpbWVvdXQ6IDUwMDAsXG4gICAqICAgdGhyb3dFcnJvcnM6IGZhbHNlXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIHJlcXVlc3Q8VCA9IFJlc3BvbnNlRGF0YT4oXG4gICAgZW5kcG9pbnQ6IHN0cmluZyxcbiAgICBjb25maWc6IFJlcXVlc3RDb25maWcgPSB7fVxuICApOiBQcm9taXNlPEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPj4ge1xuICAgIC8vIEdlbmVyYXRlIGNvcnJlbGF0aW9uIElEXG4gICAgY29uc3QgY29ycmVsYXRpb25JZCA9XG4gICAgICBjb25maWcuY29ycmVsYXRpb25JZCB8fFxuICAgICAgKCFjb25maWcuc2tpcENvcnJlbGF0aW9uSWQgJiYgdGhpcy5pbmNsdWRlQ29ycmVsYXRpb25JZFxuICAgICAgICA/IGdlbmVyYXRlQ29ycmVsYXRpb25JZCh0aGlzLmNvcnJlbGF0aW9uSWRQcmVmaXgpXG4gICAgICAgIDogdW5kZWZpbmVkKTtcblxuICAgIC8vIEdlbmVyYXRlIHJlcXVlc3Qga2V5IGZvciB0cmFja2luZ1xuICAgIGNvbnN0IHJlcXVlc3RLZXkgPSBgJHtjb25maWcubWV0aG9kIHx8ICdHRVQnfV8ke2VuZHBvaW50fV8ke0RhdGUubm93KCl9YDtcblxuICAgIC8vIENyZWF0ZSBtYXN0ZXIgY29udHJvbGxlciBmb3IgdGhpcyByZXF1ZXN0XG4gICAgY29uc3QgbWFzdGVyQ29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcblxuICAgIHRyeSB7XG4gICAgICAvLyBDb21iaW5lIGFsbCBhYm9ydCBzaWduYWxzXG4gICAgICBjb25zdCBzaWduYWxzOiBBcnJheTxBYm9ydFNpZ25hbCB8IHVuZGVmaW5lZD4gPSBbXG4gICAgICAgIGNvbmZpZy5zaWduYWwsXG4gICAgICAgIGNvbmZpZy5jYW5jZWxUb2tlbj8uc2lnbmFsLFxuICAgICAgICBtYXN0ZXJDb250cm9sbGVyLnNpZ25hbCxcbiAgICAgIF07XG5cbiAgICAgIC8vIEFkZCB0aW1lb3V0IHNpZ25hbCBpZiBjb25maWd1cmVkXG4gICAgICBjb25zdCB0aW1lb3V0ID0gY29uZmlnLnRpbWVvdXQgfHwgdGhpcy5kZWZhdWx0VGltZW91dDtcbiAgICAgIGNvbnN0IHRpbWVvdXRDb250cm9sbGVyID0gdGhpcy5zaWduYWxNYW5hZ2VyLmNyZWF0ZVRpbWVvdXRTaWduYWwodGltZW91dCk7XG5cbiAgICAgIHNpZ25hbHMucHVzaCh0aW1lb3V0Q29udHJvbGxlci5zaWduYWwpO1xuXG4gICAgICAvLyBDcmVhdGUgY29tYmluZWQgc2lnbmFsXG4gICAgICBjb25zdCBjb21iaW5lZENvbnRyb2xsZXIgPVxuICAgICAgICB0aGlzLnNpZ25hbE1hbmFnZXIuY3JlYXRlQ29tYmluZWRTaWduYWwoc2lnbmFscyk7XG5cbiAgICAgIC8vIFRyYWNrIHRoaXMgcmVxdWVzdFxuICAgICAgaWYgKGNvcnJlbGF0aW9uSWQpIHtcbiAgICAgICAgdGhpcy5yZXF1ZXN0TWFuYWdlci5hZGQocmVxdWVzdEtleSwgbWFzdGVyQ29udHJvbGxlciwgY29ycmVsYXRpb25JZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEFwcGx5IHJlcXVlc3QgaW50ZXJjZXB0b3JzXG4gICAgICBjb25zdCBmaW5hbENvbmZpZyA9XG4gICAgICAgIGF3YWl0IHRoaXMuaW50ZXJjZXB0b3JNYW5hZ2VyLmFwcGx5UmVxdWVzdEludGVyY2VwdG9ycyh7XG4gICAgICAgICAgLi4uY29uZmlnLFxuICAgICAgICAgIHNpZ25hbDogY29tYmluZWRDb250cm9sbGVyLnNpZ25hbCxcbiAgICAgICAgICBjb3JyZWxhdGlvbklkLFxuICAgICAgICB9KTtcblxuICAgICAgLy8gQnVpbGQgZnVsbCBVUkxcbiAgICAgIGNvbnN0IHVybCA9IHRoaXMudXJsQnVpbGRlci5idWlsZFVSTChcbiAgICAgICAgdGhpcy5iYXNlVVJMLFxuICAgICAgICBlbmRwb2ludCxcbiAgICAgICAgZmluYWxDb25maWcucGFyYW1zIGFzIFF1ZXJ5UGFyYW1zXG4gICAgICApO1xuXG4gICAgICAvLyBBZGQgZGVmYXVsdCBoZWFkZXJzXG4gICAgICBjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoZmluYWxDb25maWcuaGVhZGVycyk7XG5cbiAgICAgIC8vIEFkZCBjb3JyZWxhdGlvbiBJRCBoZWFkZXJcbiAgICAgIGlmIChjb3JyZWxhdGlvbklkKSB7XG4gICAgICAgIGhlYWRlcnMuc2V0KCdYLUNvcnJlbGF0aW9uLUlkJywgY29ycmVsYXRpb25JZCk7XG4gICAgICAgIGhlYWRlcnMuc2V0KCdYLVJlcXVlc3QtSWQnLCBjb3JyZWxhdGlvbklkKTtcbiAgICAgIH1cblxuICAgICAgLy8gQWRkIGF1dGggaGVhZGVyIGlmIHRva2VuIGV4aXN0c1xuICAgICAgaWYgKHRoaXMuYXV0aFRva2VuICYmICFmaW5hbENvbmZpZy5za2lwQXV0aFJlZnJlc2gpIHtcbiAgICAgICAgaGVhZGVycy5zZXQoJ0F1dGhvcml6YXRpb24nLCBgQmVhcmVyICR7dGhpcy5hdXRoVG9rZW59YCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFNldCBjb250ZW50LXR5cGUgZm9yIEpTT04gcGF5bG9hZHNcbiAgICAgIGlmIChcbiAgICAgICAgZmluYWxDb25maWcuYm9keSAmJlxuICAgICAgICB0eXBlb2YgZmluYWxDb25maWcuYm9keSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIShmaW5hbENvbmZpZy5ib2R5IGluc3RhbmNlb2YgRm9ybURhdGEpXG4gICAgICApIHtcbiAgICAgICAgaGVhZGVycy5zZXQoJ0NvbnRlbnQtVHlwZScsICdhcHBsaWNhdGlvbi9qc29uJyk7XG4gICAgICAgIGZpbmFsQ29uZmlnLmJvZHkgPSBKU09OLnN0cmluZ2lmeShmaW5hbENvbmZpZy5ib2R5KTtcbiAgICAgIH1cblxuICAgICAgZmluYWxDb25maWcuaGVhZGVycyA9IGhlYWRlcnM7XG5cbiAgICAgIC8vIENyZWF0ZSBmZXRjaCBwcm9taXNlXG4gICAgICBjb25zdCBmZXRjaFByb21pc2UgPSBhc3luYyAoKTogUHJvbWlzZTxBcGlSZXNwb25zZTxULCBBcGlFcnJvcj4+ID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVybCwge1xuICAgICAgICAgICAgLi4uZmluYWxDb25maWcsXG4gICAgICAgICAgICBzaWduYWw6IGNvbWJpbmVkQ29udHJvbGxlci5zaWduYWwsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBQYXJzZSByZXNwb25zZSBkYXRhXG4gICAgICAgICAgY29uc3QgcmVzcG9uc2VEYXRhID1cbiAgICAgICAgICAgIGF3YWl0IHRoaXMucmVzcG9uc2VQYXJzZXIucGFyc2VSZXNwb25zZShyZXNwb25zZSk7XG5cbiAgICAgICAgICAvLyBIYW5kbGUgZXJyb3IgcmVzcG9uc2VzXG4gICAgICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgICAgICAgY29uc3QgZXJyb3I6IEFwaUVycm9yID0gT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgICAgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIHJlc3BvbnNlRGF0YS50aXRsZSB8fFxuICAgICAgICAgICAgICAgICAgYEhUVFAgJHtyZXNwb25zZS5zdGF0dXN9OiAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHlwZTpcbiAgICAgICAgICAgICAgICAgIHJlc3BvbnNlRGF0YS50eXBlIHx8XG4gICAgICAgICAgICAgICAgICB0aGlzLmVycm9yTm9ybWFsaXplci5nZXRFcnJvclR5cGUocmVzcG9uc2Uuc3RhdHVzKSxcbiAgICAgICAgICAgICAgICB0aXRsZTpcbiAgICAgICAgICAgICAgICAgIHJlc3BvbnNlRGF0YS50aXRsZSB8fFxuICAgICAgICAgICAgICAgICAgdGhpcy5lcnJvck5vcm1hbGl6ZXIuZ2V0RXJyb3JUaXRsZShyZXNwb25zZS5zdGF0dXMpLFxuICAgICAgICAgICAgICAgIHN0YXR1czogcmVzcG9uc2Uuc3RhdHVzLFxuICAgICAgICAgICAgICAgIHRyYWNlSWQ6IHJlc3BvbnNlRGF0YS50cmFjZUlkIHx8IGNvcnJlbGF0aW9uSWQsXG4gICAgICAgICAgICAgICAgZXJyb3JzOiByZXNwb25zZURhdGEuZXJyb3JzLFxuICAgICAgICAgICAgICAgIGlzQWJvcnRlZDogZmFsc2UsXG4gICAgICAgICAgICAgICAgY29uZmlnOiBmaW5hbENvbmZpZyxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2Ugc2hvdWxkIHRocm93IG9yIHJldHVybiBlcnJvciBpbiByZXNwb25zZVxuICAgICAgICAgICAgaWYgKGZpbmFsQ29uZmlnLnRocm93RXJyb3JzICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIFJldHVybiBlcnJvciBpbiBBcGlSZXNwb25zZS5lcnJvciBmaWVsZFxuICAgICAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5pbnRlcmNlcHRvck1hbmFnZXIuYXBwbHlSZXNwb25zZUludGVyY2VwdG9ycyh7XG4gICAgICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICAgIH0gYXMgQXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBGb3JtYXQgc3VjY2Vzc2Z1bCByZXNwb25zZVxuICAgICAgICAgIGNvbnN0IGFwaVJlc3BvbnNlOiBBcGlSZXNwb25zZTxUPiA9IHtcbiAgICAgICAgICAgIGRhdGE6IHJlc3BvbnNlRGF0YSBhcyBULFxuICAgICAgICAgIH07XG5cbiAgICAgICAgICAvLyBBcHBseSByZXNwb25zZSBpbnRlcmNlcHRvcnNcbiAgICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5pbnRlcmNlcHRvck1hbmFnZXIuYXBwbHlSZXNwb25zZUludGVyY2VwdG9ycyhcbiAgICAgICAgICAgIGFwaVJlc3BvbnNlXG4gICAgICAgICAgKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3I6IHVua25vd24pIHtcbiAgICAgICAgICAvLyBIYW5kbGUgYWJvcnQgZXJyb3JzXG4gICAgICAgICAgaWYgKChlcnJvciBhcyBFcnJvcikubmFtZSA9PT0gJ0Fib3J0RXJyb3InKSB7XG4gICAgICAgICAgICBjb25zdCBhYm9ydEVycm9yID0gT2JqZWN0LmFzc2lnbihcbiAgICAgICAgICAgICAgbmV3IEVycm9yKChlcnJvciBhcyBFcnJvcikubWVzc2FnZSB8fCAnUmVxdWVzdCBhYm9ydGVkJyksXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB0eXBlOiAncmVxdWVzdF9jYW5jZWxsZWQnLFxuICAgICAgICAgICAgICAgIHRpdGxlOiAnUmVxdWVzdCB3YXMgY2FuY2VsbGVkJyxcbiAgICAgICAgICAgICAgICBzdGF0dXM6IDAsXG4gICAgICAgICAgICAgICAgdHJhY2VJZDogY29ycmVsYXRpb25JZCxcbiAgICAgICAgICAgICAgICBpc0Fib3J0ZWQ6IHRydWUsXG4gICAgICAgICAgICAgICAgY29uZmlnOiBmaW5hbENvbmZpZyxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2Ugc2hvdWxkIHRocm93IG9yIHJldHVybiBlcnJvciBpbiByZXNwb25zZVxuICAgICAgICAgICAgaWYgKGZpbmFsQ29uZmlnLnRocm93RXJyb3JzICE9PSBmYWxzZSkge1xuICAgICAgICAgICAgICB0aHJvdyBhYm9ydEVycm9yO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgLy8gUmV0dXJuIGVycm9yIGluIEFwaVJlc3BvbnNlLmVycm9yIGZpZWxkXG4gICAgICAgICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmludGVyY2VwdG9yTWFuYWdlci5hcHBseVJlc3BvbnNlSW50ZXJjZXB0b3JzKHtcbiAgICAgICAgICAgICAgICBlcnJvcjogYWJvcnRFcnJvcixcbiAgICAgICAgICAgICAgfSBhcyBBcGlSZXNwb25zZTxULCBBcGlFcnJvcj4pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgICB9O1xuXG4gICAgICAvLyBIYW5kbGUgcmV0cmllcyBpZiBjb25maWd1cmVkXG4gICAgICBpZiAoZmluYWxDb25maWcucmV0cmllcyAmJiBmaW5hbENvbmZpZy5yZXRyaWVzID4gMCkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5yZXRyeUhhbmRsZXIucmV0cnlSZXF1ZXN0KFxuICAgICAgICAgIGZldGNoUHJvbWlzZSxcbiAgICAgICAgICBmaW5hbENvbmZpZy5yZXRyaWVzLFxuICAgICAgICAgIGZpbmFsQ29uZmlnLnJldHJ5RGVsYXkgfHwgMTAwMCxcbiAgICAgICAgICBjb21iaW5lZENvbnRyb2xsZXIuc2lnbmFsXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhd2FpdCBmZXRjaFByb21pc2UoKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gSGFuZGxlIGVycm9yc1xuICAgICAgY29uc3QgYXBpRXJyb3I6IEFwaUVycm9yID0gdGhpcy5lcnJvck5vcm1hbGl6ZXIubm9ybWFsaXplRXJyb3IoXG4gICAgICAgIGVycm9yLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIGNvcnJlbGF0aW9uSWRcbiAgICAgICk7XG5cbiAgICAgIC8vIENoZWNrIGlmIHdlIHNob3VsZCB0aHJvdyBvciByZXR1cm4gZXJyb3IgaW4gcmVzcG9uc2VcbiAgICAgIGlmIChjb25maWcudGhyb3dFcnJvcnMgIT09IGZhbHNlKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuaW50ZXJjZXB0b3JNYW5hZ2VyLmFwcGx5RXJyb3JJbnRlcmNlcHRvcnMoYXBpRXJyb3IpO1xuICAgICAgICAvLyBUaGlzIGxpbmUgd2lsbCBuZXZlciBiZSByZWFjaGVkIGFzIGFwcGx5RXJyb3JJbnRlcmNlcHRvcnMgYWx3YXlzIHRocm93cyxcbiAgICAgICAgLy8gYnV0IFR5cGVTY3JpcHQgcmVxdWlyZXMgYSByZXR1cm4gc3RhdGVtZW50XG4gICAgICAgIHRocm93IGFwaUVycm9yO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gUmV0dXJuIGVycm9yIGluIEFwaVJlc3BvbnNlLmVycm9yIGZpZWxkXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZXJyb3I6IGFwaUVycm9yLFxuICAgICAgICB9IGFzIEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPjtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgLy8gQ2xlYW4gdXAgcmVxdWVzdCB0cmFja2luZ1xuICAgICAgdGhpcy5yZXF1ZXN0TWFuYWdlci5yZW1vdmUocmVxdWVzdEtleSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGEgR0VUIHJlcXVlc3RcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgZXhwZWN0ZWQgcmVzcG9uc2UgZGF0YSB0eXBlXG4gICAqIEBwYXJhbSBlbmRwb2ludCAtIEFQSSBlbmRwb2ludFxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgeyBkYXRhLCBlcnJvciB9ID0gYXdhaXQgY2xpZW50LmdldDxVc2VyW10+KCcvdXNlcnMnLCB7XG4gICAqICAgcGFyYW1zOiB7IGFjdGl2ZTogdHJ1ZSB9LFxuICAgKiAgIHRpbWVvdXQ6IDUwMDBcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgZ2V0PFQgPSBSZXNwb25zZURhdGE+KFxuICAgIGVuZHBvaW50OiBzdHJpbmcsXG4gICAgY29uZmlnPzogUmVxdWVzdENvbmZpZ1xuICApOiBQcm9taXNlPEFwaVJlc3BvbnNlPFQsIEFwaUVycm9yPj4ge1xuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8VD4oZW5kcG9pbnQsIHsgLi4uY29uZmlnLCBtZXRob2Q6ICdHRVQnIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGEgUE9TVCByZXF1ZXN0XG4gICAqIEB0ZW1wbGF0ZSBUIC0gVGhlIGV4cGVjdGVkIHJlc3BvbnNlIGRhdGEgdHlwZVxuICAgKiBAdGVtcGxhdGUgVERhdGEgLSBUaGUgcmVxdWVzdCBib2R5IGRhdGEgdHlwZVxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnRcbiAgICogQHBhcmFtIGRhdGEgLSBSZXF1ZXN0IGJvZHkgZGF0YVxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgeyBkYXRhLCBlcnJvciB9ID0gYXdhaXQgY2xpZW50LnBvc3Q8VXNlciwgQ3JlYXRlVXNlckR0bz4oJy91c2VycycsIHtcbiAgICogICBuYW1lOiAnSm9obiBEb2UnLFxuICAgKiAgIGVtYWlsOiAnam9obkBleGFtcGxlLmNvbSdcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgcG9zdDxUID0gUmVzcG9uc2VEYXRhLCBURGF0YSA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PihcbiAgICBlbmRwb2ludDogc3RyaW5nLFxuICAgIGRhdGE/OiBURGF0YSxcbiAgICBjb25maWc/OiBSZXF1ZXN0Q29uZmlnXG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+PiB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdDxUPihlbmRwb2ludCwgeyAuLi5jb25maWcsIG1ldGhvZDogJ1BPU1QnLCBib2R5OiBkYXRhIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGEgUFVUIHJlcXVlc3RcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgZXhwZWN0ZWQgcmVzcG9uc2UgZGF0YSB0eXBlXG4gICAqIEB0ZW1wbGF0ZSBURGF0YSAtIFRoZSByZXF1ZXN0IGJvZHkgZGF0YSB0eXBlXG4gICAqIEBwYXJhbSBlbmRwb2ludCAtIEFQSSBlbmRwb2ludFxuICAgKiBAcGFyYW0gZGF0YSAtIFJlcXVlc3QgYm9keSBkYXRhXG4gICAqIEBwYXJhbSBjb25maWcgLSBPcHRpb25hbCByZXF1ZXN0IGNvbmZpZ3VyYXRpb25cbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gQXBpUmVzcG9uc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCB7IGRhdGEsIGVycm9yIH0gPSBhd2FpdCBjbGllbnQucHV0PFVzZXIsIFVwZGF0ZVVzZXJEdG8+KFxuICAgKiAgICcvdXNlcnMvMTIzJyxcbiAgICogICB7IG5hbWU6ICdKYW5lIERvZScgfVxuICAgKiApO1xuICAgKiBgYGBcbiAgICovXG4gIHB1dDxUID0gUmVzcG9uc2VEYXRhLCBURGF0YSA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PihcbiAgICBlbmRwb2ludDogc3RyaW5nLFxuICAgIGRhdGE/OiBURGF0YSxcbiAgICBjb25maWc/OiBSZXF1ZXN0Q29uZmlnXG4gICk6IFByb21pc2U8QXBpUmVzcG9uc2U8VCwgQXBpRXJyb3I+PiB7XG4gICAgcmV0dXJuIHRoaXMucmVxdWVzdDxUPihlbmRwb2ludCwgeyAuLi5jb25maWcsIG1ldGhvZDogJ1BVVCcsIGJvZHk6IGRhdGEgfSk7XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgYSBQQVRDSCByZXF1ZXN0XG4gICAqIEB0ZW1wbGF0ZSBUIC0gVGhlIGV4cGVjdGVkIHJlc3BvbnNlIGRhdGEgdHlwZVxuICAgKiBAdGVtcGxhdGUgVERhdGEgLSBUaGUgcmVxdWVzdCBib2R5IGRhdGEgdHlwZVxuICAgKiBAcGFyYW0gZW5kcG9pbnQgLSBBUEkgZW5kcG9pbnRcbiAgICogQHBhcmFtIGRhdGEgLSBSZXF1ZXN0IGJvZHkgZGF0YVxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgeyBkYXRhLCBlcnJvciB9ID0gYXdhaXQgY2xpZW50LnBhdGNoPFVzZXI+KFxuICAgKiAgICcvdXNlcnMvMTIzJyxcbiAgICogICB7IHN0YXR1czogJ2FjdGl2ZScgfVxuICAgKiApO1xuICAgKiBgYGBcbiAgICovXG4gIHBhdGNoPFQgPSBSZXNwb25zZURhdGEsIFREYXRhID0gUmVjb3JkPHN0cmluZywgdW5rbm93bj4+KFxuICAgIGVuZHBvaW50OiBzdHJpbmcsXG4gICAgZGF0YT86IFREYXRhLFxuICAgIGNvbmZpZz86IFJlcXVlc3RDb25maWdcbiAgKTogUHJvbWlzZTxBcGlSZXNwb25zZTxULCBBcGlFcnJvcj4+IHtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0PFQ+KGVuZHBvaW50LCB7XG4gICAgICAuLi5jb25maWcsXG4gICAgICBtZXRob2Q6ICdQQVRDSCcsXG4gICAgICBib2R5OiBkYXRhLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm1zIGEgREVMRVRFIHJlcXVlc3RcbiAgICogQHRlbXBsYXRlIFQgLSBUaGUgZXhwZWN0ZWQgcmVzcG9uc2UgZGF0YSB0eXBlXG4gICAqIEBwYXJhbSBlbmRwb2ludCAtIEFQSSBlbmRwb2ludFxuICAgKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgcmVxdWVzdCBjb25maWd1cmF0aW9uXG4gICAqIEByZXR1cm5zIFByb21pc2UgcmVzb2x2aW5nIHRvIEFwaVJlc3BvbnNlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgeyBlcnJvciB9ID0gYXdhaXQgY2xpZW50LmRlbGV0ZSgnL3VzZXJzLzEyMycpO1xuICAgKiBpZiAoIWVycm9yKSB7XG4gICAqICAgY29uc29sZS5sb2coJ1VzZXIgZGVsZXRlZCBzdWNjZXNzZnVsbHknKTtcbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIGRlbGV0ZTxUID0gUmVzcG9uc2VEYXRhPihcbiAgICBlbmRwb2ludDogc3RyaW5nLFxuICAgIGNvbmZpZz86IFJlcXVlc3RDb25maWdcbiAgKTogUHJvbWlzZTxBcGlSZXNwb25zZTxULCBBcGlFcnJvcj4+IHtcbiAgICByZXR1cm4gdGhpcy5yZXF1ZXN0PFQ+KGVuZHBvaW50LCB7IC4uLmNvbmZpZywgbWV0aG9kOiAnREVMRVRFJyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtcyBhIGZpbHRlcmVkIGxpc3QgcmVxdWVzdCB3aXRoIHBhZ2luYXRpb24gYW5kIHNvcnRpbmdcbiAgICogQHRlbXBsYXRlIFRMaXN0TW9kZWwgLSBUaGUgdHlwZSBvZiBpbmRpdmlkdWFsIGxpc3QgaXRlbXNcbiAgICogQHRlbXBsYXRlIFRGaWx0ZXIgLSBUaGUgZmlsdGVyIGNyaXRlcmlhIHR5cGVcbiAgICogQHBhcmFtIHVybCAtIEFQSSBlbmRwb2ludFxuICAgKiBAcGFyYW0gZGF0YSAtIFBhZ2luYXRpb24gYW5kIGZpbHRlciBkYXRhXG4gICAqIEBwYXJhbSBjb25maWcgLSBPcHRpb25hbCByZXF1ZXN0IGNvbmZpZ3VyYXRpb25cbiAgICogQHJldHVybnMgUHJvbWlzZSByZXNvbHZpbmcgdG8gcGFnaW5hdGVkIGxpc3QgcmVzcG9uc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjb25zdCB7IGRhdGEsIGVycm9yIH0gPSBhd2FpdCBjbGllbnQuZmlsdGVyPFVzZXIsIFVzZXJGaWx0ZXI+KFxuICAgKiAgICcvdXNlcnMvZmlsdGVyJyxcbiAgICogICB7XG4gICAqICAgICBwYWdlT2Zmc2V0OiAwLFxuICAgKiAgICAgcGFnZVNpemU6IDIwLFxuICAgKiAgICAgc29ydEZpZWxkOiAnY3JlYXRlZEF0JyxcbiAgICogICAgIHNvcnRPcmRlcjogJ2Rlc2MnLFxuICAgKiAgICAgZmlsdGVyTW9kZWw6IHsgc3RhdHVzOiAnYWN0aXZlJyB9XG4gICAqICAgfVxuICAgKiApO1xuICAgKlxuICAgKiBpZiAoZGF0YSkge1xuICAgKiAgIGNvbnNvbGUubG9nKGBGb3VuZCAke2RhdGEuVG90YWx9IHVzZXJzYCk7XG4gICAqICAgY29uc29sZS5sb2coJ1VzZXJzOicsIGRhdGEuRGF0YSk7XG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBmaWx0ZXI8VExpc3RNb2RlbCwgVEZpbHRlciA9IFJlY29yZDxzdHJpbmcsIHVua25vd24+PihcbiAgICB1cmw6IHN0cmluZyxcbiAgICBkYXRhOiBQb3N0TW9kZWw8VEZpbHRlcj4sXG4gICAgY29uZmlnPzogUmVxdWVzdENvbmZpZ1xuICApOiBQcm9taXNlPEFwaVJlc3BvbnNlPExpc3RSZXNwb25zZTI8VExpc3RNb2RlbD4sIEFwaUVycm9yPj4ge1xuICAgIC8vIE1lcmdlIGJvZHk6IHsgLi4ucG9zdE1vZGVsLCAuLi5wb3N0TW9kZWwuZmlsdGVyTW9kZWwgfVxuICAgIGNvbnN0IG1lcmdlZERhdGEgPSB7IC4uLmRhdGEsIC4uLmRhdGEuZmlsdGVyTW9kZWwgfTtcblxuICAgIHJldHVybiB0aGlzLnJlcXVlc3Q8TGlzdFJlc3BvbnNlMjxUTGlzdE1vZGVsPj4odXJsLCB7XG4gICAgICAuLi5jb25maWcsXG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGJvZHk6IG1lcmdlZERhdGEsXG4gICAgfSk7XG4gIH1cbn1cbiIsICIvKipcbiAqIEBmaWxlb3ZlcnZpZXcgRmFjdG9yeSBmdW5jdGlvbnMgZm9yIGNyZWF0aW5nIGFuZCBtYW5hZ2luZyBBcGlDbGllbnQgaW5zdGFuY2VzLlxuICpcbiAqIFByb3ZpZGVzIGNvbnZlbmllbnQgZmFjdG9yeSBtZXRob2RzIGZvciBjcmVhdGluZyBwcmUtY29uZmlndXJlZCBBcGlDbGllbnQgaW5zdGFuY2VzXG4gKiB3aXRoIHNlbnNpYmxlIGRlZmF1bHRzIGFuZCBhdXRvbWF0aWMgdG9rZW4gbWFuYWdlbWVudCBmcm9tIGxvY2FsU3RvcmFnZS5cbiAqXG4gKiBAbW9kdWxlIGNyZWF0ZUFwaUNsaWVudFxuICovXG5cbmltcG9ydCB7IEFwaUNsaWVudCB9IGZyb20gJy4vQXBpQ2xpZW50JztcbmltcG9ydCB0eXBlIHsgRXJyb3JJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvRXJyb3JJbnRlcmNlcHRvcic7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3RJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvUmVxdWVzdEludGVyY2VwdG9yJztcbmltcG9ydCB0eXBlIHsgUmVzcG9uc2VJbnRlcmNlcHRvciB9IGZyb20gJy4vdHlwZXMvUmVzcG9uc2VJbnRlcmNlcHRvcic7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBvcHRpb25zIGZvciBjcmVhdGluZyBhbiBBcGlDbGllbnQgaW5zdGFuY2UuXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgaW50ZXJmYWNlIEFwaUNsaWVudENvbmZpZyB7XG4gIC8qKlxuICAgKiBCYXNlIFVSTCBmb3IgYWxsIEFQSSByZXF1ZXN0cy4gRGVmYXVsdHMgdG8gYGltcG9ydC5tZXRhLmVudi5WSVRFX0FQSV9VUkxgLlxuICAgKiBAZGVmYXVsdCBpbXBvcnQubWV0YS5lbnYuVklURV9BUElfVVJMXG4gICAqL1xuICBiYXNlVVJMPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZWZhdWx0IHRpbWVvdXQgZm9yIHJlcXVlc3RzIGluIG1pbGxpc2Vjb25kcy5cbiAgICogQGRlZmF1bHQgMzAwMDBcbiAgICovXG4gIHRpbWVvdXQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFByZWZpeCBmb3IgYXV0by1nZW5lcmF0ZWQgY29ycmVsYXRpb24gSURzIChlLmcuLCAnYXBpJywgJ3dlYicsICdtb2JpbGUnKS5cbiAgICogQGRlZmF1bHQgJ2FwaSdcbiAgICovXG4gIGNvcnJlbGF0aW9uSWRQcmVmaXg/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYXV0b21hdGljYWxseSBnZW5lcmF0ZSBhbmQgaW5jbHVkZSBjb3JyZWxhdGlvbiBJRHMgaW4gcmVxdWVzdHMuXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIGluY2x1ZGVDb3JyZWxhdGlvbklkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogSW5pdGlhbCBhdXRoZW50aWNhdGlvbiB0b2tlbiB0byBzZXQgb24gdGhlIGNsaWVudC5cbiAgICogQGRlZmF1bHQgdW5kZWZpbmVkXG4gICAqL1xuICBhdXRoVG9rZW4/OiBzdHJpbmcgfCBudWxsO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiByZXF1ZXN0IGludGVyY2VwdG9ycyB0byByZWdpc3RlciBkdXJpbmcgY2xpZW50IGNyZWF0aW9uLlxuICAgKiBAZGVmYXVsdCBbXVxuICAgKi9cbiAgcmVxdWVzdEludGVyY2VwdG9ycz86IFJlcXVlc3RJbnRlcmNlcHRvcltdO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiByZXNwb25zZSBpbnRlcmNlcHRvcnMgdG8gcmVnaXN0ZXIgZHVyaW5nIGNsaWVudCBjcmVhdGlvbi5cbiAgICogQGRlZmF1bHQgW11cbiAgICovXG4gIHJlc3BvbnNlSW50ZXJjZXB0b3JzPzogUmVzcG9uc2VJbnRlcmNlcHRvcltdO1xuXG4gIC8qKlxuICAgKiBBcnJheSBvZiBlcnJvciBpbnRlcmNlcHRvcnMgdG8gcmVnaXN0ZXIgZHVyaW5nIGNsaWVudCBjcmVhdGlvbi5cbiAgICogQGRlZmF1bHQgW11cbiAgICovXG4gIGVycm9ySW50ZXJjZXB0b3JzPzogRXJyb3JJbnRlcmNlcHRvcltdO1xufVxuXG4vKipcbiAqIEdsb2JhbCBzaW5nbGV0b24gQXBpQ2xpZW50IGluc3RhbmNlLlxuICogQGludGVybmFsXG4gKi9cbmxldCBnbG9iYWxBcGlDbGllbnQ6IEFwaUNsaWVudCB8IG51bGwgPSBudWxsO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgQXBpQ2xpZW50IGluc3RhbmNlIHdpdGggc2Vuc2libGUgZGVmYXVsdHMgYW5kIGF1dG9tYXRpYyB0b2tlbiBtYW5hZ2VtZW50LlxuICpcbiAqIFRoaXMgZmFjdG9yeSBmdW5jdGlvbjpcbiAqIC0gQ29uZmlndXJlcyB0aGUgYmFzZSBVUkwgZnJvbSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgb3IgY29uZmlnXG4gKiAtIFNldHMgdXAgYXV0b21hdGljIGF1dGhlbnRpY2F0aW9uIHRva2VuIGluamVjdGlvbiBmcm9tIGxvY2FsU3RvcmFnZSAoJ3NlcnZpY2VUb2tlbicga2V5KVxuICogLSBDb25maWd1cmVzIGNvcnJlbGF0aW9uIElEIGdlbmVyYXRpb25cbiAqIC0gUmVnaXN0ZXJzIHByb3ZpZGVkIGludGVyY2VwdG9yc1xuICpcbiAqICoqTm90ZToqKiBFYWNoIGNhbGwgY3JlYXRlcyBhIE5FVyBpbnN0YW5jZS4gVXNlIHtAbGluayBnZXRHbG9iYWxBcGlDbGllbnR9IGZvciBzaW5nbGV0b24gYmVoYXZpb3IuXG4gKlxuICogQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYXRpb24gb3B0aW9ucyBmb3IgdGhlIEFQSSBjbGllbnRcbiAqIEByZXR1cm5zIEEgZnVsbHkgY29uZmlndXJlZCBBcGlDbGllbnQgaW5zdGFuY2VcbiAqIEBwdWJsaWNcbiAqXG4gKiBAZXhhbXBsZVxuICogQmFzaWMgdXNhZ2Ugd2l0aCBkZWZhdWx0czpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGNsaWVudCA9IGNyZWF0ZUFwaUNsaWVudCgpO1xuICogLy8gVXNlcyBWSVRFX0FQSV9VUkwsIDMwcyB0aW1lb3V0LCBhdXRvIHRva2VuIGZyb20gbG9jYWxTdG9yYWdlXG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogQ3VzdG9tIGNvbmZpZ3VyYXRpb246XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBjcmVhdGVBcGlDbGllbnQoe1xuICogICBiYXNlVVJMOiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLFxuICogICB0aW1lb3V0OiA2MDAwMCxcbiAqICAgY29ycmVsYXRpb25JZFByZWZpeDogJ3dlYicsXG4gKiAgIHJlcXVlc3RJbnRlcmNlcHRvcnM6IFtcbiAqICAgICBhc3luYyAoY29uZmlnKSA9PiB7XG4gKiAgICAgICBjb25zb2xlLmxvZygnTWFraW5nIHJlcXVlc3Q6JywgY29uZmlnLnVybCk7XG4gKiAgICAgICByZXR1cm4gY29uZmlnO1xuICogICAgIH1cbiAqICAgXVxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogV2l0aCBSZWFjdCBRdWVyeTpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGFwaUNsaWVudCA9IGNyZWF0ZUFwaUNsaWVudCh7XG4gKiAgIGJhc2VVUkw6IHByb2Nlc3MuZW52LlJFQUNUX0FQUF9BUElfVVJMXG4gKiB9KTtcbiAqXG4gKiBjb25zdCBxdWVyeUNsaWVudCA9IG5ldyBRdWVyeUNsaWVudCgpO1xuICpcbiAqIGZ1bmN0aW9uIFVzZXJQcm9maWxlKHsgdXNlcklkIH0pIHtcbiAqICAgY29uc3QgeyBkYXRhIH0gPSB1c2VRdWVyeSh7XG4gKiAgICAgcXVlcnlLZXk6IFsndXNlcicsIHVzZXJJZF0sXG4gKiAgICAgcXVlcnlGbjogKCkgPT4gYXBpQ2xpZW50LmdldChgL3VzZXJzLyR7dXNlcklkfWApXG4gKiAgIH0pO1xuICogICAvLyAuLi5cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlQXBpQ2xpZW50KGNvbmZpZzogQXBpQ2xpZW50Q29uZmlnID0ge30pOiBBcGlDbGllbnQge1xuICBjb25zdCB7XG4gICAgYmFzZVVSTCA9IGltcG9ydC5tZXRhLmVudi5WSVRFX0FQSV9VUkwsXG4gICAgdGltZW91dCA9IDMwMDAwLFxuICAgIGNvcnJlbGF0aW9uSWRQcmVmaXggPSAnYXBpJyxcbiAgICBpbmNsdWRlQ29ycmVsYXRpb25JZCA9IHRydWUsXG4gICAgcmVxdWVzdEludGVyY2VwdG9ycyA9IFtdLFxuICAgIHJlc3BvbnNlSW50ZXJjZXB0b3JzID0gW10sXG4gICAgZXJyb3JJbnRlcmNlcHRvcnMgPSBbXSxcbiAgfSA9IGNvbmZpZztcblxuICBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KGJhc2VVUkwsIHRpbWVvdXQpO1xuXG4gIGNsaWVudC5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoY29uZmlnID0+IHtcbiAgICBjb25zdCB0b2tlbiA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdzZXJ2aWNlVG9rZW4nKTtcblxuICAgIGlmICh0b2tlbiAmJiAhY29uZmlnLnNraXBBdXRoUmVmcmVzaCkge1xuICAgICAgY29uZmlnLmhlYWRlcnMgPSB7XG4gICAgICAgIC4uLmNvbmZpZy5oZWFkZXJzLFxuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7dG9rZW59YCxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZztcbiAgfSk7XG5cbiAgLy8gQ29uZmlndXJlIGNvcnJlbGF0aW9uIElEXG4gIGNsaWVudC5zZXRDb3JyZWxhdGlvbklkUHJlZml4KGNvcnJlbGF0aW9uSWRQcmVmaXgpO1xuICBjbGllbnQuc2V0SW5jbHVkZUNvcnJlbGF0aW9uSWQoaW5jbHVkZUNvcnJlbGF0aW9uSWQpO1xuXG4gIC8vIC8vIFNldCBhdXRoIHRva2VuIGlmIHByb3ZpZGVkXG4gIC8vIGlmIChhdXRoVG9rZW4gIT09IHVuZGVmaW5lZCkge1xuICAvLyAgIGNsaWVudC5zZXRBdXRoVG9rZW4oYXV0aFRva2VuKTtcbiAgLy8gfVxuXG4gIC8vIEFkZCBpbnRlcmNlcHRvcnNcbiAgcmVxdWVzdEludGVyY2VwdG9ycy5mb3JFYWNoKGludGVyY2VwdG9yID0+IHtcbiAgICBjbGllbnQuYWRkUmVxdWVzdEludGVyY2VwdG9yKGludGVyY2VwdG9yKTtcbiAgfSk7XG5cbiAgcmVzcG9uc2VJbnRlcmNlcHRvcnMuZm9yRWFjaChpbnRlcmNlcHRvciA9PiB7XG4gICAgY2xpZW50LmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoaW50ZXJjZXB0b3IpO1xuICB9KTtcblxuICBlcnJvckludGVyY2VwdG9ycy5mb3JFYWNoKGludGVyY2VwdG9yID0+IHtcbiAgICBjbGllbnQuYWRkRXJyb3JJbnRlcmNlcHRvcihpbnRlcmNlcHRvcik7XG4gIH0pO1xuXG4gIHJldHVybiBjbGllbnQ7XG59XG5cbi8qKlxuICogR2V0cyBvciBjcmVhdGVzIGEgZ2xvYmFsIHNpbmdsZXRvbiBBcGlDbGllbnQgaW5zdGFuY2UuXG4gKlxuICogVGhpcyBmdW5jdGlvbiBpbXBsZW1lbnRzIHRoZSBzaW5nbGV0b24gcGF0dGVybiBmb3IgQXBpQ2xpZW50LiBJdCBjcmVhdGVzIHRoZSBjbGllbnRcbiAqIG9uIGZpcnN0IGNhbGwgYW5kIHJldHVybnMgdGhlIHNhbWUgaW5zdGFuY2Ugb24gc3Vic2VxdWVudCBjYWxscy4gVGhpcyBpcyB1c2VmdWwgZm9yOlxuICogLSBTaGFyaW5nIHRoZSBzYW1lIGNsaWVudCBhY3Jvc3MgeW91ciBlbnRpcmUgYXBwbGljYXRpb25cbiAqIC0gQXZvaWRpbmcgbXVsdGlwbGUgaW5zdGFuY2VzIHdpdGggZGlmZmVyZW50IGNvbmZpZ3VyYXRpb25zXG4gKiAtIENvbnNpc3RlbnQgaW50ZXJjZXB0b3IgYmVoYXZpb3IgYXBwLXdpZGVcbiAqXG4gKiAqKkltcG9ydGFudDoqKiBUaGUgY29uZmlnIHBhcmFtZXRlciBpcyBvbmx5IHVzZWQgb24gdGhlIEZJUlNUIGNhbGwuIFN1YnNlcXVlbnQgY2FsbHNcbiAqIGlnbm9yZSB0aGUgY29uZmlnIGFuZCByZXR1cm4gdGhlIGV4aXN0aW5nIGluc3RhbmNlLiBVc2Uge0BsaW5rIHJlc2V0R2xvYmFsQXBpQ2xpZW50fVxuICogZmlyc3QgaWYgeW91IG5lZWQgdG8gcmVjcmVhdGUgd2l0aCBkaWZmZXJlbnQgY29uZmlnLlxuICpcbiAqIEBwYXJhbSBjb25maWcgLSBDb25maWd1cmF0aW9uIG9wdGlvbnMgKG9ubHkgdXNlZCBvbiBmaXJzdCBjYWxsKVxuICogQHJldHVybnMgVGhlIGdsb2JhbCBBcGlDbGllbnQgc2luZ2xldG9uIGluc3RhbmNlXG4gKiBAcHVibGljXG4gKlxuICogQGV4YW1wbGVcbiAqIEluIHlvdXIgYXBwIGluaXRpYWxpemF0aW9uOlxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gc3JjL2xpYi9hcGkudHNcbiAqIGV4cG9ydCBjb25zdCBhcGlDbGllbnQgPSBnZXRHbG9iYWxBcGlDbGllbnQoe1xuICogICBiYXNlVVJMOiBpbXBvcnQubWV0YS5lbnYuVklURV9BUElfVVJMLFxuICogICB0aW1lb3V0OiAzMDAwMFxuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogSW1wb3J0IGFuZCB1c2UgdGhyb3VnaG91dCB5b3VyIGFwcDpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIHNyYy9mZWF0dXJlcy91c2Vycy9hcGkudHNcbiAqIGltcG9ydCB7IGdldEdsb2JhbEFwaUNsaWVudCB9IGZyb20gJ0BnbndlYnNvZnQvdWknO1xuICpcbiAqIGNvbnN0IGNsaWVudCA9IGdldEdsb2JhbEFwaUNsaWVudCgpOyAvLyBSZXR1cm5zIHNhbWUgaW5zdGFuY2VcbiAqXG4gKiBleHBvcnQgYXN5bmMgZnVuY3Rpb24gZmV0Y2hVc2VycygpIHtcbiAqICAgY29uc3QgeyBkYXRhIH0gPSBhd2FpdCBjbGllbnQuZ2V0KCcvdXNlcnMnKTtcbiAqICAgcmV0dXJuIGRhdGE7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogUmVzZXR0aW5nIGZvciB0ZXN0czpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGFmdGVyRWFjaCgoKSA9PiB7XG4gKiAgIHJlc2V0R2xvYmFsQXBpQ2xpZW50KCk7XG4gKiB9KTtcbiAqXG4gKiB0ZXN0KCdjcmVhdGVzIGZyZXNoIGNsaWVudCcsICgpID0+IHtcbiAqICAgY29uc3QgY2xpZW50ID0gZ2V0R2xvYmFsQXBpQ2xpZW50KHsgYmFzZVVSTDogJ2h0dHA6Ly90ZXN0LmxvY2FsJyB9KTtcbiAqICAgLy8gTmV3IGluc3RhbmNlIHdpdGggdGVzdCBjb25maWdcbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRHbG9iYWxBcGlDbGllbnQoY29uZmlnPzogQXBpQ2xpZW50Q29uZmlnKTogQXBpQ2xpZW50IHtcbiAgaWYgKCFnbG9iYWxBcGlDbGllbnQpIHtcbiAgICBnbG9iYWxBcGlDbGllbnQgPSBjcmVhdGVBcGlDbGllbnQoY29uZmlnKTtcbiAgfVxuXG4gIHJldHVybiBnbG9iYWxBcGlDbGllbnQ7XG59XG5cbi8qKlxuICogUmVwbGFjZXMgdGhlIGdsb2JhbCBzaW5nbGV0b24gQXBpQ2xpZW50IHdpdGggYSBjdXN0b20gaW5zdGFuY2UuXG4gKlxuICogVXNlIHRoaXMgd2hlbiB5b3UgbmVlZCBmaW5lLWdyYWluZWQgY29udHJvbCBvdmVyIHRoZSBnbG9iYWwgY2xpZW50IGluc3RhbmNlLFxuICogc3VjaCBhcyBpbiB0ZXN0aW5nIHNjZW5hcmlvcyBvciB3aGVuIHlvdSd2ZSBtYW51YWxseSBjcmVhdGVkIGEgY2xpZW50IHdpdGhcbiAqIHNwZWNpZmljIGNvbmZpZ3VyYXRpb24uXG4gKlxuICogQHBhcmFtIGNsaWVudCAtIFRoZSBBcGlDbGllbnQgaW5zdGFuY2UgdG8gdXNlIGFzIHRoZSBnbG9iYWwgc2luZ2xldG9uXG4gKiBAcHVibGljXG4gKlxuICogQGV4YW1wbGVcbiAqIFRlc3Rpbmcgd2l0aCBhIG1vY2sgY2xpZW50OlxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgbW9ja0NsaWVudCA9IG5ldyBBcGlDbGllbnQoJ2h0dHA6Ly90ZXN0LmxvY2FsJyk7XG4gKiBtb2NrQ2xpZW50LmFkZFJlc3BvbnNlSW50ZXJjZXB0b3IoYXN5bmMgKHJlc3BvbnNlKSA9PiB7XG4gKiAgIC8vIE1vY2sgcmVzcG9uc2UgZGF0YVxuICogICByZXR1cm4geyBkYXRhOiBtb2NrRGF0YSB9O1xuICogfSk7XG4gKlxuICogc2V0R2xvYmFsQXBpQ2xpZW50KG1vY2tDbGllbnQpO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIEFkdmFuY2VkIGNvbmZpZ3VyYXRpb246XG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBjbGllbnQgPSBuZXcgQXBpQ2xpZW50KCdodHRwczovL2FwaS5leGFtcGxlLmNvbScsIDYwMDAwKTtcbiAqIGNsaWVudC5zZXRDb3JyZWxhdGlvbklkUHJlZml4KCdjdXN0b20nKTtcbiAqIGNsaWVudC5hZGRSZXF1ZXN0SW50ZXJjZXB0b3IoY3VzdG9tSW50ZXJjZXB0b3IpO1xuICpcbiAqIHNldEdsb2JhbEFwaUNsaWVudChjbGllbnQpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRHbG9iYWxBcGlDbGllbnQoY2xpZW50OiBBcGlDbGllbnQpOiB2b2lkIHtcbiAgZ2xvYmFsQXBpQ2xpZW50ID0gY2xpZW50O1xufVxuXG4vKipcbiAqIFJlc2V0cyB0aGUgZ2xvYmFsIEFwaUNsaWVudCBzaW5nbGV0b24gdG8gbnVsbC5cbiAqXG4gKiBBZnRlciBjYWxsaW5nIHRoaXMsIHRoZSBuZXh0IGNhbGwgdG8ge0BsaW5rIGdldEdsb2JhbEFwaUNsaWVudH0gd2lsbCBjcmVhdGVcbiAqIGEgZnJlc2ggaW5zdGFuY2UuIFRoaXMgaXMgcGFydGljdWxhcmx5IHVzZWZ1bCBpbjpcbiAqIC0gVGVzdCBjbGVhbnVwIHRvIGVuc3VyZSB0ZXN0IGlzb2xhdGlvblxuICogLSBBcHBsaWNhdGlvbiBsb2dvdXQgdG8gY2xlYXIgYW55IGNhY2hlZCBzdGF0ZVxuICogLSBIb3QgbW9kdWxlIHJlbG9hZGluZyBkdXJpbmcgZGV2ZWxvcG1lbnRcbiAqXG4gKiBAcHVibGljXG4gKlxuICogQGV4YW1wbGVcbiAqIFRlc3QgY2xlYW51cDpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGFmdGVyRWFjaCgoKSA9PiB7XG4gKiAgIHJlc2V0R2xvYmFsQXBpQ2xpZW50KCk7XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBMb2dvdXQgZmxvdzpcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGZ1bmN0aW9uIGhhbmRsZUxvZ291dCgpIHtcbiAqICAgLy8gQ2xlYXIgYXV0aGVudGljYXRpb25cbiAqICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oJ3NlcnZpY2VUb2tlbicpO1xuICpcbiAqICAgLy8gQ2FuY2VsIGFsbCBwZW5kaW5nIHJlcXVlc3RzIGFuZCByZXNldCBjbGllbnRcbiAqICAgY29uc3QgY2xpZW50ID0gZ2V0R2xvYmFsQXBpQ2xpZW50KCk7XG4gKiAgIGNsaWVudC5jYW5jZWxBbGxSZXF1ZXN0cygpO1xuICogICByZXNldEdsb2JhbEFwaUNsaWVudCgpO1xuICpcbiAqICAgLy8gUmVkaXJlY3QgdG8gbG9naW5cbiAqICAgbmF2aWdhdGUoJy9sb2dpbicpO1xuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNldEdsb2JhbEFwaUNsaWVudCgpOiB2b2lkIHtcbiAgZ2xvYmFsQXBpQ2xpZW50ID0gbnVsbDtcbn1cbiIsICIvLyBDYW5jZWxUb2tlbiBpbXBsZW1lbnRhdGlvblxuZXhwb3J0IGNsYXNzIENhbmNlbFRva2VuIHtcbiAgcHJpdmF0ZSBhYm9ydENvbnRyb2xsZXI6IEFib3J0Q29udHJvbGxlcjtcbiAgcHJpdmF0ZSBjYW5jZWxQcm9taXNlOiBQcm9taXNlPHZvaWQ+O1xuICBwcml2YXRlIGNhbmNlbFJlc29sdmU/OiAoKSA9PiB2b2lkO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuYWJvcnRDb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpO1xuICAgIHRoaXMuY2FuY2VsUHJvbWlzZSA9IG5ldyBQcm9taXNlKHJlc29sdmUgPT4ge1xuICAgICAgdGhpcy5jYW5jZWxSZXNvbHZlID0gcmVzb2x2ZTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldCBzaWduYWwoKTogQWJvcnRTaWduYWwge1xuICAgIHJldHVybiB0aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWw7XG4gIH1cblxuICBjYW5jZWwocmVhc29uPzogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5hYm9ydENvbnRyb2xsZXIuYWJvcnQocmVhc29uKTtcbiAgICB0aGlzLmNhbmNlbFJlc29sdmU/LigpO1xuICB9XG5cbiAgZ2V0IGlzQ2FuY2VsbGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmFib3J0Q29udHJvbGxlci5zaWduYWwuYWJvcnRlZDtcbiAgfVxuXG4gIHRocm93SWZDYW5jZWxsZWQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNDYW5jZWxsZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVxdWVzdCBjYW5jZWxsZWQnKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgc291cmNlKCk6IHsgdG9rZW46IENhbmNlbFRva2VuOyBjYW5jZWw6IChyZWFzb24/OiBzdHJpbmcpID0+IHZvaWQgfSB7XG4gICAgY29uc3QgdG9rZW4gPSBuZXcgQ2FuY2VsVG9rZW4oKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0b2tlbixcbiAgICAgIGNhbmNlbDogKHJlYXNvbj86IHN0cmluZykgPT4gdG9rZW4uY2FuY2VsKHJlYXNvbiksXG4gICAgfTtcbiAgfVxufVxuIiwgIi8vIFJlYWN0IEhvb2tzIHdpdGggQXBpUmVzcG9uc2UgZm9ybWF0XG5pbXBvcnQgeyB1c2VDYWxsYmFjayB9IGZyb20gJ3JlYWN0JztcblxuaW1wb3J0IHR5cGUgeyBBcGlFcnJvciB9IGZyb20gJy4vdHlwZXMnO1xuXG4vLyBFeHBvcnQgZmFjdG9yeSBtZXRob2RzIGFuZCB0eXBlc1xuZXhwb3J0IHtcbiAgY3JlYXRlQXBpQ2xpZW50LFxuICBnZXRHbG9iYWxBcGlDbGllbnQsXG4gIHNldEdsb2JhbEFwaUNsaWVudCxcbiAgcmVzZXRHbG9iYWxBcGlDbGllbnQsXG59IGZyb20gJy4vY3JlYXRlQXBpQ2xpZW50JztcblxuZXhwb3J0IHR5cGUgeyBBcGlDbGllbnRDb25maWcgfSBmcm9tICcuL2NyZWF0ZUFwaUNsaWVudCc7XG5cbmV4cG9ydCB7IEFwaUNsaWVudCB9IGZyb20gJy4vQXBpQ2xpZW50JztcblxuLy8gSGVscGVyIGhvb2sgZm9yIGZvcm0gdmFsaWRhdGlvbiBlcnJvcnNcbmV4cG9ydCBmdW5jdGlvbiB1c2VWYWxpZGF0aW9uRXJyb3JzKGVycm9yOiBBcGlFcnJvciB8IG51bGwpIHtcbiAgY29uc3QgZ2V0RmllbGRFcnJvciA9IHVzZUNhbGxiYWNrKFxuICAgIChmaWVsZDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCA9PiB7XG4gICAgICBpZiAoIWVycm9yPy5lcnJvcnMgfHwgIWVycm9yLmVycm9yc1tmaWVsZF0pIHJldHVybiBudWxsO1xuXG4gICAgICBjb25zdCBmaWVsZEVycm9yID0gZXJyb3IuZXJyb3JzW2ZpZWxkXTtcblxuICAgICAgaWYgKHR5cGVvZiBmaWVsZEVycm9yID09PSAnc3RyaW5nJykgcmV0dXJuIGZpZWxkRXJyb3I7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShmaWVsZEVycm9yKSkgcmV0dXJuIGZpZWxkRXJyb3JbMF07XG4gICAgICBpZiAodHlwZW9mIGZpZWxkRXJyb3IgPT09ICdvYmplY3QnICYmICdtZXNzYWdlJyBpbiBmaWVsZEVycm9yKSB7XG4gICAgICAgIHJldHVybiBmaWVsZEVycm9yLm1lc3NhZ2U7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gICAgW2Vycm9yXVxuICApO1xuXG4gIGNvbnN0IGhhc0ZpZWxkRXJyb3IgPSB1c2VDYWxsYmFjayhcbiAgICAoZmllbGQ6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xuICAgICAgcmV0dXJuICEhZ2V0RmllbGRFcnJvcihmaWVsZCk7XG4gICAgfSxcbiAgICBbZ2V0RmllbGRFcnJvcl1cbiAgKTtcblxuICBjb25zdCBnZXRBbGxFcnJvcnMgPSB1c2VDYWxsYmFjaygoKTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9PiB7XG4gICAgaWYgKCFlcnJvcj8uZXJyb3JzKSByZXR1cm4ge307XG5cbiAgICBjb25zdCByZXN1bHQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICAgIE9iamVjdC5lbnRyaWVzKGVycm9yLmVycm9ycykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlLmpvaW4oJywgJyk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgJiYgJ21lc3NhZ2UnIGluIHZhbHVlKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdmFsdWUubWVzc2FnZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sIFtlcnJvcl0pO1xuXG4gIHJldHVybiB7XG4gICAgZ2V0RmllbGRFcnJvcixcbiAgICBoYXNGaWVsZEVycm9yLFxuICAgIGdldEFsbEVycm9ycyxcbiAgICBoYXNFcnJvcnM6IGVycm9yPy5lcnJvcnMsXG4gIH07XG59XG4iLCAiaW1wb3J0IHR5cGUgeyBQcm9wc1dpdGhDaGlsZHJlbiB9IGZyb20gJ3JlYWN0JztcblxudHlwZSBBdXRob3JpemVkVmlld1Byb3BzID0gUHJvcHNXaXRoQ2hpbGRyZW4gJiB7XG4gIHNob3c6IGJvb2xlYW47XG59O1xuXG5leHBvcnQgY29uc3QgQXV0aG9yaXplZFZpZXcgPSAoeyBjaGlsZHJlbiwgc2hvdyB9OiBBdXRob3JpemVkVmlld1Byb3BzKSA9PiB7XG4gIGlmICghc2hvdykgcmV0dXJuIDw+PC8+O1xuXG4gIHJldHVybiA8PntjaGlsZHJlbn08Lz47XG59O1xuIiwgImltcG9ydCB0eXBlIHsgQnV0dG9uUHJvcHMgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB7IEJ1dHRvbiB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcblxuZXhwb3J0IGNvbnN0IENhbmNlbEJ1dHRvbjogUmVhY3QuRkM8QnV0dG9uUHJvcHM+ID0gKHtcbiAgY2hpbGRyZW4gPSAnQ2FuY2VsJyxcbiAgdmFyaWFudCA9ICdvdXRsaW5lZCcsXG4gIHN4LFxuICAuLi5yZXN0XG59KSA9PiAoXG4gIDxCdXR0b24gdmFyaWFudD17dmFyaWFudH0gc3g9e3sgd2lkdGg6ICc2cmVtJywgLi4uc3ggfX0gey4uLnJlc3R9PlxuICAgIHtjaGlsZHJlbn1cbiAgPC9CdXR0b24+XG4pO1xuIiwgImltcG9ydCB0eXBlIHsgU3hQcm9wcyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuaW1wb3J0IHsgQnV0dG9uIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5cbi8qKlxuICogUHJvcHMgZm9yIHRoZSBDbGVhckJ1dHRvbiBjb21wb25lbnQuXG4gKlxuICogQHB1YmxpY1xuICovXG5pbnRlcmZhY2UgQ2xlYXJCdXR0b25Qcm9wcyB7XG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgYSBmb3JtIG9yIG9wZXJhdGlvbiBpcyBjdXJyZW50bHkgYmVpbmcgc3VibWl0dGVkLlxuICAgKiBXaGVuIHRydWUsIHRoZSBidXR0b24gaXMgZGlzYWJsZWQgdG8gcHJldmVudCBtdWx0aXBsZSBjbGVhciBhY3Rpb25zLlxuICAgKi9cbiAgaXNTdWJtaXR0aW5nOiBib29sZWFuO1xuICAvKipcbiAgICogQ2FsbGJhY2sgZnVuY3Rpb24gZXhlY3V0ZWQgd2hlbiB0aGUgY2xlYXIgYnV0dG9uIGlzIGNsaWNrZWQuXG4gICAqIFNob3VsZCBoYW5kbGUgdGhlIGNsZWFyaW5nIGxvZ2ljIChlLmcuLCBmb3JtIHJlc2V0LCBkYXRhIGNsZWFyaW5nKS5cbiAgICovXG4gIGhhbmRsZUNsZWFyOiAoKSA9PiB2b2lkO1xuICAvKipcbiAgICogT3B0aW9uYWwgTVVJIHN4IHByb3AgZm9yIGN1c3RvbSBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IG10OiAyLCBjb2xvcjogJ3dhcm5pbmcubWFpbicgfVxuICAgKi9cbiAgc3g/OiBTeFByb3BzO1xuICAvKipcbiAgICogT3B0aW9uYWwgbG9jYWxTdG9yYWdlIGtleSB0byByZW1vdmUgd2hlbiBjbGVhcmluZy5cbiAgICogSWYgcHJvdmlkZWQsIHRoZSBjb3JyZXNwb25kaW5nIGxvY2FsU3RvcmFnZSBpdGVtIHdpbGwgYmUgcmVtb3ZlZCBvbiBjbGljay5cbiAgICogQGV4YW1wbGUgXCJ1c2VyLXByZWZlcmVuY2VzXCIgb3IgXCJmb3JtLWRhdGFcIlxuICAgKi9cbiAgc3RvcmVLZXk/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogU3RhbmRhcmRpemVkIGNsZWFyIGJ1dHRvbiBjb21wb25lbnQgd2l0aCBsb2NhbFN0b3JhZ2UgaW50ZWdyYXRpb24uXG4gKlxuICogVGhpcyBjb21wb25lbnQgcHJvdmlkZXMgYSBjb25zaXN0ZW50IGNsZWFyIGJ1dHRvbiBpbXBsZW1lbnRhdGlvbiB0aGF0IGhhbmRsZXNcbiAqIGJvdGggY2FsbGJhY2sgZXhlY3V0aW9uIGFuZCBvcHRpb25hbCBsb2NhbFN0b3JhZ2UgY2xlYW51cC4gSXQgYXV0b21hdGljYWxseVxuICogZGlzYWJsZXMgZHVyaW5nIGZvcm0gc3VibWlzc2lvbnMgYW5kIGNhbiBjbGVhciBzdG9yZWQgZGF0YSB3aGVuIG5lZWRlZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogQmFzaWMgdXNhZ2U6XG4gKiBgYGB0c3hcbiAqIDxDbGVhckJ1dHRvblxuICogICBpc1N1Ym1pdHRpbmc9e2lzTG9hZGluZ31cbiAqICAgaGFuZGxlQ2xlYXI9eygpID0+IGZvcm0ucmVzZXQoKX1cbiAqIC8+XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogV2l0aCBsb2NhbFN0b3JhZ2UgY2xlYW51cDpcbiAqIGBgYHRzeFxuICogPENsZWFyQnV0dG9uXG4gKiAgIGlzU3VibWl0dGluZz17Zm9ybS5mb3JtU3RhdGUuaXNTdWJtaXR0aW5nfVxuICogICBoYW5kbGVDbGVhcj17KCkgPT4gc2V0RmlsdGVycyh7fSl9XG4gKiAgIHN0b3JlS2V5PVwidXNlci1maWx0ZXJzXCJcbiAqIC8+XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0gcHJvcHMgLSBDb21wb25lbnQgcHJvcHMgZm9yIGNsZWFyIGJ1dHRvbiBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJucyBNVUkgQnV0dG9uIGNvbXBvbmVudCBjb25maWd1cmVkIGFzIGEgY2xlYXIgYnV0dG9uXG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgQ2xlYXJCdXR0b24gPSAoe1xuICBpc1N1Ym1pdHRpbmcsXG4gIGhhbmRsZUNsZWFyLFxuICBzeCxcbiAgc3RvcmVLZXksXG59OiBDbGVhckJ1dHRvblByb3BzKSA9PiB7XG4gIGNvbnN0IG9uQ2xpY2sgPSAoKSA9PiB7XG4gICAgaGFuZGxlQ2xlYXIoKTtcbiAgICBpZiAoc3RvcmVLZXkgIT0gbnVsbCkge1xuICAgICAgbG9jYWxTdG9yYWdlLnJlbW92ZUl0ZW0oc3RvcmVLZXkpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gKFxuICAgIDxCdXR0b25cbiAgICAgIHZhcmlhbnQ9XCJvdXRsaW5lZFwiXG4gICAgICBvbkNsaWNrPXtvbkNsaWNrfVxuICAgICAgZGlzYWJsZWQ9e2lzU3VibWl0dGluZ31cbiAgICAgIHN4PXtzeH1cbiAgICA+XG4gICAgICBDbGVhclxuICAgIDwvQnV0dG9uPlxuICApO1xufTtcbiIsICJpbXBvcnQgeyBDb250YWluZXIsIHR5cGUgU3hQcm9wcyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuaW1wb3J0IHR5cGUgeyBSZWFjdE5vZGUgfSBmcm9tICdyZWFjdCc7XG5cbmludGVyZmFjZSBTaW1wbGVDb250YWluZXJQcm9wcyB7XG4gIGNoaWxkcmVuOiBSZWFjdE5vZGU7XG4gIGNsYXNzTmFtZT86IHN0cmluZztcbiAgc3g/OiBTeFByb3BzO1xufVxuXG5leHBvcnQgY29uc3QgU2ltcGxlQ29udGFpbmVyID0gKHtcbiAgY2hpbGRyZW4sXG4gIGNsYXNzTmFtZSxcbiAgc3gsXG59OiBTaW1wbGVDb250YWluZXJQcm9wcykgPT4gKFxuICA8Q29udGFpbmVyIGNsYXNzTmFtZT17Y2xhc3NOYW1lfSBzeD17eyAuLi5zeCB9fT5cbiAgICB7Y2hpbGRyZW59XG4gIDwvQ29udGFpbmVyPlxuKTtcbiIsICJpbXBvcnQgRmlsdGVyQWx0SWNvbiBmcm9tICdAbXVpL2ljb25zLW1hdGVyaWFsL0ZpbHRlckFsdCc7XG5pbXBvcnQgeyBMb2FkaW5nQnV0dG9uIH0gZnJvbSAnQG11aS9sYWInO1xuaW1wb3J0IHR5cGUgeyBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgeyBCYWRnZSB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuXG4vKipcbiAqIFByb3BzIGZvciB0aGUgRmlsdGVyQnV0dG9uIGNvbXBvbmVudC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbmludGVyZmFjZSBGaWx0ZXJCdXR0b25Qcm9wcyB7XG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgYSBmaWx0ZXIgb3BlcmF0aW9uIGlzIGN1cnJlbnRseSBiZWluZyBwcm9jZXNzZWQuXG4gICAqIFdoZW4gdHJ1ZSwgc2hvd3MgbG9hZGluZyBzcGlubmVyIGFuZCBkaXNhYmxlcyB0aGUgYnV0dG9uLlxuICAgKi9cbiAgaXNTdWJtaXR0aW5nOiBib29sZWFuO1xuICAvKipcbiAgICogQ29udHJvbHMgYnV0dG9uIHZpc2liaWxpdHkgYW5kIGVuYWJsZWQgc3RhdGUuXG4gICAqIFdoZW4gZmFsc2UsIHRoZSBidXR0b24gaXMgZGlzYWJsZWQuXG4gICAqIEBkZWZhdWx0VmFsdWUgdHJ1ZVxuICAgKi9cbiAgc2hvdz86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBDdXN0b20gdGV4dCB0byBkaXNwbGF5IG9uIHRoZSBidXR0b24uXG4gICAqIEBkZWZhdWx0VmFsdWUgXCJGaWx0ZXJcIlxuICAgKiBAZXhhbXBsZSBcIkFwcGx5IEZpbHRlcnNcIiBvciBcIlNlYXJjaFwiXG4gICAqL1xuICB0aXRsZT86IHN0cmluZztcbiAgLyoqXG4gICAqIEN1c3RvbSBpY29uIHRvIGRpc3BsYXkgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBmaWx0ZXIgaWNvbi5cbiAgICogQGV4YW1wbGUgPFNlYXJjaEljb24gLz5cbiAgICovXG4gIGljb24/OiBSZWFjdC5SZWFjdE5vZGU7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBNVUkgc3ggcHJvcCBmb3IgY3VzdG9tIGJ1dHRvbiBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IG10OiAyLCBtaW5XaWR0aDogMTIwIH1cbiAgICovXG4gIHN4PzogU3hQcm9wcztcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gaWNvbiBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IGNvbG9yOiAncHJpbWFyeS5tYWluJywgZm9udFNpemU6IDE4IH1cbiAgICovXG4gIGljb25TeD86IFN4UHJvcHM7XG59XG5cbi8qKlxuICogRmlsdGVyIGJ1dHRvbiBjb21wb25lbnQgd2l0aCBsb2FkaW5nIHN0YXRlcyBhbmQgY3VzdG9taXphYmxlIGFwcGVhcmFuY2UuXG4gKlxuICogVGhpcyBjb21wb25lbnQgcHJvdmlkZXMgYSBzdGFuZGFyZGl6ZWQgZmlsdGVyL3N1Ym1pdCBidXR0b24gd2l0aCBpbnRlZ3JhdGVkIGxvYWRpbmdcbiAqIHN0YXRlcywgaWNvbiBzdXBwb3J0LCBhbmQgYmFkZ2Ugc3R5bGluZy4gSXQncyBkZXNpZ25lZCBmb3IgdXNlIGluIGZpbHRlciBmb3Jtc1xuICogYW5kIHNlYXJjaCBpbnRlcmZhY2VzIHdoZXJlIHVzZXJzIG5lZWQgdG8gYXBwbHkgZmlsdGVyaW5nIGNyaXRlcmlhLlxuICpcbiAqIEBleGFtcGxlXG4gKiBCYXNpYyB1c2FnZTpcbiAqIGBgYHRzeFxuICogPEZpbHRlckJ1dHRvblxuICogICBpc1N1Ym1pdHRpbmc9e2lzTG9hZGluZ31cbiAqICAgc2hvdz17aGFzRmlsdGVyc31cbiAqIC8+XG4gKiBgYGBcbiAqXG4gKiBAZXhhbXBsZVxuICogQ3VzdG9tIHRpdGxlIGFuZCBpY29uOlxuICogYGBgdHN4XG4gKiA8RmlsdGVyQnV0dG9uXG4gKiAgIGlzU3VibWl0dGluZz17Zm9ybS5mb3JtU3RhdGUuaXNTdWJtaXR0aW5nfVxuICogICB0aXRsZT1cIkFwcGx5IFNlYXJjaFwiXG4gKiAgIGljb249ezxTZWFyY2hJY29uIC8+fVxuICogICBzaG93PXt0cnVlfVxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIGN1c3RvbSBzdHlsaW5nOlxuICogYGBgdHN4XG4gKiA8RmlsdGVyQnV0dG9uXG4gKiAgIGlzU3VibWl0dGluZz17aXNQcm9jZXNzaW5nfVxuICogICB0aXRsZT1cIkZpbHRlciBSZXN1bHRzXCJcbiAqICAgc3g9e3sgbWluV2lkdGg6IDE1MCwgbXQ6IDIgfX1cbiAqICAgaWNvblN4PXt7IGZvbnRTaXplOiAyMCB9fVxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBwcm9wcyAtIENvbXBvbmVudCBwcm9wcyBmb3IgZmlsdGVyIGJ1dHRvbiBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJucyBNVUkgTG9hZGluZ0J1dHRvbiBjb21wb25lbnQgY29uZmlndXJlZCBhcyBhIGZpbHRlciBidXR0b25cbiAqXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjb25zdCBGaWx0ZXJCdXR0b24gPSAoe1xuICBpc1N1Ym1pdHRpbmcsXG4gIHNob3csXG4gIHRpdGxlLFxuICBpY29uLFxuICBzeCxcbiAgaWNvblN4LFxufTogRmlsdGVyQnV0dG9uUHJvcHMpID0+IHtcbiAgcmV0dXJuIChcbiAgICA8TG9hZGluZ0J1dHRvblxuICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICB2YXJpYW50PVwiY29udGFpbmVkXCJcbiAgICAgIGxvYWRpbmc9e2lzU3VibWl0dGluZ31cbiAgICAgIGRpc2FibGVkPXshc2hvd31cbiAgICAgIGRpc2FibGVSaXBwbGVcbiAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICBzeD17e1xuICAgICAgICBkaXNwbGF5OiAnZmxleCcsXG4gICAgICAgIGFsaWduSXRlbXM6ICdjZW50ZXInLFxuICAgICAgICAuLi5zeCxcbiAgICAgIH19XG4gICAgICBzdGFydEljb249e1xuICAgICAgICA8QmFkZ2UgY29sb3I9XCJlcnJvclwiIHZhcmlhbnQ9XCJzdGFuZGFyZFwiPlxuICAgICAgICAgIHtpY29uID8gaWNvbiA6IDxGaWx0ZXJBbHRJY29uIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIyMFwiIHN4PXtpY29uU3h9IC8+fVxuICAgICAgICA8L0JhZGdlPlxuICAgICAgfVxuICAgID5cbiAgICAgIHt0aXRsZT8udHJpbSgpID09PSAnJyB8fCAhdGl0bGUgPyAnRmlsdGVyJyA6IHRpdGxlfVxuICAgIDwvTG9hZGluZ0J1dHRvbj5cbiAgKTtcbn07XG4iLCAiaW1wb3J0IENoaXAgZnJvbSAnQG11aS9tYXRlcmlhbC9DaGlwJztcbmltcG9ydCB7IG1lbW8gfSBmcm9tICdyZWFjdCc7XG5cbi8vIEluZGl2aWR1YWwgY2hpcCBjb21wb25lbnQgdG8gcHJldmVudCB1bm5lY2Vzc2FyeSByZXJlbmRlcnMgb2Ygc2libGluZyBjaGlwc1xuZXhwb3J0IGNvbnN0IEZpbHRlckNoaXAgPSBtZW1vKFxuICAoe1xuICAgIGZpZWxkS2V5LFxuICAgIGZpbHRlcixcbiAgICBvbkRlbGV0ZSxcbiAgfToge1xuICAgIGZpZWxkS2V5OiBzdHJpbmc7XG4gICAgZmlsdGVyOiB7IExhYmVsOiBzdHJpbmc7IFZhbHVlOiB1bmtub3duIH07XG4gICAgb25EZWxldGU/OiAoKSA9PiB2b2lkO1xuICB9KSA9PiB7XG4gICAgY29uc3QgaGFzVmFsdWUgPVxuICAgICAgZmlsdGVyLlZhbHVlICE9PSBudWxsICYmXG4gICAgICBmaWx0ZXIuVmFsdWUgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgZmlsdGVyLlZhbHVlICE9PSAnJztcbiAgICBjb25zdCBsYWJlbCA9IGAke2ZpZWxkS2V5LnJlcGxhY2UoJ1BLJywgJycpfTogJHtmaWx0ZXIuTGFiZWx9YDtcblxuICAgIHJldHVybiAoXG4gICAgICA8Q2hpcFxuICAgICAgICBrZXk9e2ZpZWxkS2V5fVxuICAgICAgICBsYWJlbD17bGFiZWx9XG4gICAgICAgIHZhcmlhbnQ9e2hhc1ZhbHVlID8gJ2ZpbGxlZCcgOiAnb3V0bGluZWQnfVxuICAgICAgICBzaXplPVwic21hbGxcIlxuICAgICAgICBvbkRlbGV0ZT17aGFzVmFsdWUgPyBvbkRlbGV0ZSA6IHVuZGVmaW5lZH1cbiAgICAgIC8+XG4gICAgKTtcbiAgfVxuKTtcblxuRmlsdGVyQ2hpcC5kaXNwbGF5TmFtZSA9ICdGaWx0ZXJDaGlwJztcbiIsICJpbXBvcnQgeyBDYXJkLCBDYXJkQ29udGVudCwgVHlwb2dyYXBoeSwgQm94IH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgeyBtZW1vLCB1c2VNZW1vIH0gZnJvbSAncmVhY3QnO1xuXG5pbXBvcnQgeyBGaWx0ZXJDaGlwIH0gZnJvbSAnLi9GaWx0ZXJDaGlwJztcblxuaW50ZXJmYWNlIEZpbHRlckRpc3BsYXlQcm9wczxURmlsdGVyTW9kZWw+IHtcbiAgZnJpZW5kbHlGaWx0ZXI6IFJlY29yZDxzdHJpbmcsIHsgTGFiZWw6IHN0cmluZzsgVmFsdWU6IHVua25vd24gfT47XG4gIG9uRnJpZW5kbHlGaWx0ZXJDaGFuZ2U/OiAoZmllbGRLZXk6IGtleW9mIFRGaWx0ZXJNb2RlbCkgPT4gdm9pZDtcbn1cblxuZXhwb3J0IGNvbnN0IFByb2dyYW1zRmlsdGVyRGlzcGxheSA9IG1lbW8oXG4gIDxURmlsdGVyTW9kZWwgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gICAgcHJvcHM6IEZpbHRlckRpc3BsYXlQcm9wczxURmlsdGVyTW9kZWw+XG4gICkgPT4ge1xuICAgIGNvbnN0IHsgZnJpZW5kbHlGaWx0ZXIsIG9uRnJpZW5kbHlGaWx0ZXJDaGFuZ2UgfSA9IHByb3BzO1xuXG4gICAgLy8gTWVtb2l6ZSBkZWxldGUgaGFuZGxlcnMgdG8gcHJldmVudCByZWNyZWF0aW9uXG4gICAgY29uc3QgZGVsZXRlSGFuZGxlcnMgPSB1c2VNZW1vKCgpID0+IHtcbiAgICAgIGlmICghb25GcmllbmRseUZpbHRlckNoYW5nZSkgcmV0dXJuIHt9O1xuXG4gICAgICBjb25zdCBoYW5kbGVyczogUmVjb3JkPHN0cmluZywgKCkgPT4gdm9pZD4gPSB7fTtcblxuICAgICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoZnJpZW5kbHlGaWx0ZXIpKSB7XG4gICAgICAgIGhhbmRsZXJzW2tleV0gPSAoKSA9PiBvbkZyaWVuZGx5RmlsdGVyQ2hhbmdlKGtleSBhcyBrZXlvZiBURmlsdGVyTW9kZWwpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gaGFuZGxlcnM7XG4gICAgfSwgW29uRnJpZW5kbHlGaWx0ZXJDaGFuZ2UsIGZyaWVuZGx5RmlsdGVyXSk7XG5cbiAgICAvLyBNZW1vaXplIGNoaXAgbGlzdCB0byBwcmV2ZW50IHVubmVjZXNzYXJ5IHJlY2FsY3VsYXRpb25zXG4gICAgY29uc3QgY2hpcExpc3QgPSB1c2VNZW1vKCgpID0+IHtcbiAgICAgIHJldHVybiBPYmplY3QuZW50cmllcyhmcmllbmRseUZpbHRlcikubWFwKChba2V5LCBmaWx0ZXJdKSA9PiAoXG4gICAgICAgIDxGaWx0ZXJDaGlwXG4gICAgICAgICAga2V5PXtrZXl9XG4gICAgICAgICAgZmllbGRLZXk9e2tleX1cbiAgICAgICAgICBmaWx0ZXI9e2ZpbHRlciBhcyB7IExhYmVsOiBzdHJpbmc7IFZhbHVlOiB1bmtub3duIH19XG4gICAgICAgICAgb25EZWxldGU9e2RlbGV0ZUhhbmRsZXJzW2tleV19XG4gICAgICAgIC8+XG4gICAgICApKTtcbiAgICB9LCBbZnJpZW5kbHlGaWx0ZXIsIGRlbGV0ZUhhbmRsZXJzXSk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgPENhcmQgc3g9e3sgbWI6IDIgfX0+XG4gICAgICAgIDxDYXJkQ29udGVudD5cbiAgICAgICAgICA8VHlwb2dyYXBoeSB2YXJpYW50PVwiaDZcIiBndXR0ZXJCb3R0b20+XG4gICAgICAgICAgICBBY3RpdmUgRmlsdGVyc1xuICAgICAgICAgIDwvVHlwb2dyYXBoeT5cbiAgICAgICAgICA8Qm94IGRpc3BsYXk9XCJmbGV4XCIgZ2FwPXsxfSBmbGV4V3JhcD1cIndyYXBcIj5cbiAgICAgICAgICAgIHtjaGlwTGlzdH1cbiAgICAgICAgICA8L0JveD5cbiAgICAgICAgPC9DYXJkQ29udGVudD5cbiAgICAgIDwvQ2FyZD5cbiAgICApO1xuICB9XG4pO1xuXG5Qcm9ncmFtc0ZpbHRlckRpc3BsYXkuZGlzcGxheU5hbWUgPSAnRmlsdGVyRGlzcGxheSc7XG5cbmV4cG9ydCB0eXBlIHsgRmlsdGVyRGlzcGxheVByb3BzIH07XG4iLCAiaW1wb3J0IE1hbmFnZVNlYXJjaEljb24gZnJvbSAnQG11aS9pY29ucy1tYXRlcmlhbC9NYW5hZ2VTZWFyY2gnO1xuaW1wb3J0IHR5cGUgeyBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQge1xuICBCb3gsXG4gIENhcmQsXG4gIENhcmRDb250ZW50LFxuICBDYXJkSGVhZGVyLFxuICBEaXZpZGVyLFxuICBHcmlkLFxuICBUeXBvZ3JhcGh5LFxuICB1c2VUaGVtZSxcbn0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgdHlwZSB7IFByb3BzV2l0aENoaWxkcmVuLCBSZWFjdE5vZGUgfSBmcm9tICdyZWFjdCc7XG5cbi8qKlxuICogUHJvcHMgZm9yIHRoZSBGaWx0ZXJXcmFwcGVyIGNvbXBvbmVudC5cbiAqXG4gKiBAcHVibGljXG4gKi9cbnR5cGUgRmlsdGVyV3JhcHBlclByb3BzID0gUHJvcHNXaXRoQ2hpbGRyZW48e1xuICAvKipcbiAgICogVGl0bGUgdGV4dCBkaXNwbGF5ZWQgaW4gdGhlIGNhcmQgaGVhZGVyLlxuICAgKiBAZGVmYXVsdFZhbHVlIFwiRmlsdGVyXCJcbiAgICogQGV4YW1wbGUgXCJTZWFyY2ggQ3JpdGVyaWFcIiBvciBcIkFkdmFuY2VkIEZpbHRlcnNcIlxuICAgKi9cbiAgdGl0bGU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgYWN0aXZlIGZpbHRlcnMgdG8gZGlzcGxheSBpbiB0aGUgaGVhZGVyLlxuICAgKiBPbmx5IHNob3duIHdoZW4gc2hvd0NvdW50IGlzIHRydWUuXG4gICAqIEBleGFtcGxlIDMgZm9yIFwiRmlsdGVyICgzKVwiXG4gICAqL1xuICBmaWx0ZXJDb3VudD86IG51bWJlcjtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gY2FyZCBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IG10OiAyLCBib3hTaGFkb3c6IDIgfVxuICAgKi9cbiAgY2FyZFN4PzogU3hQcm9wcztcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gdGl0bGUgdGV4dCBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IGZvbnRTaXplOiAxOCwgZm9udFdlaWdodDogJ2JvbGQnIH1cbiAgICovXG4gIHRleHRTeD86IFN4UHJvcHM7XG4gIC8qKlxuICAgKiBDdXN0b20gaWNvbiB0byBkaXNwbGF5IGluc3RlYWQgb2YgdGhlIGRlZmF1bHQgc2VhcmNoIGljb24uXG4gICAqIEBleGFtcGxlIDxGaWx0ZXJMaXN0SWNvbiAvPlxuICAgKi9cbiAgaWNvbj86IFJlYWN0Tm9kZTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIE1VSSBzeCBwcm9wIGZvciBjdXN0b20gaWNvbiBzdHlsaW5nLlxuICAgKiBAZXhhbXBsZSB7IGNvbG9yOiAnc2Vjb25kYXJ5Lm1haW4nLCBmb250U2l6ZTogMjQgfVxuICAgKi9cbiAgaWNvblN4PzogU3hQcm9wcztcbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZGlzcGxheSB0aGUgZmlsdGVyIGNvdW50IGluIHRoZSBoZWFkZXIuXG4gICAqIEBkZWZhdWx0VmFsdWUgZmFsc2VcbiAgICovXG4gIHNob3dDb3VudD86IGJvb2xlYW47XG59PjtcblxuLyoqXG4gKiBDYXJkLWJhc2VkIHdyYXBwZXIgY29tcG9uZW50IGZvciBvcmdhbml6aW5nIGZpbHRlciBjb250cm9scyBhbmQgZm9ybSBlbGVtZW50cy5cbiAqXG4gKiBUaGlzIGNvbXBvbmVudCBwcm92aWRlcyBhIGNvbnNpc3RlbnQgbGF5b3V0IGZvciBmaWx0ZXIgaW50ZXJmYWNlcyB3aXRoIGEgaGVhZGVyLFxuICogb3B0aW9uYWwgZmlsdGVyIGNvdW50IGRpc3BsYXksIGFuZCBhIGdyaWQtYmFzZWQgY29udGVudCBhcmVhLiBJdCdzIGRlc2lnbmVkIHRvXG4gKiBjb250YWluIGZvcm0gY29udHJvbHMgYW5kIGZpbHRlciBlbGVtZW50cyBpbiBhIHZpc3VhbGx5IG9yZ2FuaXplZCBtYW5uZXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIEJhc2ljIHVzYWdlOlxuICogYGBgdHN4XG4gKiA8RmlsdGVyV3JhcHBlcj5cbiAqICAgPEdyaWQgaXRlbSB4cz17MTJ9IG1kPXs2fT5cbiAqICAgICA8VGV4dEZpZWxkIGxhYmVsPVwiU2VhcmNoXCIgLz5cbiAqICAgPC9HcmlkPlxuICogICA8R3JpZCBpdGVtIHhzPXsxMn0gbWQ9ezZ9PlxuICogICAgIDxTZWxlY3QgbGFiZWw9XCJDYXRlZ29yeVwiIC8+XG4gKiAgIDwvR3JpZD5cbiAqIDwvRmlsdGVyV3JhcHBlcj5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIGN1c3RvbSB0aXRsZSBhbmQgY291bnQ6XG4gKiBgYGB0c3hcbiAqIDxGaWx0ZXJXcmFwcGVyXG4gKiAgIHRpdGxlPVwiQWR2YW5jZWQgU2VhcmNoXCJcbiAqICAgZmlsdGVyQ291bnQ9e2FjdGl2ZUZpbHRlcnMubGVuZ3RofVxuICogICBzaG93Q291bnQ9e3RydWV9XG4gKiA+XG4gKiAgIHtmaWx0ZXJDb250cm9sc31cbiAqIDwvRmlsdGVyV3JhcHBlcj5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIGN1c3RvbSBzdHlsaW5nOlxuICogYGBgdHN4XG4gKiA8RmlsdGVyV3JhcHBlclxuICogICB0aXRsZT1cIlByb2R1Y3QgRmlsdGVyc1wiXG4gKiAgIGljb249ezxGaWx0ZXJMaXN0SWNvbiAvPn1cbiAqICAgY2FyZFN4PXt7IG10OiAzLCBib3JkZXJSYWRpdXM6IDIgfX1cbiAqICAgdGV4dFN4PXt7IGNvbG9yOiAnc2Vjb25kYXJ5Lm1haW4nIH19XG4gKiA+XG4gKiAgIHtjaGlsZHJlbn1cbiAqIDwvRmlsdGVyV3JhcHBlcj5cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSBwcm9wcyAtIENvbXBvbmVudCBwcm9wcyBpbmNsdWRpbmcgY2hpbGRyZW4gYW5kIHN0eWxpbmcgb3B0aW9uc1xuICogQHJldHVybnMgTVVJIENhcmQgY29tcG9uZW50IHdpdGggc3RydWN0dXJlZCBmaWx0ZXIgbGF5b3V0XG4gKlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY29uc3QgRmlsdGVyV3JhcHBlciA9ICh7XG4gIGNoaWxkcmVuLFxuICB0aXRsZSxcbiAgZmlsdGVyQ291bnQsXG4gIGNhcmRTeCxcbiAgdGV4dFN4LFxuICBpY29uLFxuICBpY29uU3gsXG4gIHNob3dDb3VudCxcbn06IEZpbHRlcldyYXBwZXJQcm9wcykgPT4ge1xuICBjb25zdCB0aGVtZSA9IHVzZVRoZW1lKCk7XG5cbiAgcmV0dXJuIChcbiAgICA8Q2FyZFxuICAgICAgc3g9e3tcbiAgICAgICAgcG9zaXRpb246ICdyZWxhdGl2ZScsXG4gICAgICAgIGJvcmRlclJhZGl1czogJzBweCcsXG4gICAgICAgIG1iOiAyLFxuICAgICAgICAuLi5jYXJkU3gsXG4gICAgICB9fVxuICAgID5cbiAgICAgIDxDYXJkSGVhZGVyXG4gICAgICAgIHN4PXt7XG4gICAgICAgICAgZGlzcGxheTogJ2ZsZXgnLFxuICAgICAgICAgIGZsZXhXcmFwOiAnd3JhcCcsXG4gICAgICAgICAgcDogJzFyZW0nLFxuICAgICAgICAgICcuTXVpQ2FyZEhlYWRlci1hY3Rpb24nOiB7XG4gICAgICAgICAgICBtYXJnaW46IDAsXG4gICAgICAgICAgICBhbGlnblNlbGY6ICdjZW50ZXInLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYWxpZ25JdGVtczogJ2NlbnRlcicsXG4gICAgICAgIH19XG4gICAgICAgIHRpdGxlPXtcbiAgICAgICAgICA8Qm94IHN4PXt7IGRpc3BsYXk6ICdmbGV4JywgYWxpZ25JdGVtczogJ2NlbnRlcicsIGdhcDogMC41IH19PlxuICAgICAgICAgICAge2ljb24gPyAoXG4gICAgICAgICAgICAgIGljb25cbiAgICAgICAgICAgICkgOiAoXG4gICAgICAgICAgICAgIDxNYW5hZ2VTZWFyY2hJY29uXG4gICAgICAgICAgICAgICAgc3g9e3tcbiAgICAgICAgICAgICAgICAgIGhlaWdodDogJzIuNXJlbScsXG4gICAgICAgICAgICAgICAgICBjb2xvcjogdGhlbWUucGFsZXR0ZS5wcmltYXJ5Lm1haW4sXG4gICAgICAgICAgICAgICAgICAuLi5pY29uU3gsXG4gICAgICAgICAgICAgICAgfX1cbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICl9XG4gICAgICAgICAgICA8VHlwb2dyYXBoeVxuICAgICAgICAgICAgICB2YXJpYW50PVwiaDVcIlxuICAgICAgICAgICAgICBzeD17e1xuICAgICAgICAgICAgICAgIGZvbnRXZWlnaHQ6ICdib2xkJyxcbiAgICAgICAgICAgICAgICBjb2xvcjogdGhlbWUucGFsZXR0ZS5wcmltYXJ5Lm1haW4sXG4gICAgICAgICAgICAgICAgLi4udGV4dFN4LFxuICAgICAgICAgICAgICB9fVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7dGl0bGUgPyB0aXRsZSA6ICdGaWx0ZXInfXsnICd9XG4gICAgICAgICAgICAgIHtzaG93Q291bnQgPyBgKCR7ZmlsdGVyQ291bnQgPyBmaWx0ZXJDb3VudCA6IDB9KWAgOiA8PjwvPn1cbiAgICAgICAgICAgIDwvVHlwb2dyYXBoeT5cbiAgICAgICAgICA8L0JveD5cbiAgICAgICAgfVxuICAgICAgPjwvQ2FyZEhlYWRlcj5cbiAgICAgIDxEaXZpZGVyIC8+XG4gICAgICA8Q2FyZENvbnRlbnQgc3g9e3sgcHk6IDIgfX0+XG4gICAgICAgIDxHcmlkIGNvbnRhaW5lciBzcGFjaW5nPXsyfT5cbiAgICAgICAgICB7Y2hpbGRyZW59XG4gICAgICAgIDwvR3JpZD5cbiAgICAgIDwvQ2FyZENvbnRlbnQ+XG4gICAgPC9DYXJkPlxuICApO1xufTtcbiIsICIvLyBjb3JlL2NvbXBvbmVudHMvRm9vdGVyL2luZGV4LnRzeFxuaW1wb3J0IHsgQm94LCBUeXBvZ3JhcGh5IH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuXG5leHBvcnQgY29uc3QgRm9vdGVyOiBSZWFjdC5GQyA9ICgpID0+IHtcbiAgY29uc3QgY3VycmVudFllYXIgPSBuZXcgRGF0ZSgpLmdldEZ1bGxZZWFyKCk7XG5cbiAgcmV0dXJuIChcbiAgICA8Qm94XG4gICAgICBjb21wb25lbnQ9XCJmb290ZXJcIlxuICAgICAgc3g9e3tcbiAgICAgICAgcHk6IDIsXG4gICAgICAgIHB4OiA0LFxuICAgICAgICBtdDogJ2F1dG8nLFxuICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoZW1lID0+XG4gICAgICAgICAgdGhlbWUucGFsZXR0ZS5tb2RlID09PSAnbGlnaHQnXG4gICAgICAgICAgICA/IHRoZW1lLnBhbGV0dGUuZ3JleVsyMDBdXG4gICAgICAgICAgICA6IHRoZW1lLnBhbGV0dGUuZ3JleVs4MDBdLFxuICAgICAgfX1cbiAgICA+XG4gICAgICA8VHlwb2dyYXBoeSB2YXJpYW50PVwiYm9keTJcIiBjb2xvcj1cInRleHQuc2Vjb25kYXJ5XCIgYWxpZ249XCJjZW50ZXJcIj5cbiAgICAgICAge2BcdTAwQTkgQ29weXJpZ2h0ICR7Y3VycmVudFllYXJ9IEdOLiBBbGwgcmlnaHRzIHJlc2VydmVkIGJ5IFBhcnVsIFVuaXZlcnNpdHkuYH1cbiAgICAgIDwvVHlwb2dyYXBoeT5cbiAgICA8L0JveD5cbiAgKTtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBTeFByb3BzIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgeyBHcmlkLCBUb29sdGlwLCBUeXBvZ3JhcGh5IH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5cbi8qKlxuICogUHJvcHMgZm9yIHRoZSBMYWJlbFRleHQgY29tcG9uZW50LlxuICpcbiAqIEBwdWJsaWNcbiAqL1xuaW50ZXJmYWNlIExhYmVsVGV4dFByb3BzIHtcbiAgLyoqXG4gICAqIExhYmVsIHRleHQgdG8gZGlzcGxheSBvbiB0aGUgbGVmdCBzaWRlLlxuICAgKiBAZXhhbXBsZSBcIk5hbWVcIiBvciBcIkVtYWlsIEFkZHJlc3NcIlxuICAgKi9cbiAgbGFiZWw6IHN0cmluZztcbiAgLyoqXG4gICAqIFZhbHVlIGNvbnRlbnQgdG8gZGlzcGxheSBvbiB0aGUgcmlnaHQgc2lkZS5cbiAgICogQ2FuIGJlIHRleHQsIG51bWJlcnMsIG9yIFJlYWN0IGVsZW1lbnRzLlxuICAgKiBAZXhhbXBsZSBcIkpvaG4gRG9lXCIgb3IgPExpbms+VmlldyBEZXRhaWxzPC9MaW5rPlxuICAgKi9cbiAgdmFsdWU6IFJlYWN0LlJlYWN0Tm9kZTtcbiAgLyoqXG4gICAqIEN1c3RvbSBncmlkIHNpemluZyBmb3IgbGFiZWwgYW5kIHZhbHVlIHNlY3Rpb25zLlxuICAgKiBAZGVmYXVsdFZhbHVlIHsgbGFiZWxTaXplOiB7IHhzOiA2LCBzbTogNiwgbWQ6IDYgfSwgdmFsdWVTaXplOiB7IHhzOiAxMiwgc206IDYsIG1kOiA2IH0gfVxuICAgKi9cbiAgZ3JpZFNpemU/OiB7XG4gICAgLyoqIEdyaWQgc2l6ZSBjb25maWd1cmF0aW9uIGZvciB0aGUgbGFiZWwgc2VjdGlvbiAqL1xuICAgIGxhYmVsU2l6ZTogeyB4czogbnVtYmVyOyBzbTogbnVtYmVyOyBtZDogbnVtYmVyIH07XG4gICAgLyoqIEdyaWQgc2l6ZSBjb25maWd1cmF0aW9uIGZvciB0aGUgdmFsdWUgc2VjdGlvbiAqL1xuICAgIHZhbHVlU2l6ZTogeyB4czogbnVtYmVyOyBzbTogbnVtYmVyOyBtZDogbnVtYmVyIH07XG4gIH07XG4gIC8qKlxuICAgKiBHcmlkIHNpemUgY29uZmlndXJhdGlvbiBmb3IgdGhlIGVudGlyZSBjb250YWluZXIuXG4gICAqIEBkZWZhdWx0VmFsdWUgeyB4czogMTIsIHNtOiA2LCBtZDogNiB9XG4gICAqL1xuICBjb250YWluZXJTaXplPzogeyB4czogbnVtYmVyOyBzbTogbnVtYmVyOyBtZDogbnVtYmVyIH07XG4gIC8qKlxuICAgKiBPcHRpb25hbCBNVUkgc3ggcHJvcCBmb3IgY3VzdG9tIGxhYmVsIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgZm9udFdlaWdodDogJ2JvbGQnLCBjb2xvcjogJ3ByaW1hcnkubWFpbicgfVxuICAgKi9cbiAgbGFiZWxTeD86IFN4UHJvcHM7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBNVUkgc3ggcHJvcCBmb3IgY3VzdG9tIHZhbHVlIHN0eWxpbmcuXG4gICAqIEBleGFtcGxlIHsgY29sb3I6ICd0ZXh0LnNlY29uZGFyeScsIGZvbnRTdHlsZTogJ2l0YWxpYycgfVxuICAgKi9cbiAgdmFsdWVTeD86IFN4UHJvcHM7XG59XG5cbi8qKlxuICogUmVzcG9uc2l2ZSBsYWJlbC12YWx1ZSBkaXNwbGF5IGNvbXBvbmVudCB3aXRoIGhvdmVyIGVmZmVjdHMgYW5kIHRleHQgdHJ1bmNhdGlvbi5cbiAqXG4gKiBUaGlzIGNvbXBvbmVudCBjcmVhdGVzIGEgY29uc2lzdGVudCBsYWJlbC12YWx1ZSBwYWlyIGxheW91dCB0aGF0IGFkYXB0cyB0byBkaWZmZXJlbnRcbiAqIHNjcmVlbiBzaXplcy4gSXQgaW5jbHVkZXMgaG92ZXIgZWZmZWN0cywgdGV4dCB0cnVuY2F0aW9uIHdpdGggdG9vbHRpcHMsIGFuZFxuICogY3VzdG9taXphYmxlIGdyaWQgc2l6aW5nIGZvciBmbGV4aWJsZSBsYXlvdXRzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBCYXNpYyB1c2FnZTpcbiAqIGBgYHRzeFxuICogPExhYmVsVGV4dFxuICogICBsYWJlbD1cIkZ1bGwgTmFtZVwiXG4gKiAgIHZhbHVlPVwiSm9obiBEb2VcIlxuICogLz5cbiAqIGBgYFxuICpcbiAqIEBleGFtcGxlXG4gKiBXaXRoIFJlYWN0IGVsZW1lbnQgdmFsdWU6XG4gKiBgYGB0c3hcbiAqIDxMYWJlbFRleHRcbiAqICAgbGFiZWw9XCJQcm9maWxlXCJcbiAqICAgdmFsdWU9ezxMaW5rIGhyZWY9XCIvcHJvZmlsZVwiPlZpZXcgUHJvZmlsZTwvTGluaz59XG4gKiAvPlxuICogYGBgXG4gKlxuICogQGV4YW1wbGVcbiAqIEN1c3RvbSBncmlkIHNpemluZzpcbiAqIGBgYHRzeFxuICogPExhYmVsVGV4dFxuICogICBsYWJlbD1cIkRlc2NyaXB0aW9uXCJcbiAqICAgdmFsdWU9e2xvbmdEZXNjcmlwdGlvbn1cbiAqICAgZ3JpZFNpemU9e3tcbiAqICAgICBsYWJlbFNpemU6IHsgeHM6IDEyLCBzbTogMywgbWQ6IDIgfSxcbiAqICAgICB2YWx1ZVNpemU6IHsgeHM6IDEyLCBzbTogOSwgbWQ6IDEwIH1cbiAqICAgfX1cbiAqICAgY29udGFpbmVyU2l6ZT17eyB4czogMTIsIHNtOiAxMiwgbWQ6IDEyIH19XG4gKiAvPlxuICogYGBgXG4gKlxuICogQHBhcmFtIHByb3BzIC0gQ29tcG9uZW50IHByb3BzIGZvciBsYWJlbC12YWx1ZSBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJucyBHcmlkLWJhc2VkIGxheW91dCB3aXRoIGxhYmVsIGFuZCB2YWx1ZSBzZWN0aW9uc1xuICpcbiAqIEBwdWJsaWNcbiAqL1xuZXhwb3J0IGNvbnN0IExhYmVsVGV4dCA9ICh7XG4gIGxhYmVsLFxuICB2YWx1ZSxcbiAgZ3JpZFNpemUsXG4gIGNvbnRhaW5lclNpemUsXG4gIGxhYmVsU3gsXG4gIHZhbHVlU3gsXG59OiBMYWJlbFRleHRQcm9wcykgPT4ge1xuICBjb25zdCBkZWZhdWx0R3JpZFNpemUgPSB7XG4gICAgbGFiZWxTaXplOiB7IHhzOiA2LCBzbTogNiwgbWQ6IDYgfSxcbiAgICB2YWx1ZVNpemU6IHsgeHM6IDEyLCBzbTogNiwgbWQ6IDYgfSxcbiAgfTtcbiAgY29uc3QgZGVmYXVsdENvbnRhaW5lclNpemUgPSB7IHhzOiAxMiwgc206IDYsIG1kOiA2IH07XG4gIGNvbnN0IHNpemUgPSBncmlkU2l6ZSB8fCBkZWZhdWx0R3JpZFNpemU7XG4gIGNvbnN0IGNvbnRhaW5lciA9IGNvbnRhaW5lclNpemUgfHwgZGVmYXVsdENvbnRhaW5lclNpemU7XG5cbiAgcmV0dXJuIChcbiAgICA8R3JpZFxuICAgICAgc2l6ZT17Y29udGFpbmVyfVxuICAgICAgc3g9e3tcbiAgICAgICAgZGlzcGxheTogJ2ZsZXgnLFxuICAgICAgICBmbGV4RGlyZWN0aW9uOiB7IHhzOiAnY29sdW1uJywgc206ICdyb3cnLCBtZDogJ3JvdycgfSxcbiAgICAgICAgJyY6aG92ZXInOiB7IGJnY29sb3I6ICcjZWZlZmVmJywgb3ZlcmZsb3c6ICdoaWRkZW4nIH0sXG4gICAgICB9fVxuICAgID5cbiAgICAgIDxHcmlkXG4gICAgICAgIHNpemU9e3NpemUubGFiZWxTaXplfVxuICAgICAgICBzeD17e1xuICAgICAgICAgIHBhZGRpbmc6ICc1cHgnLFxuICAgICAgICAgIGZvbnRTaXplOiAnMTRweCcsXG4gICAgICAgICAgdGV4dEFsaWduOiB7IHhzOiAnbGVmdCcsIHNtOiAncmlnaHQnLCBtZDogJ3JpZ2h0JyB9LFxuICAgICAgICAgIC4uLmxhYmVsU3gsXG4gICAgICAgIH19XG4gICAgICA+XG4gICAgICAgIHtsYWJlbH0gOlxuICAgICAgPC9HcmlkPlxuICAgICAgPEdyaWRcbiAgICAgICAgc2l6ZT17c2l6ZS52YWx1ZVNpemV9XG4gICAgICAgIHN4PXt7IHBhZGRpbmc6ICc1cHgnLCBkaXNwbGF5OiAnZmxleCcsIGZsZXhXcmFwOiAnd3JhcCcgfX1cbiAgICAgID5cbiAgICAgICAgPFRvb2x0aXAgdGl0bGU9e3ZhbHVlfSBhcnJvdz5cbiAgICAgICAgICA8VHlwb2dyYXBoeVxuICAgICAgICAgICAgc3g9e3tcbiAgICAgICAgICAgICAgZm9udFNpemU6ICcxNHB4JyxcbiAgICAgICAgICAgICAgd29yZEJyZWFrOiAnYnJlYWstd29yZCcsXG4gICAgICAgICAgICAgIG92ZXJmbG93OiAnaGlkZGVuJyxcbiAgICAgICAgICAgICAgZGlzcGxheTogJy13ZWJraXQtYm94JyxcbiAgICAgICAgICAgICAgdGV4dE92ZXJmbG93OiAnZWxsaXBzaXMnLFxuICAgICAgICAgICAgICBXZWJraXRMaW5lQ2xhbXA6IDIsXG4gICAgICAgICAgICAgIFdlYmtpdEJveE9yaWVudDogJ3ZlcnRpY2FsJyxcbiAgICAgICAgICAgICAgLi4udmFsdWVTeCxcbiAgICAgICAgICAgICAgY29sb3I6ICcjMDc4ZGVlJyxcbiAgICAgICAgICAgIH19XG4gICAgICAgICAgPlxuICAgICAgICAgICAge3ZhbHVlID8gdmFsdWUgOiAnLSd9XG4gICAgICAgICAgPC9UeXBvZ3JhcGh5PlxuICAgICAgICA8L1Rvb2x0aXA+XG4gICAgICA8L0dyaWQ+XG4gICAgPC9HcmlkPlxuICApO1xufTtcbiIsICJpbXBvcnQgdHlwZSB7IFByb3BzV2l0aENoaWxkcmVuIH0gZnJvbSAncmVhY3QnO1xuXG5pbnRlcmZhY2UgUmVuZGVySWZQcm9wcyB7XG4gIHNob3c6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjb25zdCBSZW5kZXJJZiA9ICh7XG4gIHNob3csXG4gIGNoaWxkcmVuLFxufTogUHJvcHNXaXRoQ2hpbGRyZW48UmVuZGVySWZQcm9wcz4pID0+IHtcbiAgcmV0dXJuIHNob3cgPyA8PntjaGlsZHJlbn08Lz4gOiBudWxsO1xufTtcbiIsICJpbXBvcnQgdHlwZSB7IFN4UHJvcHMsIFRoZW1lIH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgeyBCb3gsIERpdmlkZXIsIEdyaWQsIFN0YWNrLCBUeXBvZ3JhcGh5IH0gZnJvbSAnQG11aS9tYXRlcmlhbCc7XG5pbXBvcnQgdHlwZSB7IFByb3BzV2l0aENoaWxkcmVuLCBSZWFjdE5vZGUgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBtZW1vLCB1c2VNZW1vIH0gZnJvbSAncmVhY3QnO1xuXG4vLyBTZWN0aW9uIGJveCBjb25maWd1cmF0aW9uXG5leHBvcnQgaW50ZXJmYWNlIFNlY3Rpb25Cb3hQcm9wcyBleHRlbmRzIFByb3BzV2l0aENoaWxkcmVuIHtcbiAgdGl0bGU6IHN0cmluZztcbiAgc3BhY2luZz86IG51bWJlcjtcbiAgY29udGFpbmVyU3g/OiBTeFByb3BzPFRoZW1lPjtcbiAgdGl0bGVTeD86IFN4UHJvcHM8VGhlbWU+O1xuICB2YXJpYW50PzogJ2RlZmF1bHQnIHwgJ2Zvcm0nIHwgJ2luZm8nIHwgJ3dhcm5pbmcnIHwgJ2Vycm9yJztcbiAgaWNvbj86IFJlYWN0Tm9kZTtcbiAgYWN0aW9ucz86IFJlYWN0Tm9kZTtcbiAgY29sbGFwc2libGU/OiBib29sZWFuO1xuICBkZWZhdWx0RXhwYW5kZWQ/OiBib29sZWFuO1xufVxuXG4vLyBUaGVtZSBjb25maWd1cmF0aW9uIGZvciBzZWN0aW9uIHZhcmlhbnRzXG5jb25zdCBnZXRTZWN0aW9uVGhlbWUgPSAodmFyaWFudDogU2VjdGlvbkJveFByb3BzWyd2YXJpYW50J10gPSAnZGVmYXVsdCcpID0+IHtcbiAgY29uc3QgdGhlbWVzID0ge1xuICAgIGRlZmF1bHQ6IHtcbiAgICAgIGJnY29sb3I6ICcjZmFlYmQ3JyxcbiAgICAgIGNvbG9yOiAnIzkyNWQyMScsXG4gICAgfSxcbiAgICBmb3JtOiB7XG4gICAgICBiZ2NvbG9yOiAnI2NkY2VkMScsXG4gICAgICBjb2xvcjogJ2JsYWNrJyxcbiAgICB9LFxuICAgIGluZm86IHtcbiAgICAgIGJnY29sb3I6ICcjZTNmMmZkJyxcbiAgICAgIGNvbG9yOiAnIzE5NzZkMicsXG4gICAgfSxcbiAgICB3YXJuaW5nOiB7XG4gICAgICBiZ2NvbG9yOiAnI2ZmZjNlMCcsXG4gICAgICBjb2xvcjogJyNmNTdjMDAnLFxuICAgIH0sXG4gICAgZXJyb3I6IHtcbiAgICAgIGJnY29sb3I6ICcjZmZlYmVlJyxcbiAgICAgIGNvbG9yOiAnI2QzMmYyZicsXG4gICAgfSxcbiAgfTtcblxuICByZXR1cm4gdGhlbWVzW3ZhcmlhbnRdO1xufTtcblxuLy8gTWVtb2l6ZWQgU2VjdGlvbkJveCBjb21wb25lbnQgZm9yIHBlcmZvcm1hbmNlXG5leHBvcnQgY29uc3QgU2VjdGlvbkJveCA9IG1lbW88U2VjdGlvbkJveFByb3BzPihcbiAgKHtcbiAgICB0aXRsZSxcbiAgICBjaGlsZHJlbixcbiAgICBzcGFjaW5nID0gMCxcbiAgICBjb250YWluZXJTeCxcbiAgICB0aXRsZVN4LFxuICAgIHZhcmlhbnQgPSAnZGVmYXVsdCcsXG4gICAgaWNvbixcbiAgICBhY3Rpb25zLFxuICB9KSA9PiB7XG4gICAgY29uc3QgdGhlbWVDb2xvcnMgPSB1c2VNZW1vKCgpID0+IGdldFNlY3Rpb25UaGVtZSh2YXJpYW50KSwgW3ZhcmlhbnRdKTtcblxuICAgIGNvbnN0IGhlYWRlclN4ID0gdXNlTWVtbyhcbiAgICAgICgpID0+ICh7XG4gICAgICAgIHB4OiAxLjUsXG4gICAgICAgIHB5OiAwLjEsXG4gICAgICAgIHdpZHRoOiAnZml0LWNvbnRlbnQnLFxuICAgICAgICAuLi50aGVtZUNvbG9ycyxcbiAgICAgICAgLi4udGl0bGVTeCxcbiAgICAgIH0pLFxuICAgICAgW3RoZW1lQ29sb3JzLCB0aXRsZVN4XVxuICAgICk7XG5cbiAgICBjb25zdCBjb250ZW50U3ggPSB1c2VNZW1vKFxuICAgICAgKCkgPT4gKHtcbiAgICAgICAgcGFkZGluZzogJzE2cHgnLFxuICAgICAgICAuLi5jb250YWluZXJTeCxcbiAgICAgIH0pLFxuICAgICAgW2NvbnRhaW5lclN4XVxuICAgICk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgPD5cbiAgICAgICAgPEJveCBzeD17eyBkaXNwbGF5OiAnZmxleCcsIGZsZXhEaXJlY3Rpb246ICdjb2x1bW4nLCB3aWR0aDogJzEwMCUnIH19PlxuICAgICAgICAgIDxTdGFja1xuICAgICAgICAgICAgZGlyZWN0aW9uPVwicm93XCJcbiAgICAgICAgICAgIGp1c3RpZnlDb250ZW50PVwic3BhY2UtYmV0d2VlblwiXG4gICAgICAgICAgICBhbGlnbkl0ZW1zPVwiY2VudGVyXCJcbiAgICAgICAgICAgIHN4PXtoZWFkZXJTeH1cbiAgICAgICAgICA+XG4gICAgICAgICAgICA8U3RhY2sgZGlyZWN0aW9uPVwicm93XCIgYWxpZ25JdGVtcz1cImNlbnRlclwiIHNwYWNpbmc9ezF9PlxuICAgICAgICAgICAgICB7aWNvbn1cbiAgICAgICAgICAgICAgPFR5cG9ncmFwaHkgc3g9e3sgZm9udFNpemU6ICcxNXB4JywgZm9udFdlaWdodDogNDAwIH19PlxuICAgICAgICAgICAgICAgIHt0aXRsZX1cbiAgICAgICAgICAgICAgPC9UeXBvZ3JhcGh5PlxuICAgICAgICAgICAgPC9TdGFjaz5cbiAgICAgICAgICAgIHthY3Rpb25zfVxuICAgICAgICAgIDwvU3RhY2s+XG4gICAgICAgICAgPERpdmlkZXIgLz5cbiAgICAgICAgPC9Cb3g+XG4gICAgICAgIDxHcmlkIGNvbnRhaW5lciBzcGFjaW5nPXtzcGFjaW5nfSBzeD17Y29udGVudFN4fT5cbiAgICAgICAgICB7Y2hpbGRyZW59XG4gICAgICAgIDwvR3JpZD5cbiAgICAgIDwvPlxuICAgICk7XG4gIH1cbik7XG4iLCAiaW1wb3J0IHsgVGFiQ29udGV4dCB9IGZyb20gJ0BtdWkvbGFiJztcbmltcG9ydCB0eXBlIHsgU3hQcm9wcyB9IGZyb20gJ0BtdWkvbWF0ZXJpYWwnO1xuaW1wb3J0IHsgQm94LCBUYWIsIFRhYnMgfSBmcm9tICdAbXVpL21hdGVyaWFsJztcbmltcG9ydCB0eXBlIHsgUHJvcHNXaXRoQ2hpbGRyZW4gfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgUmVhY3QsIHsgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGFiSXRlbSB7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIHZhbHVlOiBudW1iZXI7XG4gIHBlcm1pc3Npb24/OiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgQ3VzdG9tVGFic1Byb3BzIHtcbiAgdGFiczogVGFiSXRlbVtdO1xuICBkZWZhdWx0VmFsdWU/OiBudW1iZXI7XG4gIG9uVGFiQ2hhbmdlPzogKG5ld1ZhbHVlOiBudW1iZXIpID0+IHZvaWQ7XG4gIHRhYlN4PzogU3hQcm9wcztcbiAgdGFic1N4PzogU3hQcm9wcztcbn1cblxuZXhwb3J0IGNvbnN0IFNpbXBsZVRhYnMgPSAoe1xuICB0YWJzLFxuICBkZWZhdWx0VmFsdWUgPSAxLFxuICBvblRhYkNoYW5nZSxcbiAgY2hpbGRyZW4sXG4gIHRhYlN4LFxuICB0YWJzU3gsXG59OiBDdXN0b21UYWJzUHJvcHMgJiBQcm9wc1dpdGhDaGlsZHJlbikgPT4ge1xuICBjb25zdCBbdmFsdWUsIHNldFZhbHVlXSA9IHVzZVN0YXRlPG51bWJlcj4oZGVmYXVsdFZhbHVlKTtcblxuICBjb25zdCBoYW5kbGVDaGFuZ2UgPSAoZXZlbnQ6IFJlYWN0LlN5bnRoZXRpY0V2ZW50LCBuZXdWYWx1ZTogbnVtYmVyKSA9PiB7XG4gICAgc2V0VmFsdWUobmV3VmFsdWUpO1xuICAgIGlmIChvblRhYkNoYW5nZSkgb25UYWJDaGFuZ2UobmV3VmFsdWUpO1xuICB9O1xuXG4gIHJldHVybiAoXG4gICAgPFRhYkNvbnRleHQgdmFsdWU9e3ZhbHVlfT5cbiAgICAgIDxCb3ggc3g9e3sgYm9yZGVyQm90dG9tOiAxLCBib3JkZXJDb2xvcjogJ2RpdmlkZXInLCB3aWR0aDogJzEwMCUnIH19PlxuICAgICAgICA8VGFic1xuICAgICAgICAgIHZhbHVlPXt2YWx1ZX1cbiAgICAgICAgICBvbkNoYW5nZT17aGFuZGxlQ2hhbmdlfVxuICAgICAgICAgIHN4PXt7IHB4OiAyLCBweTogMCwgLi4udGFic1N4IH19XG4gICAgICAgID5cbiAgICAgICAgICB7dGFicy5tYXAodGFiID0+IChcbiAgICAgICAgICAgIDxUYWJcbiAgICAgICAgICAgICAga2V5PXt0YWIudmFsdWV9XG4gICAgICAgICAgICAgIGxhYmVsPXt0YWIubGFiZWx9XG4gICAgICAgICAgICAgIHZhbHVlPXt0YWIudmFsdWV9XG4gICAgICAgICAgICAgIGRpc2FibGVkPXt0YWIucGVybWlzc2lvbiA9PT0gZmFsc2V9XG4gICAgICAgICAgICAgIHN4PXt7IGZvbnRTaXplOiAnMXJlbScsIC4uLnRhYlN4IH19XG4gICAgICAgICAgICAvPlxuICAgICAgICAgICkpfVxuICAgICAgICA8L1RhYnM+XG4gICAgICA8L0JveD5cblxuICAgICAge2NoaWxkcmVufVxuICAgIDwvVGFiQ29udGV4dD5cbiAgKTtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBMb2FkaW5nQnV0dG9uUHJvcHMgfSBmcm9tICdAbXVpL2xhYic7XG5pbXBvcnQgeyBMb2FkaW5nQnV0dG9uIH0gZnJvbSAnQG11aS9sYWInO1xuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcblxudHlwZSBTdWJtaXRCdXR0b25Qcm9wcyA9IE9taXQ8XG4gIExvYWRpbmdCdXR0b25Qcm9wcyxcbiAgJ2NoaWxkcmVuJyB8ICd2YXJpYW50JyB8ICdjb2xvcicgfCAndHlwZSdcbj47XG5cbmV4cG9ydCBjb25zdCBTdWJtaXRCdXR0b246IFJlYWN0LkZDPFN1Ym1pdEJ1dHRvblByb3BzPiA9ICh7XG4gIGxvYWRpbmcgPSBmYWxzZSxcbiAgLi4ucmVzdFxufSkgPT4gKFxuICA8TG9hZGluZ0J1dHRvblxuICAgIGxvYWRpbmc9e2xvYWRpbmd9XG4gICAgdmFyaWFudD1cImNvbnRhaW5lZFwiXG4gICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICB0eXBlPVwic3VibWl0XCJcbiAgICB7Li4ucmVzdH1cbiAgICBzeD17eyBmb250V2VpZ2h0OiA0MDAgfX1cbiAgPlxuICAgIFN1Ym1pdFxuICA8L0xvYWRpbmdCdXR0b24+XG4pO1xuIiwgImltcG9ydCB0eXBlIFJlYWN0IGZyb20gJ3JlYWN0JztcbmltcG9ydCB7IGZvcndhcmRSZWYgfSBmcm9tICdyZWFjdCc7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFNoYXJlZCB0eXBlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuZXhwb3J0IGludGVyZmFjZSBEYXRhTW9kYWxCdXR0b25zIHtcbiAgb25TdWJtaXQ/OiAoKSA9PiB2b2lkO1xuICBvbkNhbmNlbD86ICgpID0+IHZvaWQ7XG4gIGlzUGVuZGluZz86IGJvb2xlYW47XG4gIGlzU3VjY2Vzcz86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YU1vZGFsQ29tcG9uZW50UHJvcHM8VERhdGE+IHtcbiAgZGF0YT86IFREYXRhO1xuICBpc0VkaXRpbmc/OiBib29sZWFuO1xuICByZWY/OiBSZWFjdC5SZWY8RGF0YU1vZGFsQnV0dG9ucz47IC8vIFx1RDgzRFx1REM0OCBwdXQgcmVmIGludG8gcHJvcHNcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUHJvamVjdC1zcGVjaWZpYyBIT0Ncbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmV4cG9ydCBmdW5jdGlvbiB3aXRoRGF0YU1vZGFsPFREYXRhPihcbiAgY29tcG9uZW50OiAoXG4gICAgcHJvcHM6IERhdGFNb2RhbENvbXBvbmVudFByb3BzPFREYXRhPlxuICApID0+IFJlYWN0LlJlYWN0RWxlbWVudCB8IG51bGxcbikge1xuICByZXR1cm4gZm9yd2FyZFJlZjxEYXRhTW9kYWxCdXR0b25zLCBEYXRhTW9kYWxDb21wb25lbnRQcm9wczxURGF0YT4+KFxuICAgIChwcm9wcywgcmVmKSA9PiBjb21wb25lbnQoeyAuLi5wcm9wcywgcmVmIH0pXG4gICk7XG59XG4iLCAiZXhwb3J0IGludGVyZmFjZSBDb25maWdWYWx1ZSB7XG4gIGFwaUJhc2VVcmw6IHN0cmluZztcbiAgZGVmYXVsdFBhZ2VTaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBDb25maWc6IENvbmZpZ1ZhbHVlID0ge1xuICBkZWZhdWx0UGFnZVNpemU6IDIwLFxuICBhcGlCYXNlVXJsOiAnaHR0cDovL2xvY2FsaG9zdDo1MTQzJyxcbiAgLy8gYXBpQmFzZVVybDogJ2h0dHA6Ly8xOTIuMTY4LjEuMjQ2OjUxNDMnLFxufTtcblxuZXhwb3J0IGNvbnN0IGRhdGVUaW1lUGF0dGVybnMgPSB7XG4gIGRhdGVUaW1lOiAnREQgTU1NIFlZWVkgaDptbSBBJywgLy8gMTcgQXByIDIwMjIgMTI6MDAgYW1cbiAgZGF0ZTogJ0REIE1NTSBZWVlZJywgLy8gMTcgQXByIDIwMjJcbiAgbW9udGhfeWVhcl9zaG9ydF9mb3JtYXQ6ICdNTU0gWVlZWScsXG4gIG1vbnRoX3llYXJfZnVsbF9mb3JtYXQ6ICdNTU1NIFlZWVknLFxuICB5ZWFyOiAnWVlZWScsXG4gIHRpbWU6ICdoOm1tIGEnLCAvLyAxMjowMCBhbVxuICBzcGxpdDoge1xuICAgIGRhdGVUaW1lOiAnREQvTU0vWVlZWSBoOm1tIEEnLCAvLyAxNy8wNC8yMDIyIDEyOjAwIGFtXG4gICAgZGF0ZTogJ0REL01NL1lZWVknLCAvLyAxNy8wNC8yMDIyXG4gIH0sXG4gIHBhcmFtQ2FzZToge1xuICAgIGRhdGVUaW1lOiAnREQtTU0tWVlZWSBoOm1tIEEnLCAvLyAxNy0wNC0yMDIyIDEyOjAwIGFtXG4gICAgZGF0ZTogJ0RELU1NLVlZWVknLCAvLyAxNy0wNC0yMDIyXG4gICAgZGF0ZVJldmVyc2U6ICdZWVlZLU1NLUREJywgLy8gMjAyMi0wNC0xNyBmb3IgY29tcGFyZSBkYXRlXG4gICAgTW9udGhZZWFyOiAnTU1NLVlZWVknLFxuICB9LFxufTtcbiIsICJpbXBvcnQgeyB1c2VNZW1vIH0gZnJvbSAncmVhY3QnO1xuXG5pbXBvcnQgeyBjcmVhdGVBcGlDbGllbnQgfSBmcm9tICcuLi9hcGkvY3JlYXRlQXBpQ2xpZW50JztcbmltcG9ydCB0eXBlIHsgQXBpQ2xpZW50Q29uZmlnIH0gZnJvbSAnLi4vYXBpL2NyZWF0ZUFwaUNsaWVudCc7XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VBcGlDbGllbnQoY29uZmlnOiBBcGlDbGllbnRDb25maWcgPSB7fSkge1xuICByZXR1cm4gdXNlTWVtbyhcbiAgICAoKSA9PiBjcmVhdGVBcGlDbGllbnQoY29uZmlnKSxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1kZXBzXG4gICAgW1xuICAgICAgY29uZmlnLmJhc2VVUkwsXG4gICAgICBjb25maWcudGltZW91dCxcbiAgICAgIGNvbmZpZy5jb3JyZWxhdGlvbklkUHJlZml4LFxuICAgICAgY29uZmlnLmluY2x1ZGVDb3JyZWxhdGlvbklkLFxuICAgICAgY29uZmlnLmF1dGhUb2tlbixcbiAgICAgIGNvbmZpZy5yZXF1ZXN0SW50ZXJjZXB0b3JzLFxuICAgICAgY29uZmlnLnJlc3BvbnNlSW50ZXJjZXB0b3JzLFxuICAgICAgY29uZmlnLmVycm9ySW50ZXJjZXB0b3JzLFxuICAgIF1cbiAgKTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7IFZhbGlkYXRpb25FcnJvcnMgfSBmcm9tICdAZ253ZWJzb2Z0L3VpJztcbmltcG9ydCB7IHVzZUNhbGxiYWNrIH0gZnJvbSAncmVhY3QnO1xuaW1wb3J0IHR5cGUgeyBVc2VGb3JtU2V0RXJyb3IsIEZpZWxkVmFsdWVzLCBQYXRoIH0gZnJvbSAncmVhY3QtaG9vay1mb3JtJztcbmltcG9ydCB7IHRvYXN0IH0gZnJvbSAnc29ubmVyJztcblxuaW1wb3J0IHR5cGUgeyBBcGlFcnJvciB9IGZyb20gJy4uL2FwaS90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3VjY2Vzc01lc3NhZ2Uge1xuICBjcmVhdGU6IHN0cmluZztcbiAgdXBkYXRlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXJyb3JNZXNzYWdlIHtcbiAgbm9DaGFuZ2VzOiBzdHJpbmc7XG4gIGdlbmVyYWw6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBVc2VGb3JtRXJyb3JIYW5kbGVyT3B0aW9uczxURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcz4ge1xuICBzZXRFcnJvcj86IFVzZUZvcm1TZXRFcnJvcjxURmllbGRWYWx1ZXM+O1xuICBzdWNjZXNzTWVzc2FnZT86IFN1Y2Nlc3NNZXNzYWdlO1xuICBlcnJvck1lc3NhZ2U/OiBFcnJvck1lc3NhZ2U7XG59XG5cbmV4cG9ydCB0eXBlIFN1Y2Nlc3NIYW5kbGVyID0gKFxuICBpc0VkaXRpbmc6IGJvb2xlYW4sXG4gIHJvd3NBZmZlY3RlZD86IG51bWJlclxuKSA9PiBib29sZWFuO1xuXG5leHBvcnQgdHlwZSBFcnJvckhhbmRsZXIgPSAocHJvY2Vzc2VkRXJyb3I6IEFwaUVycm9yKSA9PiB2b2lkO1xuXG5leHBvcnQgaW50ZXJmYWNlIFVzZUZvcm1FcnJvckhhbmRsZXJSZXR1cm4ge1xuICBoYW5kbGVTdWNjZXNzOiBTdWNjZXNzSGFuZGxlcjtcbiAgaGFuZGxlRXJyb3I6IEVycm9ySGFuZGxlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBVc2VEZWxldGVIYW5kbGVyT3B0aW9ucyB7XG4gIHN1Y2Nlc3NNZXNzYWdlPzogc3RyaW5nO1xuICBlcnJvck1lc3NhZ2U/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogSG9vayB0byBoYW5kbGUgQVBJIGVycm9ycyBpbiBmb3JtcyB3aXRoIHN0YW5kYXJkaXplZCBlcnJvciBoYW5kbGluZyBhbmQgdG9hc3QgbWVzc2FnZXNcbiAqL1xuZXhwb3J0IGNvbnN0IHVzZUZvcm1FcnJvckhhbmRsZXIgPSA8VEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXM+KHtcbiAgc2V0RXJyb3IsXG4gIHN1Y2Nlc3NNZXNzYWdlID0ge1xuICAgIGNyZWF0ZTogJ0NyZWF0ZWQgc3VjY2Vzc2Z1bGx5JyxcbiAgICB1cGRhdGU6ICdVcGRhdGVkIHN1Y2Nlc3NmdWxseScsXG4gIH0sXG4gIGVycm9yTWVzc2FnZSA9IHtcbiAgICBub0NoYW5nZXM6ICdObyBjaGFuZ2VzIHdlcmUgbWFkZScsXG4gICAgZ2VuZXJhbDogJ0ZhaWxlZCB0byBzYXZlLiBQbGVhc2UgdHJ5IGFnYWluLicsXG4gIH0sXG59OiBVc2VGb3JtRXJyb3JIYW5kbGVyT3B0aW9uczxURmllbGRWYWx1ZXM+KTogVXNlRm9ybUVycm9ySGFuZGxlclJldHVybiA9PiB7XG4gIGNvbnN0IGdldEZpZWxkRXJyb3IgPSB1c2VDYWxsYmFjayhcbiAgICAoXG4gICAgICBmaWVsZHM6IFZhbGlkYXRpb25FcnJvcnMgfCB1bmRlZmluZWQsXG4gICAgICBmaWVsZE5hbWU6IHN0cmluZ1xuICAgICk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gICAgICBpZiAoIWZpZWxkcyB8fCAhZmllbGRzW2ZpZWxkTmFtZV0pIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIGNvbnN0IGZpZWxkRXJyb3IgPSBmaWVsZHNbZmllbGROYW1lXTtcblxuICAgICAgaWYgKHR5cGVvZiBmaWVsZEVycm9yID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gZmllbGRFcnJvcjtcbiAgICAgIH1cblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZmllbGRFcnJvcikpIHtcbiAgICAgICAgcmV0dXJuIGZpZWxkRXJyb3Iuam9pbignLCAnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBmaWVsZEVycm9yID09PSAnb2JqZWN0JyAmJiAnbWVzc2FnZScgaW4gZmllbGRFcnJvcikge1xuICAgICAgICByZXR1cm4gZmllbGRFcnJvci5tZXNzYWdlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH0sXG4gICAgW11cbiAgKTtcblxuICBjb25zdCBoYW5kbGVTdWNjZXNzID0gdXNlQ2FsbGJhY2soXG4gICAgKGlzRWRpdGluZzogYm9vbGVhbiwgcm93c0FmZmVjdGVkPzogbnVtYmVyKSA9PiB7XG4gICAgICBpZiAocm93c0FmZmVjdGVkICE9PSB1bmRlZmluZWQgJiYgcm93c0FmZmVjdGVkID4gMCkge1xuICAgICAgICB0b2FzdC5zdWNjZXNzKFxuICAgICAgICAgIGlzRWRpdGluZyA/IHN1Y2Nlc3NNZXNzYWdlLnVwZGF0ZSA6IHN1Y2Nlc3NNZXNzYWdlLmNyZWF0ZVxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChyb3dzQWZmZWN0ZWQgPT09IDApIHtcbiAgICAgICAgdG9hc3QuZXJyb3IoZXJyb3JNZXNzYWdlLm5vQ2hhbmdlcyk7XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiByb3dzQWZmZWN0ZWQgaXMgdW5kZWZpbmVkLCBhc3N1bWUgc3VjY2Vzc1xuICAgICAgdG9hc3Quc3VjY2Vzcyhpc0VkaXRpbmcgPyBzdWNjZXNzTWVzc2FnZS51cGRhdGUgOiBzdWNjZXNzTWVzc2FnZS5jcmVhdGUpO1xuXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9LFxuICAgIFtzdWNjZXNzTWVzc2FnZSwgZXJyb3JNZXNzYWdlXVxuICApO1xuXG4gIGNvbnN0IGhhbmRsZUVycm9yID0gdXNlQ2FsbGJhY2soXG4gICAgKHByb2Nlc3NlZEVycm9yOiBBcGlFcnJvcikgPT4ge1xuICAgICAgaWYgKFxuICAgICAgICBwcm9jZXNzZWRFcnJvci50eXBlID09PSAndmFsaWRhdGlvbl9lcnJvcicgJiZcbiAgICAgICAgcHJvY2Vzc2VkRXJyb3IuZXJyb3JzICYmXG4gICAgICAgIHNldEVycm9yXG4gICAgICApIHtcbiAgICAgICAgLy8gU2V0IGZpZWxkLXNwZWNpZmljIGVycm9ycyB1c2luZyByZWFjdC1ob29rLWZvcm0ncyBzZXRFcnJvciAob25seSBpZiBzZXRFcnJvciBpcyBwcm92aWRlZClcbiAgICAgICAgT2JqZWN0LmtleXMocHJvY2Vzc2VkRXJyb3IuZXJyb3JzKS5mb3JFYWNoKGZpZWxkTmFtZSA9PiB7XG4gICAgICAgICAgY29uc3QgZmllbGRFcnJvciA9IGdldEZpZWxkRXJyb3IocHJvY2Vzc2VkRXJyb3IuZXJyb3JzLCBmaWVsZE5hbWUpO1xuXG4gICAgICAgICAgaWYgKGZpZWxkRXJyb3IpIHtcbiAgICAgICAgICAgIHNldEVycm9yKGZpZWxkTmFtZSBhcyBQYXRoPFRGaWVsZFZhbHVlcz4sIHtcbiAgICAgICAgICAgICAgdHlwZTogJ3NlcnZlcicsXG4gICAgICAgICAgICAgIG1lc3NhZ2U6IGZpZWxkRXJyb3IsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFNob3cgZ2VuZXJhbCB2YWxpZGF0aW9uIGVycm9yIHRvYXN0XG4gICAgICAgIHRvYXN0LmVycm9yKFxuICAgICAgICAgIHByb2Nlc3NlZEVycm9yLnRpdGxlIHx8ICdQbGVhc2UgY2hlY2sgdGhlIGZvcm0gZm9yIHZhbGlkYXRpb24gZXJyb3JzJ1xuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gU2hvdyBnZW5lcmFsIGVycm9yIHRvYXN0IGZvciBub24tdmFsaWRhdGlvbiBlcnJvcnMgb3Igd2hlbiBzZXRFcnJvciBpcyBub3QgYXZhaWxhYmxlXG4gICAgICAgIHRvYXN0LmVycm9yKHByb2Nlc3NlZEVycm9yLnRpdGxlIHx8IGVycm9yTWVzc2FnZS5nZW5lcmFsKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIFtlcnJvck1lc3NhZ2UuZ2VuZXJhbCwgZ2V0RmllbGRFcnJvciwgc2V0RXJyb3JdXG4gICk7XG5cbiAgcmV0dXJuIHtcbiAgICBoYW5kbGVTdWNjZXNzLFxuICAgIGhhbmRsZUVycm9yLFxuICB9O1xufTtcblxuLyoqXG4gKiBDb252ZW5pZW5jZSBob29rIGZvciBkZWxldGUgb3BlcmF0aW9ucyB0aGF0IGRvbid0IG5lZWQgZm9ybSBmaWVsZCB2YWxpZGF0aW9uXG4gKiBVc2VzIHVzZUZvcm1FcnJvckhhbmRsZXIgaW50ZXJuYWxseSBidXQgd2l0aCBzaW1wbGlmaWVkIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGNvbnN0IHVzZURlbGV0ZUhhbmRsZXIgPSAoe1xuICBzdWNjZXNzTWVzc2FnZSA9ICdEZWxldGVkIHN1Y2Nlc3NmdWxseScsXG4gIGVycm9yTWVzc2FnZSA9ICdGYWlsZWQgdG8gZGVsZXRlLiBQbGVhc2UgdHJ5IGFnYWluLicsXG59OiBVc2VEZWxldGVIYW5kbGVyT3B0aW9ucyA9IHt9KTogVXNlRm9ybUVycm9ySGFuZGxlclJldHVybiA9PiB7XG4gIHJldHVybiB1c2VGb3JtRXJyb3JIYW5kbGVyKHtcbiAgICBzdWNjZXNzTWVzc2FnZToge1xuICAgICAgY3JlYXRlOiBzdWNjZXNzTWVzc2FnZSwgLy8gTm90IHVzZWQgZm9yIGRlbGV0ZSwgYnV0IHJlcXVpcmVkIGZvciB0eXBlXG4gICAgICB1cGRhdGU6IHN1Y2Nlc3NNZXNzYWdlLFxuICAgIH0sXG4gICAgZXJyb3JNZXNzYWdlOiB7XG4gICAgICBub0NoYW5nZXM6ICdObyBjaGFuZ2VzIHdlcmUgbWFkZScsIC8vIE5vdCB0eXBpY2FsbHkgdXNlZCBmb3IgZGVsZXRlXG4gICAgICBnZW5lcmFsOiBlcnJvck1lc3NhZ2UsXG4gICAgfSxcbiAgICAvLyBzZXRFcnJvciBpcyBvbWl0dGVkICh1bmRlZmluZWQpIGZvciBkZWxldGUgb3BlcmF0aW9uc1xuICB9KTtcbn07XG4iLCAiaW1wb3J0IHR5cGUgeyBRdWVyeUNsaWVudCwgUXVlcnlLZXkgfSBmcm9tICdAdGFuc3RhY2svcmVhY3QtcXVlcnknO1xuaW1wb3J0IHsgdXNlUXVlcnlDbGllbnQgfSBmcm9tICdAdGFuc3RhY2svcmVhY3QtcXVlcnknO1xuaW1wb3J0IHsgdXNlTWVtbyB9IGZyb20gJ3JlYWN0JztcblxuLy8gTWluaW1hbCB0eXBlLXNhZmUgY2FjaGUgdXRpbGl0eSBmb3IgcXVlcnkga2V5IGZhY3Rvcmllc1xuZXhwb3J0IGNsYXNzIENhY2hlVXRpbGl0eSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcXVlcnlDbGllbnQ6IFF1ZXJ5Q2xpZW50KSB7fVxuXG4gIC8qKlxuICAgKiBHZXQgY2FjaGVkIGRhdGEgdXNpbmcgb25seSB0aGUgcXVlcnlLZXkgZnJvbSBxdWVyeSBmYWN0b3J5XG4gICAqL1xuICBnZXRDYWNoZWREYXRhPFQ+KHF1ZXJ5S2V5OiBRdWVyeUtleSk6IFQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5Q2xpZW50LmdldFF1ZXJ5RGF0YTxUPihxdWVyeUtleSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNhY2hlZCBkYXRhIHdpdGggdHJhbnNmb3JtYXRpb24gdXNpbmcgc2VsZWN0IGZ1bmN0aW9uXG4gICAqL1xuICBnZXRDYWNoZWREYXRhV2l0aFNlbGVjdDxULCBSPihcbiAgICBxdWVyeUtleTogUXVlcnlLZXksXG4gICAgc2VsZWN0OiAoZGF0YTogVCkgPT4gUlxuICApOiBSIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBjYWNoZWREYXRhID0gdGhpcy5xdWVyeUNsaWVudC5nZXRRdWVyeURhdGE8VD4ocXVlcnlLZXkpO1xuXG4gICAgaWYgKGNhY2hlZERhdGEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VsZWN0KGNhY2hlZERhdGEpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VDYWNoZVV0aWxpdHkoKTogQ2FjaGVVdGlsaXR5IHtcbiAgY29uc3QgcXVlcnlDbGllbnQgPSB1c2VRdWVyeUNsaWVudCgpO1xuXG4gIHJldHVybiB1c2VNZW1vKCgpID0+IG5ldyBDYWNoZVV0aWxpdHkocXVlcnlDbGllbnQpLCBbcXVlcnlDbGllbnRdKTtcbn1cbiIsICJpbXBvcnQgdHlwZSB7XG4gIENvbnRyb2wsXG4gIERlZXBQYXJ0aWFsU2tpcEFycmF5S2V5LFxuICBGaWVsZFZhbHVlcyxcbiAgUGF0aCxcbiAgUGF0aFZhbHVlLFxufSBmcm9tICdyZWFjdC1ob29rLWZvcm0nO1xuaW1wb3J0IHsgdXNlV2F0Y2ggfSBmcm9tICdyZWFjdC1ob29rLWZvcm0nO1xuXG4vKipcbiAqIENvcmUgd2F0Y2ggZnVuY3Rpb25zIGZvciBSZWFjdCBIb29rIEZvcm1cbiAqIFRoZXNlIGFyZSB0aGUgcHJpbWFyeSBidWlsZGluZyBibG9ja3MgZm9yIGZvcm0gd2F0Y2hpbmdcbiAqL1xuXG4vKipcbiAqIFV0aWxpdHkgdHlwZSB0byBlbnN1cmUgYXJyYXkgZWxlbWVudHMgYXJlIGFsbCBQYXRoPFQ+XG4gKi9cbmV4cG9ydCB0eXBlIFBhdGhBcnJheTxUIGV4dGVuZHMgRmllbGRWYWx1ZXM+ID0gUmVhZG9ubHlBcnJheTxQYXRoPFQ+PjtcblxuLyoqXG4gKiBIb29rIHRvIHdhdGNoIGVudGlyZSBmb3JtIC0gcmV0dXJucyBhbGwgZm9ybSB2YWx1ZXNcbiAqL1xuZXhwb3J0IGNvbnN0IHVzZVdhdGNoRm9ybSA9IDxURmllbGRWYWx1ZXMgZXh0ZW5kcyBGaWVsZFZhbHVlcz4oXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPlxuKTogRGVlcFBhcnRpYWxTa2lwQXJyYXlLZXk8VEZpZWxkVmFsdWVzPiA9PiB1c2VXYXRjaCh7IGNvbnRyb2wgfSk7XG5cbi8qKlxuICogSG9vayB0byB3YXRjaCBzaW5nbGUgZmllbGQgYnkgcGF0aCAtIHN1cHBvcnRzIGFueSBuZXN0ZWQgcGF0aFxuICovXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hGaWVsZCA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxuPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxuICBuYW1lOiBUTmFtZVxuKTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWU+ID0+IHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZSB9KTtcblxuLyoqXG4gKiBIb29rIHRvIHdhdGNoIG11bHRpcGxlIGZpZWxkcyBieSBwYXRocyAtIHJldHVybnMgYXJyYXkgb2YgdmFsdWVzXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VXYXRjaEZpZWxkcyA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFROYW1lcyBleHRlbmRzIFJlYWRvbmx5QXJyYXk8UGF0aDxURmllbGRWYWx1ZXM+Pixcbj4oXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcbiAgbmFtZXM6IFROYW1lc1xuKTogQXJyYXk8UGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWVzW251bWJlcl0+PiA9PlxuICB1c2VXYXRjaCh7IGNvbnRyb2wsIG5hbWU6IG5hbWVzIH0pIGFzIEFycmF5PFxuICAgIFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIFROYW1lc1tudW1iZXJdPlxuICA+O1xuIiwgImltcG9ydCB7IHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlU3RhdGUgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgdHlwZSB7IENvbnRyb2wsIEZpZWxkVmFsdWVzLCBQYXRoLCBQYXRoVmFsdWUgfSBmcm9tICdyZWFjdC1ob29rLWZvcm0nO1xuaW1wb3J0IHsgdXNlV2F0Y2ggfSBmcm9tICdyZWFjdC1ob29rLWZvcm0nO1xuXG4vKipcbiAqIFV0aWxpdHkgd2F0Y2ggZnVuY3Rpb25zIGZvciBSZWFjdCBIb29rIEZvcm1cbiAqIEVuaGFuY2VkIGZ1bmN0aW9uYWxpdHkgZm9yIHNwZWNpZmljIHVzZSBjYXNlc1xuICovXG5cbi8qKlxuICogV2F0Y2ggZmllbGQgd2l0aCB0cmFuc2Zvcm1hdGlvbi9zZWxlY3RvclxuICovXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hUcmFuc2Zvcm0gPSA8XG4gIFRGaWVsZFZhbHVlcyBleHRlbmRzIEZpZWxkVmFsdWVzLFxuICBUTmFtZSBleHRlbmRzIFBhdGg8VEZpZWxkVmFsdWVzPixcbiAgVE91dHB1dCxcbj4oXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcbiAgbmFtZTogVE5hbWUsXG4gIHRyYW5zZm9ybTogKHZhbHVlOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4pID0+IFRPdXRwdXRcbik6IFRPdXRwdXQgPT4ge1xuICBjb25zdCB2YWx1ZSA9IHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZSB9KTtcblxuICByZXR1cm4gdXNlTWVtbygoKSA9PiB0cmFuc2Zvcm0odmFsdWUpLCBbdmFsdWUsIHRyYW5zZm9ybV0pO1xufTtcblxuLyoqXG4gKiBXYXRjaCBmaWVsZCB3aXRoIGRlZmF1bHQgZmFsbGJhY2sgdmFsdWVcbiAqL1xuZXhwb3J0IGNvbnN0IHVzZVdhdGNoRGVmYXVsdCA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxuPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxuICBuYW1lOiBUTmFtZSxcbiAgZGVmYXVsdFZhbHVlOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT5cbik6IFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIFROYW1lPiA9PiB7XG4gIGNvbnN0IHZhbHVlID0gdXNlV2F0Y2goeyBjb250cm9sLCBuYW1lIH0pO1xuXG4gIHJldHVybiB2YWx1ZSA/PyBkZWZhdWx0VmFsdWU7XG59O1xuXG4vKipcbiAqIFdhdGNoIGZpZWxkIGFzIGJvb2xlYW4gd2l0aCBndWFyYW50ZWVkIGJvb2xlYW4gcmV0dXJuXG4gKi9cbmV4cG9ydCBjb25zdCB1c2VXYXRjaEJvb2xlYW4gPSA8XG4gIFRGaWVsZFZhbHVlcyBleHRlbmRzIEZpZWxkVmFsdWVzLFxuICBUTmFtZSBleHRlbmRzIFBhdGg8VEZpZWxkVmFsdWVzPixcbj4oXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcbiAgbmFtZTogVE5hbWUsXG4gIGRlZmF1bHRWYWx1ZSA9IGZhbHNlXG4pOiBib29sZWFuID0+IHtcbiAgY29uc3QgdmFsdWUgPSB1c2VXYXRjaCh7IGNvbnRyb2wsIG5hbWUgfSk7XG5cbiAgcmV0dXJuIEJvb2xlYW4odmFsdWUgPz8gZGVmYXVsdFZhbHVlKTtcbn07XG5cbi8qKlxuICogV2F0Y2ggbXVsdGlwbGUgZmllbGRzIGFuZCByZXR1cm4gYW4gb2JqZWN0IHdpdGggZmllbGQgcGF0aHMgYXMga2V5c1xuICovXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hCYXRjaCA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFRGaWVsZHMgZXh0ZW5kcyBSZWFkb25seUFycmF5PFBhdGg8VEZpZWxkVmFsdWVzPj4sXG4+KFxuICBjb250cm9sOiBDb250cm9sPFRGaWVsZFZhbHVlcz4sXG4gIGZpZWxkczogVEZpZWxkc1xuKTogeyBbSyBpbiBURmllbGRzW251bWJlcl1dOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBLPiB9ID0+IHtcbiAgY29uc3QgdmFsdWVzID0gdXNlV2F0Y2goeyBjb250cm9sLCBuYW1lOiBmaWVsZHMgfSk7XG5cbiAgcmV0dXJuIHVzZU1lbW8oKCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHt9IGFzIHsgW0sgaW4gVEZpZWxkc1tudW1iZXJdXTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgSz4gfTtcblxuICAgIGZpZWxkcy5mb3JFYWNoKChmaWVsZCwgaW5kZXgpID0+IHtcbiAgICAgIHJlc3VsdFtmaWVsZCBhcyBURmllbGRzW251bWJlcl1dID0gdmFsdWVzW2luZGV4XTtcbiAgICB9KTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sIFt2YWx1ZXMsIGZpZWxkc10pO1xufTtcblxuLyoqXG4gKiBXYXRjaCBmaWVsZCBjb25kaXRpb25hbGx5IGJhc2VkIG9uIGJvb2xlYW4gZmxhZ1xuICovXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hDb25kaXRpb25hbCA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxuPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxuICBuYW1lOiBUTmFtZSxcbiAgc2hvdWxkV2F0Y2g6IGJvb2xlYW4sXG4gIGZhbGxiYWNrPzogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWU+XG4pOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4gfCB1bmRlZmluZWQgPT4ge1xuICBjb25zdCBhY3RpdmVWYWx1ZSA9IHVzZVdhdGNoKHtcbiAgICBjb250cm9sLFxuICAgIG5hbWUsXG4gICAgZGlzYWJsZWQ6ICFzaG91bGRXYXRjaCxcbiAgfSk7XG5cbiAgcmV0dXJuIHNob3VsZFdhdGNoID8gYWN0aXZlVmFsdWUgOiBmYWxsYmFjaztcbn07XG5cbi8qKlxuICogV2F0Y2ggZmllbGQgd2l0aCBkZWJvdW5jZWQgdXBkYXRlc1xuICovXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hEZWJvdW5jZWQgPSA8XG4gIFRGaWVsZFZhbHVlcyBleHRlbmRzIEZpZWxkVmFsdWVzLFxuICBUTmFtZSBleHRlbmRzIFBhdGg8VEZpZWxkVmFsdWVzPixcbj4oXG4gIGNvbnRyb2w6IENvbnRyb2w8VEZpZWxkVmFsdWVzPixcbiAgbmFtZTogVE5hbWUsXG4gIGRlbGF5ID0gMzAwXG4pOiBQYXRoVmFsdWU8VEZpZWxkVmFsdWVzLCBUTmFtZT4gPT4ge1xuICBjb25zdCB2YWx1ZSA9IHVzZVdhdGNoKHsgY29udHJvbCwgbmFtZSB9KTtcbiAgY29uc3QgW2RlYm91bmNlZFZhbHVlLCBzZXREZWJvdW5jZWRWYWx1ZV0gPVxuICAgIHVzZVN0YXRlPFBhdGhWYWx1ZTxURmllbGRWYWx1ZXMsIFROYW1lPj4odmFsdWUpO1xuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgY29uc3QgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHNldERlYm91bmNlZFZhbHVlKHZhbHVlKTtcbiAgICB9LCBkZWxheSk7XG5cbiAgICByZXR1cm4gKCkgPT4gY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgfSwgW3ZhbHVlLCBkZWxheV0pO1xuXG4gIHJldHVybiBkZWJvdW5jZWRWYWx1ZTtcbn07XG5cbi8qKlxuICogV2F0Y2ggZmllbGQgd2l0aCBtZW1vaXplZCBzZWxlY3RvciBmdW5jdGlvblxuICovXG5leHBvcnQgY29uc3QgdXNlV2F0Y2hTZWxlY3RvciA9IDxcbiAgVEZpZWxkVmFsdWVzIGV4dGVuZHMgRmllbGRWYWx1ZXMsXG4gIFROYW1lIGV4dGVuZHMgUGF0aDxURmllbGRWYWx1ZXM+LFxuICBUT3V0cHV0LFxuPihcbiAgY29udHJvbDogQ29udHJvbDxURmllbGRWYWx1ZXM+LFxuICBuYW1lOiBUTmFtZSxcbiAgc2VsZWN0b3I6ICh2YWx1ZTogUGF0aFZhbHVlPFRGaWVsZFZhbHVlcywgVE5hbWU+KSA9PiBUT3V0cHV0LFxuICBkZXBzOiBSZWFjdC5EZXBlbmRlbmN5TGlzdCA9IFtdXG4pOiBUT3V0cHV0ID0+IHtcbiAgY29uc3QgdmFsdWUgPSB1c2VXYXRjaCh7IGNvbnRyb2wsIG5hbWUgfSk7XG5cbiAgcmV0dXJuIHVzZU1lbW8oXG4gICAgKCkgPT4gc2VsZWN0b3IodmFsdWUpLFxuICAgIFt2YWx1ZSwgc2VsZWN0b3IsIC4uLmRlcHNdIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgcmVhY3QtaG9va3MvZXhoYXVzdGl2ZS1kZXBzXG4gICk7XG59O1xuIiwgIi8qKlxuICogRW5oYW5jZWQgVHlwZVNjcmlwdCB1dGlsaXRpZXMgZm9yIFJlYWN0IEhvb2sgRm9ybSdzIHVzZVdhdGNoXG4gKlxuICogVGhpcyBtb2R1bGUgcHJvdmlkZXMgYSBjb21wcmVoZW5zaXZlIHNldCBvZiB0eXBlLXNhZmUgd2F0Y2ggZnVuY3Rpb25zXG4gKiB3aXRoIGJldHRlciBlcmdvbm9taWNzIGFuZCBhZGRpdGlvbmFsIGZ1bmN0aW9uYWxpdHkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IHVzZVdhdGNoRmllbGQsIHVzZVdhdGNoQm9vbGVhbiwgdHlwZWRXYXRjaCB9IGZyb20gJ3NyYy91dGlscy93YXRjaCc7XG4gKlxuICogLy8gRGlyZWN0IHVzYWdlIChpbnNpZGUgUmVhY3QgY29tcG9uZW50cylcbiAqIGNvbnN0IGVtYWlsID0gdXNlV2F0Y2hGaWVsZChjb250cm9sLCAndXNlci5lbWFpbCcpO1xuICogY29uc3QgaXNBZG1pbiA9IHVzZVdhdGNoQm9vbGVhbihjb250cm9sLCAndXNlci5pc0FkbWluJyk7XG4gKlxuICogLy8gT2JqZWN0LWJhc2VkIHVzYWdlIChpbnNpZGUgUmVhY3QgY29tcG9uZW50cylcbiAqIGNvbnN0IGVtYWlsID0gdHlwZWRXYXRjaC5maWVsZChjb250cm9sLCAndXNlci5lbWFpbCcpO1xuICogY29uc3QgaXNBZG1pbiA9IHR5cGVkV2F0Y2guYm9vbGVhbihjb250cm9sLCAndXNlci5pc0FkbWluJyk7XG4gKiBgYGBcbiAqL1xuXG4vLyBDb3JlIGZ1bmN0aW9uc1xuZXhwb3J0IHsgdXNlV2F0Y2hGaWVsZCwgdXNlV2F0Y2hGaWVsZHMsIHVzZVdhdGNoRm9ybSB9IGZyb20gJy4vY29yZSc7XG5cbi8vIFV0aWxpdHkgZnVuY3Rpb25zXG5leHBvcnQge1xuICB1c2VXYXRjaEJhdGNoLFxuICB1c2VXYXRjaEJvb2xlYW4sXG4gIHVzZVdhdGNoQ29uZGl0aW9uYWwsXG4gIHVzZVdhdGNoRGVib3VuY2VkLFxuICB1c2VXYXRjaERlZmF1bHQsXG4gIHVzZVdhdGNoU2VsZWN0b3IsXG4gIHVzZVdhdGNoVHJhbnNmb3JtLFxufSBmcm9tICcuL3V0aWxpdGllcyc7XG5cbmV4cG9ydCB0eXBlIHsgUGF0aEFycmF5IH0gZnJvbSAnLi9jb3JlJztcblxuLy8gSW1wb3J0IGFsbCBmdW5jdGlvbnMgZm9yIGRlZmF1bHQgZXhwb3J0XG5pbXBvcnQgeyB1c2VXYXRjaEZpZWxkLCB1c2VXYXRjaEZpZWxkcywgdXNlV2F0Y2hGb3JtIH0gZnJvbSAnLi9jb3JlJztcbmltcG9ydCB7XG4gIHVzZVdhdGNoQmF0Y2gsXG4gIHVzZVdhdGNoQm9vbGVhbixcbiAgdXNlV2F0Y2hDb25kaXRpb25hbCxcbiAgdXNlV2F0Y2hEZWJvdW5jZWQsXG4gIHVzZVdhdGNoRGVmYXVsdCxcbiAgdXNlV2F0Y2hTZWxlY3RvcixcbiAgdXNlV2F0Y2hUcmFuc2Zvcm0sXG59IGZyb20gJy4vdXRpbGl0aWVzJztcblxuLyoqXG4gKiBPcmdhbml6ZWQgdXRpbGl0aWVzIGJ5IHVzZSBjYXNlXG4gKiBQcm92aWRlcyBhIGNvbnZlbmllbnQgb2JqZWN0LWJhc2VkIEFQSSBmb3IgYWxsIHdhdGNoIGZ1bmN0aW9uc1xuICovXG5leHBvcnQgY29uc3QgdHlwZWRXYXRjaCA9IHtcbiAgLy8gPT09IENPUkUgRlVOQ1RJT05TID09PVxuICAvKiogV2F0Y2ggZW50aXJlIGZvcm0gKi9cbiAgZm9ybTogdXNlV2F0Y2hGb3JtLFxuICAvKiogV2F0Y2ggc2luZ2xlIGZpZWxkICovXG4gIGZpZWxkOiB1c2VXYXRjaEZpZWxkLFxuICAvKiogV2F0Y2ggbXVsdGlwbGUgZmllbGRzICovXG4gIGZpZWxkczogdXNlV2F0Y2hGaWVsZHMsXG5cbiAgLy8gPT09IFVUSUxJVFkgRlVOQ1RJT05TID09PVxuICAvKiogV2F0Y2ggd2l0aCB0cmFuc2Zvcm1hdGlvbiAqL1xuICB0cmFuc2Zvcm06IHVzZVdhdGNoVHJhbnNmb3JtLFxuICAvKiogV2F0Y2ggd2l0aCBkZWZhdWx0IHZhbHVlICovXG4gIHdpdGhEZWZhdWx0OiB1c2VXYXRjaERlZmF1bHQsXG4gIC8qKiBXYXRjaCBhcyBib29sZWFuICovXG4gIGJvb2xlYW46IHVzZVdhdGNoQm9vbGVhbixcbiAgLyoqIFdhdGNoIG11bHRpcGxlIHdpdGggY3VzdG9tIGtleXMgKi9cbiAgYmF0Y2g6IHVzZVdhdGNoQmF0Y2gsXG4gIC8qKiBXYXRjaCBjb25kaXRpb25hbGx5ICovXG4gIGNvbmRpdGlvbmFsOiB1c2VXYXRjaENvbmRpdGlvbmFsLFxuICAvKiogV2F0Y2ggd2l0aCBkZWJvdW5jaW5nICovXG4gIGRlYm91bmNlZDogdXNlV2F0Y2hEZWJvdW5jZWQsXG4gIC8qKiBXYXRjaCB3aXRoIHNlbGVjdG9yICovXG4gIHNlbGVjdG9yOiB1c2VXYXRjaFNlbGVjdG9yLFxufSBhcyBjb25zdDtcbiIsICJleHBvcnQgY29uc3QgY2FsY3VsYXRlRmlsdGVyQ291bnQgPSAobW9kZWw6IG9iamVjdCk6IG51bWJlciA9PlxuICBPYmplY3QudmFsdWVzKG1vZGVsKS5maWx0ZXIoXG4gICAgdiA9PiB2ICE9PSBudWxsICYmIHYgIT09IHVuZGVmaW5lZCAmJiBTdHJpbmcodikudHJpbSgpICE9PSAnJ1xuICApLmxlbmd0aDtcbiIsICJpbXBvcnQgdHlwZSB7IERheWpzLCBPcFVuaXRUeXBlIH0gZnJvbSAnZGF5anMnO1xuaW1wb3J0IGRheWpzIGZyb20gJ2RheWpzJztcbmltcG9ydCBkdXJhdGlvbiBmcm9tICdkYXlqcy9wbHVnaW4vZHVyYXRpb24nO1xuaW1wb3J0IHJlbGF0aXZlVGltZSBmcm9tICdkYXlqcy9wbHVnaW4vcmVsYXRpdmVUaW1lJztcblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEBEb2NzXG4gKiBodHRwczovL2RheS5qcy5vcmcvZG9jcy9lbi9kaXNwbGF5L2Zvcm1hdFxuICovXG5cbi8qKlxuICogRGVmYXVsdCB0aW1lem9uZXNcbiAqIGh0dHBzOi8vZGF5LmpzLm9yZy9kb2NzL2VuL3RpbWV6b25lL3NldC1kZWZhdWx0LXRpbWV6b25lI2RvY3NOYXZcbiAqXG4gKi9cblxuLyoqXG4gKiBVVENcbiAqIGh0dHBzOi8vZGF5LmpzLm9yZy9kb2NzL2VuL3BsdWdpbi91dGNcbiAqIEBpbnN0YWxsXG4gKiBpbXBvcnQgdXRjIGZyb20gJ2RheWpzL3BsdWdpbi91dGMnO1xuICogZGF5anMuZXh0ZW5kKHV0Yyk7XG4gKiBAdXNhZ2VcbiAqIGRheWpzKCkudXRjKCkuZm9ybWF0KClcbiAqXG4gKi9cblxuZGF5anMuZXh0ZW5kKGR1cmF0aW9uKTtcbmRheWpzLmV4dGVuZChyZWxhdGl2ZVRpbWUpO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCB0eXBlIERhdGVQaWNrZXJGb3JtYXQgPVxuICB8IERheWpzXG4gIHwgRGF0ZVxuICB8IHN0cmluZ1xuICB8IG51bWJlclxuICB8IG51bGxcbiAgfCB1bmRlZmluZWQ7XG5cbmV4cG9ydCBjb25zdCBmb3JtYXRQYXR0ZXJucyA9IHtcbiAgZGF0ZVRpbWU6ICdERCBNTU0gWVlZWSBoOm1tIEEnLCAvLyAxNyBBcHIgMjAyMiAxMjowMCBhbVxuICBkYXRlOiAnREQgTU1NIFlZWVknLCAvLyAxNyBBcHIgMjAyMlxuICBtb250aF95ZWFyX3Nob3J0X2Zvcm1hdDogJ01NTSBZWVlZJyxcbiAgbW9udGhfeWVhcl9mdWxsX2Zvcm1hdDogJ01NTU0gWVlZWScsXG4gIHllYXI6ICdZWVlZJyxcbiAgdGltZTogJ2g6bW0gYScsIC8vIDEyOjAwIGFtXG4gIHNwbGl0OiB7XG4gICAgZGF0ZVRpbWU6ICdERC9NTS9ZWVlZIGg6bW0gQScsIC8vIDE3LzA0LzIwMjIgMTI6MDAgYW1cbiAgICBkYXRlOiAnREQvTU0vWVlZWScsIC8vIDE3LzA0LzIwMjJcbiAgfSxcbiAgcGFyYW1DYXNlOiB7XG4gICAgZGF0ZVRpbWU6ICdERC1NTS1ZWVlZIGg6bW0gQScsIC8vIDE3LTA0LTIwMjIgMTI6MDAgYW1cbiAgICBkYXRlOiAnREQtTU0tWVlZWScsIC8vIDE3LTA0LTIwMjJcbiAgICBkYXRlUmV2ZXJzZTogJ1lZWVktTU0tREQnLCAvLyAyMDIyLTA0LTE3IGZvciBjb21wYXJlIGRhdGVcbiAgICBNb250aFllYXI6ICdNTU0tWVlZWScsXG4gIH0sXG59O1xuXG5jb25zdCBpc1ZhbGlkRGF0ZSA9IChkYXRlOiBEYXRlUGlja2VyRm9ybWF0KSA9PlxuICBkYXRlICE9PSBudWxsICYmIGRhdGUgIT09IHVuZGVmaW5lZCAmJiBkYXlqcyhkYXRlKS5pc1ZhbGlkKCk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGZ1bmN0aW9uIHRvZGF5KHRlbXBsYXRlPzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGRheWpzKG5ldyBEYXRlKCkpLnN0YXJ0T2YoJ2RheScpLmZvcm1hdCh0ZW1wbGF0ZSk7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBAb3V0cHV0IDE3IEFwciAyMDIyIDEyOjAwIGFtXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmRGF0ZVRpbWUoZGF0ZTogRGF0ZVBpY2tlckZvcm1hdCwgdGVtcGxhdGU/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIWlzVmFsaWREYXRlKGRhdGUpKSB7XG4gICAgcmV0dXJuICdJbnZhbGlkIGRhdGUnO1xuICB9XG5cbiAgcmV0dXJuIGRheWpzKGRhdGUpLmZvcm1hdCh0ZW1wbGF0ZSA/PyBmb3JtYXRQYXR0ZXJucy5kYXRlVGltZSk7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBAb3V0cHV0IDE3IEFwciAyMDIyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmRGF0ZShkYXRlOiBEYXRlUGlja2VyRm9ybWF0LCB0ZW1wbGF0ZT86IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmICghaXNWYWxpZERhdGUoZGF0ZSkpIHtcbiAgICByZXR1cm4gJ0ludmFsaWQgZGF0ZSc7XG4gIH1cblxuICByZXR1cm4gZGF5anMoZGF0ZSkuZm9ybWF0KHRlbXBsYXRlID8/IGZvcm1hdFBhdHRlcm5zLmRhdGUpO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQG91dHB1dCAxMjowMCBhbVxuICovXG5leHBvcnQgZnVuY3Rpb24gZlRpbWUoZGF0ZTogRGF0ZVBpY2tlckZvcm1hdCwgdGVtcGxhdGU/OiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAoIWlzVmFsaWREYXRlKGRhdGUpKSB7XG4gICAgcmV0dXJuICdJbnZhbGlkIGRhdGUnO1xuICB9XG5cbiAgcmV0dXJuIGRheWpzKGRhdGUpLmZvcm1hdCh0ZW1wbGF0ZSA/PyBmb3JtYXRQYXR0ZXJucy50aW1lKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEBvdXRwdXQgMTcxMzI1MDEwMFxuICovXG5leHBvcnQgZnVuY3Rpb24gZlRpbWVzdGFtcChkYXRlOiBEYXRlUGlja2VyRm9ybWF0KTogbnVtYmVyIHwgJ0ludmFsaWQgZGF0ZScge1xuICBpZiAoIWlzVmFsaWREYXRlKGRhdGUpKSB7XG4gICAgcmV0dXJuICdJbnZhbGlkIGRhdGUnO1xuICB9XG5cbiAgcmV0dXJuIGRheWpzKGRhdGUpLnZhbHVlT2YoKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEBvdXRwdXQgYSBmZXcgc2Vjb25kcywgMiB5ZWFyc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZlRvTm93KGRhdGU6IERhdGVQaWNrZXJGb3JtYXQpOiBzdHJpbmcge1xuICBpZiAoIWlzVmFsaWREYXRlKGRhdGUpKSB7XG4gICAgcmV0dXJuICdJbnZhbGlkIGRhdGUnO1xuICB9XG5cbiAgcmV0dXJuIGRheWpzKGRhdGUpLnRvTm93KHRydWUpO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQG91dHB1dCBib29sZWFuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmSXNCZXR3ZWVuKFxuICBpbnB1dERhdGU6IERhdGVQaWNrZXJGb3JtYXQsXG4gIHN0YXJ0RGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcbiAgZW5kRGF0ZTogRGF0ZVBpY2tlckZvcm1hdFxuKTogYm9vbGVhbiB7XG4gIGlmIChcbiAgICAhaXNWYWxpZERhdGUoaW5wdXREYXRlKSB8fFxuICAgICFpc1ZhbGlkRGF0ZShzdGFydERhdGUpIHx8XG4gICAgIWlzVmFsaWREYXRlKGVuZERhdGUpXG4gICkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IGZvcm1hdHRlZElucHV0RGF0ZSA9IGZUaW1lc3RhbXAoaW5wdXREYXRlKTtcbiAgY29uc3QgZm9ybWF0dGVkU3RhcnREYXRlID0gZlRpbWVzdGFtcChzdGFydERhdGUpO1xuICBjb25zdCBmb3JtYXR0ZWRFbmREYXRlID0gZlRpbWVzdGFtcChlbmREYXRlKTtcblxuICBpZiAoXG4gICAgZm9ybWF0dGVkSW5wdXREYXRlID09PSAnSW52YWxpZCBkYXRlJyB8fFxuICAgIGZvcm1hdHRlZFN0YXJ0RGF0ZSA9PT0gJ0ludmFsaWQgZGF0ZScgfHxcbiAgICBmb3JtYXR0ZWRFbmREYXRlID09PSAnSW52YWxpZCBkYXRlJ1xuICApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gKFxuICAgIGZvcm1hdHRlZElucHV0RGF0ZSA+PSBmb3JtYXR0ZWRTdGFydERhdGUgJiZcbiAgICBmb3JtYXR0ZWRJbnB1dERhdGUgPD0gZm9ybWF0dGVkRW5kRGF0ZVxuICApO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQG91dHB1dCBib29sZWFuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmSXNBZnRlcihcbiAgc3RhcnREYXRlOiBEYXRlUGlja2VyRm9ybWF0LFxuICBlbmREYXRlOiBEYXRlUGlja2VyRm9ybWF0XG4pOiBib29sZWFuIHtcbiAgaWYgKCFpc1ZhbGlkRGF0ZShzdGFydERhdGUpIHx8ICFpc1ZhbGlkRGF0ZShlbmREYXRlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiBkYXlqcyhzdGFydERhdGUpLmlzQWZ0ZXIoZW5kRGF0ZSk7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBAb3V0cHV0IGJvb2xlYW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZJc1NhbWUoXG4gIHN0YXJ0RGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcbiAgZW5kRGF0ZTogRGF0ZVBpY2tlckZvcm1hdCxcbiAgdW5pdFRvQ29tcGFyZT86IE9wVW5pdFR5cGVcbik6IGJvb2xlYW4ge1xuICBpZiAoIWlzVmFsaWREYXRlKHN0YXJ0RGF0ZSkgfHwgIWlzVmFsaWREYXRlKGVuZERhdGUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIGRheWpzKHN0YXJ0RGF0ZSkuaXNTYW1lKGVuZERhdGUsIHVuaXRUb0NvbXBhcmUgPz8gJ3llYXInKTtcbn1cblxuLyoqXG4gKiBAb3V0cHV0XG4gKiBTYW1lIGRheTogMjYgQXByIDIwMjRcbiAqIFNhbWUgbW9udGg6IDI1IC0gMjYgQXByIDIwMjRcbiAqIFNhbWUgbW9udGg6IDI1IC0gMjYgQXByIDIwMjRcbiAqIFNhbWUgeWVhcjogMjUgQXByIC0gMjYgTWF5IDIwMjRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZEYXRlUmFuZ2VTaG9ydExhYmVsKFxuICBzdGFydERhdGU6IERhdGVQaWNrZXJGb3JtYXQsXG4gIGVuZERhdGU6IERhdGVQaWNrZXJGb3JtYXQsXG4gIGluaXRpYWw/OiBib29sZWFuXG4pOiBzdHJpbmcge1xuICBpZiAoXG4gICAgIWlzVmFsaWREYXRlKHN0YXJ0RGF0ZSkgfHxcbiAgICAhaXNWYWxpZERhdGUoZW5kRGF0ZSkgfHxcbiAgICBmSXNBZnRlcihzdGFydERhdGUsIGVuZERhdGUpXG4gICkge1xuICAgIHJldHVybiAnSW52YWxpZCBkYXRlJztcbiAgfVxuXG4gIGxldCBsYWJlbCA9IGAke2ZEYXRlKHN0YXJ0RGF0ZSl9IC0gJHtmRGF0ZShlbmREYXRlKX1gO1xuXG4gIGlmIChpbml0aWFsKSB7XG4gICAgcmV0dXJuIGxhYmVsO1xuICB9XG5cbiAgY29uc3QgaXNTYW1lWWVhciA9IGZJc1NhbWUoc3RhcnREYXRlLCBlbmREYXRlLCAneWVhcicpO1xuICBjb25zdCBpc1NhbWVNb250aCA9IGZJc1NhbWUoc3RhcnREYXRlLCBlbmREYXRlLCAnbW9udGgnKTtcbiAgY29uc3QgaXNTYW1lRGF5ID0gZklzU2FtZShzdGFydERhdGUsIGVuZERhdGUsICdkYXknKTtcblxuICBpZiAoaXNTYW1lWWVhciAmJiAhaXNTYW1lTW9udGgpIHtcbiAgICBsYWJlbCA9IGAke2ZEYXRlKHN0YXJ0RGF0ZSwgJ0REIE1NTScpfSAtICR7ZkRhdGUoZW5kRGF0ZSl9YDtcbiAgfSBlbHNlIGlmIChpc1NhbWVZZWFyICYmIGlzU2FtZU1vbnRoICYmICFpc1NhbWVEYXkpIHtcbiAgICBsYWJlbCA9IGAke2ZEYXRlKHN0YXJ0RGF0ZSwgJ0REJyl9IC0gJHtmRGF0ZShlbmREYXRlKX1gO1xuICB9IGVsc2UgaWYgKGlzU2FtZVllYXIgJiYgaXNTYW1lTW9udGggJiYgaXNTYW1lRGF5KSB7XG4gICAgbGFiZWwgPSBgJHtmRGF0ZShlbmREYXRlKX1gO1xuICB9XG5cbiAgcmV0dXJuIGxhYmVsO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQG91dHB1dCAyMDI0LTA1LTI4VDA1OjU1OjMxKzAwOjAwXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRHVyYXRpb25Qcm9wcyB7XG4gIHllYXJzPzogbnVtYmVyO1xuICBtb250aHM/OiBudW1iZXI7XG4gIGRheXM/OiBudW1iZXI7XG4gIGhvdXJzPzogbnVtYmVyO1xuICBtaW51dGVzPzogbnVtYmVyO1xuICBzZWNvbmRzPzogbnVtYmVyO1xuICBtaWxsaXNlY29uZHM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmQWRkKHtcbiAgeWVhcnMgPSAwLFxuICBtb250aHMgPSAwLFxuICBkYXlzID0gMCxcbiAgaG91cnMgPSAwLFxuICBtaW51dGVzID0gMCxcbiAgc2Vjb25kcyA9IDAsXG4gIG1pbGxpc2Vjb25kcyA9IDAsXG59OiBEdXJhdGlvblByb3BzKSB7XG4gIGNvbnN0IHJlc3VsdCA9IGRheWpzKClcbiAgICAuYWRkKFxuICAgICAgZGF5anMuZHVyYXRpb24oe1xuICAgICAgICB5ZWFycyxcbiAgICAgICAgbW9udGhzLFxuICAgICAgICBkYXlzLFxuICAgICAgICBob3VycyxcbiAgICAgICAgbWludXRlcyxcbiAgICAgICAgc2Vjb25kcyxcbiAgICAgICAgbWlsbGlzZWNvbmRzLFxuICAgICAgfSlcbiAgICApXG4gICAgLmZvcm1hdCgpO1xuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogQG91dHB1dCAyMDI0LTA1LTI4VDA1OjU1OjMxKzAwOjAwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmU3ViKHtcbiAgeWVhcnMgPSAwLFxuICBtb250aHMgPSAwLFxuICBkYXlzID0gMCxcbiAgaG91cnMgPSAwLFxuICBtaW51dGVzID0gMCxcbiAgc2Vjb25kcyA9IDAsXG4gIG1pbGxpc2Vjb25kcyA9IDAsXG59OiBEdXJhdGlvblByb3BzKSB7XG4gIGNvbnN0IHJlc3VsdCA9IGRheWpzKClcbiAgICAuc3VidHJhY3QoXG4gICAgICBkYXlqcy5kdXJhdGlvbih7XG4gICAgICAgIHllYXJzLFxuICAgICAgICBtb250aHMsXG4gICAgICAgIGRheXMsXG4gICAgICAgIGhvdXJzLFxuICAgICAgICBtaW51dGVzLFxuICAgICAgICBzZWNvbmRzLFxuICAgICAgICBtaWxsaXNlY29uZHMsXG4gICAgICB9KVxuICAgIClcbiAgICAuZm9ybWF0KCk7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cbiIsICJ0eXBlIEVtcHR5VmFsdWU8VD4gPSBUIGV4dGVuZHMgbnVtYmVyXG4gID8gMFxuICA6IFQgZXh0ZW5kcyBzdHJpbmdcbiAgICA/IG51bGxcbiAgICA6IFQgZXh0ZW5kcyBib29sZWFuXG4gICAgICA/IG51bGxcbiAgICAgIDogVCBleHRlbmRzIERhdGVcbiAgICAgICAgPyBudWxsXG4gICAgICAgIDogVCBleHRlbmRzIG9iamVjdFxuICAgICAgICAgID8gbnVsbFxuICAgICAgICAgIDogbnVsbDtcblxudHlwZSBFbXB0eU9iamVjdDxUIGV4dGVuZHMgb2JqZWN0PiA9IHtcbiAgW0sgaW4ga2V5b2YgVF06IEVtcHR5VmFsdWU8VFtLXT47XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RW1wdHlPYmplY3Q8VCBleHRlbmRzIG9iamVjdD4oXG4gIGRhdGE6IFQsXG4gIGRlZmF1bHRWYWx1ZXM6IFBhcnRpYWw8VD4gPSB7fVxuKTogRW1wdHlPYmplY3Q8VD4gJiBQYXJ0aWFsPFQ+IHtcbiAgY29uc3Qgb2JqID0ge30gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG5cbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMoZGF0YSkgYXMgQXJyYXk8a2V5b2YgVD4pIHtcbiAgICBjb25zdCB2YWx1ZSA9IGRhdGFba2V5XTtcbiAgICBjb25zdCB0eXBlID0gdHlwZW9mIHZhbHVlO1xuXG4gICAgaWYgKHR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICBvYmpba2V5IGFzIHN0cmluZ10gPSAwO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycgfHwgdHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICBvYmpba2V5IGFzIHN0cmluZ10gPSBudWxsO1xuICAgIH0gZWxzZSBpZiAodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICBvYmpba2V5IGFzIHN0cmluZ10gPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmpba2V5IGFzIHN0cmluZ10gPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7IC4uLm9iaiwgLi4uZGVmYXVsdFZhbHVlcyB9IGFzIEVtcHR5T2JqZWN0PFQ+ICYgUGFydGlhbDxUPjtcbn1cbiIsICJpbXBvcnQgeyB1c2VSZWYsIHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XG5cbi8qKlxuICogSG9vayB0byBtYWludGFpbiBzdGFibGUgcm93IGNvdW50IGZvciBkYXRhIGdyaWRzIGR1cmluZyBsb2FkaW5nIHN0YXRlcy5cbiAqIFByZXZlbnRzIHBhZ2luYXRpb24ganVtcGluZyBieSBwcmVzZXJ2aW5nIHRoZSBsYXN0IGtub3duIHRvdGFsIGNvdW50LlxuICpcbiAqIEBwYXJhbSBjdXJyZW50VG90YWwgLSBDdXJyZW50IHRvdGFsIGZyb20gQVBJIHJlc3BvbnNlXG4gKiBAcmV0dXJucyBTdGFibGUgcm93IGNvdW50IHRoYXQgcGVyc2lzdHMgZHVyaW5nIGxvYWRpbmdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZVN0YWJsZVJvd0NvdW50KGN1cnJlbnRUb3RhbDogbnVtYmVyIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcbiAgY29uc3Qgcm93Q291bnRSZWYgPSB1c2VSZWYoY3VycmVudFRvdGFsIHx8IDApO1xuXG4gIGNvbnN0IHN0YWJsZVJvd0NvdW50ID0gdXNlTWVtbygoKSA9PiB7XG4gICAgaWYgKGN1cnJlbnRUb3RhbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICByb3dDb3VudFJlZi5jdXJyZW50ID0gY3VycmVudFRvdGFsO1xuICAgIH1cblxuICAgIHJldHVybiByb3dDb3VudFJlZi5jdXJyZW50O1xuICB9LCBbY3VycmVudFRvdGFsXSk7XG5cbiAgcmV0dXJuIHN0YWJsZVJvd0NvdW50O1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjtBQXdCQSxTQUFTLGVBQXVCO0FBQzlCLE1BQUksT0FBTyxXQUFXLGVBQWUsT0FBTyxZQUFZO0FBQ3RELFdBQU8sT0FBTyxXQUFXO0FBQUEsRUFDM0I7QUFHQSxTQUFPLHVDQUF1QyxRQUFRLFNBQVMsT0FBSztBQUNsRSxVQUFNLElBQUssS0FBSyxPQUFPLElBQUksS0FBTTtBQUNqQyxVQUFNLElBQUksTUFBTSxNQUFNLElBQUssSUFBSSxJQUFPO0FBRXRDLFdBQU8sRUFBRSxTQUFTLEVBQUU7QUFBQSxFQUN0QixDQUFDO0FBQ0g7QUE0Q08sU0FBUyxzQkFBc0IsUUFBeUI7QUFDN0QsUUFBTSxPQUFPLGFBQWE7QUFFMUIsU0FBTyxTQUFTLEdBQUcsTUFBTSxJQUFJLElBQUksS0FBSztBQUN4Qzs7O0FDakVPLElBQU0sa0JBQU4sTUFBc0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFxQjNCLGFBQWEsUUFBd0I7QUFDbkMsUUFBSSxVQUFVLE9BQU8sU0FBUyxLQUFLO0FBQ2pDLGFBQU8sV0FBVyxNQUFNLHFC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SUFDdkIsT0FBTztBQUNMLFVBQUksR0FBYSxJQUFJO0FBQUEsSUFDdkI7QUFBQSxFQUNGO0FBRUEsU0FBTyxFQUFFLEdBQUcsS0FBSyxHQUFHLGNBQWM7QUFDcEM7OztBQ3RDQSxTQUFTLFFBQVEsV0FBQUcsZ0JBQWU7QUFTekIsU0FBUyxrQkFBa0IsY0FBMEM7QUFDMUUsUUFBTSxjQUFjLE9BQU8sZ0JBQWdCLENBQUM7QUFFNUMsUUFBTSxpQkFBaUJBLFNBQVEsTUFBTTtBQUNuQyxRQUFJLGlCQUFpQixRQUFXO0FBQzlCLGtCQUFZLFVBQVU7QUFBQSxJQUN4QjtBQUVBLFdBQU8sWUFBWTtBQUFBLEVBQ3JCLEdBQUcsQ0FBQyxZQUFZLENBQUM7QUFFakIsU0FBTztBQUNUOyIsCiAgIm5hbWVzIjogWyJjb25maWciLCAianN4IiwgIkJ1dHRvbiIsICJqc3giLCAianN4IiwgImpzeCIsICJqc3giLCAibWVtbyIsICJqc3giLCAibWVtbyIsICJCb3giLCAiQ2FyZCIsICJDYXJkQ29udGVudCIsICJUeXBvZ3JhcGh5IiwgIkZyYWdtZW50IiwgImpzeCIsICJqc3hzIiwgIkJveCIsICJUeXBvZ3JhcGh5IiwgImpzeCIsICJHcmlkIiwgIlR5cG9ncmFwaHkiLCAianN4IiwgImpzeHMiLCAiRnJhZ21lbnQiLCAianN4IiwgIkJveCIsICJEaXZpZGVyIiwgIkdyaWQiLCAiVHlwb2dyYXBoeSIsICJtZW1vIiwgInVzZU1lbW8iLCAiRnJhZ21lbnQiLCAianN4IiwgImpzeHMiLCAiQm94IiwgImpzeCIsICJqc3hzIiwgIkxvYWRpbmdCdXR0b24iLCAianN4IiwgInVzZU1lbW8iLCAidXNlTWVtbyIsICJ1c2VDYWxsYmFjayIsICJ1c2VNZW1vIiwgInVzZU1lbW8iLCAidXNlU3RhdGUiLCAidXNlV2F0Y2giLCAidXNlTWVtbyJdCn0K