@gnwebsoft/ui 4.0.13 → 4.0.15

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