@ieeesa-npm/groups 0.15.3 → 0.15.5

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.
@@ -0,0 +1,396 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { HttpParams } from '@angular/common/http';
3
+ import { BehaviorSubject, EMPTY, Subject, takeUntil } from 'rxjs';
4
+ import { map, catchError } from 'rxjs/operators';
5
+ import { saveAs } from 'file-saver';
6
+ import { ExportFormat, PolicyConfirmationDialogComponent, ExportSuccessDialogComponent, } from '@ieeesa-npm/presentation';
7
+ import { AlertType } from '@ieeesa-npm/models';
8
+ import * as screenTexts from '../assets/constants.json';
9
+ import * as i0 from "@angular/core";
10
+ import * as i1 from "@angular/common/http";
11
+ import * as i2 from "@angular/material/dialog";
12
+ import * as i3 from "@ieeesa-npm/utility";
13
+ /**
14
+ * RosterExportService owns the complete group roster export flow:
15
+ * 1. Manages export popover open/close state
16
+ * 2. Opens IEEE Data Access and Use Policy confirmation dialog
17
+ * 3. Calls the backend roster export API (blob response)
18
+ * 4. Triggers file download via File System Access API / file-saver
19
+ * 5. Shows success/error dialogs and toasts
20
+ *
21
+ * The component only needs to:
22
+ * - Subscribe to `isPopoverOpen$` for popover visibility
23
+ * - Call `togglePopover()` on Export button click
24
+ * - Call `onFormatSelected(format, groupId, groupName)` when user picks a format
25
+ *
26
+ * Follows the same pattern as MeetingExportService in the events-and-meetings library.
27
+ * @export
28
+ * @class RosterExportService
29
+ */
30
+ export class RosterExportService {
31
+ constructor(
32
+ // eslint-disable-next-line no-unused-vars
33
+ httpClient,
34
+ // eslint-disable-next-line no-unused-vars
35
+ dialog,
36
+ // eslint-disable-next-line no-unused-vars
37
+ alertService) {
38
+ this.httpClient = httpClient;
39
+ this.dialog = dialog;
40
+ this.alertService = alertService;
41
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
+ this.constants = screenTexts;
43
+ this.destroy$ = new Subject();
44
+ /** Controls popover open/close state */
45
+ this.isPopoverOpenSubject$ = new BehaviorSubject(false);
46
+ this.isPopoverOpen$ = this.isPopoverOpenSubject$.asObservable();
47
+ /** Controls in-progress state for button disable */
48
+ this.isExportInProgressSubject$ = new BehaviorSubject(false);
49
+ this.isExportInProgress$ = this.isExportInProgressSubject$.asObservable();
50
+ /** Format options for the export popover */
51
+ this.exportFormatOptions = [
52
+ {
53
+ label: this.constants?.rosterExport?.formatOptions?.csv?.label ?? 'CSV',
54
+ value: ExportFormat.CSV,
55
+ ariaLabel: this.constants?.rosterExport?.formatOptions?.csv?.ariaLabel ?? 'Export roster as CSV',
56
+ },
57
+ {
58
+ label: this.constants?.rosterExport?.formatOptions?.excel?.label ?? 'Excel',
59
+ value: ExportFormat.EXCEL,
60
+ ariaLabel: this.constants?.rosterExport?.formatOptions?.excel?.ariaLabel ?? 'Export roster as Excel',
61
+ },
62
+ ];
63
+ /** Subtitle labels for the format selection cards */
64
+ this.exportFormatSubtitles = {
65
+ csv: this.constants?.rosterExport?.formatOptions?.csv?.subtitle ?? 'Comma separated file',
66
+ xls: this.constants?.rosterExport?.formatOptions?.excel?.subtitle ?? 'Spreadsheet File',
67
+ };
68
+ /** Popover title */
69
+ this.popoverTitle = this.constants?.rosterExport?.popoverTitle ?? 'Select the file format for roster export.';
70
+ }
71
+ /**
72
+ * Sets the API base URL for roster export calls.
73
+ * @param {string} url - Base URL (e.g., 'https://saappsapidev.ieee.org/v1')
74
+ * @memberof RosterExportService
75
+ */
76
+ setApiBaseUrl(url) {
77
+ this.apiBaseUrl = url;
78
+ }
79
+ /**
80
+ * Toggles the export format popover open/closed.
81
+ * Called by the component on Export button click.
82
+ * @memberof RosterExportService
83
+ */
84
+ togglePopover() {
85
+ this.isPopoverOpenSubject$.next(!this.isPopoverOpenSubject$.getValue());
86
+ }
87
+ /**
88
+ * Closes the export format popover.
89
+ * @memberof RosterExportService
90
+ */
91
+ closePopover() {
92
+ this.isPopoverOpenSubject$.next(false);
93
+ }
94
+ /**
95
+ * Handles format selection from the export popover.
96
+ * Closes popover, opens IEEE Policy dialog, on confirm triggers export.
97
+ * This is the main entry point called by the component after user picks a format.
98
+ * @param {ExportFormat} format - Selected format (CSV or XLS)
99
+ * @param {string} groupId - The group ID to export the roster for
100
+ * @param {string} groupName - The group name for filename generation
101
+ * @memberof RosterExportService
102
+ */
103
+ onFormatSelected(format, groupId, groupName) {
104
+ this.closePopover();
105
+ const dialogData = {
106
+ title: this.constants?.rosterExport?.policyDialog?.title ?? 'IEEE Data Access and Use Policy',
107
+ bodyText: this.constants?.rosterExport?.policyDialog?.bodyText ?? 'The application is governed by IEEE\'s data access and use policy. Data can only be used for its original intended purpose. Click "Confirm" to export the data into a CSV/Excel file or click "Cancel" to cancel the download.',
108
+ policyUrl: this.constants?.rosterExport?.policyDialog?.policyUrl ?? 'https://www.ieee.org/ieee-data-access-and-use-policy.html',
109
+ policyLinkText: this.constants?.rosterExport?.policyDialog?.policyLinkText ?? 'data access and use policy',
110
+ cancelLabel: this.constants?.rosterExport?.policyDialog?.cancelLabel ?? 'Cancel',
111
+ confirmLabel: this.constants?.rosterExport?.policyDialog?.confirmLabel ?? 'Confirm',
112
+ };
113
+ const dialogRef = this.dialog.open(PolicyConfirmationDialogComponent, {
114
+ data: dialogData,
115
+ width: '637px',
116
+ panelClass: ['ieeesa-policy-dialog'],
117
+ });
118
+ dialogRef.afterClosed()
119
+ .pipe(takeUntil(this.destroy$))
120
+ .subscribe((confirmed) => {
121
+ if (confirmed) {
122
+ this.startExport(format, groupId, groupName);
123
+ }
124
+ });
125
+ }
126
+ /**
127
+ * Starts the export after the user confirms the policy dialog.
128
+ *
129
+ * When the File System Access API is available, the native Save picker is opened
130
+ * HERE — synchronously within the confirm handler — while the user activation from
131
+ * the confirm click is still valid. (Opening it later, inside the async HTTP
132
+ * response callback, would exceed the activation window and the browser would
133
+ * reject it with a SecurityError.) The obtained file handle is then passed to the
134
+ * HTTP flow, which writes the downloaded bytes to it once the response arrives, so
135
+ * the success dialog is still shown only AFTER the file is saved.
136
+ *
137
+ * If the user cancels the picker we abort before making the request. If the API is
138
+ * unavailable (Firefox/Safari) we proceed without a handle and fall back to
139
+ * `saveAs()` after the response.
140
+ * @param {ExportFormat} format
141
+ * @param {string} groupId
142
+ * @param {string} groupName
143
+ * @memberof RosterExportService
144
+ */
145
+ startExport(format, groupId, groupName) {
146
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
+ const showSaveFilePicker = window.showSaveFilePicker;
148
+ if (typeof showSaveFilePicker !== 'function') {
149
+ // API unavailable: no handle; executeExport() will use the saveAs() fallback.
150
+ this.executeExport(format, groupId, groupName, null);
151
+ return;
152
+ }
153
+ const mimeType = format === ExportFormat.CSV
154
+ ? 'text/csv'
155
+ : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
156
+ const extension = format === ExportFormat.CSV ? '.csv' : '.xlsx';
157
+ const suggestedName = this.buildFilename(groupName, format);
158
+ // Open the picker now, while the confirm-click activation is still valid.
159
+ showSaveFilePicker({
160
+ suggestedName,
161
+ types: [
162
+ {
163
+ description: format === ExportFormat.CSV ? 'CSV File' : 'Excel File',
164
+ accept: { [mimeType]: [extension] },
165
+ },
166
+ ],
167
+ })
168
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
169
+ .then((handle) => {
170
+ this.executeExport(format, groupId, groupName, handle);
171
+ })
172
+ .catch((error) => {
173
+ // User cancelled the Save dialog — abort silently, no request made.
174
+ if (error instanceof DOMException && error.name === 'AbortError') {
175
+ return;
176
+ }
177
+ // Any other picker error: fall back to the saveAs() flow.
178
+ this.executeExport(format, groupId, groupName, null);
179
+ });
180
+ }
181
+ /**
182
+ * Executes the roster export API call and writes the downloaded file.
183
+ * Endpoint: GET /v1/groups/roster/export/{groupId}?format=csv|xlsx
184
+ * When a pre-obtained file handle is provided (from the picker opened at confirm
185
+ * time) the bytes are written to it; otherwise it falls back to `saveAs()`.
186
+ * The success dialog is shown only after the file has been written.
187
+ * @param {ExportFormat} format - The selected export format
188
+ * @param {string} groupId - The group identifier
189
+ * @param {string} groupName - The group name for filename
190
+ * @param {FileSystemFileHandle | null} fileHandle - Handle from the Save picker, or null
191
+ * @memberof RosterExportService
192
+ */
193
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
194
+ executeExport(format, groupId, groupName, fileHandle) {
195
+ this.isExportInProgressSubject$.next(true);
196
+ // Backend expects 'csv' or 'xlsx'. The ExportFormat.EXCEL enum value is
197
+ // 'xls', so it must be mapped to 'xlsx' here — sending 'xls' is rejected
198
+ // with error code 1079.
199
+ const formatValue = format === ExportFormat.CSV ? 'csv' : 'xlsx';
200
+ const params = new HttpParams().set('format', formatValue);
201
+ const url = `${this.getExportApiUrl()}/groups/roster/export/${groupId}`;
202
+ this.httpClient
203
+ .get(url, {
204
+ params,
205
+ responseType: 'blob',
206
+ observe: 'response',
207
+ })
208
+ .pipe(map((response) => {
209
+ const filename = this.extractFilenameFromResponse(response, format, groupName);
210
+ return { blob: response.body, filename };
211
+ }), catchError(() => {
212
+ this.isExportInProgressSubject$.next(false);
213
+ this.alertService.showMessage({
214
+ status: 'custom',
215
+ message: this.constants?.rosterExport?.messages?.exportFailed ?? 'Failed to export roster. Please try again.',
216
+ alertType: AlertType.ERROR,
217
+ isCloseNeeded: true,
218
+ });
219
+ // Error is fully handled (alert shown). Complete the stream instead of
220
+ // rethrowing, so the next-only subscribe does not report it as an
221
+ // unhandled RxJS error.
222
+ return EMPTY;
223
+ }), takeUntil(this.destroy$))
224
+ .subscribe({
225
+ next: (result) => {
226
+ // Write to the pre-obtained handle (picker opened at confirm time) or fall
227
+ // back to saveAs(). Success dialog only shows after the file is written.
228
+ this.downloadFile(result.blob, result.filename, format, fileHandle)
229
+ .then(({ saved }) => {
230
+ this.isExportInProgressSubject$.next(false);
231
+ if (saved) {
232
+ this.showExportSuccessDialogAfterDownload(result.filename);
233
+ }
234
+ })
235
+ .catch(() => {
236
+ this.isExportInProgressSubject$.next(false);
237
+ this.alertService.showMessage({
238
+ status: 'custom',
239
+ message: this.constants?.rosterExport?.messages?.exportFailed ?? 'Failed to export roster. Please try again.',
240
+ alertType: AlertType.ERROR,
241
+ isCloseNeeded: true,
242
+ });
243
+ });
244
+ },
245
+ });
246
+ }
247
+ /**
248
+ * Shows the export success dialog after a successful file download.
249
+ * @param {string} filename - The downloaded filename
250
+ * @memberof RosterExportService
251
+ */
252
+ showExportSuccessDialogAfterDownload(filename) {
253
+ const successMessage = this.constants?.rosterExport?.successDialog?.message ?? 'The file was downloaded successfully.';
254
+ const closeLabel = this.constants?.rosterExport?.successDialog?.closeButton ?? 'Close';
255
+ const dialogData = {
256
+ message: successMessage,
257
+ filename,
258
+ closeLabel,
259
+ };
260
+ this.dialog.open(ExportSuccessDialogComponent, {
261
+ data: dialogData,
262
+ width: '467px',
263
+ panelClass: ['ieeesa-export-success-dialog-panel'],
264
+ autoFocus: false,
265
+ });
266
+ }
267
+ /**
268
+ * Returns the API base URL for roster export.
269
+ * @return {string}
270
+ * @memberof RosterExportService
271
+ */
272
+ getExportApiUrl() {
273
+ if (!this.apiBaseUrl) {
274
+ throw new Error('RosterExportService apiBaseUrl is not set. Call setApiBaseUrl() before export.');
275
+ }
276
+ // apiBaseUrl already carries the version segment (e.g. '.../v1'), same as every
277
+ // other GroupsService call which is built as `${apiBaseUrl}/groups/...`. So the
278
+ // caller only appends '/groups/roster/export/{groupId}' — the version is NOT
279
+ // repeated here. Strip a trailing slash to avoid a double slash before '/groups'.
280
+ return this.apiBaseUrl.replace(/\/+$/, '');
281
+ }
282
+ /**
283
+ * Extracts filename from Content-Disposition header.
284
+ * Falls back to buildFilename() if header is missing.
285
+ * @param {HttpResponse<Blob>} response
286
+ * @param {ExportFormat} format
287
+ * @param {string} groupName
288
+ * @return {string}
289
+ * @memberof RosterExportService
290
+ */
291
+ extractFilenameFromResponse(response, format, groupName) {
292
+ const contentDisposition = response.headers.get('Content-Disposition');
293
+ if (contentDisposition) {
294
+ const filenameMatch = contentDisposition.match(/filename="?([^"]+)"?/);
295
+ if (filenameMatch && filenameMatch[1]) {
296
+ return filenameMatch[1].replace(/[/\\:*?"<>|]/g, '_').substring(0, 200);
297
+ }
298
+ }
299
+ return this.buildFilename(groupName, format);
300
+ }
301
+ /**
302
+ * Builds a sanitized filename for the roster export.
303
+ * Pattern: {SanitizedGroupName}_Roster.{extension}
304
+ * @param {string} groupName
305
+ * @param {ExportFormat} format
306
+ * @return {string}
307
+ * @memberof RosterExportService
308
+ */
309
+ buildFilename(groupName, format) {
310
+ const sanitized = this.sanitizeGroupName(groupName);
311
+ const extension = format === ExportFormat.CSV ? 'csv' : 'xlsx';
312
+ return `${sanitized}_Roster.${extension}`;
313
+ }
314
+ /**
315
+ * Sanitizes the group name for use in a filename.
316
+ * Replaces non-alphanumeric characters (except hyphen/underscore) with underscore,
317
+ * collapses consecutive underscores, and truncates to 200 chars.
318
+ * @param {string} groupName
319
+ * @return {string}
320
+ * @memberof RosterExportService
321
+ */
322
+ sanitizeGroupName(groupName) {
323
+ if (!groupName) {
324
+ return 'Unnamed_Group';
325
+ }
326
+ const sanitized = groupName
327
+ .replace(/[^a-zA-Z0-9_-]/g, '_')
328
+ .replace(/_+/g, '_')
329
+ .substring(0, 200);
330
+ return sanitized || 'Unnamed_Group';
331
+ }
332
+ /**
333
+ * Writes the downloaded bytes to disk and resolves ONLY when the save has actually
334
+ * completed.
335
+ *
336
+ * The Save picker is opened earlier (at policy-confirm time, while user activation
337
+ * is still valid — see {@link startExport}); this method only writes to the handle
338
+ * it produced. That keeps the "success dialog after save" ordering without hitting
339
+ * the SecurityError that occurs when the picker is opened from this async callback.
340
+ *
341
+ * When no handle is provided (File System Access API unavailable, or the picker
342
+ * errored), we fall back to FileSaver's `saveAs()`, which resolves immediately.
343
+ * @param {Blob} blob - The file contents
344
+ * @param {string} filename - The suggested filename (used by the saveAs fallback)
345
+ * @param {ExportFormat} format - The selected export format (drives MIME type)
346
+ * @param {FileSystemFileHandle | null} fileHandle - Handle from the Save picker, or null
347
+ * @return {Promise<{ saved: boolean }>} Resolves with `saved: true` once written.
348
+ * @memberof RosterExportService
349
+ */
350
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
351
+ async downloadFile(blob, filename, format, fileHandle) {
352
+ const mimeType = format === ExportFormat.CSV
353
+ ? 'text/csv'
354
+ : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
355
+ const typedBlob = new Blob([blob], { type: mimeType });
356
+ // No handle (API unavailable or picker errored) → standard download.
357
+ if (!fileHandle) {
358
+ saveAs(typedBlob, filename);
359
+ return { saved: true };
360
+ }
361
+ // Write to the location the user already chose at confirm time.
362
+ const writable = await fileHandle.createWritable();
363
+ await writable.write(typedBlob);
364
+ await writable.close();
365
+ return { saved: true };
366
+ }
367
+ /**
368
+ * Cleanup — call from the component's ngOnDestroy.
369
+ * @memberof RosterExportService
370
+ */
371
+ destroy() {
372
+ this.destroy$.next(true);
373
+ // This service is providedIn: 'root' (singleton), so its state survives
374
+ // navigation. Reset the UI-facing flags so a new roster component instance
375
+ // does not inherit a stale-open popover or a permanently-disabled export
376
+ // button if the user left the page mid-export or with the popover open.
377
+ this.isPopoverOpenSubject$.next(false);
378
+ this.isExportInProgressSubject$.next(false);
379
+ // Signal current takeUntil subscriptions to unsubscribe, then re-create the
380
+ // subject. This service is a providedIn: 'root' singleton whose destroy() is
381
+ // called on every ViewRosterComponent teardown; completing destroy$ would
382
+ // permanently close it, so later exports could never be torn down. A fresh
383
+ // subject keeps the teardown channel usable across component lifecycles.
384
+ this.destroy$.next(true);
385
+ this.destroy$ = new Subject();
386
+ }
387
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RosterExportService, deps: [{ token: i1.HttpClient }, { token: i2.MatDialog }, { token: i3.AlertsService }], target: i0.ɵɵFactoryTarget.Injectable }); }
388
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RosterExportService, providedIn: 'root' }); }
389
+ }
390
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RosterExportService, decorators: [{
391
+ type: Injectable,
392
+ args: [{
393
+ providedIn: 'root',
394
+ }]
395
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }, { type: i2.MatDialog }, { type: i3.AlertsService }]; } });
396
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9zdGVyLWV4cG9ydC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZ3JvdXBzL3NyYy9saWIvc2VydmljZXMvcm9zdGVyLWV4cG9ydC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFjLFVBQVUsRUFBZ0IsTUFBTSxzQkFBc0IsQ0FBQztBQUU1RSxPQUFPLEVBQUUsZUFBZSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLFlBQVksQ0FBQztBQUNwQyxPQUFPLEVBQ0wsWUFBWSxFQUVaLGlDQUFpQyxFQUVqQyw0QkFBNEIsR0FFN0IsTUFBTSwwQkFBMEIsQ0FBQztBQUNsQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFL0MsT0FBTyxLQUFLLFdBQVcsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7QUFFeEQ7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFJSCxNQUFNLE9BQU8sbUJBQW1CO0lBcUM5QjtJQUNFLDBDQUEwQztJQUNsQyxVQUFzQjtJQUM5QiwwQ0FBMEM7SUFDbEMsTUFBaUI7SUFDekIsMENBQTBDO0lBQ2xDLFlBQTJCO1FBSjNCLGVBQVUsR0FBVixVQUFVLENBQVk7UUFFdEIsV0FBTSxHQUFOLE1BQU0sQ0FBVztRQUVqQixpQkFBWSxHQUFaLFlBQVksQ0FBZTtRQTFDckMsOERBQThEO1FBQ3RELGNBQVMsR0FBUSxXQUFXLENBQUM7UUFFN0IsYUFBUSxHQUFHLElBQUksT0FBTyxFQUFXLENBQUM7UUFFMUMsd0NBQXdDO1FBQ2hDLDBCQUFxQixHQUFHLElBQUksZUFB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QUcsTUFBTSxVQUFVLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDbkQsTUFBTSxRQUFRLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ2hDLE1BQU0sUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVEOzs7T0FHRztJQUNILE9BQU87UUFDTCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN6Qix3RUFBd0U7UUFDeEUsMkVBQTJFO1FBQzNFLHlFQUF5RTtRQUN6RSx3RUFBd0U7UUFDeEUsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2QyxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVDLDRFQUE0RTtRQUM1RSw2RUFBNkU7UUFDN0UsMEVBQTBFO1FBQzFFLDJFQUEyRTtRQUMzRSx5RUFBeUU7UUFDekUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLE9BQU8sRUFBVyxDQUFDO0lBQ3pDLENBQUM7K0dBdFlVLG1CQUFtQjttSEFBbkIsbUJBQW1CLGNBRmxCLE1BQU07OzRGQUVQLG1CQUFtQjtrQkFIL0IsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEh0dHBDbGllbnQsIEh0dHBQYXJhbXMsIEh0dHBSZXNwb25zZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHsgTWF0RGlhbG9nIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcclxuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBFTVBUWSwgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IG1hcCwgY2F0Y2hFcnJvciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgc2F2ZUFzIH0gZnJvbSAnZmlsZS1zYXZlcic7XHJcbmltcG9ydCB7XHJcbiAgRXhwb3J0Rm9ybWF0LFxyXG4gIEV4cG9ydEZvcm1hdE9wdGlvbixcclxuICBQb2xpY3lDb25maXJtYXRpb25EaWFsb2dDb21wb25lbnQsXHJcbiAgUG9saWN5Q29uZmlybWF0aW9uRGlhbG9nRGF0YSxcclxuICBFeHBvcnRTdWNjZXNzRGlhbG9nQ29tcG9uZW50LFxyXG4gIEV4cG9ydFN1Y2Nlc3NEaWFsb2dEYXRhLFxyXG59IGZyb20gJ0BpZWVlc2EtbnBtL3ByZXNlbnRhdGlvbic7XHJcbmltcG9ydCB7IEFsZXJ0VHlwZSB9IGZyb20gJ0BpZWVlc2EtbnBtL21vZGVscyc7XHJcbmltcG9ydCB7IEFsZXJ0c1NlcnZpY2UgfSBmcm9tICdAaWVlZXNhLW5wbS91dGlsaXR5JztcclxuaW1wb3J0ICogYXMgc2NyZWVuVGV4dHMgZnJvbSAnLi4vYXNzZXRzL2NvbnN0YW50cy5qc29uJztcclxuXHJcbi8qKlxyXG4gKiBSb3N0ZXJFeHBvcnRTZXJ2aWNlIG93bnMgdGhlIGNvbXBsZXRlIGdyb3VwIHJvc3RlciBleHBvcnQgZmxvdzpcclxuICogMS4gTWFuYWdlcyBleHBvcnQgcG9wb3ZlciBvcGVuL2Nsb3NlIHN0YXRlXHJcbiAqIDIuIE9wZW5zIElFRUUgRGF0YSBBY2Nlc3MgYW5kIFVzZSBQb2xpY3kgY29uZmlybWF0aW9uIGRpYWxvZ1xyXG4gKiAzLiBDYWxscyB0aGUgYmFja2VuZCByb3N0ZXIgZXhwb3J0IEFQSSAoYmxvYiByZXNwb25zZSlcclxuICogNC4gVHJpZ2dlcnMgZmlsZSBkb3dubG9hZCB2aWEgRmlsZSBTeXN0ZW0gQWNjZXNzIEFQSSAvIGZpbGUtc2F2ZXJcclxuICogNS4gU2hvd3Mgc3VjY2Vzcy9lcnJvciBkaWFsb2dzIGFuZCB0b2FzdHNcclxuICpcclxuICogVGhlIGNvbXBvbmVudCBvbmx5IG5lZWRzIHRvOlxyXG4gKiAtIFN1YnNjcmliZSB0byBgaXNQb3BvdmVyT3BlbiRgIGZvciBwb3BvdmVyIHZpc2liaWxpdHlcclxuICogLSBDYWxsIGB0b2dnbGVQb3BvdmVyKClgIG9uIEV4cG9ydCBidXR0b24gY2xpY2tcclxuICogLSBDYWxsIGBvbkZvcm1hdFNlbGVjdGVkKGZvcm1hdCwgZ3JvdXBJZCwgZ3JvdXBOYW1lKWAgd2hlbiB1c2VyIHBpY2tzIGEgZm9ybWF0XHJcbiAqXHJcbiAqIEZvbGxvd3MgdGhlIHNhbWUgcGF0dGVybiBhcyBNZWV0aW5nRXhwb3J0U2VydmljZSBpbiB0aGUgZXZlbnRzLWFuZC1tZWV0aW5ncyBsaWJyYXJ5LlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBjbGFzcyBSb3N0ZXJFeHBvcnRTZXJ2aWNlXHJcbiAqL1xyXG5ASW5qZWN0YWJsZSh7XHJcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgUm9zdGVyRXhwb3J0U2VydmljZSB7XHJcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcclxuICBwcml2YXRlIGNvbnN0YW50czogYW55ID0gc2NyZWVuVGV4dHM7XHJcbiAgcHJpdmF0ZSBhcGlCYXNlVXJsITogc3RyaW5nO1xyXG4gIHByaXZhdGUgZGVzdHJveSQgPSBuZXcgU3ViamVjdDxib29sZWFuPigpO1xyXG5cclxuICAvKiogQ29udHJvbHMgcG9wb3ZlciBvcGVuL2Nsb3NlIHN0YXRlICovXHJcbiAgcHJpdmF0ZSBpc1BvcG92ZXJPcGVuU3ViamVjdCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcclxuICBpc1BvcG92ZXJPcGVuJCA9IHRoaXMuaXNQb3BvdmVyT3BlblN1YmplY3QkLmFzT2JzZXJ2YWJsZSgpO1xyXG5cclxuICAvKiogQ29udHJvbHMgaW4tcHJvZ3Jlc3Mgc3RhdGUgZm9yIGJ1dHRvbiBkaXNhYmxlICovXHJcbiAgcHJpdmF0ZSBpc0V4cG9ydEluUHJvZ3Jlc3NTdWJqZWN0JCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xyXG4gIGlzRXhwb3J0SW5Qcm9ncmVzcyQgPSB0aGlzLmlzRXhwb3J0SW5Qcm9ncmVzc1N1YmplY3QkLmFzT2JzZXJ2YWJsZSgpO1xyXG5cclxuICAvKiogRm9ybWF0IG9wdGlvbnMgZm9yIHRoZSBleHBvcnQgcG9wb3ZlciAqL1xyXG4gIGV4cG9ydEZvcm1hdE9wdGlvbnM6IEV4cG9ydEZvcm1hdE9wdGlvbltdID0gW1xyXG4gICAge1xyXG4gICAgICBsYWJlbDogdGhpcy5jb25zdGFudHM/LnJvc3RlckV4cG9ydD8uZm9ybWF0T3B0aW9ucz8uY3N2Py5sYWJlbCA/PyAnQ1NWJyxcclxuICAgICAgdmFsdWU6IEV4cG9ydEZvcm1hdC5DU1YsXHJcbiAgICAgIGFyaWFMYWJlbDogdGhpcy5jb25zdGFudHM/LnJvc3RlckV4cG9ydD8uZm9ybWF0T3B0aW9ucz8uY3N2Py5hcmlhTGFiZWwgPz8gJ0V4cG9ydCByb3N0ZXIgYXMgQ1NWJyxcclxuICAgIH0sXHJcbiAgICB7XHJcbiAgICAgIGxhYmVsOiB0aGlzLmNvbnN0YW50cz8ucm9zdGVyRXhwb3J0Py5mb3JtYXRPcHRpb25zPy5leGNlbD8ubGFiZWwgPz8gJ0V4Y2VsJyxcclxuICAgICAgdmFsdWU6IEV4cG9ydEZvcm1hdC5FWENFTCxcclxuICAgICAgYXJpYUxhYmVsOiB0aGlzLmNvbnN0YW50cz8ucm9zdGVyRXhwb3J0Py5mb3JtYXRPcHRpb25zPy5leGNlbD8uYXJpYUxhYmVsID8/ICdFeHBvcnQgcm9zdGVyIGFzIEV4Y2VsJyxcclxuICAgIH0sXHJcbiAgXTtcclxuXHJcbiAgLyoqIFN1YnRpdGxlIGxhYmVscyBmb3IgdGhlIGZvcm1hdCBzZWxlY3Rpb24gY2FyZHMgKi9cclxuICBleHBvcnRGb3JtYXRTdWJ0aXRsZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XHJcbiAgICBjc3Y6IHRoaXMuY29uc3RhbnRzPy5yb3N0ZXJFeHBvcnQ/LmZvcm1hdE9wdGlvbnM/LmNzdj8uc3VidGl0bGUgPz8gJ0NvbW1hIHNlcGFyYXRlZCBmaWxlJyxcclxuICAgIHhsczogdGhpcy5jb25zdGFudHM/LnJvc3RlckV4cG9ydD8uZm9ybWF0T3B0aW9ucz8uZXhjZWw/LnN1YnRpdGxlID8/ICdTcHJlYWRzaGVldCBGaWxlJyxcclxuICB9O1xyXG5cclxuICAvKiogUG9wb3ZlciB0aXRsZSAqL1xyXG4gIHBvcG92ZXJUaXRsZSA9IHRoaXMuY29uc3RhbnRzPy5yb3N0ZXJFeHBvcnQ/LnBvcG92ZXJUaXRsZSA/PyAnU2VsZWN0IHRoZSBmaWxlIGZvcm1hdCBmb3Igcm9zdGVyIGV4cG9ydC4nO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xyXG4gICAgcHJpdmF0ZSBodHRwQ2xpZW50OiBIdHRwQ2xpZW50LFxyXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXHJcbiAgICBwcml2YXRlIGRpYWxvZzogTWF0RGlhbG9nLFxyXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXHJcbiAgICBwcml2YXRlIGFsZXJ0U2VydmljZTogQWxlcnRzU2VydmljZVxyXG4gICkge31cclxuXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgQVBJIGJhc2UgVVJMIGZvciByb3N0ZXIgZXhwb3J0IGNhbGxzLlxyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1cmwgLSBCYXNlIFVSTCAoZS5nLiwgJ2h0dHBzOi8vc2FhcHBzYXBpZGV2LmllZWUub3JnL3YxJylcclxuICAgKiBAbWVtYmVyb2YgUm9zdGVyRXhwb3J0U2VydmljZVxyXG4gICAqL1xyXG4gIHNldEFwaUJhc2VVcmwodXJsOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuYXBpQmFzZVVybCA9IHVybDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRvZ2dsZXMgdGhlIGV4cG9ydCBmb3JtYXQgcG9wb3ZlciBvcGVuL2Nsb3NlZC5cclxuICAgKiBDYWxsZWQgYnkgdGhlIGNvbXBvbmVudCBvbiBFeHBvcnQgYnV0dG9uIGNsaWNrLlxyXG4gICAqIEBtZW1iZXJvZiBSb3N0ZXJFeHBvcnRTZXJ2aWNlXHJcbiAgICovXHJcbiAgdG9nZ2xlUG9wb3ZlcigpOiB2b2lkIHtcclxuICAgIHRoaXMuaXNQb3BvdmVyT3BlblN1YmplY3QkLm5leHQoIXRoaXMuaXNQb3BvdmVyT3BlblN1YmplY3QkLmdldFZhbHVlKCkpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2xvc2VzIHRoZSBleHBvcnQgZm9ybWF0IHBvcG92ZXIuXHJcbiAgICogQG1lbWJlcm9mIFJvc3RlckV4cG9ydFNlcnZpY2VcclxuICAgKi9cclxuICBjbG9zZVBvcG92ZXIoKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzUG9wb3Zlck9wZW5TdWJqZWN0JC5uZXh0KGZhbHNlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhhbmRsZXMgZm9ybWF0IHNlbGVjdGlvbiBmcm9tIHRoZSBleHBvcnQgcG9wb3Zlci5cclxuICAgKiBDbG9zZXMgcG9wb3Zlciwgb3BlbnMgSUVFRSBQb2xpY3kgZGlhbG9nLCBvbiBjb25maXJtIHRyaWdnZXJzIGV4cG9ydC5cclxuICAgKiBUaGlzIGlzIHRoZSBtYWluIGVudHJ5IHBvaW50IGNhbGxlZCBieSB0aGUgY29tcG9uZW50IGFmdGVyIHVzZXIgcGlja3MgYSBmb3JtYXQuXHJcbiAgICogQHBhcmFtIHtFeHBvcnRGb3JtYXR9IGZvcm1hdCAtIFNlbGVjdGVkIGZvcm1hdCAoQ1NWIG9yIFhMUylcclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZ3JvdXBJZCAtIFRoZSBncm91cCBJRCB0byBleHBvcnQgdGhlIHJvc3RlciBmb3JcclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZ3JvdXBOYW1lIC0gVGhlIGdyb3VwIG5hbWUgZm9yIGZpbGVuYW1lIGdlbmVyYXRpb25cclxuICAgKiBAbWVtYmVyb2YgUm9zdGVyRXhwb3J0U2VydmljZVxyXG4gICAqL1xyXG4gIG9uRm9ybWF0U2VsZWN0ZWQoZm9ybWF0OiBFeHBvcnRGb3JtYXQsIGdyb3VwSWQ6IHN0cmluZywgZ3JvdXBOYW1lOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuY2xvc2VQb3BvdmVyKCk7XHJcblxyXG4gICAgY29uc3QgZGlhbG9nRGF0YTogUG9saWN5Q29uZmlybWF0aW9uRGlhbG9nRGF0YSA9IHtcclxuICAgICAgdGl0bGU6IHRoaXMuY29uc3RhbnRzPy5yb3N0ZXJFeHBvcnQ/LnBvbGljeURpYWxvZz8udGl0bGUgPz8gJ0lFRUUgRGF0YSBBY2Nlc3MgYW5kIFVzZSBQb2xpY3knLFxyXG4gICAgICBib2R5VGV4dDogdGhpcy5jb25zdGFudHM/LnJvc3RlckV4cG9ydD8ucG9saWN5RGlhbG9nPy5ib2R5VGV4dCA/PyAnVGhlIGFwcGxpY2F0aW9uIGlzIGdvdmVybmVkIGJ5IElFRUVcXCdzIGRhdGEgYWNjZXNzIGFuZCB1c2UgcG9saWN5LiBEYXRhIGNhbiBvbmx5IGJlIHVzZWQgZm9yIGl0cyBvcmlnaW5hbCBpbnRlbmRlZCBwdXJwb3NlLiBDbGljayBcIkNvbmZpcm1cIiB0byBleHBvcnQgdGhlIGRhdGEgaW50byBhIENTVi9FeGNlbCBmaWxlIG9yIGNsaWNrIFwiQ2FuY2VsXCIgdG8gY2FuY2VsIHRoZSBkb3dubG9hZC4nLFxyXG4gICAgICBwb2xpY3lVcmw6IHRoaXMuY29uc3RhbnRzPy5yb3N0ZXJFeHBvcnQ/LnBvbGljeURpYWxvZz8ucG9saWN5VXJsID8/ICdodHRwczovL3d3dy5pZWVlLm9yZy9pZWVlLWRhdGEtYWNjZXNzLWFuZC11c2UtcG9saWN5Lmh0bWwnLFxyXG4gICAgICBwb2xpY3lMaW5rVGV4dDogdGhpcy5jb25zdGFudHM/LnJvc3RlckV4cG9ydD8ucG9saWN5RGlhbG9nPy5wb2xpY3lMaW5rVGV4dCA/PyAnZGF0YSBhY2Nlc3MgYW5kIHVzZSBwb2xpY3knLFxyXG4gICAgICBjYW5jZWxMYWJlbDogdGhpcy5jb25zdGFudHM/LnJvc3RlckV4cG9ydD8ucG9saWN5RGlhbG9nPy5jYW5jZWxMYWJlbCA/PyAnQ2FuY2VsJyxcclxuICAgICAgY29uZmlybUxhYmVsOiB0aGlzLmNvbnN0YW50cz8ucm9zdGVyRXhwb3J0Py5wb2xpY3lEaWFsb2c/LmNvbmZpcm1MYWJlbCA/PyAnQ29uZmlybScsXHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGRpYWxvZ1JlZiA9IHRoaXMuZGlhbG9nLm9wZW4oUG9saWN5Q29uZmlybWF0aW9uRGlhbG9nQ29tcG9uZW50LCB7XHJcbiAgICAgIGRhdGE6IGRpYWxvZ0RhdGEsXHJcbiAgICAgIHdpZHRoOiAnNjM3cHgnLFxyXG4gICAgICBwYW5lbENsYXNzOiBbJ2llZWVzYS1wb2xpY3ktZGlhbG9nJ10sXHJcbiAgICB9KTtcclxuXHJcbiAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKVxyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoKGNvbmZpcm1lZDogYm9vbGVhbikgPT4ge1xyXG4gICAgICAgIGlmIChjb25maXJtZWQpIHtcclxuICAgICAgICAgIHRoaXMuc3RhcnRFeHBvcnQoZm9ybWF0LCBncm91cElkLCBncm91cE5hbWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTdGFydHMgdGhlIGV4cG9ydCBhZnRlciB0aGUgdXNlciBjb25maXJtcyB0aGUgcG9saWN5IGRpYWxvZy5cclxuICAgKlxyXG4gICAqIFdoZW4gdGhlIEZpbGUgU3lzdGVtIEFjY2VzcyBBUEkgaXMgYXZhaWxhYmxlLCB0aGUgbmF0aXZlIFNhdmUgcGlja2VyIGlzIG9wZW5lZFxyXG4gICAqIEhFUkUg4oCUIHN5bmNocm9ub3VzbHkgd2l0aGluIHRoZSBjb25maXJtIGhhbmRsZXIg4oCUIHdoaWxlIHRoZSB1c2VyIGFjdGl2YXRpb24gZnJvbVxyXG4gICAqIHRoZSBjb25maXJtIGNsaWNrIGlzIHN0aWxsIHZhbGlkLiAoT3BlbmluZyBpdCBsYXRlciwgaW5zaWRlIHRoZSBhc3luYyBIVFRQXHJcbiAgICogcmVzcG9uc2UgY2FsbGJhY2ssIHdvdWxkIGV4Y2VlZCB0aGUgYWN0aXZhdGlvbiB3aW5kb3cgYW5kIHRoZSBicm93c2VyIHdvdWxkXHJcbiAgICogcmVqZWN0IGl0IHdpdGggYSBTZWN1cml0eUVycm9yLikgVGhlIG9idGFpbmVkIGZpbGUgaGFuZGxlIGlzIHRoZW4gcGFzc2VkIHRvIHRoZVxyXG4gICAqIEhUVFAgZmxvdywgd2hpY2ggd3JpdGVzIHRoZSBkb3dubG9hZGVkIGJ5dGVzIHRvIGl0IG9uY2UgdGhlIHJlc3BvbnNlIGFycml2ZXMsIHNvXHJcbiAgICogdGhlIHN1Y2Nlc3MgZGlhbG9nIGlzIHN0aWxsIHNob3duIG9ubHkgQUZURVIgdGhlIGZpbGUgaXMgc2F2ZWQuXHJcbiAgICpcclxuICAgKiBJZiB0aGUgdXNlciBjYW5jZWxzIHRoZSBwaWNrZXIgd2UgYWJvcnQgYmVmb3JlIG1ha2luZyB0aGUgcmVxdWVzdC4gSWYgdGhlIEFQSSBpc1xyXG4gICAqIHVuYXZhaWxhYmxlIChGaXJlZm94L1NhZmFyaSkgd2UgcHJvY2VlZCB3aXRob3V0IGEgaGFuZGxlIGFuZCBmYWxsIGJhY2sgdG9cclxuICAgKiBgc2F2ZUFzKClgIGFmdGVyIHRoZSByZXNwb25zZS5cclxuICAgKiBAcGFyYW0ge0V4cG9ydEZvcm1hdH0gZm9ybWF0XHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGdyb3VwSWRcclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZ3JvdXBOYW1lXHJcbiAgICogQG1lbWJlcm9mIFJvc3RlckV4cG9ydFNlcnZpY2VcclxuICAgKi9cclxuICBwcml2YXRlIHN0YXJ0RXhwb3J0KGZvcm1hdDogRXhwb3J0Rm9ybWF0LCBncm91cElkOiBzdHJpbmcsIGdyb3VwTmFtZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxyXG4gICAgY29uc3Qgc2hvd1NhdmVGaWxlUGlja2VyID0gKHdpbmRvdyBhcyBhbnkpLnNob3dTYXZlRmlsZVBpY2tlcjtcclxuXHJcbiAgICBpZiAodHlwZW9mIHNob3dTYXZlRmlsZVBpY2tlciAhPT0gJ2Z1bmN0aW9uJykge1xyXG4gICAgICAvLyBBUEkgdW5hdmFpbGFibGU6IG5vIGhhbmRsZTsgZXhlY3V0ZUV4cG9ydCgpIHdpbGwgdXNlIHRoZSBzYXZlQXMoKSBmYWxsYmFjay5cclxuICAgICAgdGhpcy5leGVjdXRlRXhwb3J0KGZvcm1hdCwgZ3JvdXBJZCwgZ3JvdXBOYW1lLCBudWxsKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IG1pbWVUeXBlID0gZm9ybWF0ID09PSBFeHBvcnRGb3JtYXQuQ1NWXHJcbiAgICAgID8gJ3RleHQvY3N2J1xyXG4gICAgICA6ICdhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC5zaGVldCc7XHJcbiAgICBjb25zdCBleHRlbnNpb24gPSBmb3JtYXQgPT09IEV4cG9ydEZvcm1hdC5DU1YgPyAnLmNzdicgOiAnLnhsc3gnO1xyXG4gICAgY29uc3Qgc3VnZ2VzdGVkTmFtZSA9IHRoaXMuYnVpbGRGaWxlbmFtZShncm91cE5hbWUsIGZvcm1hdCk7XHJcblxyXG4gICAgLy8gT3BlbiB0aGUgcGlja2VyIG5vdywgd2hpbGUgdGhlIGNvbmZpcm0tY2xpY2sgYWN0aXZhdGlvbiBpcyBzdGlsbCB2YWxpZC5cclxuICAgIHNob3dTYXZlRmlsZVBpY2tlcih7XHJcbiAgICAgIHN1Z2dlc3RlZE5hbWUsXHJcbiAgICAgIHR5cGVzOiBbXHJcbiAgICAgICAge1xyXG4gICAgICAgICAgZGVzY3JpcHRpb246IGZvcm1hdCA9PT0gRXhwb3J0Rm9ybWF0LkNTViA/ICdDU1YgRmlsZScgOiAnRXhjZWwgRmlsZScsXHJcbiAgICAgICAgICBhY2NlcHQ6IHsgW21pbWVUeXBlXTogW2V4dGVuc2lvbl0gfSxcclxuICAgICAgICB9LFxyXG4gICAgICBdLFxyXG4gICAgfSlcclxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcclxuICAgICAgLnRoZW4oKGhhbmRsZTogYW55KSA9PiB7XHJcbiAgICAgICAgdGhpcy5leGVjdXRlRXhwb3J0KGZvcm1hdCwgZ3JvdXBJZCwgZ3JvdXBOYW1lLCBoYW5kbGUpO1xyXG4gICAgICB9KVxyXG4gICAgICAuY2F0Y2goKGVycm9yOiB1bmtub3duKSA9PiB7XHJcbiAgICAgICAgLy8gVXNlciBjYW5jZWxsZWQgdGhlIFNhdmUgZGlhbG9nIOKAlCBhYm9ydCBzaWxlbnRseSwgbm8gcmVxdWVzdCBtYWRlLlxyXG4gICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIERPTUV4Y2VwdGlvbiAmJiBlcnJvci5uYW1lID09PSAnQWJvcnRFcnJvcicpIHtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gQW55IG90aGVyIHBpY2tlciBlcnJvcjogZmFsbCBiYWNrIHRvIHRoZSBzYXZlQXMoKSBmbG93LlxyXG4gICAgICAgIHRoaXMuZXhlY3V0ZUV4cG9ydChmb3JtYXQsIGdyb3VwSWQsIGdyb3VwTmFtZSwgbnVsbCk7XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRXhlY3V0ZXMgdGhlIHJvc3RlciBleHBvcnQgQVBJIGNhbGwgYW5kIHdyaXRlcyB0aGUgZG93bmxvYWRlZCBmaWxlLlxyXG4gICAqIEVuZHBvaW50OiBHRVQgL3YxL2dyb3Vwcy9yb3N0ZXIvZXhwb3J0L3tncm91cElkfT9mb3JtYXQ9Y3N2fHhsc3hcclxuICAgKiBXaGVuIGEgcHJlLW9idGFpbmVkIGZpbGUgaGFuZGxlIGlzIHByb3ZpZGVkIChmcm9tIHRoZSBwaWNrZXIgb3BlbmVkIGF0IGNvbmZpcm1cclxuICAgKiB0aW1lKSB0aGUgYnl0ZXMgYXJlIHdyaXR0ZW4gdG8gaXQ7IG90aGVyd2lzZSBpdCBmYWxscyBiYWNrIHRvIGBzYXZlQXMoKWAuXHJcbiAgICogVGhlIHN1Y2Nlc3MgZGlhbG9nIGlzIHNob3duIG9ubHkgYWZ0ZXIgdGhlIGZpbGUgaGFzIGJlZW4gd3JpdHRlbi5cclxuICAgKiBAcGFyYW0ge0V4cG9ydEZvcm1hdH0gZm9ybWF0IC0gVGhlIHNlbGVjdGVkIGV4cG9ydCBmb3JtYXRcclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZ3JvdXBJZCAtIFRoZSBncm91cCBpZGVudGlmaWVyXHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGdyb3VwTmFtZSAtIFRoZSBncm91cCBuYW1lIGZvciBmaWxlbmFtZVxyXG4gICAqIEBwYXJhbSB7RmlsZVN5c3RlbUZpbGVIYW5kbGUgfCBudWxsfSBmaWxlSGFuZGxlIC0gSGFuZGxlIGZyb20gdGhlIFNhdmUgcGlja2VyLCBvciBudWxsXHJcbiAgICogQG1lbWJlcm9mIFJvc3RlckV4cG9ydFNlcnZpY2VcclxuICAgKi9cclxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxyXG4gIHByaXZhdGUgZXhlY3V0ZUV4cG9ydChmb3JtYXQ6IEV4cG9ydEZvcm1hdCwgZ3JvdXBJZDogc3RyaW5nLCBncm91cE5hbWU6IHN0cmluZywgZmlsZUhhbmRsZTogYW55KTogdm9pZCB7XHJcbiAgICB0aGlzLmlzRXhwb3J0SW5Qcm9ncmVzc1N1YmplY3QkLm5leHQodHJ1ZSk7XHJcblxyXG4gICAgLy8gQmFja2VuZCBleHBlY3RzICdjc3YnIG9yICd4bHN4Jy4gVGhlIEV4cG9ydEZvcm1hdC5FWENFTCBlbnVtIHZhbHVlIGlzXHJcbiAgICAvLyAneGxzJywgc28gaXQgbXVzdCBiZSBtYXBwZWQgdG8gJ3hsc3gnIGhlcmUg4oCUIHNlbmRpbmcgJ3hscycgaXMgcmVqZWN0ZWRcclxuICAgIC8vIHdpdGggZXJyb3IgY29kZSAxMDc5LlxyXG4gICAgY29uc3QgZm9ybWF0VmFsdWUgPSBmb3JtYXQgPT09IEV4cG9ydEZvcm1hdC5DU1YgPyAnY3N2JyA6ICd4bHN4JztcclxuICAgIGNvbnN0IHBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKCkuc2V0KCdmb3JtYXQnLCBmb3JtYXRWYWx1ZSk7XHJcbiAgICBjb25zdCB1cmwgPSBgJHt0aGlzLmdldEV4cG9ydEFwaVVybCgpfS9ncm91cHMvcm9zdGVyL2V4cG9ydC8ke2dyb3VwSWR9YDtcclxuXHJcbiAgICB0aGlzLmh0dHBDbGllbnRcclxuICAgICAgLmdldCh1cmwsIHtcclxuICAgICAgICBwYXJhbXMsXHJcbiAgICAgICAgcmVzcG9uc2VUeXBlOiAnYmxvYicsXHJcbiAgICAgICAgb2JzZXJ2ZTogJ3Jlc3BvbnNlJyxcclxuICAgICAgfSlcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgbWFwKChyZXNwb25zZTogSHR0cFJlc3BvbnNlPEJsb2I+KSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBmaWxlbmFtZSA9IHRoaXMuZXh0cmFjdEZpbGVuYW1lRnJvbVJlc3BvbnNlKHJlc3BvbnNlLCBmb3JtYXQsIGdyb3VwTmFtZSk7XHJcbiAgICAgICAgICByZXR1cm4geyBibG9iOiByZXNwb25zZS5ib2R5IGFzIEJsb2IsIGZpbGVuYW1lIH07XHJcbiAgICAgICAgfSksXHJcbiAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmlzRXhwb3J0SW5Qcm9ncmVzc1N1YmplY3QkLm5leHQoZmFsc2UpO1xyXG4gICAgICAgICAgdGhpcy5hbGVydFNlcnZpY2Uuc2hvd01lc3NhZ2Uoe1xyXG4gICAgICAgICAgICBzdGF0dXM6ICdjdXN0b20nLFxyXG4gICAgICAgICAgICBtZXNzYWdlOiB0aGlzLmNvbnN0YW50cz8ucm9zdGVyRXhwb3J0Py5tZXNzYWdlcz8uZXhwb3J0RmFpbGVkID8/ICdGYWlsZWQgdG8gZXhwb3J0IHJvc3Rlci4gUGxlYXNlIHRyeSBhZ2Fpbi4nLFxyXG4gICAgICAgICAgICBhbGVydFR5cGU6IEFsZXJ0VHlwZS5FUlJPUixcclxuICAgICAgICAgICAgaXNDbG9zZU5lZWRlZDogdHJ1ZSxcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgLy8gRXJyb3IgaXMgZnVsbHkgaGFuZGxlZCAoYWxlcnQgc2hvd24pLiBDb21wbGV0ZSB0aGUgc3RyZWFtIGluc3RlYWQgb2ZcclxuICAgICAgICAgIC8vIHJldGhyb3dpbmcsIHNvIHRoZSBuZXh0LW9ubHkgc3Vic2NyaWJlIGRvZXMgbm90IHJlcG9ydCBpdCBhcyBhblxyXG4gICAgICAgICAgLy8gdW5oYW5kbGVkIFJ4SlMgZXJyb3IuXHJcbiAgICAgICAgICByZXR1cm4gRU1QVFk7XHJcbiAgICAgICAgfSksXHJcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpXHJcbiAgICAgIClcclxuICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKHJlc3VsdCkgPT4ge1xyXG4gICAgICAgICAgLy8gV3JpdGUgdG8gdGhlIHByZS1vYnRhaW5lZCBoYW5kbGUgKHBpY2tlciBvcGVuZWQgYXQgY29uZmlybSB0aW1lKSBvciBmYWxsXHJcbiAgICAgICAgICAvLyBiYWNrIHRvIHNhdmVBcygpLiBTdWNjZXNzIGRpYWxvZyBvbmx5IHNob3dzIGFmdGVyIHRoZSBmaWxlIGlzIHdyaXR0ZW4uXHJcbiAgICAgICAgICB0aGlzLmRvd25sb2FkRmlsZShyZXN1bHQuYmxvYiwgcmVzdWx0LmZpbGVuYW1lLCBmb3JtYXQsIGZpbGVIYW5kbGUpXHJcbiAgICAgICAgICAgIC50aGVuKCh7IHNhdmVkIH0pID0+IHtcclxuICAgICAgICAgICAgICB0aGlzLmlzRXhwb3J0SW5Qcm9ncmVzc1N1YmplY3QkLm5leHQoZmFsc2UpO1xyXG4gICAgICAgICAgICAgIGlmIChzYXZlZCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5zaG93RXhwb3J0U3VjY2Vzc0RpYWxvZ0FmdGVyRG93bmxvYWQocmVzdWx0LmZpbGVuYW1lKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIC5jYXRjaCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgdGhpcy5pc0V4cG9ydEluUHJvZ3Jlc3NTdWJqZWN0JC5uZXh0KGZhbHNlKTtcclxuICAgICAgICAgICAgICB0aGlzLmFsZXJ0U2VydmljZS5zaG93TWVzc2FnZSh7XHJcbiAgICAgICAgICAgICAgICBzdGF0dXM6ICdjdXN0b20nLFxyXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogdGhpcy5jb25zdGFudHM/LnJvc3RlckV4cG9ydD8ubWVzc2FnZXM/LmV4cG9ydEZhaWxlZCA/PyAnRmFpbGVkIHRvIGV4cG9ydCByb3N0ZXIuIFBsZWFzZSB0cnkgYWdhaW4uJyxcclxuICAgICAgICAgICAgICAgIGFsZXJ0VHlwZTogQWxlcnRUeXBlLkVSUk9SLFxyXG4gICAgICAgICAgICAgICAgaXNDbG9zZU5lZWRlZDogdHJ1ZSxcclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSxcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTaG93cyB0aGUgZXhwb3J0IHN1Y2Nlc3MgZGlhbG9nIGFmdGVyIGEgc3VjY2Vzc2Z1bCBmaWxlIGRvd25sb2FkLlxyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFRoZSBkb3dubG9hZGVkIGZpbGVuYW1lXHJcbiAgICogQG1lbWJlcm9mIFJvc3RlckV4cG9ydFNlcnZpY2VcclxuICAgKi9cclxuICBwcml2YXRlIHNob3dFeHBvcnRTdWNjZXNzRGlhbG9nQWZ0ZXJEb3dubG9hZChmaWxlbmFtZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBzdWNjZXNzTWVzc2FnZSA9IHRoaXMuY29uc3RhbnRzPy5yb3N0ZXJFeHBvcnQ/LnN1Y2Nlc3NEaWFsb2c/Lm1lc3NhZ2UgPz8gJ1RoZSBmaWxlIHdhcyBkb3dubG9hZGVkIHN1Y2Nlc3NmdWxseS4nO1xyXG4gICAgY29uc3QgY2xvc2VMYWJlbCA9IHRoaXMuY29uc3RhbnRzPy5yb3N0ZXJFeHBvcnQ/LnN1Y2Nlc3NEaWFsb2c/LmNsb3NlQnV0dG9uID8/ICdDbG9zZSc7XHJcblxyXG4gICAgY29uc3QgZGlhbG9nRGF0YTogRXhwb3J0U3VjY2Vzc0RpYWxvZ0RhdGEgPSB7XHJcbiAgICAgIG1lc3NhZ2U6IHN1Y2Nlc3NNZXNzYWdlLFxyXG4gICAgICBmaWxlbmFtZSxcclxuICAgICAgY2xvc2VMYWJlbCxcclxuICAgIH07XHJcblxyXG4gICAgdGhpcy5kaWFsb2cub3BlbihFeHBvcnRTdWNjZXNzRGlhbG9nQ29tcG9uZW50LCB7XHJcbiAgICAgIGRhdGE6IGRpYWxvZ0RhdGEsXHJcbiAgICAgIHdpZHRoOiAnNDY3cHgnLFxyXG4gICAgICBwYW5lbENsYXNzOiBbJ2llZWVzYS1leHBvcnQtc3VjY2Vzcy1kaWFsb2ctcGFuZWwnXSxcclxuICAgICAgYXV0b0ZvY3VzOiBmYWxzZSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmV0dXJucyB0aGUgQVBJIGJhc2UgVVJMIGZvciByb3N0ZXIgZXhwb3J0LlxyXG4gICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgKiBAbWVtYmVyb2YgUm9zdGVyRXhwb3J0U2VydmljZVxyXG4gICAqL1xyXG4gIHByaXZhdGUgZ2V0RXhwb3J0QXBpVXJsKCk6IHN0cmluZyB7XHJcbiAgICBpZiAoIXRoaXMuYXBpQmFzZVVybCkge1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Jvc3RlckV4cG9ydFNlcnZpY2UgYXBpQmFzZVVybCBpcyBub3Qgc2V0LiBDYWxsIHNldEFwaUJhc2VVcmwoKSBiZWZvcmUgZXhwb3J0LicpO1xyXG4gICAgfVxyXG4gICAgLy8gYXBpQmFzZVVybCBhbHJlYWR5IGNhcnJpZXMgdGhlIHZlcnNpb24gc2VnbWVudCAoZS5nLiAnLi4uL3YxJyksIHNhbWUgYXMgZXZlcnlcclxuICAgIC8vIG90aGVyIEdyb3Vwc1NlcnZpY2UgY2FsbCB3aGljaCBpcyBidWlsdCBhcyBgJHthcGlCYXNlVXJsfS9ncm91cHMvLi4uYC4gU28gdGhlXHJcbiAgICAvLyBjYWxsZXIgb25seSBhcHBlbmRzICcvZ3JvdXBzL3Jvc3Rlci9leHBvcnQve2dyb3VwSWR9JyDigJQgdGhlIHZlcnNpb24gaXMgTk9UXHJcbiAgICAvLyByZXBlYXRlZCBoZXJlLiBTdHJpcCBhIHRyYWlsaW5nIHNsYXNoIHRvIGF2b2lkIGEgZG91YmxlIHNsYXNoIGJlZm9yZSAnL2dyb3VwcycuXHJcbiAgICByZXR1cm4gdGhpcy5hcGlCYXNlVXJsLnJlcGxhY2UoL1xcLyskLywgJycpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogRXh0cmFjdHMgZmlsZW5hbWUgZnJvbSBDb250ZW50LURpc3Bvc2l0aW9uIGhlYWRlci5cclxuICAgKiBGYWxscyBiYWNrIHRvIGJ1aWxkRmlsZW5hbWUoKSBpZiBoZWFkZXIgaXMgbWlzc2luZy5cclxuICAgKiBAcGFyYW0ge0h0dHBSZXNwb25zZTxCbG9iPn0gcmVzcG9uc2VcclxuICAgKiBAcGFyYW0ge0V4cG9ydEZvcm1hdH0gZm9ybWF0XHJcbiAgICogQHBhcmFtIHtzdHJpbmd9IGdyb3VwTmFtZVxyXG4gICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgKiBAbWVtYmVyb2YgUm9zdGVyRXhwb3J0U2VydmljZVxyXG4gICAqL1xyXG4gIHByaXZhdGUgZXh0cmFjdEZpbGVuYW1lRnJvbVJlc3BvbnNlKHJlc3BvbnNlOiBIdHRwUmVzcG9uc2U8QmxvYj4sIGZvcm1hdDogRXhwb3J0Rm9ybWF0LCBncm91cE5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBjb250ZW50RGlzcG9zaXRpb24gPSByZXNwb25zZS5oZWFkZXJzLmdldCgnQ29udGVudC1EaXNwb3NpdGlvbicpO1xyXG4gICAgaWYgKGNvbnRlbnREaXNwb3NpdGlvbikge1xyXG4gICAgICBjb25zdCBmaWxlbmFtZU1hdGNoID0gY29udGVudERpc3Bvc2l0aW9uLm1hdGNoKC9maWxlbmFtZT1cIj8oW15cIl0rKVwiPy8pO1xyXG4gICAgICBpZiAoZmlsZW5hbWVNYXRjaCAmJiBmaWxlbmFtZU1hdGNoWzFdKSB7XHJcbiAgICAgICAgcmV0dXJuIGZpbGVuYW1lTWF0Y2hbMV0ucmVwbGFjZSgvWy9cXFxcOio/XCI8PnxdL2csICdfJykuc3Vic3RyaW5nKDAsIDIwMCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiB0aGlzLmJ1aWxkRmlsZW5hbWUoZ3JvdXBOYW1lLCBmb3JtYXQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQnVpbGRzIGEgc2FuaXRpemVkIGZpbGVuYW1lIGZvciB0aGUgcm9zdGVyIGV4cG9ydC5cclxuICAgKiBQYXR0ZXJuOiB7U2FuaXRpemVkR3JvdXBOYW1lfV9Sb3N0ZXIue2V4dGVuc2lvbn1cclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZ3JvdXBOYW1lXHJcbiAgICogQHBhcmFtIHtFeHBvcnRGb3JtYXR9IGZvcm1hdFxyXG4gICAqIEByZXR1cm4ge3N0cmluZ31cclxuICAgKiBAbWVtYmVyb2YgUm9zdGVyRXhwb3J0U2VydmljZVxyXG4gICAqL1xyXG4gIGJ1aWxkRmlsZW5hbWUoZ3JvdXBOYW1lOiBzdHJpbmcsIGZvcm1hdDogRXhwb3J0Rm9ybWF0KTogc3RyaW5nIHtcclxuICAgIGNvbnN0IHNhbml0aXplZCA9IHRoaXMuc2FuaXRpemVHcm91cE5hbWUoZ3JvdXBOYW1lKTtcclxuICAgIGNvbnN0IGV4dGVuc2lvbiA9IGZvcm1hdCA9PT0gRXhwb3J0Rm9ybWF0LkNTViA/ICdjc3YnIDogJ3hsc3gnO1xyXG4gICAgcmV0dXJuIGAke3Nhbml0aXplZH1fUm9zdGVyLiR7ZXh0ZW5zaW9ufWA7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTYW5pdGl6ZXMgdGhlIGdyb3VwIG5hbWUgZm9yIHVzZSBpbiBhIGZpbGVuYW1lLlxyXG4gICAqIFJlcGxhY2VzIG5vbi1hbHBoYW51bWVyaWMgY2hhcmFjdGVycyAoZXhjZXB0IGh5cGhlbi91bmRlcnNjb3JlKSB3aXRoIHVuZGVyc2NvcmUsXHJcbiAgICogY29sbGFwc2VzIGNvbnNlY3V0aXZlIHVuZGVyc2NvcmVzLCBhbmQgdHJ1bmNhdGVzIHRvIDIwMCBjaGFycy5cclxuICAgKiBAcGFyYW0ge3N0cmluZ30gZ3JvdXBOYW1lXHJcbiAgICogQHJldHVybiB7c3RyaW5nfVxyXG4gICAqIEBtZW1iZXJvZiBSb3N0ZXJFeHBvcnRTZXJ2aWNlXHJcbiAgICovXHJcbiAgc2FuaXRpemVHcm91cE5hbWUoZ3JvdXBOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgaWYgKCFncm91cE5hbWUpIHtcclxuICAgICAgcmV0dXJuICdVbm5hbWVkX0dyb3VwJztcclxuICAgIH1cclxuICAgIGNvbnN0IHNhbml0aXplZCA9IGdyb3VwTmFtZVxyXG4gICAgICAucmVwbGFjZSgvW15hLXpBLVowLTlfLV0vZywgJ18nKVxyXG4gICAgICAucmVwbGFjZSgvXysvZywgJ18nKVxyXG4gICAgICAuc3Vic3RyaW5nKDAsIDIwMCk7XHJcblxyXG4gICAgcmV0dXJuIHNhbml0aXplZCB8fCAnVW5uYW1lZF9Hcm91cCc7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBXcml0ZXMgdGhlIGRvd25sb2FkZWQgYnl0ZXMgdG8gZGlzayBhbmQgcmVzb2x2ZXMgT05MWSB3aGVuIHRoZSBzYXZlIGhhcyBhY3R1YWxseVxyXG4gICAqIGNvbXBsZXRlZC5cclxuICAgKlxyXG4gICAqIFRoZSBTYXZlIHBpY2tlciBpcyBvcGVuZWQgZWFybGllciAoYXQgcG9saWN5LWNvbmZpcm0gdGltZSwgd2hpbGUgdXNlciBhY3RpdmF0aW9uXHJcbiAgICogaXMgc3RpbGwgdmFsaWQg4oCUIHNlZSB7QGxpbmsgc3RhcnRFeHBvcnR9KTsgdGhpcyBtZXRob2Qgb25seSB3cml0ZXMgdG8gdGhlIGhhbmRsZVxyXG4gICAqIGl0IHByb2R1Y2VkLiBUaGF0IGtlZXBzIHRoZSBcInN1Y2Nlc3MgZGlhbG9nIGFmdGVyIHNhdmVcIiBvcmRlcmluZyB3aXRob3V0IGhpdHRpbmdcclxuICAgKiB0aGUgU2VjdXJpdHlFcnJvciB0aGF0IG9jY3VycyB3aGVuIHRoZSBwaWNrZXIgaXMgb3BlbmVkIGZyb20gdGhpcyBhc3luYyBjYWxsYmFjay5cclxuICAgKlxyXG4gICAqIFdoZW4gbm8gaGFuZGxlIGlzIHByb3ZpZGVkIChGaWxlIFN5c3RlbSBBY2Nlc3MgQVBJIHVuYXZhaWxhYmxlLCBvciB0aGUgcGlja2VyXHJcbiAgICogZXJyb3JlZCksIHdlIGZhbGwgYmFjayB0byBGaWxlU2F2ZXIncyBgc2F2ZUFzKClgLCB3aGljaCByZXNvbHZlcyBpbW1lZGlhdGVseS5cclxuICAgKiBAcGFyYW0ge0Jsb2J9IGJsb2IgLSBUaGUgZmlsZSBjb250ZW50c1xyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWxlbmFtZSAtIFRoZSBzdWdnZXN0ZWQgZmlsZW5hbWUgKHVzZWQgYnkgdGhlIHNhdmVBcyBmYWxsYmFjaylcclxuICAgKiBAcGFyYW0ge0V4cG9ydEZvcm1hdH0gZm9ybWF0IC0gVGhlIHNlbGVjdGVkIGV4cG9ydCBmb3JtYXQgKGRyaXZlcyBNSU1FIHR5cGUpXHJcbiAgICogQHBhcmFtIHtGaWxlU3lzdGVtRmlsZUhhbmRsZSB8IG51bGx9IGZpbGVIYW5kbGUgLSBIYW5kbGUgZnJvbSB0aGUgU2F2ZSBwaWNrZXIsIG9yIG51bGxcclxuICAgKiBAcmV0dXJuIHtQcm9taXNlPHsgc2F2ZWQ6IGJvb2xlYW4gfT59IFJlc29sdmVzIHdpdGggYHNhdmVkOiB0cnVlYCBvbmNlIHdyaXR0ZW4uXHJcbiAgICogQG1lbWJlcm9mIFJvc3RlckV4cG9ydFNlcnZpY2VcclxuICAgKi9cclxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxyXG4gIGFzeW5jIGRvd25sb2FkRmlsZShibG9iOiBCbG9iLCBmaWxlbmFtZTogc3RyaW5nLCBmb3JtYXQ6IEV4cG9ydEZvcm1hdCwgZmlsZUhhbmRsZTogYW55KTogUHJvbWlzZTx7IHNhdmVkOiBib29sZWFuIH0+IHtcclxuICAgIGNvbnN0IG1pbWVUeXBlID0gZm9ybWF0ID09PSBFeHBvcnRGb3JtYXQuQ1NWXHJcbiAgICAgID8gJ3RleHQvY3N2J1xyXG4gICAgICA6ICdhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC5zaGVldCc7XHJcbiAgICBjb25zdCB0eXBlZEJsb2IgPSBuZXcgQmxvYihbYmxvYl0sIHsgdHlwZTogbWltZVR5cGUgfSk7XHJcblxyXG4gICAgLy8gTm8gaGFuZGxlIChBUEkgdW5hdmFpbGFibGUgb3IgcGlja2VyIGVycm9yZWQpIOKGkiBzdGFuZGFyZCBkb3dubG9hZC5cclxuICAgIGlmICghZmlsZUhhbmRsZSkge1xyXG4gICAgICBzYXZlQXModHlwZWRCbG9iLCBmaWxlbmFtZSk7XHJcbiAgICAgIHJldHVybiB7IHNhdmVkOiB0cnVlIH07XHJcbiAgICB9XHJcblxyXG4gICAgLy8gV3JpdGUgdG8gdGhlIGxvY2F0aW9uIHRoZSB1c2VyIGFscmVhZHkgY2hvc2UgYXQgY29uZmlybSB0aW1lLlxyXG4gICAgY29uc3Qgd3JpdGFibGUgPSBhd2FpdCBmaWxlSGFuZGxlLmNyZWF0ZVdyaXRhYmxlKCk7XHJcbiAgICBhd2FpdCB3cml0YWJsZS53cml0ZSh0eXBlZEJsb2IpO1xyXG4gICAgYXdhaXQgd3JpdGFibGUuY2xvc2UoKTtcclxuICAgIHJldHVybiB7IHNhdmVkOiB0cnVlIH07XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDbGVhbnVwIOKAlCBjYWxsIGZyb20gdGhlIGNvbXBvbmVudCdzIG5nT25EZXN0cm95LlxyXG4gICAqIEBtZW1iZXJvZiBSb3N0ZXJFeHBvcnRTZXJ2aWNlXHJcbiAgICovXHJcbiAgZGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuZGVzdHJveSQubmV4dCh0cnVlKTtcclxuICAgIC8vIFRoaXMgc2VydmljZSBpcyBwcm92aWRlZEluOiAncm9vdCcgKHNpbmdsZXRvbiksIHNvIGl0cyBzdGF0ZSBzdXJ2aXZlc1xyXG4gICAgLy8gbmF2aWdhdGlvbi4gUmVzZXQgdGhlIFVJLWZhY2luZyBmbGFncyBzbyBhIG5ldyByb3N0ZXIgY29tcG9uZW50IGluc3RhbmNlXHJcbiAgICAvLyBkb2VzIG5vdCBpbmhlcml0IGEgc3RhbGUtb3BlbiBwb3BvdmVyIG9yIGEgcGVybWFuZW50bHktZGlzYWJsZWQgZXhwb3J0XHJcbiAgICAvLyBidXR0b24gaWYgdGhlIHVzZXIgbGVmdCB0aGUgcGFnZSBtaWQtZXhwb3J0IG9yIHdpdGggdGhlIHBvcG92ZXIgb3Blbi5cclxuICAgIHRoaXMuaXNQb3BvdmVyT3BlblN1YmplY3QkLm5leHQoZmFsc2UpO1xyXG4gICAgdGhpcy5pc0V4cG9ydEluUHJvZ3Jlc3NTdWJqZWN0JC5uZXh0KGZhbHNlKTtcclxuICAgIC8vIFNpZ25hbCBjdXJyZW50IHRha2VVbnRpbCBzdWJzY3JpcHRpb25zIHRvIHVuc3Vic2NyaWJlLCB0aGVuIHJlLWNyZWF0ZSB0aGVcclxuICAgIC8vIHN1YmplY3QuIFRoaXMgc2VydmljZSBpcyBhIHByb3ZpZGVkSW46ICdyb290JyBzaW5nbGV0b24gd2hvc2UgZGVzdHJveSgpIGlzXHJcbiAgICAvLyBjYWxsZWQgb24gZXZlcnkgVmlld1Jvc3RlckNvbXBvbmVudCB0ZWFyZG93bjsgY29tcGxldGluZyBkZXN0cm95JCB3b3VsZFxyXG4gICAgLy8gcGVybWFuZW50bHkgY2xvc2UgaXQsIHNvIGxhdGVyIGV4cG9ydHMgY291bGQgbmV2ZXIgYmUgdG9ybiBkb3duLiBBIGZyZXNoXHJcbiAgICAvLyBzdWJqZWN0IGtlZXBzIHRoZSB0ZWFyZG93biBjaGFubmVsIHVzYWJsZSBhY3Jvc3MgY29tcG9uZW50IGxpZmVjeWNsZXMuXHJcbiAgICB0aGlzLmRlc3Ryb3kkLm5leHQodHJ1ZSk7XHJcbiAgICB0aGlzLmRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcclxuICB9XHJcbn1cclxuIl19
@@ -27,6 +27,7 @@ export * from './lib/models/table-column-schema-user-group.model';
27
27
  export * from './lib/models/parent-groups-info.model';
28
28
  export * from './lib/models/reciprocal-credit.model';
29
29
  export * from './lib/services/groups.service';
30
+ export * from './lib/services/roster-export.service';
30
31
  export * from './lib/assets/form-validations';
31
32
  export * from './lib/groups.module';
32
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2dyb3Vwcy9zcmMvcHVibGljLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUNILGNBQWMsc0RBQXNELENBQUM7QUFDckUsY0FBYyxnREFBZ0QsQ0FBQztBQUMvRCxjQUFjLDREQUE0RCxDQUFDO0FBQzNFLGNBQWMsZ0ZBQWdGLENBQUM7QUFDL0YsY0FBYyxrRUFBa0UsQ0FBQztBQUNqRixjQUFjLHdCQUF3QixDQUFDO0FBRXZDLGNBQWMsaUNBQWlDLENBQUM7QUFDaEQsY0FBYyxpQ0FBaUMsQ0FBQztBQUNoRCxjQUFjLHdDQUF3QyxDQUFDO0FBQ3ZELGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLCtCQUErQixDQUFDO0FBQzlDLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyxpQ0FBaUMsQ0FBQztBQUNoRCxjQUFjLG9DQUFvQyxDQUFDO0FBQ25ELGNBQWMsMkNBQTJDLENBQUM7QUFDMUQsY0FBYyx5Q0FBeUMsQ0FBQztBQUN4RCxjQUFjLG1DQUFtQyxDQUFDO0FBQ2xELGNBQWMsZ0NBQWdDLENBQUM7QUFDL0MsY0FBYyxpQ0FBaUMsQ0FBQztBQUNoRCxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsZ0NBQWdDLENBQUM7QUFDL0MsY0FBYyxtREFBbUQsQ0FBQztBQUNsRSxjQUFjLHVDQUF1QyxDQUFDO0FBQ3RELGNBQWMsc0NBQXNDLENBQUM7QUFFckQsY0FBYywrQkFBK0IsQ0FBQztBQUU5QyxjQUFjLCtCQUErQixDQUFDO0FBRTlDLGNBQWMscUJBQXFCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBQdWJsaWMgQVBJIFN1cmZhY2Ugb2YgZ3JvdXBzXHJcbiAqL1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb21wb25lbnRzL2NyZWF0ZS1ncm91cC9jcmVhdGUtZ3JvdXAuY29tcG9uZW50JztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvY29tcG9uZW50cy90cmVlLXZpZXcvdHJlZS12aWV3LmNvbXBvbmVudCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbXBvbmVudHMvZWRpdC11c2VyLXJvbGVzL2VkaXQtdXNlci1yb2xlcy5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb21wb25lbnRzL3JlY2lwcm9jYWwtY3JlZGl0LXNlY3Rpb24vcmVjaXByb2NhbC1jcmVkaXQtc2VjdGlvbi5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb21wb25lbnRzL2FkZC13b3JraW5nLWdyb3Vwcy9hZGQtd29ya2luZy1ncm91cHMuY29tcG9uZW50JztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvZ3JvdXBzLmNvbXBvbmVudCc7XHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvY3JlYXRlLWdyb3VwLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL2dyb3VwLWFjdGlvbi5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9ncm91cC1mdW5jdGlvbi10eXBlLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL2dyb3VwLWluZm8ubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvZ3JvdXAtdHlwZXMubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvdmlldy1ncm91cC5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9lZGl0LWdyb3VwLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL2RlbGV0ZS1ncm91cC5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9ncm91cC11c2VyLWluZm8ubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvYWRkLW9yLWVkaXQtdXNlci1ncm91cC5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9yb3N0ZXItZnVuY3Rpb24tdHlwZS5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9jbGFzc2lmaWNhdGlvbi5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9maWx0ZXItdHlwZS5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9vcmdhbml6YXRpb24ubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvcm9sZS10eXBlLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL3Jvc3Rlci10eXBlLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL3RhYmxlLWNvbHVtbi1zY2hlbWEtdXNlci1ncm91cC5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9wYXJlbnQtZ3JvdXBzLWluZm8ubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvcmVjaXByb2NhbC1jcmVkaXQubW9kZWwnO1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvc2VydmljZXMvZ3JvdXBzLnNlcnZpY2UnO1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvYXNzZXRzL2Zvcm0tdmFsaWRhdGlvbnMnO1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvZ3JvdXBzLm1vZHVsZSc7XHJcbiJdfQ==
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL2dyb3Vwcy9zcmMvcHVibGljLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUNILGNBQWMsc0RBQXNELENBQUM7QUFDckUsY0FBYyxnREFBZ0QsQ0FBQztBQUMvRCxjQUFjLDREQUE0RCxDQUFDO0FBQzNFLGNBQWMsZ0ZBQWdGLENBQUM7QUFDL0YsY0FBYyxrRUFBa0UsQ0FBQztBQUNqRixjQUFjLHdCQUF3QixDQUFDO0FBRXZDLGNBQWMsaUNBQWlDLENBQUM7QUFDaEQsY0FBYyxpQ0FBaUMsQ0FBQztBQUNoRCxjQUFjLHdDQUF3QyxDQUFDO0FBQ3ZELGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLCtCQUErQixDQUFDO0FBQzlDLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyxpQ0FBaUMsQ0FBQztBQUNoRCxjQUFjLG9DQUFvQyxDQUFDO0FBQ25ELGNBQWMsMkNBQTJDLENBQUM7QUFDMUQsY0FBYyx5Q0FBeUMsQ0FBQztBQUN4RCxjQUFjLG1DQUFtQyxDQUFDO0FBQ2xELGNBQWMsZ0NBQWdDLENBQUM7QUFDL0MsY0FBYyxpQ0FBaUMsQ0FBQztBQUNoRCxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsZ0NBQWdDLENBQUM7QUFDL0MsY0FBYyxtREFBbUQsQ0FBQztBQUNsRSxjQUFjLHVDQUF1QyxDQUFDO0FBQ3RELGNBQWMsc0NBQXNDLENBQUM7QUFFckQsY0FBYywrQkFBK0IsQ0FBQztBQUM5QyxjQUFjLHNDQUFzQyxDQUFDO0FBRXJELGNBQWMsK0JBQStCLENBQUM7QUFFOUMsY0FBYyxxQkFBcUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXHJcbiAqIFB1YmxpYyBBUEkgU3VyZmFjZSBvZiBncm91cHNcclxuICovXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbXBvbmVudHMvY3JlYXRlLWdyb3VwL2NyZWF0ZS1ncm91cC5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jb21wb25lbnRzL3RyZWUtdmlldy90cmVlLXZpZXcuY29tcG9uZW50JztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvY29tcG9uZW50cy9lZGl0LXVzZXItcm9sZXMvZWRpdC11c2VyLXJvbGVzLmNvbXBvbmVudCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbXBvbmVudHMvcmVjaXByb2NhbC1jcmVkaXQtc2VjdGlvbi9yZWNpcHJvY2FsLWNyZWRpdC1zZWN0aW9uLmNvbXBvbmVudCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NvbXBvbmVudHMvYWRkLXdvcmtpbmctZ3JvdXBzL2FkZC13b3JraW5nLWdyb3Vwcy5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9ncm91cHMuY29tcG9uZW50JztcclxuXHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9jcmVhdGUtZ3JvdXAubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvZ3JvdXAtYWN0aW9uLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL2dyb3VwLWZ1bmN0aW9uLXR5cGUubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvZ3JvdXAtaW5mby5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9ncm91cC10eXBlcy5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy92aWV3LWdyb3VwLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL2VkaXQtZ3JvdXAubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvZGVsZXRlLWdyb3VwLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL2dyb3VwLXVzZXItaW5mby5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9hZGQtb3ItZWRpdC11c2VyLWdyb3VwLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL3Jvc3Rlci1mdW5jdGlvbi10eXBlLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL2NsYXNzaWZpY2F0aW9uLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL2ZpbHRlci10eXBlLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL29yZ2FuaXphdGlvbi5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9yb2xlLXR5cGUubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvcm9zdGVyLXR5cGUubW9kZWwnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9tb2RlbHMvdGFibGUtY29sdW1uLXNjaGVtYS11c2VyLWdyb3VwLm1vZGVsJztcclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbW9kZWxzL3BhcmVudC1ncm91cHMtaW5mby5tb2RlbCc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL21vZGVscy9yZWNpcHJvY2FsLWNyZWRpdC5tb2RlbCc7XHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9zZXJ2aWNlcy9ncm91cHMuc2VydmljZSc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL3NlcnZpY2VzL3Jvc3Rlci1leHBvcnQuc2VydmljZSc7XHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9hc3NldHMvZm9ybS12YWxpZGF0aW9ucyc7XHJcblxyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9ncm91cHMubW9kdWxlJztcclxuIl19