@aquera/ngx-smart-table 0.0.17-alpha → 0.0.18-alpha

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 (170) hide show
  1. package/{fesm2020 → fesm2022}/aquera-ngx-smart-table.mjs +1579 -2101
  2. package/fesm2022/aquera-ngx-smart-table.mjs.map +1 -0
  3. package/package.json +8 -16
  4. package/types/aquera-ngx-smart-table.d.ts +5909 -0
  5. package/aquera-ngx-smart-table.d.ts +0 -5
  6. package/esm2020/aquera-ngx-smart-table.mjs +0 -5
  7. package/esm2020/lib/builder/components/builder-preview/builder-preview.component.mjs +0 -63
  8. package/esm2020/lib/builder/components/builder-toolbar/builder-toolbar.component.mjs +0 -115
  9. package/esm2020/lib/builder/components/column-editor/column-editor.component.mjs +0 -206
  10. package/esm2020/lib/builder/components/column-list/column-list.component.mjs +0 -125
  11. package/esm2020/lib/builder/components/definition-builder/definition-builder.component.mjs +0 -105
  12. package/esm2020/lib/builder/components/table-config-editor/table-config-editor.component.mjs +0 -132
  13. package/esm2020/lib/builder/definition-builder.module.mjs +0 -70
  14. package/esm2020/lib/builder/models/builder-state.interface.mjs +0 -5
  15. package/esm2020/lib/builder/services/definition-builder.service.mjs +0 -251
  16. package/esm2020/lib/builder/services/definition-export.service.mjs +0 -167
  17. package/esm2020/lib/builder/services/definition-import.service.mjs +0 -193
  18. package/esm2020/lib/builder/services/sample-data-generator.service.mjs +0 -126
  19. package/esm2020/lib/builder/utils/config-validator.util.mjs +0 -165
  20. package/esm2020/lib/builder/utils/typescript-generator.util.mjs +0 -206
  21. package/esm2020/lib/editors/index.mjs +0 -9
  22. package/esm2020/lib/editors/nile-autocomplete-editor.mjs +0 -228
  23. package/esm2020/lib/editors/nile-calendar-editor.mjs +0 -211
  24. package/esm2020/lib/editors/nile-date-picker-editor.mjs +0 -188
  25. package/esm2020/lib/editors/nile-input-editor.mjs +0 -235
  26. package/esm2020/lib/editors/nile-select-editor.mjs +0 -498
  27. package/esm2020/lib/factories/column-config.factory.mjs +0 -231
  28. package/esm2020/lib/models/autosave-config.interface.mjs +0 -8
  29. package/esm2020/lib/models/base-column-config.class.mjs +0 -253
  30. package/esm2020/lib/models/cell-strategies.interface.mjs +0 -6
  31. package/esm2020/lib/models/cell-types.mjs +0 -147
  32. package/esm2020/lib/models/column-action.interface.mjs +0 -6
  33. package/esm2020/lib/models/column-config.interface.mjs +0 -43
  34. package/esm2020/lib/models/column-config.utils.mjs +0 -101
  35. package/esm2020/lib/models/row-action.interface.mjs +0 -5
  36. package/esm2020/lib/models/row-validator.interface.mjs +0 -2
  37. package/esm2020/lib/models/schema-validation.interface.mjs +0 -2
  38. package/esm2020/lib/models/sheet-action.interface.mjs +0 -5
  39. package/esm2020/lib/models/sheet-config.interface.mjs +0 -5
  40. package/esm2020/lib/models/table-config.interface.mjs +0 -107
  41. package/esm2020/lib/models/table-validator.interface.mjs +0 -2
  42. package/esm2020/lib/models/workbook-action.interface.mjs +0 -5
  43. package/esm2020/lib/models/workbook-config.interface.mjs +0 -5
  44. package/esm2020/lib/renderer/components/st-add-column-button/st-add-column-button.component.mjs +0 -24
  45. package/esm2020/lib/renderer/components/st-cell/st-cell.component.mjs +0 -397
  46. package/esm2020/lib/renderer/components/st-column-editor-modal/st-column-editor-modal.component.mjs +0 -103
  47. package/esm2020/lib/renderer/components/st-column-filter/st-column-filter.component.mjs +0 -383
  48. package/esm2020/lib/renderer/components/st-column-menu/st-column-menu.component.mjs +0 -232
  49. package/esm2020/lib/renderer/components/st-column-visibility/st-column-visibility.component.mjs +0 -97
  50. package/esm2020/lib/renderer/components/st-header/st-header.component.mjs +0 -157
  51. package/esm2020/lib/renderer/components/st-pagination/st-pagination.component.mjs +0 -87
  52. package/esm2020/lib/renderer/components/st-row-actions-dropdown/st-row-actions-dropdown.component.mjs +0 -167
  53. package/esm2020/lib/renderer/components/st-sheet/st-sheet.component.mjs +0 -165
  54. package/esm2020/lib/renderer/components/st-sheet-actions/st-sheet-actions.component.mjs +0 -112
  55. package/esm2020/lib/renderer/components/st-table/st-table.component.mjs +0 -1453
  56. package/esm2020/lib/renderer/components/st-table-actions/st-table-actions.component.mjs +0 -169
  57. package/esm2020/lib/renderer/components/st-workbook/st-workbook.component.mjs +0 -581
  58. package/esm2020/lib/renderer/directives/click-outside.directive.mjs +0 -28
  59. package/esm2020/lib/renderer/directives/st-column-resize.directive.mjs +0 -108
  60. package/esm2020/lib/renderer/directives/st-keyboard-navigation.directive.mjs +0 -83
  61. package/esm2020/lib/renderer/models/cell-state.interface.mjs +0 -66
  62. package/esm2020/lib/renderer/models/cell.class.mjs +0 -389
  63. package/esm2020/lib/renderer/models/row-validation-state.interface.mjs +0 -7
  64. package/esm2020/lib/renderer/models/sheet-state.class.mjs +0 -90
  65. package/esm2020/lib/renderer/models/sheet-state.interface.mjs +0 -5
  66. package/esm2020/lib/renderer/models/table-state.class.mjs +0 -871
  67. package/esm2020/lib/renderer/models/table-state.interface.mjs +0 -5
  68. package/esm2020/lib/renderer/models/table-types.mjs +0 -29
  69. package/esm2020/lib/renderer/models/table-validation-state.interface.mjs +0 -7
  70. package/esm2020/lib/renderer/models/workbook-state.class.mjs +0 -174
  71. package/esm2020/lib/renderer/models/workbook-state.interface.mjs +0 -5
  72. package/esm2020/lib/renderer/models/z-index.enum.mjs +0 -55
  73. package/esm2020/lib/schemas/table-config.schema.mjs +0 -472
  74. package/esm2020/lib/services/autosave.service.mjs +0 -92
  75. package/esm2020/lib/services/custom-validation-rules.util.mjs +0 -124
  76. package/esm2020/lib/services/json-schema-validator.service.mjs +0 -216
  77. package/esm2020/lib/services/row-validation.service.mjs +0 -42
  78. package/esm2020/lib/services/validation-logger.service.mjs +0 -177
  79. package/esm2020/lib/services/virtual-scroll.service.mjs +0 -52
  80. package/esm2020/lib/shared/shared-table-components.module.mjs +0 -35
  81. package/esm2020/lib/smart-table.module.mjs +0 -124
  82. package/esm2020/lib/strategies/default-editors.mjs +0 -433
  83. package/esm2020/lib/strategies/default-formatters.mjs +0 -238
  84. package/esm2020/lib/strategies/default-validators.mjs +0 -327
  85. package/esm2020/public-api.mjs +0 -146
  86. package/fesm2015/aquera-ngx-smart-table.mjs +0 -12347
  87. package/fesm2015/aquera-ngx-smart-table.mjs.map +0 -1
  88. package/fesm2020/aquera-ngx-smart-table.mjs.map +0 -1
  89. package/lib/builder/components/builder-preview/builder-preview.component.d.ts +0 -31
  90. package/lib/builder/components/builder-toolbar/builder-toolbar.component.d.ts +0 -53
  91. package/lib/builder/components/column-editor/column-editor.component.d.ts +0 -69
  92. package/lib/builder/components/column-list/column-list.component.d.ts +0 -65
  93. package/lib/builder/components/definition-builder/definition-builder.component.d.ts +0 -58
  94. package/lib/builder/components/table-config-editor/table-config-editor.component.d.ts +0 -32
  95. package/lib/builder/definition-builder.module.d.ts +0 -15
  96. package/lib/builder/models/builder-state.interface.d.ts +0 -93
  97. package/lib/builder/services/definition-builder.service.d.ts +0 -80
  98. package/lib/builder/services/definition-export.service.d.ts +0 -59
  99. package/lib/builder/services/definition-import.service.d.ts +0 -31
  100. package/lib/builder/services/sample-data-generator.service.d.ts +0 -41
  101. package/lib/builder/utils/config-validator.util.d.ts +0 -32
  102. package/lib/builder/utils/typescript-generator.util.d.ts +0 -29
  103. package/lib/editors/index.d.ts +0 -8
  104. package/lib/editors/nile-autocomplete-editor.d.ts +0 -102
  105. package/lib/editors/nile-calendar-editor.d.ts +0 -88
  106. package/lib/editors/nile-date-picker-editor.d.ts +0 -97
  107. package/lib/editors/nile-input-editor.d.ts +0 -67
  108. package/lib/editors/nile-select-editor.d.ts +0 -113
  109. package/lib/factories/column-config.factory.d.ts +0 -73
  110. package/lib/models/autosave-config.interface.d.ts +0 -23
  111. package/lib/models/base-column-config.class.d.ts +0 -115
  112. package/lib/models/cell-strategies.interface.d.ts +0 -188
  113. package/lib/models/cell-types.d.ts +0 -337
  114. package/lib/models/column-action.interface.d.ts +0 -86
  115. package/lib/models/column-config.interface.d.ts +0 -272
  116. package/lib/models/column-config.utils.d.ts +0 -37
  117. package/lib/models/row-action.interface.d.ts +0 -86
  118. package/lib/models/row-validator.interface.d.ts +0 -37
  119. package/lib/models/schema-validation.interface.d.ts +0 -42
  120. package/lib/models/sheet-action.interface.d.ts +0 -59
  121. package/lib/models/sheet-config.interface.d.ts +0 -41
  122. package/lib/models/table-config.interface.d.ts +0 -251
  123. package/lib/models/table-validator.interface.d.ts +0 -40
  124. package/lib/models/workbook-action.interface.d.ts +0 -95
  125. package/lib/models/workbook-config.interface.d.ts +0 -107
  126. package/lib/renderer/components/st-add-column-button/st-add-column-button.component.d.ts +0 -9
  127. package/lib/renderer/components/st-cell/st-cell.component.d.ts +0 -69
  128. package/lib/renderer/components/st-column-editor-modal/st-column-editor-modal.component.d.ts +0 -39
  129. package/lib/renderer/components/st-column-filter/st-column-filter.component.d.ts +0 -139
  130. package/lib/renderer/components/st-column-menu/st-column-menu.component.d.ts +0 -81
  131. package/lib/renderer/components/st-column-visibility/st-column-visibility.component.d.ts +0 -44
  132. package/lib/renderer/components/st-header/st-header.component.d.ts +0 -93
  133. package/lib/renderer/components/st-pagination/st-pagination.component.d.ts +0 -42
  134. package/lib/renderer/components/st-row-actions-dropdown/st-row-actions-dropdown.component.d.ts +0 -67
  135. package/lib/renderer/components/st-sheet/st-sheet.component.d.ts +0 -98
  136. package/lib/renderer/components/st-sheet-actions/st-sheet-actions.component.d.ts +0 -58
  137. package/lib/renderer/components/st-table/st-table.component.d.ts +0 -380
  138. package/lib/renderer/components/st-table-actions/st-table-actions.component.d.ts +0 -77
  139. package/lib/renderer/components/st-workbook/st-workbook.component.d.ts +0 -275
  140. package/lib/renderer/directives/click-outside.directive.d.ts +0 -10
  141. package/lib/renderer/directives/st-column-resize.directive.d.ts +0 -44
  142. package/lib/renderer/directives/st-keyboard-navigation.directive.d.ts +0 -19
  143. package/lib/renderer/models/cell-state.interface.d.ts +0 -118
  144. package/lib/renderer/models/cell.class.d.ts +0 -174
  145. package/lib/renderer/models/row-validation-state.interface.d.ts +0 -27
  146. package/lib/renderer/models/sheet-state.class.d.ts +0 -67
  147. package/lib/renderer/models/sheet-state.interface.d.ts +0 -55
  148. package/lib/renderer/models/table-state.class.d.ts +0 -320
  149. package/lib/renderer/models/table-state.interface.d.ts +0 -18
  150. package/lib/renderer/models/table-types.d.ts +0 -228
  151. package/lib/renderer/models/table-validation-state.interface.d.ts +0 -34
  152. package/lib/renderer/models/workbook-state.class.d.ts +0 -117
  153. package/lib/renderer/models/workbook-state.interface.d.ts +0 -71
  154. package/lib/renderer/models/z-index.enum.d.ts +0 -44
  155. package/lib/schemas/table-config.schema.d.ts +0 -455
  156. package/lib/services/autosave.service.d.ts +0 -73
  157. package/lib/services/custom-validation-rules.util.d.ts +0 -12
  158. package/lib/services/json-schema-validator.service.d.ts +0 -49
  159. package/lib/services/row-validation.service.d.ts +0 -17
  160. package/lib/services/validation-logger.service.d.ts +0 -87
  161. package/lib/services/virtual-scroll.service.d.ts +0 -44
  162. package/lib/shared/shared-table-components.module.d.ts +0 -9
  163. package/lib/smart-table.module.d.ts +0 -26
  164. package/lib/strategies/default-editors.d.ts +0 -109
  165. package/lib/strategies/default-formatters.d.ts +0 -116
  166. package/lib/strategies/default-validators.d.ts +0 -113
  167. package/public-api.d.ts +0 -70
  168. package/src/lib/builder/README.md +0 -30
  169. package/src/lib/editors/README.md +0 -303
  170. package/src/lib/renderer/components/st-column-filter/README.md +0 -286
@@ -1,871 +0,0 @@
1
- /**
2
- * TableState - Reactive state management for table operations
3
- * Event-driven architecture: tracks state, emits events, consumer handles async data operations
4
- */
5
- import { BehaviorSubject, Subject } from 'rxjs';
6
- import { map, distinctUntilChanged } from 'rxjs/operators';
7
- import { SortDirection, FilterOperator } from './table-types';
8
- import { NavigationDirection } from '../../models/cell-types';
9
- /**
10
- * TableState class - Column-driven, event-emitting state management
11
- * NO data manipulation - only state tracking and event emission
12
- */
13
- export class TableState {
14
- /**
15
- * Constructor
16
- * @param columns Reference to columns array
17
- * @param config Initial configuration
18
- */
19
- constructor(columns, config) {
20
- // Row number column width for sticky offset calculation
21
- this._rowNumberWidth = 0;
22
- // Settings column width for sticky offset calculation
23
- this._settingsColumnWidth = 0;
24
- // Pending focus position after a new row is added
25
- // Set when requestAddRow is emitted, cleared when focus is applied
26
- this._pendingFocusAfterRowAdd = null;
27
- // Dimensions for boundary checking
28
- this._rowCount = 0;
29
- this._columnCount = 0;
30
- this._columns = columns;
31
- this._initialConfig = {
32
- initialPage: config?.initialPage ?? 0,
33
- pageSize: config?.pageSize ?? 25
34
- };
35
- // Initialize pagination state
36
- this._pagination$ = new BehaviorSubject({
37
- currentPage: this._initialConfig.initialPage,
38
- pageSize: this._initialConfig.pageSize,
39
- totalItems: 0,
40
- totalPages: 0
41
- });
42
- // Initialize state change subject
43
- this._stateChange$ = new Subject();
44
- // Initialize focus and editing position tracking
45
- this._focusedCellPosition$ = new BehaviorSubject(null);
46
- this.focusedCellPosition$ = this._focusedCellPosition$.asObservable();
47
- this._editingCellPosition$ = new BehaviorSubject(null);
48
- this.editingCellPosition$ = this._editingCellPosition$.asObservable();
49
- // Initialize validation state
50
- this._tableValidationState$ = new BehaviorSubject({
51
- isValid: true,
52
- totalRows: 0,
53
- validRows: 0,
54
- invalidRows: 0,
55
- rowStates: new Map(),
56
- lastUpdated: new Date()
57
- });
58
- this.tableValidationState$ = this._tableValidationState$.asObservable();
59
- // Initialize request add row subject
60
- this._requestAddRow$ = new Subject();
61
- this.requestAddRow$ = this._requestAddRow$.asObservable();
62
- this._columnCount = columns.filter(c => c.visible !== false).length;
63
- // Setup observables
64
- this.paginationChange$ = this._pagination$.asObservable().pipe(distinctUntilChanged((a, b) => a.currentPage === b.currentPage &&
65
- a.pageSize === b.pageSize &&
66
- a.totalItems === b.totalItems));
67
- this.state$ = this._pagination$.pipe(map(() => this.buildStateSnapshot()));
68
- this.stateChange$ = this._stateChange$.asObservable();
69
- // Clear focus/editing on pagination changes
70
- this.paginationChange$.subscribe(() => {
71
- this.clearFocus();
72
- this.clearEditingCell();
73
- });
74
- }
75
- // ============================================================================
76
- // STATE ACCESS METHODS
77
- // ============================================================================
78
- /**
79
- * Get current state snapshot
80
- */
81
- getState() {
82
- return this.buildStateSnapshot();
83
- }
84
- /**
85
- * Get current pagination state
86
- */
87
- getPagination() {
88
- return { ...this._pagination$.value };
89
- }
90
- /**
91
- * Get columns with sorting enabled
92
- */
93
- getSortedColumns() {
94
- return this._columns.filter(col => col.sortEnabled === true);
95
- }
96
- /**
97
- * Get columns with filtering enabled
98
- */
99
- getFilteredColumns() {
100
- return this._columns.filter(col => col.filterConfig?.enabled === true);
101
- }
102
- /**
103
- * Get current columns reference
104
- */
105
- getColumns() {
106
- return this._columns;
107
- }
108
- // ============================================================================
109
- // PAGINATION METHODS
110
- // ============================================================================
111
- /**
112
- * Set current page
113
- * @param page Page number (0-indexed)
114
- */
115
- setPage(page) {
116
- const currentState = this._pagination$.value;
117
- if (page < 0 || page >= currentState.totalPages) {
118
- console.warn(`Invalid page number: ${page}. Valid range: 0-${currentState.totalPages - 1}`);
119
- return;
120
- }
121
- this._pagination$.next({
122
- ...currentState,
123
- currentPage: page
124
- });
125
- this.emitStateChange('pagination');
126
- }
127
- /**
128
- * Set page size
129
- * @param size Number of items per page
130
- */
131
- setPageSize(size) {
132
- if (size <= 0) {
133
- console.warn(`Invalid page size: ${size}. Must be greater than 0.`);
134
- return;
135
- }
136
- const currentState = this._pagination$.value;
137
- const newTotalPages = this.calculateTotalPages(currentState.totalItems, size);
138
- this._pagination$.next({
139
- currentPage: 0,
140
- pageSize: size,
141
- totalItems: currentState.totalItems,
142
- totalPages: newTotalPages
143
- });
144
- this.emitStateChange('pagination');
145
- }
146
- /**
147
- * Set total items (called after API response)
148
- * @param total Total number of items
149
- */
150
- setTotalItems(total) {
151
- const currentState = this._pagination$.value;
152
- const newTotalPages = this.calculateTotalPages(total, currentState.pageSize);
153
- this._pagination$.next({
154
- ...currentState,
155
- totalItems: total,
156
- totalPages: newTotalPages
157
- });
158
- // Don't emit state change here - this is called after data load
159
- }
160
- /**
161
- * Go to next page
162
- */
163
- nextPage() {
164
- const currentState = this._pagination$.value;
165
- if (this.hasNextPage()) {
166
- this.setPage(currentState.currentPage + 1);
167
- }
168
- }
169
- /**
170
- * Go to previous page
171
- */
172
- previousPage() {
173
- const currentState = this._pagination$.value;
174
- if (this.hasPreviousPage()) {
175
- this.setPage(currentState.currentPage - 1);
176
- }
177
- }
178
- /**
179
- * Go to first page
180
- */
181
- firstPage() {
182
- this.setPage(0);
183
- }
184
- /**
185
- * Go to last page
186
- */
187
- lastPage() {
188
- const currentState = this._pagination$.value;
189
- if (currentState.totalPages > 0) {
190
- this.setPage(currentState.totalPages - 1);
191
- }
192
- }
193
- /**
194
- * Check if there is a next page
195
- */
196
- hasNextPage() {
197
- const currentState = this._pagination$.value;
198
- return currentState.currentPage < currentState.totalPages - 1;
199
- }
200
- /**
201
- * Check if there is a previous page
202
- */
203
- hasPreviousPage() {
204
- const currentState = this._pagination$.value;
205
- return currentState.currentPage > 0;
206
- }
207
- // ============================================================================
208
- // SORTING METHODS (operate on column configs)
209
- // ============================================================================
210
- /**
211
- * Set sort on a column (clears other sorts)
212
- * @param columnKey Column key
213
- * @param direction Sort direction
214
- */
215
- setSortOnColumn(columnKey, direction) {
216
- const column = this.findColumn(columnKey);
217
- if (!column) {
218
- console.warn(`Column not found: ${columnKey}`);
219
- return;
220
- }
221
- if (column.sortable === false) {
222
- console.warn(`Column ${columnKey} is not sortable`);
223
- return;
224
- }
225
- // Clear all other sorts
226
- this._columns.forEach(col => {
227
- if (col.key !== columnKey) {
228
- col.sortDirection = SortDirection.NONE;
229
- col.sortEnabled = false;
230
- }
231
- });
232
- // Set sort on target column
233
- column.sortDirection = direction;
234
- column.sortEnabled = direction !== SortDirection.NONE;
235
- this.emitStateChange('sorting');
236
- }
237
- /**
238
- * Add sort to a column (for multi-column sorting)
239
- * @param columnKey Column key
240
- * @param direction Sort direction
241
- */
242
- addSortToColumn(columnKey, direction) {
243
- const column = this.findColumn(columnKey);
244
- if (!column) {
245
- console.warn(`Column not found: ${columnKey}`);
246
- return;
247
- }
248
- if (column.sortable === false) {
249
- console.warn(`Column ${columnKey} is not sortable`);
250
- return;
251
- }
252
- column.sortDirection = direction;
253
- column.sortEnabled = direction !== SortDirection.NONE;
254
- this.emitStateChange('sorting');
255
- }
256
- /**
257
- * Toggle sort on a column (cycles through none -> asc -> desc -> none)
258
- * @param columnKey Column key
259
- */
260
- toggleSortOnColumn(columnKey) {
261
- const column = this.findColumn(columnKey);
262
- if (!column) {
263
- console.warn(`Column not found: ${columnKey}`);
264
- return;
265
- }
266
- if (column.sortable === false) {
267
- console.warn(`Column ${columnKey} is not sortable`);
268
- return;
269
- }
270
- const currentDirection = column.sortDirection || SortDirection.NONE;
271
- let newDirection;
272
- switch (currentDirection) {
273
- case SortDirection.NONE:
274
- newDirection = SortDirection.ASC;
275
- break;
276
- case SortDirection.ASC:
277
- newDirection = SortDirection.DESC;
278
- break;
279
- case SortDirection.DESC:
280
- newDirection = SortDirection.NONE;
281
- break;
282
- default:
283
- newDirection = SortDirection.ASC;
284
- }
285
- column.sortDirection = newDirection;
286
- column.sortEnabled = newDirection !== SortDirection.NONE;
287
- this.clearFocus();
288
- this.clearEditingCell();
289
- this.emitStateChange('sorting');
290
- }
291
- /**
292
- * Clear all sorting
293
- */
294
- clearAllSorting() {
295
- this._columns.forEach(col => {
296
- col.sortDirection = SortDirection.NONE;
297
- col.sortEnabled = false;
298
- });
299
- this.clearFocus();
300
- this.clearEditingCell();
301
- this.emitStateChange('sorting');
302
- }
303
- /**
304
- * Get sort configuration for a column
305
- * @param columnKey Column key
306
- * @returns Sort configuration or null
307
- */
308
- getSortForColumn(columnKey) {
309
- const column = this.findColumn(columnKey);
310
- if (!column) {
311
- return null;
312
- }
313
- return {
314
- direction: column.sortDirection || SortDirection.NONE,
315
- enabled: column.sortEnabled || false
316
- };
317
- }
318
- // ============================================================================
319
- // FILTERING METHODS (operate on column configs)
320
- // ============================================================================
321
- /**
322
- * Set filter on a column
323
- * @param columnKey Column key
324
- * @param operator Filter operator
325
- * @param value Filter value
326
- */
327
- setFilterOnColumn(columnKey, operator, value) {
328
- const column = this.findColumn(columnKey);
329
- if (!column) {
330
- console.warn(`Column not found: ${columnKey}`);
331
- return;
332
- }
333
- if (column.filterable === false) {
334
- console.warn(`Column ${columnKey} is not filterable`);
335
- return;
336
- }
337
- // Initialize filterConfig if it doesn't exist
338
- if (!column.filterConfig) {
339
- column.filterConfig = {};
340
- }
341
- column.filterConfig.operator = operator;
342
- column.filterConfig.value = value;
343
- column.filterConfig.enabled = true;
344
- this.clearFocus();
345
- this.clearEditingCell();
346
- this.emitStateChange('filtering');
347
- }
348
- /**
349
- * Clear filter on a column
350
- * @param columnKey Column key
351
- */
352
- clearFilterOnColumn(columnKey) {
353
- const column = this.findColumn(columnKey);
354
- if (!column) {
355
- console.warn(`Column not found: ${columnKey}`);
356
- return;
357
- }
358
- // Initialize filterConfig if it doesn't exist (for consistency with setFilterOnColumn)
359
- if (!column.filterConfig) {
360
- column.filterConfig = {};
361
- }
362
- column.filterConfig.value = undefined;
363
- column.filterConfig.enabled = false;
364
- this.clearFocus();
365
- this.clearEditingCell();
366
- this.emitStateChange('filtering');
367
- }
368
- /**
369
- * Clear all filters
370
- */
371
- clearAllFilters() {
372
- this._columns.forEach(col => {
373
- // Initialize filterConfig if it doesn't exist (for consistency with setFilterOnColumn)
374
- if (!col.filterConfig) {
375
- col.filterConfig = {};
376
- }
377
- col.filterConfig.value = undefined;
378
- col.filterConfig.enabled = false;
379
- });
380
- this.clearFocus();
381
- this.clearEditingCell();
382
- this.emitStateChange('filtering');
383
- }
384
- /**
385
- * Set filter enabled state
386
- * @param columnKey Column key
387
- * @param enabled Whether filter is enabled
388
- */
389
- setFilterEnabled(columnKey, enabled) {
390
- const column = this.findColumn(columnKey);
391
- if (!column) {
392
- console.warn(`Column not found: ${columnKey}`);
393
- return;
394
- }
395
- // Initialize filterConfig if it doesn't exist
396
- if (!column.filterConfig) {
397
- column.filterConfig = {};
398
- }
399
- column.filterConfig.enabled = enabled;
400
- this.emitStateChange('filtering');
401
- }
402
- /**
403
- * Get filter configuration for a column
404
- * @param columnKey Column key
405
- * @returns Filter configuration or null
406
- */
407
- getFilterForColumn(columnKey) {
408
- const column = this.findColumn(columnKey);
409
- if (!column) {
410
- return null;
411
- }
412
- return {
413
- operator: column.filterConfig?.operator || FilterOperator.CONTAINS,
414
- value: column.filterConfig?.value,
415
- enabled: column.filterConfig?.enabled || false
416
- };
417
- }
418
- // ============================================================================
419
- // STICKY COLUMN MANAGEMENT
420
- // ============================================================================
421
- /**
422
- * Get sticky columns grouped by position
423
- * @returns Object with left and right sticky column keys
424
- */
425
- getStickyColumns() {
426
- const left = this._columns
427
- .filter(col => col.sticky === 'left')
428
- .map(col => col.key);
429
- const right = this._columns
430
- .filter(col => col.sticky === 'right')
431
- .map(col => col.key);
432
- return { left, right };
433
- }
434
- /**
435
- * Set sticky position for a column
436
- * @param columnKey Column key
437
- * @param position Sticky position ('left', 'right', or false)
438
- */
439
- setStickyColumn(columnKey, position) {
440
- const column = this.findColumn(columnKey);
441
- if (!column) {
442
- console.warn(`Column not found: ${columnKey}`);
443
- return;
444
- }
445
- column.sticky = position;
446
- this.calculateStickyOffsets();
447
- this.emitStateChange('column-config');
448
- }
449
- /**
450
- * Calculate sticky offsets for all sticky columns
451
- * This calculates cumulative widths for positioning
452
- * @param rowNumberWidth Optional width of row number column to account for in left offset
453
- * @param settingsColumnWidth Optional width of settings column to account for in right offset
454
- */
455
- calculateStickyOffsets(rowNumberWidth, settingsColumnWidth) {
456
- // Update stored row number width if provided
457
- if (rowNumberWidth !== undefined) {
458
- this._rowNumberWidth = rowNumberWidth;
459
- }
460
- // Update stored settings column width if provided
461
- if (settingsColumnWidth !== undefined) {
462
- this._settingsColumnWidth = settingsColumnWidth;
463
- }
464
- // Calculate left sticky offsets
465
- // Account for row number column width
466
- let leftOffset = this._rowNumberWidth;
467
- this._columns.forEach(col => {
468
- if (col.sticky === 'left') {
469
- col.stickyOffset = leftOffset;
470
- leftOffset += col.width || 100;
471
- }
472
- });
473
- // Calculate right sticky offsets
474
- // Account for settings column width (row actions column)
475
- let rightOffset = this._settingsColumnWidth;
476
- for (let i = this._columns.length - 1; i >= 0; i--) {
477
- const col = this._columns[i];
478
- if (col.sticky === 'right') {
479
- col.stickyOffset = rightOffset;
480
- rightOffset += col.width || 100;
481
- }
482
- }
483
- }
484
- // ============================================================================
485
- // COLUMN MANAGEMENT
486
- // ============================================================================
487
- /**
488
- * Update columns reference
489
- * @param columns New columns array
490
- */
491
- updateColumns(columns) {
492
- this._columns = columns;
493
- this.calculateStickyOffsets();
494
- this.emitStateChange('column-config');
495
- }
496
- // ============================================================================
497
- // COLUMN VISIBILITY METHODS
498
- // ============================================================================
499
- /**
500
- * Toggle visibility of a column
501
- * @param columnKey Column key
502
- */
503
- toggleColumnVisibility(columnKey) {
504
- const column = this.findColumn(columnKey);
505
- if (!column) {
506
- console.warn(`Column not found: ${columnKey}`);
507
- return;
508
- }
509
- // Check if column is hideable
510
- if (column.hideable === false) {
511
- console.warn(`Column ${columnKey} cannot be hidden (hideable is false)`);
512
- return;
513
- }
514
- const currentVisibility = column.visible !== false; // Default to true if not set
515
- column.visible = !currentVisibility;
516
- this.emitStateChange('column-visibility');
517
- }
518
- /**
519
- * Set visibility of a column
520
- * @param columnKey Column key
521
- * @param visible Whether column should be visible
522
- */
523
- setColumnVisibility(columnKey, visible) {
524
- const column = this.findColumn(columnKey);
525
- if (!column) {
526
- console.warn(`Column not found: ${columnKey}`);
527
- return;
528
- }
529
- // Check if column is hideable (only when trying to hide)
530
- if (!visible && column.hideable === false) {
531
- console.warn(`Column ${columnKey} cannot be hidden (hideable is false)`);
532
- return;
533
- }
534
- column.visible = visible;
535
- this.emitStateChange('column-visibility');
536
- }
537
- /**
538
- * Get all visible columns
539
- * @returns Array of visible column configs
540
- */
541
- getVisibleColumns() {
542
- return this._columns.filter(col => col.visible !== false); // Default to true if not set
543
- }
544
- /**
545
- * Get visibility state for all columns
546
- * @returns Array of column visibility info
547
- */
548
- getAllColumnsVisibility() {
549
- return this._columns.map(col => ({
550
- key: col.key,
551
- header: col.header || col.key,
552
- visible: col.visible !== false,
553
- hideable: col.hideable !== false // Default to true if not set
554
- }));
555
- }
556
- // ============================================================================
557
- // KEYBOARD NAVIGATION & FOCUS MANAGEMENT
558
- // ============================================================================
559
- /**
560
- * Set table dimensions for navigation boundaries
561
- */
562
- setDimensions(rowCount, columnCount) {
563
- const previousRowCount = this._rowCount;
564
- this._rowCount = rowCount;
565
- this._columnCount = columnCount;
566
- // Update total rows in validation state
567
- this.setValidationRowCount(rowCount);
568
- // Check if a new row was added and we have a pending focus
569
- if (this._pendingFocusAfterRowAdd && rowCount > previousRowCount) {
570
- const { columnIndex } = this._pendingFocusAfterRowAdd;
571
- // Focus the last row (newly added) at the pending column
572
- const newRowIndex = rowCount - 1;
573
- this._pendingFocusAfterRowAdd = null; // Clear pending focus
574
- // Delay focus to ensure DOM is updated
575
- setTimeout(() => {
576
- this.focusCell(newRowIndex, columnIndex);
577
- }, 0);
578
- }
579
- }
580
- /**
581
- * Focus a cell by position
582
- */
583
- focusCell(rowIndex, columnIndex) {
584
- if (rowIndex < 0 || rowIndex >= this._rowCount)
585
- return;
586
- if (columnIndex < 0 || columnIndex >= this._columnCount)
587
- return;
588
- this._focusedCellPosition$.next({ rowIndex, columnIndex });
589
- this.emitStateChange('cell-focus');
590
- }
591
- /**
592
- * Get currently focused position
593
- */
594
- getFocusedPosition() {
595
- return this._focusedCellPosition$.value;
596
- }
597
- /**
598
- * Notify that a cell entered edit mode
599
- */
600
- setEditingCell(rowIndex, columnIndex) {
601
- this._editingCellPosition$.next({ rowIndex, columnIndex });
602
- this.emitStateChange('cell-edit-start');
603
- }
604
- /**
605
- * Notify that edit mode ended
606
- */
607
- clearEditingCell() {
608
- this._editingCellPosition$.next(null);
609
- this.emitStateChange('cell-edit-end');
610
- }
611
- /**
612
- * Check if any cell is currently editing
613
- */
614
- isAnyCellEditing() {
615
- return this._editingCellPosition$.value !== null;
616
- }
617
- /**
618
- * Get currently editing position
619
- */
620
- getEditingPosition() {
621
- return this._editingCellPosition$.value;
622
- }
623
- /**
624
- * Move focus in a direction using NavigationDirection enum
625
- * @param direction The navigation direction
626
- * @param addRowOnNavigatePastEnd If true, emits requestAddRow when navigating past last row
627
- */
628
- moveFocus(direction, addRowOnNavigatePastEnd = false) {
629
- // Block navigation if any cell is editing
630
- if (this.isAnyCellEditing()) {
631
- return false;
632
- }
633
- const current = this._focusedCellPosition$.value;
634
- if (!current)
635
- return false;
636
- let newRow = current.rowIndex;
637
- let newCol = current.columnIndex;
638
- // Use NavigationDirection enum values
639
- switch (direction) {
640
- case NavigationDirection.UP:
641
- newRow--;
642
- break;
643
- case NavigationDirection.DOWN:
644
- newRow++;
645
- break;
646
- case NavigationDirection.LEFT:
647
- newCol--;
648
- break;
649
- case NavigationDirection.RIGHT:
650
- newCol++;
651
- break;
652
- }
653
- // Check if navigating past last row (arrow down at bottom)
654
- if (direction === NavigationDirection.DOWN && newRow >= this._rowCount) {
655
- if (addRowOnNavigatePastEnd) {
656
- // Store pending focus for when the new row is added
657
- this._pendingFocusAfterRowAdd = { columnIndex: current.columnIndex };
658
- // Emit request to add a new row, keeping the same column for focus
659
- this._requestAddRow$.next({ focusColumn: current.columnIndex });
660
- }
661
- return false;
662
- }
663
- if (newRow < 0 || newRow >= this._rowCount)
664
- return false;
665
- if (newCol < 0 || newCol >= this._columnCount)
666
- return false;
667
- this.focusCell(newRow, newCol);
668
- return true;
669
- }
670
- /**
671
- * Clear focus
672
- */
673
- clearFocus() {
674
- this._focusedCellPosition$.next(null);
675
- this.emitStateChange('cell-focus');
676
- }
677
- /**
678
- * Check if navigation is active
679
- */
680
- isNavigationActive() {
681
- return this._focusedCellPosition$.value !== null;
682
- }
683
- // ============================================================================
684
- // VALIDATION STATE METHODS
685
- // ============================================================================
686
- /**
687
- * Update cell validation and accumulate into row/table validation state
688
- * Only stores invalid states - valid rows are automatically removed
689
- */
690
- updateCellValidation(rowIndex, columnKey, isValid, error) {
691
- const currentState = this._tableValidationState$.value;
692
- const rowStates = new Map(currentState.rowStates);
693
- // Get existing row state (only exists if row has errors)
694
- let rowState = rowStates.get(rowIndex);
695
- if (!isValid && error) {
696
- // Cell is invalid - add or update error
697
- if (!rowState) {
698
- // Create new row state for this invalid row
699
- rowState = {
700
- rowIndex,
701
- isValid: false,
702
- invalidCellCount: 1,
703
- cellErrors: new Map([[columnKey, error]]),
704
- lastValidated: new Date()
705
- };
706
- }
707
- else {
708
- // Update existing row state
709
- const cellErrors = new Map(rowState.cellErrors);
710
- cellErrors.set(columnKey, error);
711
- rowState = {
712
- rowIndex,
713
- isValid: false,
714
- invalidCellCount: cellErrors.size,
715
- cellErrors,
716
- lastValidated: new Date()
717
- };
718
- }
719
- rowStates.set(rowIndex, rowState);
720
- }
721
- else {
722
- // Cell is valid - remove error if it exists
723
- if (rowState) {
724
- const cellErrors = new Map(rowState.cellErrors);
725
- cellErrors.delete(columnKey);
726
- if (cellErrors.size === 0) {
727
- // No more errors in this row - remove row state completely
728
- rowStates.delete(rowIndex);
729
- }
730
- else {
731
- // Still has other errors - update row state
732
- rowState = {
733
- rowIndex,
734
- isValid: false,
735
- invalidCellCount: cellErrors.size,
736
- cellErrors,
737
- lastValidated: new Date()
738
- };
739
- rowStates.set(rowIndex, rowState);
740
- }
741
- }
742
- // If rowState doesn't exist, cell was already valid - do nothing
743
- }
744
- // Recalculate table state
745
- // All rows in rowStates map are invalid by definition
746
- const invalidRows = rowStates.size;
747
- const newTableState = {
748
- isValid: invalidRows === 0,
749
- totalRows: currentState.totalRows,
750
- validRows: currentState.totalRows - invalidRows,
751
- invalidRows,
752
- rowStates,
753
- lastUpdated: new Date()
754
- };
755
- // Emit new state
756
- this._tableValidationState$.next(newTableState);
757
- }
758
- /**
759
- * Get current table validation state
760
- */
761
- getTableValidationState() {
762
- return this._tableValidationState$.value;
763
- }
764
- /**
765
- * Set total rows for validation state tracking
766
- */
767
- setValidationRowCount(totalRows) {
768
- const currentState = this._tableValidationState$.value;
769
- this._tableValidationState$.next({
770
- ...currentState,
771
- totalRows,
772
- lastUpdated: new Date()
773
- });
774
- }
775
- // ============================================================================
776
- // STATE RESET
777
- // ============================================================================
778
- /**
779
- * Reset to initial configuration
780
- */
781
- reset() {
782
- this.resetPagination();
783
- this.resetAllSorting();
784
- this.resetAllFilters();
785
- }
786
- /**
787
- * Reset pagination only
788
- */
789
- resetPagination() {
790
- this._pagination$.next({
791
- currentPage: this._initialConfig.initialPage,
792
- pageSize: this._initialConfig.pageSize,
793
- totalItems: 0,
794
- totalPages: 0
795
- });
796
- this.emitStateChange('pagination');
797
- }
798
- /**
799
- * Reset all column sorts
800
- */
801
- resetAllSorting() {
802
- this.clearAllSorting();
803
- }
804
- /**
805
- * Reset all column filters
806
- */
807
- resetAllFilters() {
808
- this.clearAllFilters();
809
- }
810
- // ============================================================================
811
- // INTERNAL METHODS
812
- // ============================================================================
813
- /**
814
- * Find a column by key
815
- * @param columnKey Column key
816
- * @returns Column config or undefined
817
- */
818
- findColumn(columnKey) {
819
- return this._columns.find(col => col.key === columnKey);
820
- }
821
- /**
822
- * Calculate total pages
823
- * @param totalItems Total number of items
824
- * @param pageSize Page size
825
- * @returns Total number of pages
826
- */
827
- calculateTotalPages(totalItems = 0, pageSize = 25) {
828
- if (totalItems === 0 || pageSize === 0) {
829
- return 0;
830
- }
831
- return Math.ceil(totalItems / pageSize);
832
- }
833
- /**
834
- * Emit state change event
835
- * @param type Type of change
836
- */
837
- emitStateChange(type) {
838
- const state = this.buildStateSnapshot();
839
- this._stateChange$.next({
840
- type,
841
- state
842
- });
843
- }
844
- /**
845
- * Build state snapshot from current state
846
- * @returns State snapshot
847
- */
848
- buildStateSnapshot() {
849
- return {
850
- pagination: this.getPagination(),
851
- // Build full sort state with direction and priority
852
- sortedColumns: this._columns
853
- .filter(col => col.sortEnabled === true)
854
- .map((col, index) => ({
855
- columnKey: col.key,
856
- direction: col.sortDirection || SortDirection.NONE,
857
- priority: index // Sort order based on enablement order
858
- })),
859
- // Build full filter state with operator and value
860
- filteredColumns: this._columns
861
- .filter(col => col.filterConfig?.enabled === true)
862
- .map(col => ({
863
- columnKey: col.key,
864
- operator: col.filterConfig?.operator || FilterOperator.CONTAINS,
865
- value: col.filterConfig?.value,
866
- enabled: true
867
- }))
868
- };
869
- }
870
- }
871
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtc3RhdGUuY2xhc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zbWFydC10YWJsZS9zcmMvbGliL3JlbmRlcmVyL21vZGVscy90YWJsZS1zdGF0ZS5jbGFzcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsZUFBZSxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUM1RCxPQUFPLEVBQUUsR0FBRyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFM0QsT0FBTyxFQUVMLGFBQWEsRUFDYixjQUFjLEVBSWYsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFJOUQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUEwRHJCOzs7O09BSUc7SUFDSCxZQUFZLE9BQTRCLEVBQUUsTUFBeUI7UUFsRG5FLHdEQUF3RDtRQUNoRCxvQkFBZSxHQUFXLENBQUMsQ0FBQztRQUVwQyxzREFBc0Q7UUFDOUMseUJBQW9CLEdBQVcsQ0FBQyxDQUFDO1FBa0J6QyxrREFBa0Q7UUFDbEQsbUVBQW1FO1FBQzNELDZCQUF3QixHQUFtQyxJQUFJLENBQUM7UUFFeEUsbUNBQW1DO1FBQzNCLGNBQVMsR0FBVyxDQUFDLENBQUM7UUFDdEIsaUJBQVksR0FBVyxDQUFDLENBQUM7UUF1Qi9CLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1FBQ3hCLElBQUksQ0FBQyxjQUFjLEdBQUc7WUFDcEIsV0FBVyxFQUFFLE1BQU0sRUFBRSxXQUFXLElBQUksQ0FBQztZQUNyQyxRQUFRLEVBQUUsTUFBTSxFQUFFLFFBQVEsSUFBSSxFQUFFO1NBQ2pDLENBQUM7UUFFRiw4QkFBOEI7UUFDOUIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLGVBQWUsQ0FBa0I7WUFDdkQsV0FBVyxFQUFFLElB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QUMsYUFBYSxDQUFDLElBQUksQ0FBQztZQUN0QixJQUFJO1lBQ0osS0FBSztTQUNOLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7O09BR0c7SUFDSyxrQkFBa0I7UUFDeEIsT0FBTztZQUNMLFVBQVUsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFO1lBRWhDLG9EQUFvRDtZQUNwRCxhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVE7aUJBQ3pCLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEtBQUssSUFBSSxDQUFDO2lCQUN2QyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUNwQixTQUFTLEVBQUUsR0FBRyxDQUFDLEdBQUc7Z0JBQ2xCLFNBQVMsRUFBRSxHQUFHLENBQUMsYUFBYSxJQUFJLGFBQWEsQ0FBQyxJQUFJO2dCQUNsRCxRQUFRLEVBQUUsS0FBSyxDQUFFLHVDQUF1QzthQUN6RCxDQUFDLENBQUM7WUFFTCxrREFBa0Q7WUFDbEQsZUFBZSxFQUFFLElBQUksQ0FBQyxRQUFRO2lCQUMzQixNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLE9BQU8sS0FBSyxJQUFJLENBQUM7aUJBQ2pELEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQ1gsU0FBUyxFQUFFLEdBQUcsQ0FBQyxHQUFHO2dCQUNsQixRQUFRLEVBQUUsR0FBRyxDQUFDLFlBQVksRUFBRSxRQUFRLElBQUksY0FBYyxDQUFDLFFBQVE7Z0JBQy9ELEtBQUssRUFBRSxHQUFHLENBQUMsWUFBWSxFQUFFLEtBQUs7Z0JBQzlCLE9BQU8sRUFBRSxJQUFJO2FBQ2QsQ0FBQyxDQUFDO1NBQ04sQ0FBQztJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGFibGVTdGF0ZSAtIFJlYWN0aXZlIHN0YXRlIG1hbmFnZW1lbnQgZm9yIHRhYmxlIG9wZXJhdGlvbnNcbiAqIEV2ZW50LWRyaXZlbiBhcmNoaXRlY3R1cmU6IHRyYWNrcyBzdGF0ZSwgZW1pdHMgZXZlbnRzLCBjb25zdW1lciBoYW5kbGVzIGFzeW5jIGRhdGEgb3BlcmF0aW9uc1xuICovXG5cbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IENvbHVtbkNvbmZpZyB9IGZyb20gJy4uLy4uL21vZGVscy9jb2x1bW4tY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBcbiAgUGFnaW5hdGlvblN0YXRlLCBcbiAgU29ydERpcmVjdGlvbiwgXG4gIEZpbHRlck9wZXJhdG9yLFxuICBUYWJsZVN0YXRlQ2hhbmdlRXZlbnQsXG4gIFRhYmxlU3RhdGVTbmFwc2hvdCxcbiAgQ2VsbEZvY3VzUG9zaXRpb25cbn0gZnJvbSAnLi90YWJsZS10eXBlcyc7XG5pbXBvcnQgeyBUYWJsZVN0YXRlQ29uZmlnIH0gZnJvbSAnLi90YWJsZS1zdGF0ZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgTmF2aWdhdGlvbkRpcmVjdGlvbiB9IGZyb20gJy4uLy4uL21vZGVscy9jZWxsLXR5cGVzJztcbmltcG9ydCB7IFJvd1ZhbGlkYXRpb25TdGF0ZSB9IGZyb20gJy4vcm93LXZhbGlkYXRpb24tc3RhdGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IFRhYmxlVmFsaWRhdGlvblN0YXRlIH0gZnJvbSAnLi90YWJsZS12YWxpZGF0aW9uLXN0YXRlLmludGVyZmFjZSc7XG5cbi8qKlxuICogVGFibGVTdGF0ZSBjbGFzcyAtIENvbHVtbi1kcml2ZW4sIGV2ZW50LWVtaXR0aW5nIHN0YXRlIG1hbmFnZW1lbnRcbiAqIE5PIGRhdGEgbWFuaXB1bGF0aW9uIC0gb25seSBzdGF0ZSB0cmFja2luZyBhbmQgZXZlbnQgZW1pc3Npb25cbiAqL1xuZXhwb3J0IGNsYXNzIFRhYmxlU3RhdGUge1xuICAvLyBSZWZlcmVuY2UgdG8gY29sdW1ucyBhcnJheSAoY29sdW1uLWRyaXZlbiBhcmNoaXRlY3R1cmUpXG4gIHByaXZhdGUgX2NvbHVtbnM6IENvbHVtbkNvbmZpZzxhbnk+W107XG4gIFxuICAvLyBQYWdpbmF0aW9uIHN0YXRlXG4gIHByaXZhdGUgX3BhZ2luYXRpb24kOiBCZWhhdmlvclN1YmplY3Q8UGFnaW5hdGlvblN0YXRlPjtcbiAgXG4gIC8vIFN0YXRlIGNoYW5nZSBldmVudHNcbiAgcHJpdmF0ZSBfc3RhdGVDaGFuZ2UkOiBTdWJqZWN0PFRhYmxlU3RhdGVDaGFuZ2VFdmVudD47XG4gIFxuICAvLyBJbml0aWFsIGNvbmZpZ3VyYXRpb25cbiAgcHJpdmF0ZSBfaW5pdGlhbENvbmZpZzogVGFibGVTdGF0ZUNvbmZpZztcbiAgXG4gIC8vIFJvdyBudW1iZXIgY29sdW1uIHdpZHRoIGZvciBzdGlja3kgb2Zmc2V0IGNhbGN1bGF0aW9uXG4gIHByaXZhdGUgX3Jvd051bWJlcldpZHRoOiBudW1iZXIgPSAwO1xuXG4gIC8vIFNldHRpbmdzIGNvbHVtbiB3aWR0aCBmb3Igc3RpY2t5IG9mZnNldCBjYWxjdWxhdGlvblxuICBwcml2YXRlIF9zZXR0aW5nc0NvbHVtbldpZHRoOiBudW1iZXIgPSAwO1xuICBcbiAgLy8gRm9jdXMgcG9zaXRpb24gdHJhY2tpbmdcbiAgcHJpdmF0ZSBfZm9jdXNlZENlbGxQb3NpdGlvbiQ6IEJlaGF2aW9yU3ViamVjdDxDZWxsRm9jdXNQb3NpdGlvbiB8IG51bGw+O1xuICBwdWJsaWMgcmVhZG9ubHkgZm9jdXNlZENlbGxQb3NpdGlvbiQ6IE9ic2VydmFibGU8Q2VsbEZvY3VzUG9zaXRpb24gfCBudWxsPjtcbiAgXG4gIC8vIEVkaXRpbmcgcG9zaXRpb24gdHJhY2tpbmdcbiAgcHJpdmF0ZSBfZWRpdGluZ0NlbGxQb3NpdGlvbiQ6IEJlaGF2aW9yU3ViamVjdDxDZWxsRm9jdXNQb3NpdGlvbiB8IG51bGw+O1xuICBwdWJsaWMgcmVhZG9ubHkgZWRpdGluZ0NlbGxQb3NpdGlvbiQ6IE9ic2VydmFibGU8Q2VsbEZvY3VzUG9zaXRpb24gfCBudWxsPjtcbiAgXG4gIC8vIFZhbGlkYXRpb24gc3RhdGUgdHJhY2tpbmdcbiAgcHJpdmF0ZSBfdGFibGVWYWxpZGF0aW9uU3RhdGUkOiBCZWhhdmlvclN1YmplY3Q8VGFibGVWYWxpZGF0aW9uU3RhdGU+O1xuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVWYWxpZGF0aW9uU3RhdGUkOiBPYnNlcnZhYmxlPFRhYmxlVmFsaWRhdGlvblN0YXRlPjtcbiAgXG4gIC8vIFJlcXVlc3QgdG8gYWRkIGEgbmV3IHJvdyAoZW1pdHRlZCB3aGVuIG5hdmlnYXRpbmcgcGFzdCBsYXN0IHJvdylcbiAgcHJpdmF0ZSBfcmVxdWVzdEFkZFJvdyQ6IFN1YmplY3Q8eyBmb2N1c0NvbHVtbjogbnVtYmVyIH0+O1xuICBwdWJsaWMgcmVhZG9ubHkgcmVxdWVzdEFkZFJvdyQ6IE9ic2VydmFibGU8eyBmb2N1c0NvbHVtbjogbnVtYmVyIH0+O1xuICBcbiAgLy8gUGVuZGluZyBmb2N1cyBwb3NpdGlvbiBhZnRlciBhIG5ldyByb3cgaXMgYWRkZWRcbiAgLy8gU2V0IHdoZW4gcmVxdWVzdEFkZFJvdyBpcyBlbWl0dGVkLCBjbGVhcmVkIHdoZW4gZm9jdXMgaXMgYXBwbGllZFxuICBwcml2YXRlIF9wZW5kaW5nRm9jdXNBZnRlclJvd0FkZDogeyBjb2x1bW5JbmRleDogbnVtYmVyIH0gfCBudWxsID0gbnVsbDtcbiAgXG4gIC8vIERpbWVuc2lvbnMgZm9yIGJvdW5kYXJ5IGNoZWNraW5nXG4gIHByaXZhdGUgX3Jvd0NvdW50OiBudW1iZXIgPSAwO1xuICBwcml2YXRlIF9jb2x1bW5Db3VudDogbnVtYmVyID0gMDtcblxuICAvKipcbiAgICogT2JzZXJ2YWJsZSBvZiBjb21wbGV0ZSBzdGF0ZSBzbmFwc2hvdFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHN0YXRlJDogT2JzZXJ2YWJsZTxUYWJsZVN0YXRlU25hcHNob3Q+O1xuXG4gIC8qKlxuICAgKiBPYnNlcnZhYmxlIG9mIHN0YXRlIGNoYW5nZSBldmVudHNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzdGF0ZUNoYW5nZSQ6IE9ic2VydmFibGU8VGFibGVTdGF0ZUNoYW5nZUV2ZW50PjtcblxuICAvKipcbiAgICogT2JzZXJ2YWJsZSBvZiBwYWdpbmF0aW9uIHN0YXRlIGNoYW5nZXNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBwYWdpbmF0aW9uQ2hhbmdlJDogT2JzZXJ2YWJsZTxQYWdpbmF0aW9uU3RhdGU+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0gY29sdW1ucyBSZWZlcmVuY2UgdG8gY29sdW1ucyBhcnJheVxuICAgKiBAcGFyYW0gY29uZmlnIEluaXRpYWwgY29uZmlndXJhdGlvblxuICAgKi9cbiAgY29uc3RydWN0b3IoY29sdW1uczogQ29sdW1uQ29uZmlnPGFueT5bXSwgY29uZmlnPzogVGFibGVTdGF0ZUNvbmZpZykge1xuICAgIHRoaXMuX2NvbHVtbnMgPSBjb2x1bW5zO1xuICAgIHRoaXMuX2luaXRpYWxDb25maWcgPSB7XG4gICAgICBpbml0aWFsUGFnZTogY29uZmlnPy5pbml0aWFsUGFnZSA/PyAwLFxuICAgICAgcGFnZVNpemU6IGNvbmZpZz8ucGFnZVNpemUgPz8gMjVcbiAgICB9O1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBwYWdpbmF0aW9uIHN0YXRlXG4gICAgdGhpcy5fcGFnaW5hdGlvbiQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFBhZ2luYXRpb25TdGF0ZT4oe1xuICAgICAgY3VycmVudFBhZ2U6IHRoaXMuX2luaXRpYWxDb25maWcuaW5pdGlhbFBhZ2UhLFxuICAgICAgcGFnZVNpemU6IHRoaXMuX2luaXRpYWxDb25maWcucGFnZVNpemUhLFxuICAgICAgdG90YWxJdGVtczogMCxcbiAgICAgIHRvdGFsUGFnZXM6IDBcbiAgICB9KTtcblxuICAgIC8vIEluaXRpYWxpemUgc3RhdGUgY2hhbmdlIHN1YmplY3RcbiAgICB0aGlzLl9zdGF0ZUNoYW5nZSQgPSBuZXcgU3ViamVjdDxUYWJsZVN0YXRlQ2hhbmdlRXZlbnQ+KCk7XG4gICAgXG4gICAgLy8gSW5pdGlhbGl6ZSBmb2N1cyBhbmQgZWRpdGluZyBwb3NpdGlvbiB0cmFja2luZ1xuICAgIHRoaXMuX2ZvY3VzZWRDZWxsUG9zaXRpb24kID0gbmV3IEJlaGF2aW9yU3ViamVjdDxDZWxsRm9jdXNQb3NpdGlvbiB8IG51bGw+KG51bGwpO1xuICAgIHRoaXMuZm9jdXNlZENlbGxQb3NpdGlvbiQgPSB0aGlzLl9mb2N1c2VkQ2VsbFBvc2l0aW9uJC5hc09ic2VydmFibGUoKTtcbiAgICBcbiAgICB0aGlzLl9lZGl0aW5nQ2VsbFBvc2l0aW9uJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Q2VsbEZvY3VzUG9zaXRpb24gfCBudWxsPihudWxsKTtcbiAgICB0aGlzLmVkaXRpbmdDZWxsUG9zaXRpb24kID0gdGhpcy5fZWRpdGluZ0NlbGxQb3NpdGlvbiQuYXNPYnNlcnZhYmxlKCk7XG4gICAgXG4gICAgLy8gSW5pdGlhbGl6ZSB2YWxpZGF0aW9uIHN0YXRlXG4gICAgdGhpcy5fdGFibGVWYWxpZGF0aW9uU3RhdGUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxUYWJsZVZhbGlkYXRpb25TdGF0ZT4oe1xuICAgICAgaXNWYWxpZDogdHJ1ZSxcbiAgICAgIHRvdGFsUm93czogMCxcbiAgICAgIHZhbGlkUm93czogMCxcbiAgICAgIGludmFsaWRSb3dzOiAwLFxuICAgICAgcm93U3RhdGVzOiBuZXcgTWFwKCksXG4gICAgICBsYXN0VXBkYXRlZDogbmV3IERhdGUoKVxuICAgIH0pO1xuICAgIHRoaXMudGFibGVWYWxpZGF0aW9uU3RhdGUkID0gdGhpcy5fdGFibGVWYWxpZGF0aW9uU3RhdGUkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIFxuICAgIC8vIEluaXRpYWxpemUgcmVxdWVzdCBhZGQgcm93IHN1YmplY3RcbiAgICB0aGlzLl9yZXF1ZXN0QWRkUm93JCA9IG5ldyBTdWJqZWN0PHsgZm9jdXNDb2x1bW46IG51bWJlciB9PigpO1xuICAgIHRoaXMucmVxdWVzdEFkZFJvdyQgPSB0aGlzLl9yZXF1ZXN0QWRkUm93JC5hc09ic2VydmFibGUoKTtcbiAgICBcbiAgICB0aGlzLl9jb2x1bW5Db3VudCA9IGNvbHVtbnMuZmlsdGVyKGMgPT4gYy52aXNpYmxlICE9PSBmYWxzZSkubGVuZ3RoO1xuXG4gICAgLy8gU2V0dXAgb2JzZXJ2YWJsZXNcbiAgICB0aGlzLnBhZ2luYXRpb25DaGFuZ2UkID0gdGhpcy5fcGFnaW5hdGlvbiQuYXNPYnNlcnZhYmxlKCkucGlwZShcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKChhLCBiKSA9PiBcbiAgICAgICAgYS5jdXJyZW50UGFnZSA9PT0gYi5jdXJyZW50UGFnZSAmJiBcbiAgICAgICAgYS5wYWdlU2l6ZSA9PT0gYi5wYWdlU2l6ZSAmJlxuICAgICAgICBhLnRvdGFsSXRlbXMgPT09IGIudG90YWxJdGVtc1xuICAgICAgKVxuICAgICk7XG5cbiAgICB0aGlzLnN0YXRlJCA9IHRoaXMuX3BhZ2luYXRpb24kLnBpcGUoXG4gICAgICBtYXAoKCkgPT4gdGhpcy5idWlsZFN0YXRlU25hcHNob3QoKSlcbiAgICApO1xuXG4gICAgdGhpcy5zdGF0ZUNoYW5nZSQgPSB0aGlzLl9zdGF0ZUNoYW5nZSQuYXNPYnNlcnZhYmxlKCk7XG4gICAgXG4gICAgLy8gQ2xlYXIgZm9jdXMvZWRpdGluZyBvbiBwYWdpbmF0aW9uIGNoYW5nZXNcbiAgICB0aGlzLnBhZ2luYXRpb25DaGFuZ2UkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLmNsZWFyRm9jdXMoKTtcbiAgICAgIHRoaXMuY2xlYXJFZGl0aW5nQ2VsbCgpO1xuICAgIH0pO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBTVEFURSBBQ0NFU1MgTUVUSE9EU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IHN0YXRlIHNuYXBzaG90XG4gICAqL1xuICBnZXRTdGF0ZSgpOiBUYWJsZVN0YXRlU25hcHNob3Qge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkU3RhdGVTbmFwc2hvdCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IHBhZ2luYXRpb24gc3RhdGVcbiAgICovXG4gIGdldFBhZ2luYXRpb24oKTogUGFnaW5hdGlvblN0YXRlIHtcbiAgICByZXR1cm4geyAuLi50aGlzLl9wYWdpbmF0aW9uJC52YWx1ZSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjb2x1bW5zIHdpdGggc29ydGluZyBlbmFibGVkXG4gICAqL1xuICBnZXRTb3J0ZWRDb2x1bW5zKCk6IENvbHVtbkNvbmZpZzxhbnk+W10ge1xuICAgIHJldHVybiB0aGlzLl9jb2x1bW5zLmZpbHRlcihjb2wgPT4gY29sLnNvcnRFbmFibGVkID09PSB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY29sdW1ucyB3aXRoIGZpbHRlcmluZyBlbmFibGVkXG4gICAqL1xuICBnZXRGaWx0ZXJlZENvbHVtbnMoKTogQ29sdW1uQ29uZmlnPGFueT5bXSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbHVtbnMuZmlsdGVyKGNvbCA9PiBjb2wuZmlsdGVyQ29uZmlnPy5lbmFibGVkID09PSB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY3VycmVudCBjb2x1bW5zIHJlZmVyZW5jZVxuICAgKi9cbiAgZ2V0Q29sdW1ucygpOiBDb2x1bW5Db25maWc8YW55PltdIHtcbiAgICByZXR1cm4gdGhpcy5fY29sdW1ucztcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gUEFHSU5BVElPTiBNRVRIT0RTXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogU2V0IGN1cnJlbnQgcGFnZVxuICAgKiBAcGFyYW0gcGFnZSBQYWdlIG51bWJlciAoMC1pbmRleGVkKVxuICAgKi9cbiAgc2V0UGFnZShwYWdlOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLl9wYWdpbmF0aW9uJC52YWx1ZTtcbiAgICBpZiAocGFnZSA8IDAgfHwgcGFnZSA+PSBjdXJyZW50U3RhdGUudG90YWxQYWdlcykge1xuICAgICAgY29uc29sZS53YXJuKGBJbnZhbGlkIHBhZ2UgbnVtYmVyOiAke3BhZ2V9LiBWYWxpZCByYW5nZTogMC0ke2N1cnJlbnRTdGF0ZS50b3RhbFBhZ2VzIC0gMX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9wYWdpbmF0aW9uJC5uZXh0KHtcbiAgICAgIC4uLmN1cnJlbnRTdGF0ZSxcbiAgICAgIGN1cnJlbnRQYWdlOiBwYWdlXG4gICAgfSk7XG4gICAgdGhpcy5lbWl0U3RhdGVDaGFuZ2UoJ3BhZ2luYXRpb24nKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgcGFnZSBzaXplXG4gICAqIEBwYXJhbSBzaXplIE51bWJlciBvZiBpdGVtcyBwZXIgcGFnZVxuICAgKi9cbiAgc2V0UGFnZVNpemUoc2l6ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHNpemUgPD0gMCkge1xuICAgICAgY29uc29sZS53YXJuKGBJbnZhbGlkIHBhZ2Ugc2l6ZTogJHtzaXplfS4gTXVzdCBiZSBncmVhdGVyIHRoYW4gMC5gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLl9wYWdpbmF0aW9uJC52YWx1ZTtcbiAgICBjb25zdCBuZXdUb3RhbFBhZ2VzID0gdGhpcy5jYWxjdWxhdGVUb3RhbFBhZ2VzKGN1cnJlbnRTdGF0ZS50b3RhbEl0ZW1zLCBzaXplKTtcbiAgICBcbiAgICB0aGlzLl9wYWdpbmF0aW9uJC5uZXh0KHtcbiAgICAgIGN1cnJlbnRQYWdlOiAwLCAvLyBSZXNldCB0byBmaXJzdCBwYWdlXG4gICAgICBwYWdlU2l6ZTogc2l6ZSxcbiAgICAgIHRvdGFsSXRlbXM6IGN1cnJlbnRTdGF0ZS50b3RhbEl0ZW1zLFxuICAgICAgdG90YWxQYWdlczogbmV3VG90YWxQYWdlc1xuICAgIH0pO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdwYWdpbmF0aW9uJyk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRvdGFsIGl0ZW1zIChjYWxsZWQgYWZ0ZXIgQVBJIHJlc3BvbnNlKVxuICAgKiBAcGFyYW0gdG90YWwgVG90YWwgbnVtYmVyIG9mIGl0ZW1zXG4gICAqL1xuICBzZXRUb3RhbEl0ZW1zKHRvdGFsOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLl9wYWdpbmF0aW9uJC52YWx1ZTtcbiAgICBjb25zdCBuZXdUb3RhbFBhZ2VzID0gdGhpcy5jYWxjdWxhdGVUb3RhbFBhZ2VzKHRvdGFsLCBjdXJyZW50U3RhdGUucGFnZVNpemUpO1xuICAgIFxuICAgIHRoaXMuX3BhZ2luYXRpb24kLm5leHQoe1xuICAgICAgLi4uY3VycmVudFN0YXRlLFxuICAgICAgdG90YWxJdGVtczogdG90YWwsXG4gICAgICB0b3RhbFBhZ2VzOiBuZXdUb3RhbFBhZ2VzXG4gICAgfSk7XG4gICAgLy8gRG9uJ3QgZW1pdCBzdGF0ZSBjaGFuZ2UgaGVyZSAtIHRoaXMgaXMgY2FsbGVkIGFmdGVyIGRhdGEgbG9hZFxuICB9XG5cbiAgLyoqXG4gICAqIEdvIHRvIG5leHQgcGFnZVxuICAgKi9cbiAgbmV4dFBhZ2UoKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy5fcGFnaW5hdGlvbiQudmFsdWU7XG4gICAgaWYgKHRoaXMuaGFzTmV4dFBhZ2UoKSkge1xuICAgICAgdGhpcy5zZXRQYWdlKGN1cnJlbnRTdGF0ZS5jdXJyZW50UGFnZSArIDEpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHbyB0byBwcmV2aW91cyBwYWdlXG4gICAqL1xuICBwcmV2aW91c1BhZ2UoKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy5fcGFnaW5hdGlvbiQudmFsdWU7XG4gICAgaWYgKHRoaXMuaGFzUHJldmlvdXNQYWdlKCkpIHtcbiAgICAgIHRoaXMuc2V0UGFnZShjdXJyZW50U3RhdGUuY3VycmVudFBhZ2UgLSAxKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR28gdG8gZmlyc3QgcGFnZVxuICAgKi9cbiAgZmlyc3RQYWdlKCk6IHZvaWQge1xuICAgIHRoaXMuc2V0UGFnZSgwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHbyB0byBsYXN0IHBhZ2VcbiAgICovXG4gIGxhc3RQYWdlKCk6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMuX3BhZ2luYXRpb24kLnZhbHVlO1xuICAgIGlmIChjdXJyZW50U3RhdGUudG90YWxQYWdlcyA+IDApIHtcbiAgICAgIHRoaXMuc2V0UGFnZShjdXJyZW50U3RhdGUudG90YWxQYWdlcyAtIDEpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGVyZSBpcyBhIG5leHQgcGFnZVxuICAgKi9cbiAgaGFzTmV4dFBhZ2UoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy5fcGFnaW5hdGlvbiQudmFsdWU7XG4gICAgcmV0dXJuIGN1cnJlbnRTdGF0ZS5jdXJyZW50UGFnZSA8IGN1cnJlbnRTdGF0ZS50b3RhbFBhZ2VzIC0gMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGVyZSBpcyBhIHByZXZpb3VzIHBhZ2VcbiAgICovXG4gIGhhc1ByZXZpb3VzUGFnZSgpOiBib29sZWFuIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLl9wYWdpbmF0aW9uJC52YWx1ZTtcbiAgICByZXR1cm4gY3VycmVudFN0YXRlLmN1cnJlbnRQYWdlID4gMDtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gU09SVElORyBNRVRIT0RTIChvcGVyYXRlIG9uIGNvbHVtbiBjb25maWdzKVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIFNldCBzb3J0IG9uIGEgY29sdW1uIChjbGVhcnMgb3RoZXIgc29ydHMpXG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcGFyYW0gZGlyZWN0aW9uIFNvcnQgZGlyZWN0aW9uXG4gICAqL1xuICBzZXRTb3J0T25Db2x1bW4oY29sdW1uS2V5OiBzdHJpbmcsIGRpcmVjdGlvbjogU29ydERpcmVjdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZmluZENvbHVtbihjb2x1bW5LZXkpO1xuICAgIGlmICghY29sdW1uKSB7XG4gICAgICBjb25zb2xlLndhcm4oYENvbHVtbiBub3QgZm91bmQ6ICR7Y29sdW1uS2V5fWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChjb2x1bW4uc29ydGFibGUgPT09IGZhbHNlKSB7XG4gICAgICBjb25zb2xlLndhcm4oYENvbHVtbiAke2NvbHVtbktleX0gaXMgbm90IHNvcnRhYmxlYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2xlYXIgYWxsIG90aGVyIHNvcnRzXG4gICAgdGhpcy5fY29sdW1ucy5mb3JFYWNoKGNvbCA9PiB7XG4gICAgICBpZiAoY29sLmtleSAhPT0gY29sdW1uS2V5KSB7XG4gICAgICAgIGNvbC5zb3J0RGlyZWN0aW9uID0gU29ydERpcmVjdGlvbi5OT05FO1xuICAgICAgICBjb2wuc29ydEVuYWJsZWQgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFNldCBzb3J0IG9uIHRhcmdldCBjb2x1bW5cbiAgICBjb2x1bW4uc29ydERpcmVjdGlvbiA9IGRpcmVjdGlvbjtcbiAgICBjb2x1bW4uc29ydEVuYWJsZWQgPSBkaXJlY3Rpb24gIT09IFNvcnREaXJlY3Rpb24uTk9ORTtcblxuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdzb3J0aW5nJyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHNvcnQgdG8gYSBjb2x1bW4gKGZvciBtdWx0aS1jb2x1bW4gc29ydGluZylcbiAgICogQHBhcmFtIGNvbHVtbktleSBDb2x1bW4ga2V5XG4gICAqIEBwYXJhbSBkaXJlY3Rpb24gU29ydCBkaXJlY3Rpb25cbiAgICovXG4gIGFkZFNvcnRUb0NvbHVtbihjb2x1bW5LZXk6IHN0cmluZywgZGlyZWN0aW9uOiBTb3J0RGlyZWN0aW9uKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5maW5kQ29sdW1uKGNvbHVtbktleSk7XG4gICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uIG5vdCBmb3VuZDogJHtjb2x1bW5LZXl9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNvbHVtbi5zb3J0YWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgIGNvbnNvbGUud2FybihgQ29sdW1uICR7Y29sdW1uS2V5fSBpcyBub3Qgc29ydGFibGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb2x1bW4uc29ydERpcmVjdGlvbiA9IGRpcmVjdGlvbjtcbiAgICBjb2x1bW4uc29ydEVuYWJsZWQgPSBkaXJlY3Rpb24gIT09IFNvcnREaXJlY3Rpb24uTk9ORTtcblxuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdzb3J0aW5nJyk7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlIHNvcnQgb24gYSBjb2x1bW4gKGN5Y2xlcyB0aHJvdWdoIG5vbmUgLT4gYXNjIC0+IGRlc2MgLT4gbm9uZSlcbiAgICogQHBhcmFtIGNvbHVtbktleSBDb2x1bW4ga2V5XG4gICAqL1xuICB0b2dnbGVTb3J0T25Db2x1bW4oY29sdW1uS2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gbm90IGZvdW5kOiAke2NvbHVtbktleX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY29sdW1uLnNvcnRhYmxlID09PSBmYWxzZSkge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gJHtjb2x1bW5LZXl9IGlzIG5vdCBzb3J0YWJsZWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnREaXJlY3Rpb24gPSBjb2x1bW4uc29ydERpcmVjdGlvbiB8fCBTb3J0RGlyZWN0aW9uLk5PTkU7XG4gICAgbGV0IG5ld0RpcmVjdGlvbjogU29ydERpcmVjdGlvbjtcblxuICAgIHN3aXRjaCAoY3VycmVudERpcmVjdGlvbikge1xuICAgICAgY2FzZSBTb3J0RGlyZWN0aW9uLk5PTkU6XG4gICAgICAgIG5ld0RpcmVjdGlvbiA9IFNvcnREaXJlY3Rpb24uQVNDO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgU29ydERpcmVjdGlvbi5BU0M6XG4gICAgICAgIG5ld0RpcmVjdGlvbiA9IFNvcnREaXJlY3Rpb24uREVTQztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFNvcnREaXJlY3Rpb24uREVTQzpcbiAgICAgICAgbmV3RGlyZWN0aW9uID0gU29ydERpcmVjdGlvbi5OT05FO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIG5ld0RpcmVjdGlvbiA9IFNvcnREaXJlY3Rpb24uQVNDO1xuICAgIH1cblxuICAgIGNvbHVtbi5zb3J0RGlyZWN0aW9uID0gbmV3RGlyZWN0aW9uO1xuICAgIGNvbHVtbi5zb3J0RW5hYmxlZCA9IG5ld0RpcmVjdGlvbiAhPT0gU29ydERpcmVjdGlvbi5OT05FO1xuXG4gICAgdGhpcy5jbGVhckZvY3VzKCk7XG4gICAgdGhpcy5jbGVhckVkaXRpbmdDZWxsKCk7XG4gICAgdGhpcy5lbWl0U3RhdGVDaGFuZ2UoJ3NvcnRpbmcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhciBhbGwgc29ydGluZ1xuICAgKi9cbiAgY2xlYXJBbGxTb3J0aW5nKCk6IHZvaWQge1xuICAgIHRoaXMuX2NvbHVtbnMuZm9yRWFjaChjb2wgPT4ge1xuICAgICAgY29sLnNvcnREaXJlY3Rpb24gPSBTb3J0RGlyZWN0aW9uLk5PTkU7XG4gICAgICBjb2wuc29ydEVuYWJsZWQgPSBmYWxzZTtcbiAgICB9KTtcblxuICAgIHRoaXMuY2xlYXJGb2N1cygpO1xuICAgIHRoaXMuY2xlYXJFZGl0aW5nQ2VsbCgpO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdzb3J0aW5nJyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHNvcnQgY29uZmlndXJhdGlvbiBmb3IgYSBjb2x1bW5cbiAgICogQHBhcmFtIGNvbHVtbktleSBDb2x1bW4ga2V5XG4gICAqIEByZXR1cm5zIFNvcnQgY29uZmlndXJhdGlvbiBvciBudWxsXG4gICAqL1xuICBnZXRTb3J0Rm9yQ29sdW1uKGNvbHVtbktleTogc3RyaW5nKTogeyBkaXJlY3Rpb246IFNvcnREaXJlY3Rpb247IGVuYWJsZWQ6IGJvb2xlYW4gfSB8IG51bGwge1xuICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZmluZENvbHVtbihjb2x1bW5LZXkpO1xuICAgIGlmICghY29sdW1uKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGlyZWN0aW9uOiBjb2x1bW4uc29ydERpcmVjdGlvbiB8fCBTb3J0RGlyZWN0aW9uLk5PTkUsXG4gICAgICBlbmFibGVkOiBjb2x1bW4uc29ydEVuYWJsZWQgfHwgZmFsc2VcbiAgICB9O1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBGSUxURVJJTkcgTUVUSE9EUyAob3BlcmF0ZSBvbiBjb2x1bW4gY29uZmlncylcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBTZXQgZmlsdGVyIG9uIGEgY29sdW1uXG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcGFyYW0gb3BlcmF0b3IgRmlsdGVyIG9wZXJhdG9yXG4gICAqIEBwYXJhbSB2YWx1ZSBGaWx0ZXIgdmFsdWVcbiAgICovXG4gIHNldEZpbHRlck9uQ29sdW1uKGNvbHVtbktleTogc3RyaW5nLCBvcGVyYXRvcjogRmlsdGVyT3BlcmF0b3IsIHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gbm90IGZvdW5kOiAke2NvbHVtbktleX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoY29sdW1uLmZpbHRlcmFibGUgPT09IGZhbHNlKSB7XG4gICAgICBjb25zb2xlLndhcm4oYENvbHVtbiAke2NvbHVtbktleX0gaXMgbm90IGZpbHRlcmFibGVgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBJbml0aWFsaXplIGZpbHRlckNvbmZpZyBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgaWYgKCFjb2x1bW4uZmlsdGVyQ29uZmlnKSB7XG4gICAgICBjb2x1bW4uZmlsdGVyQ29uZmlnID0ge307XG4gICAgfVxuXG4gICAgY29sdW1uLmZpbHRlckNvbmZpZy5vcGVyYXRvciA9IG9wZXJhdG9yO1xuICAgIGNvbHVtbi5maWx0ZXJDb25maWcudmFsdWUgPSB2YWx1ZTtcbiAgICBjb2x1bW4uZmlsdGVyQ29uZmlnLmVuYWJsZWQgPSB0cnVlO1xuXG4gICAgdGhpcy5jbGVhckZvY3VzKCk7XG4gICAgdGhpcy5jbGVhckVkaXRpbmdDZWxsKCk7XG4gICAgdGhpcy5lbWl0U3RhdGVDaGFuZ2UoJ2ZpbHRlcmluZycpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFyIGZpbHRlciBvbiBhIGNvbHVtblxuICAgKiBAcGFyYW0gY29sdW1uS2V5IENvbHVtbiBrZXlcbiAgICovXG4gIGNsZWFyRmlsdGVyT25Db2x1bW4oY29sdW1uS2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gbm90IGZvdW5kOiAke2NvbHVtbktleX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBJbml0aWFsaXplIGZpbHRlckNvbmZpZyBpZiBpdCBkb2Vzbid0IGV4aXN0IChmb3IgY29uc2lzdGVuY3kgd2l0aCBzZXRGaWx0ZXJPbkNvbHVtbilcbiAgICBpZiAoIWNvbHVtbi5maWx0ZXJDb25maWcpIHtcbiAgICAgIGNvbHVtbi5maWx0ZXJDb25maWcgPSB7fTtcbiAgICB9XG5cbiAgICBjb2x1bW4uZmlsdGVyQ29uZmlnLnZhbHVlID0gdW5kZWZpbmVkO1xuICAgIGNvbHVtbi5maWx0ZXJDb25maWcuZW5hYmxlZCA9IGZhbHNlO1xuXG4gICAgdGhpcy5jbGVhckZvY3VzKCk7XG4gICAgdGhpcy5jbGVhckVkaXRpbmdDZWxsKCk7XG4gICAgdGhpcy5lbWl0U3RhdGVDaGFuZ2UoJ2ZpbHRlcmluZycpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFyIGFsbCBmaWx0ZXJzXG4gICAqL1xuICBjbGVhckFsbEZpbHRlcnMoKTogdm9pZCB7XG4gICAgdGhpcy5fY29sdW1ucy5mb3JFYWNoKGNvbCA9PiB7XG4gICAgICAvLyBJbml0aWFsaXplIGZpbHRlckNvbmZpZyBpZiBpdCBkb2Vzbid0IGV4aXN0IChmb3IgY29uc2lzdGVuY3kgd2l0aCBzZXRGaWx0ZXJPbkNvbHVtbilcbiAgICAgIGlmICghY29sLmZpbHRlckNvbmZpZykge1xuICAgICAgICBjb2wuZmlsdGVyQ29uZmlnID0ge307XG4gICAgICB9XG4gICAgICBcbiAgICAgIGNvbC5maWx0ZXJDb25maWcudmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICBjb2wuZmlsdGVyQ29uZmlnLmVuYWJsZWQgPSBmYWxzZTtcbiAgICB9KTtcblxuICAgIHRoaXMuY2xlYXJGb2N1cygpO1xuICAgIHRoaXMuY2xlYXJFZGl0aW5nQ2VsbCgpO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdmaWx0ZXJpbmcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgZmlsdGVyIGVuYWJsZWQgc3RhdGVcbiAgICogQHBhcmFtIGNvbHVtbktleSBDb2x1bW4ga2V5XG4gICAqIEBwYXJhbSBlbmFibGVkIFdoZXRoZXIgZmlsdGVyIGlzIGVuYWJsZWRcbiAgICovXG4gIHNldEZpbHRlckVuYWJsZWQoY29sdW1uS2V5OiBzdHJpbmcsIGVuYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gbm90IGZvdW5kOiAke2NvbHVtbktleX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBJbml0aWFsaXplIGZpbHRlckNvbmZpZyBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgaWYgKCFjb2x1bW4uZmlsdGVyQ29uZmlnKSB7XG4gICAgICBjb2x1bW4uZmlsdGVyQ29uZmlnID0ge307XG4gICAgfVxuXG4gICAgY29sdW1uLmZpbHRlckNvbmZpZy5lbmFibGVkID0gZW5hYmxlZDtcblxuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdmaWx0ZXJpbmcnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgZmlsdGVyIGNvbmZpZ3VyYXRpb24gZm9yIGEgY29sdW1uXG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcmV0dXJucyBGaWx0ZXIgY29uZmlndXJhdGlvbiBvciBudWxsXG4gICAqL1xuICBnZXRGaWx0ZXJGb3JDb2x1bW4oY29sdW1uS2V5OiBzdHJpbmcpOiB7IG9wZXJhdG9yOiBGaWx0ZXJPcGVyYXRvcjsgdmFsdWU6IGFueTsgZW5hYmxlZDogYm9vbGVhbiB9IHwgbnVsbCB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5maW5kQ29sdW1uKGNvbHVtbktleSk7XG4gICAgaWYgKCFjb2x1bW4pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBvcGVyYXRvcjogY29sdW1uLmZpbHRlckNvbmZpZz8ub3BlcmF0b3IgfHwgRmlsdGVyT3BlcmF0b3IuQ09OVEFJTlMsXG4gICAgICB2YWx1ZTogY29sdW1uLmZpbHRlckNvbmZpZz8udmFsdWUsXG4gICAgICBlbmFibGVkOiBjb2x1bW4uZmlsdGVyQ29uZmlnPy5lbmFibGVkIHx8IGZhbHNlXG4gICAgfTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gU1RJQ0tZIENPTFVNTiBNQU5BR0VNRU5UXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogR2V0IHN0aWNreSBjb2x1bW5zIGdyb3VwZWQgYnkgcG9zaXRpb25cbiAgICogQHJldHVybnMgT2JqZWN0IHdpdGggbGVmdCBhbmQgcmlnaHQgc3RpY2t5IGNvbHVtbiBrZXlzXG4gICAqL1xuICBnZXRTdGlja3lDb2x1bW5zKCk6IHsgbGVmdDogc3RyaW5nW107IHJpZ2h0OiBzdHJpbmdbXSB9IHtcbiAgICBjb25zdCBsZWZ0ID0gdGhpcy5fY29sdW1uc1xuICAgICAgLmZpbHRlcihjb2wgPT4gY29sLnN0aWNreSA9PT0gJ2xlZnQnKVxuICAgICAgLm1hcChjb2wgPT4gY29sLmtleSk7XG4gICAgXG4gICAgY29uc3QgcmlnaHQgPSB0aGlzLl9jb2x1bW5zXG4gICAgICAuZmlsdGVyKGNvbCA9PiBjb2wuc3RpY2t5ID09PSAncmlnaHQnKVxuICAgICAgLm1hcChjb2wgPT4gY29sLmtleSk7XG4gICAgXG4gICAgcmV0dXJuIHsgbGVmdCwgcmlnaHQgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgc3RpY2t5IHBvc2l0aW9uIGZvciBhIGNvbHVtblxuICAgKiBAcGFyYW0gY29sdW1uS2V5IENvbHVtbiBrZXlcbiAgICogQHBhcmFtIHBvc2l0aW9uIFN0aWNreSBwb3NpdGlvbiAoJ2xlZnQnLCAncmlnaHQnLCBvciBmYWxzZSlcbiAgICovXG4gIHNldFN0aWNreUNvbHVtbihjb2x1bW5LZXk6IHN0cmluZywgcG9zaXRpb246ICdsZWZ0JyB8ICdyaWdodCcgfCBmYWxzZSk6IHZvaWQge1xuICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZmluZENvbHVtbihjb2x1bW5LZXkpO1xuICAgIGlmICghY29sdW1uKSB7XG4gICAgICBjb25zb2xlLndhcm4oYENvbHVtbiBub3QgZm91bmQ6ICR7Y29sdW1uS2V5fWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIChjb2x1bW4gYXMgYW55KS5zdGlja3kgPSBwb3NpdGlvbjtcbiAgICB0aGlzLmNhbGN1bGF0ZVN0aWNreU9mZnNldHMoKTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnY29sdW1uLWNvbmZpZycpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSBzdGlja3kgb2Zmc2V0cyBmb3IgYWxsIHN0aWNreSBjb2x1bW5zXG4gICAqIFRoaXMgY2FsY3VsYXRlcyBjdW11bGF0aXZlIHdpZHRocyBmb3IgcG9zaXRpb25pbmdcbiAgICogQHBhcmFtIHJvd051bWJlcldpZHRoIE9wdGlvbmFsIHdpZHRoIG9mIHJvdyBudW1iZXIgY29sdW1uIHRvIGFjY291bnQgZm9yIGluIGxlZnQgb2Zmc2V0XG4gICAqIEBwYXJhbSBzZXR0aW5nc0NvbHVtbldpZHRoIE9wdGlvbmFsIHdpZHRoIG9mIHNldHRpbmdzIGNvbHVtbiB0byBhY2NvdW50IGZvciBpbiByaWdodCBvZmZzZXRcbiAgICovXG4gIGNhbGN1bGF0ZVN0aWNreU9mZnNldHMocm93TnVtYmVyV2lkdGg/OiBudW1iZXIsIHNldHRpbmdzQ29sdW1uV2lkdGg/OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBVcGRhdGUgc3RvcmVkIHJvdyBudW1iZXIgd2lkdGggaWYgcHJvdmlkZWRcbiAgICBpZiAocm93TnVtYmVyV2lkdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5fcm93TnVtYmVyV2lkdGggPSByb3dOdW1iZXJXaWR0aDtcbiAgICB9XG4gICAgXG4gICAgLy8gVXBkYXRlIHN0b3JlZCBzZXR0aW5ncyBjb2x1bW4gd2lkdGggaWYgcHJvdmlkZWRcbiAgICBpZiAoc2V0dGluZ3NDb2x1bW5XaWR0aCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLl9zZXR0aW5nc0NvbHVtbldpZHRoID0gc2V0dGluZ3NDb2x1bW5XaWR0aDtcbiAgICB9XG4gICAgXG4gICAgLy8gQ2FsY3VsYXRlIGxlZnQgc3RpY2t5IG9mZnNldHNcbiAgICAvLyBBY2NvdW50IGZvciByb3cgbnVtYmVyIGNvbHVtbiB3aWR0aFxuICAgIGxldCBsZWZ0T2Zmc2V0ID0gdGhpcy5fcm93TnVtYmVyV2lkdGg7XG4gICAgdGhpcy5fY29sdW1ucy5mb3JFYWNoKGNvbCA9PiB7XG4gICAgICBpZiAoY29sLnN0aWNreSA9PT0gJ2xlZnQnKSB7XG4gICAgICAgIChjb2wgYXMgYW55KS5zdGlja3lPZmZzZXQgPSBsZWZ0T2Zmc2V0O1xuICAgICAgICBsZWZ0T2Zmc2V0ICs9IChjb2wud2lkdGggYXMgbnVtYmVyKSB8fCAxMDA7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBDYWxjdWxhdGUgcmlnaHQgc3RpY2t5IG9mZnNldHNcbiAgICAvLyBBY2NvdW50IGZvciBzZXR0aW5ncyBjb2x1bW4gd2lkdGggKHJvdyBhY3Rpb25zIGNvbHVtbilcbiAgICBsZXQgcmlnaHRPZmZzZXQgPSB0aGlzLl9zZXR0aW5nc0NvbHVtbldpZHRoO1xuICAgIGZvciAobGV0IGkgPSB0aGlzLl9jb2x1bW5zLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBjb25zdCBjb2wgPSB0aGlzLl9jb2x1bW5zW2ldO1xuICAgICAgaWYgKGNvbC5zdGlja3kgPT09ICdyaWdodCcpIHtcbiAgICAgICAgKGNvbCBhcyBhbnkpLnN0aWNreU9mZnNldCA9IHJpZ2h0T2Zmc2V0O1xuICAgICAgICByaWdodE9mZnNldCArPSAoY29sLndpZHRoIGFzIG51bWJlcikgfHwgMTAwO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gQ09MVU1OIE1BTkFHRU1FTlRcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgY29sdW1ucyByZWZlcmVuY2VcbiAgICogQHBhcmFtIGNvbHVtbnMgTmV3IGNvbHVtbnMgYXJyYXlcbiAgICovXG4gIHVwZGF0ZUNvbHVtbnMoY29sdW1uczogQ29sdW1uQ29uZmlnPGFueT5bXSk6IHZvaWQge1xuICAgIHRoaXMuX2NvbHVtbnMgPSBjb2x1bW5zO1xuICAgIHRoaXMuY2FsY3VsYXRlU3RpY2t5T2Zmc2V0cygpO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdjb2x1bW4tY29uZmlnJyk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIENPTFVNTiBWSVNJQklMSVRZIE1FVEhPRFNcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBUb2dnbGUgdmlzaWJpbGl0eSBvZiBhIGNvbHVtblxuICAgKiBAcGFyYW0gY29sdW1uS2V5IENvbHVtbiBrZXlcbiAgICovXG4gIHRvZ2dsZUNvbHVtblZpc2liaWxpdHkoY29sdW1uS2V5OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmZpbmRDb2x1bW4oY29sdW1uS2V5KTtcbiAgICBpZiAoIWNvbHVtbikge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gbm90IGZvdW5kOiAke2NvbHVtbktleX1gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiBjb2x1bW4gaXMgaGlkZWFibGVcbiAgICBpZiAoY29sdW1uLmhpZGVhYmxlID09PSBmYWxzZSkge1xuICAgICAgY29uc29sZS53YXJuKGBDb2x1bW4gJHtjb2x1bW5LZXl9IGNhbm5vdCBiZSBoaWRkZW4gKGhpZGVhYmxlIGlzIGZhbHNlKWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGN1cnJlbnRWaXNpYmlsaXR5ID0gY29sdW1uLnZpc2libGUgIT09IGZhbHNlOyAvLyBEZWZhdWx0IHRvIHRydWUgaWYgbm90IHNldFxuICAgIChjb2x1bW4gYXMgYW55KS52aXNpYmxlID0gIWN1cnJlbnRWaXNpYmlsaXR5O1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdjb2x1bW4tdmlzaWJpbGl0eScpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB2aXNpYmlsaXR5IG9mIGEgY29sdW1uXG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcGFyYW0gdmlzaWJsZSBXaGV0aGVyIGNvbHVtbiBzaG91bGQgYmUgdmlzaWJsZVxuICAgKi9cbiAgc2V0Q29sdW1uVmlzaWJpbGl0eShjb2x1bW5LZXk6IHN0cmluZywgdmlzaWJsZTogYm9vbGVhbik6IHZvaWQge1xuICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuZmluZENvbHVtbihjb2x1bW5LZXkpO1xuICAgIGlmICghY29sdW1uKSB7XG4gICAgICBjb25zb2xlLndhcm4oYENvbHVtbiBub3QgZm91bmQ6ICR7Y29sdW1uS2V5fWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIGNvbHVtbiBpcyBoaWRlYWJsZSAob25seSB3aGVuIHRyeWluZyB0byBoaWRlKVxuICAgIGlmICghdmlzaWJsZSAmJiBjb2x1bW4uaGlkZWFibGUgPT09IGZhbHNlKSB7XG4gICAgICBjb25zb2xlLndhcm4oYENvbHVtbiAke2NvbHVtbktleX0gY2Fubm90IGJlIGhpZGRlbiAoaGlkZWFibGUgaXMgZmFsc2UpYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgKGNvbHVtbiBhcyBhbnkpLnZpc2libGUgPSB2aXNpYmxlO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdjb2x1bW4tdmlzaWJpbGl0eScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgdmlzaWJsZSBjb2x1bW5zXG4gICAqIEByZXR1cm5zIEFycmF5IG9mIHZpc2libGUgY29sdW1uIGNvbmZpZ3NcbiAgICovXG4gIGdldFZpc2libGVDb2x1bW5zKCk6IENvbHVtbkNvbmZpZzxhbnk+W10ge1xuICAgIHJldHVybiB0aGlzLl9jb2x1bW5zLmZpbHRlcihjb2wgPT4gY29sLnZpc2libGUgIT09IGZhbHNlKTsgLy8gRGVmYXVsdCB0byB0cnVlIGlmIG5vdCBzZXRcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdmlzaWJpbGl0eSBzdGF0ZSBmb3IgYWxsIGNvbHVtbnNcbiAgICogQHJldHVybnMgQXJyYXkgb2YgY29sdW1uIHZpc2liaWxpdHkgaW5mb1xuICAgKi9cbiAgZ2V0QWxsQ29sdW1uc1Zpc2liaWxpdHkoKTogeyBrZXk6IHN0cmluZzsgaGVhZGVyOiBzdHJpbmc7IHZpc2libGU6IGJvb2xlYW47IGhpZGVhYmxlOiBib29sZWFuIH1bXSB7XG4gICAgcmV0dXJuIHRoaXMuX2NvbHVtbnMubWFwKGNvbCA9PiAoe1xuICAgICAga2V5OiBjb2wua2V5LFxuICAgICAgaGVhZGVyOiBjb2wuaGVhZGVyIHx8IGNvbC5rZXksXG4gICAgICB2aXNpYmxlOiBjb2wudmlzaWJsZSAhPT0gZmFsc2UsIC8vIERlZmF1bHQgdG8gdHJ1ZSBpZiBub3Qgc2V0XG4gICAgICBoaWRlYWJsZTogY29sLmhpZGVhYmxlICE9PSBmYWxzZSAvLyBEZWZhdWx0IHRvIHRydWUgaWYgbm90IHNldFxuICAgIH0pKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gS0VZQk9BUkQgTkFWSUdBVElPTiAmIEZPQ1VTIE1BTkFHRU1FTlRcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBTZXQgdGFibGUgZGltZW5zaW9ucyBmb3IgbmF2aWdhdGlvbiBib3VuZGFyaWVzXG4gICAqL1xuICBzZXREaW1lbnNpb25zKHJvd0NvdW50OiBudW1iZXIsIGNvbHVtbkNvdW50OiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBwcmV2aW91c1Jvd0NvdW50ID0gdGhpcy5fcm93Q291bnQ7XG4gICAgdGhpcy5fcm93Q291bnQgPSByb3dDb3VudDtcbiAgICB0aGlzLl9jb2x1bW5Db3VudCA9IGNvbHVtbkNvdW50O1xuICAgIFxuICAgIC8vIFVwZGF0ZSB0b3RhbCByb3dzIGluIHZhbGlkYXRpb24gc3RhdGVcbiAgICB0aGlzLnNldFZhbGlkYXRpb25Sb3dDb3VudChyb3dDb3VudCk7XG4gICAgXG4gICAgLy8gQ2hlY2sgaWYgYSBuZXcgcm93IHdhcyBhZGRlZCBhbmQgd2UgaGF2ZSBhIHBlbmRpbmcgZm9jdXNcbiAgICBpZiAodGhpcy5fcGVuZGluZ0ZvY3VzQWZ0ZXJSb3dBZGQgJiYgcm93Q291bnQgPiBwcmV2aW91c1Jvd0NvdW50KSB7XG4gICAgICBjb25zdCB7IGNvbHVtbkluZGV4IH0gPSB0aGlzLl9wZW5kaW5nRm9jdXNBZnRlclJvd0FkZDtcbiAgICAgIC8vIEZvY3VzIHRoZSBsYXN0IHJvdyAobmV3bHkgYWRkZWQpIGF0IHRoZSBwZW5kaW5nIGNvbHVtblxuICAgICAgY29uc3QgbmV3Um93SW5kZXggPSByb3dDb3VudCAtIDE7XG4gICAgICB0aGlzLl9wZW5kaW5nRm9jdXNBZnRlclJvd0FkZCA9IG51bGw7IC8vIENsZWFyIHBlbmRpbmcgZm9jdXNcbiAgICAgIFxuICAgICAgLy8gRGVsYXkgZm9jdXMgdG8gZW5zdXJlIERPTSBpcyB1cGRhdGVkXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdGhpcy5mb2N1c0NlbGwobmV3Um93SW5kZXgsIGNvbHVtbkluZGV4KTtcbiAgICAgIH0sIDApO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEZvY3VzIGEgY2VsbCBieSBwb3NpdGlvblxuICAgKi9cbiAgZm9jdXNDZWxsKHJvd0luZGV4OiBudW1iZXIsIGNvbHVtbkluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAocm93SW5kZXggPCAwIHx8IHJvd0luZGV4ID49IHRoaXMuX3Jvd0NvdW50KSByZXR1cm47XG4gICAgaWYgKGNvbHVtbkluZGV4IDwgMCB8fCBjb2x1bW5JbmRleCA+PSB0aGlzLl9jb2x1bW5Db3VudCkgcmV0dXJuO1xuICAgIFxuICAgIHRoaXMuX2ZvY3VzZWRDZWxsUG9zaXRpb24kLm5leHQoeyByb3dJbmRleCwgY29sdW1uSW5kZXggfSk7XG4gICAgdGhpcy5lbWl0U3RhdGVDaGFuZ2UoJ2NlbGwtZm9jdXMnKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCBjdXJyZW50bHkgZm9jdXNlZCBwb3NpdGlvblxuICAgKi9cbiAgZ2V0Rm9jdXNlZFBvc2l0aW9uKCk6IENlbGxGb2N1c1Bvc2l0aW9uIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX2ZvY3VzZWRDZWxsUG9zaXRpb24kLnZhbHVlO1xuICB9XG4gIFxuICAvKipcbiAgICogTm90aWZ5IHRoYXQgYSBjZWxsIGVudGVyZWQgZWRpdCBtb2RlXG4gICAqL1xuICBzZXRFZGl0aW5nQ2VsbChyb3dJbmRleDogbnVtYmVyLCBjb2x1bW5JbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5fZWRpdGluZ0NlbGxQb3NpdGlvbiQubmV4dCh7IHJvd0luZGV4LCBjb2x1bW5JbmRleCB9KTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnY2VsbC1lZGl0LXN0YXJ0Jyk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBOb3RpZnkgdGhhdCBlZGl0IG1vZGUgZW5kZWRcbiAgICovXG4gIGNsZWFyRWRpdGluZ0NlbGwoKTogdm9pZCB7XG4gICAgdGhpcy5fZWRpdGluZ0NlbGxQb3NpdGlvbiQubmV4dChudWxsKTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnY2VsbC1lZGl0LWVuZCcpO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2hlY2sgaWYgYW55IGNlbGwgaXMgY3VycmVudGx5IGVkaXRpbmdcbiAgICovXG4gIGlzQW55Q2VsbEVkaXRpbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2VkaXRpbmdDZWxsUG9zaXRpb24kLnZhbHVlICE9PSBudWxsO1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IGN1cnJlbnRseSBlZGl0aW5nIHBvc2l0aW9uXG4gICAqL1xuICBnZXRFZGl0aW5nUG9zaXRpb24oKTogQ2VsbEZvY3VzUG9zaXRpb24gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fZWRpdGluZ0NlbGxQb3NpdGlvbiQudmFsdWU7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBNb3ZlIGZvY3VzIGluIGEgZGlyZWN0aW9uIHVzaW5nIE5hdmlnYXRpb25EaXJlY3Rpb24gZW51bVxuICAgKiBAcGFyYW0gZGlyZWN0aW9uIFRoZSBuYXZpZ2F0aW9uIGRpcmVjdGlvblxuICAgKiBAcGFyYW0gYWRkUm93T25OYXZpZ2F0ZVBhc3RFbmQgSWYgdHJ1ZSwgZW1pdHMgcmVxdWVzdEFkZFJvdyB3aGVuIG5hdmlnYXRpbmcgcGFzdCBsYXN0IHJvd1xuICAgKi9cbiAgbW92ZUZvY3VzKGRpcmVjdGlvbjogTmF2aWdhdGlvbkRpcmVjdGlvbiwgYWRkUm93T25OYXZpZ2F0ZVBhc3RFbmQ6IGJvb2xlYW4gPSBmYWxzZSk6IGJvb2xlYW4ge1xuICAgIC8vIEJsb2NrIG5hdmlnYXRpb24gaWYgYW55IGNlbGwgaXMgZWRpdGluZ1xuICAgIGlmICh0aGlzLmlzQW55Q2VsbEVkaXRpbmcoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5fZm9jdXNlZENlbGxQb3NpdGlvbiQudmFsdWU7XG4gICAgaWYgKCFjdXJyZW50KSByZXR1cm4gZmFsc2U7XG4gICAgXG4gICAgbGV0IG5ld1JvdyA9IGN1cnJlbnQucm93SW5kZXg7XG4gICAgbGV0IG5ld0NvbCA9IGN1cnJlbnQuY29sdW1uSW5kZXg7XG4gICAgXG4gICAgLy8gVXNlIE5hdmlnYXRpb25EaXJlY3Rpb24gZW51bSB2YWx1ZXNcbiAgICBzd2l0Y2ggKGRpcmVjdGlvbikge1xuICAgICAgY2FzZSBOYXZpZ2F0aW9uRGlyZWN0aW9uLlVQOiBuZXdSb3ctLTsgYnJlYWs7XG4gICAgICBjYXNlIE5hdmlnYXRpb25EaXJlY3Rpb24uRE9XTjogbmV3Um93Kys7IGJyZWFrO1xuICAgICAgY2FzZSBOYXZpZ2F0aW9uRGlyZWN0aW9uLkxFRlQ6IG5ld0NvbC0tOyBicmVhaztcbiAgICAgIGNhc2UgTmF2aWdhdGlvbkRpcmVjdGlvbi5SSUdIVDogbmV3Q29sKys7IGJyZWFrO1xuICAgIH1cbiAgICBcbiAgICAvLyBDaGVjayBpZiBuYXZpZ2F0aW5nIHBhc3QgbGFzdCByb3cgKGFycm93IGRvd24gYXQgYm90dG9tKVxuICAgIGlmIChkaXJlY3Rpb24gPT09IE5hdmlnYXRpb25EaXJlY3Rpb24uRE9XTiAmJiBuZXdSb3cgPj0gdGhpcy5fcm93Q291bnQpIHtcbiAgICAgIGlmIChhZGRSb3dPbk5hdmlnYXRlUGFzdEVuZCkge1xuICAgICAgICAvLyBTdG9yZSBwZW5kaW5nIGZvY3VzIGZvciB3aGVuIHRoZSBuZXcgcm93IGlzIGFkZGVkXG4gICAgICAgIHRoaXMuX3BlbmRpbmdGb2N1c0FmdGVyUm93QWRkID0geyBjb2x1bW5JbmRleDogY3VycmVudC5jb2x1bW5JbmRleCB9O1xuICAgICAgICAvLyBFbWl0IHJlcXVlc3QgdG8gYWRkIGEgbmV3IHJvdywga2VlcGluZyB0aGUgc2FtZSBjb2x1bW4gZm9yIGZvY3VzXG4gICAgICAgIHRoaXMuX3JlcXVlc3RBZGRSb3ckLm5leHQoeyBmb2N1c0NvbHVtbjogY3VycmVudC5jb2x1bW5JbmRleCB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgXG4gICAgaWYgKG5ld1JvdyA8IDAgfHwgbmV3Um93ID49IHRoaXMuX3Jvd0NvdW50KSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKG5ld0NvbCA8IDAgfHwgbmV3Q29sID49IHRoaXMuX2NvbHVtbkNvdW50KSByZXR1cm4gZmFsc2U7XG4gICAgXG4gICAgdGhpcy5mb2N1c0NlbGwobmV3Um93LCBuZXdDb2wpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2xlYXIgZm9jdXNcbiAgICovXG4gIGNsZWFyRm9jdXMoKTogdm9pZCB7XG4gICAgdGhpcy5fZm9jdXNlZENlbGxQb3NpdGlvbiQubmV4dChudWxsKTtcbiAgICB0aGlzLmVtaXRTdGF0ZUNoYW5nZSgnY2VsbC1mb2N1cycpO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2hlY2sgaWYgbmF2aWdhdGlvbiBpcyBhY3RpdmVcbiAgICovXG4gIGlzTmF2aWdhdGlvbkFjdGl2ZSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fZm9jdXNlZENlbGxQb3NpdGlvbiQudmFsdWUgIT09IG51bGw7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFZBTElEQVRJT04gU1RBVEUgTUVUSE9EU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIFxuICAvKipcbiAgICogVXBkYXRlIGNlbGwgdmFsaWRhdGlvbiBhbmQgYWNjdW11bGF0ZSBpbnRvIHJvdy90YWJsZSB2YWxpZGF0aW9uIHN0YXRlXG4gICAqIE9ubHkgc3RvcmVzIGludmFsaWQgc3RhdGVzIC0gdmFsaWQgcm93cyBhcmUgYXV0b21hdGljYWxseSByZW1vdmVkXG4gICAqL1xuICB1cGRhdGVDZWxsVmFsaWRhdGlvbihyb3dJbmRleDogbnVtYmVyLCBjb2x1bW5LZXk6IHN0cmluZywgaXNWYWxpZDogYm9vbGVhbiwgZXJyb3I/OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLl90YWJsZVZhbGlkYXRpb25TdGF0ZSQudmFsdWU7XG4gICAgY29uc3Qgcm93U3RhdGVzID0gbmV3IE1hcChjdXJyZW50U3RhdGUucm93U3RhdGVzKTtcbiAgICBcbiAgICAvLyBHZXQgZXhpc3Rpbmcgcm93IHN0YXRlIChvbmx5IGV4aXN0cyBpZiByb3cgaGFzIGVycm9ycylcbiAgICBsZXQgcm93U3RhdGUgPSByb3dTdGF0ZXMuZ2V0KHJvd0luZGV4KTtcbiAgICBcbiAgICBpZiAoIWlzVmFsaWQgJiYgZXJyb3IpIHtcbiAgICAgIC8vIENlbGwgaXMgaW52YWxpZCAtIGFkZCBvciB1cGRhdGUgZXJyb3JcbiAgICAgIGlmICghcm93U3RhdGUpIHtcbiAgICAgICAgLy8gQ3JlYXRlIG5ldyByb3cgc3RhdGUgZm9yIHRoaXMgaW52YWxpZCByb3dcbiAgICAgICAgcm93U3RhdGUgPSB7XG4gICAgICAgICAgcm93SW5kZXgsXG4gICAgICAgICAgaXNWYWxpZDogZmFsc2UsXG4gICAgICAgICAgaW52YWxpZENlbGxDb3VudDogMSxcbiAgICAgICAgICBjZWxsRXJyb3JzOiBuZXcgTWFwKFtbY29sdW1uS2V5LCBlcnJvcl1dKSxcbiAgICAgICAgICBsYXN0VmFsaWRhdGVkOiBuZXcgRGF0ZSgpXG4gICAgICAgIH07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBVcGRhdGUgZXhpc3Rpbmcgcm93IHN0YXRlXG4gICAgICAgIGNvbnN0IGNlbGxFcnJvcnMgPSBuZXcgTWFwKHJvd1N0YXRlLmNlbGxFcnJvcnMpO1xuICAgICAgICBjZWxsRXJyb3JzLnNldChjb2x1bW5LZXksIGVycm9yKTtcbiAgICAgICAgXG4gICAgICAgIHJvd1N0YXRlID0ge1xuICAgICAgICAgIHJvd0luZGV4LFxuICAgICAgICAgIGlzVmFsaWQ6IGZhbHNlLFxuICAgICAgICAgIGludmFsaWRDZWxsQ291bnQ6IGNlbGxFcnJvcnMuc2l6ZSxcbiAgICAgICAgICBjZWxsRXJyb3JzLFxuICAgICAgICAgIGxhc3RWYWxpZGF0ZWQ6IG5ldyBEYXRlKClcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJvd1N0YXRlcy5zZXQocm93SW5kZXgsIHJvd1N0YXRlKTtcbiAgICAgIFxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDZWxsIGlzIHZhbGlkIC0gcmVtb3ZlIGVycm9yIGlmIGl0IGV4aXN0c1xuICAgICAgaWYgKHJvd1N0YXRlKSB7XG4gICAgICAgIGNvbnN0IGNlbGxFcnJvcnMgPSBuZXcgTWFwKHJvd1N0YXRlLmNlbGxFcnJvcnMpO1xuICAgICAgICBjZWxsRXJyb3JzLmRlbGV0ZShjb2x1bW5LZXkpO1xuICAgICAgICBcbiAgICAgICAgaWYgKGNlbGxFcnJvcnMuc2l6ZSA9PT0gMCkge1xuICAgICAgICAgIC8vIE5vIG1vcmUgZXJyb3JzIGluIHRoaXMgcm93IC0gcmVtb3ZlIHJvdyBzdGF0ZSBjb21wbGV0ZWx5XG4gICAgICAgICAgcm93U3RhdGVzLmRlbGV0ZShyb3dJbmRleCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gU3RpbGwgaGFzIG90aGVyIGVycm9ycyAtIHVwZGF0ZSByb3cgc3RhdGVcbiAgICAgICAgICByb3dTdGF0ZSA9IHtcbiAgICAgICAgICAgIHJvd0luZGV4LFxuICAgICAgICAgICAgaXNWYWxpZDogZmFsc2UsXG4gICAgICAgICAgICBpbnZhbGlkQ2VsbENvdW50OiBjZWxsRXJyb3JzLnNpemUsXG4gICAgICAgICAgICBjZWxsRXJyb3JzLFxuICAgICAgICAgICAgbGFzdFZhbGlkYXRlZDogbmV3IERhdGUoKVxuICAgICAgICAgIH07XG4gICAgICAgICAgcm93U3RhdGVzLnNldChyb3dJbmRleCwgcm93U3RhdGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBJZiByb3dTdGF0ZSBkb2Vzbid0IGV4aXN0LCBjZWxsIHdhcyBhbHJlYWR5IHZhbGlkIC0gZG8gbm90aGluZ1xuICAgIH1cbiAgICBcbiAgICAvLyBSZWNhbGN1bGF0ZSB0YWJsZSBzdGF0ZVxuICAgIC8vIEFsbCByb3dzIGluIHJvd1N0YXRlcyBtYXAgYXJlIGludmFsaWQgYnkgZGVmaW5pdGlvblxuICAgIGNvbnN0IGludmFsaWRSb3dzID0gcm93U3RhdGVzLnNpemU7XG4gICAgXG4gICAgY29uc3QgbmV3VGFibGVTdGF0ZTogVGFibGVWYWxpZGF0aW9uU3RhdGUgPSB7XG4gICAgICBpc1ZhbGlkOiBpbnZhbGlkUm93cyA9PT0gMCxcbiAgICAgIHRvdGFsUm93czogY3VycmVudFN0YXRlLnRvdGFsUm93cywgLy8gS2VlcCB0cmFjayBvZiB0b3RhbCByb3dzIHNlcGFyYXRlbHlcbiAgICAgIHZhbGlkUm93czogY3VycmVudFN0YXRlLnRvdGFsUm93cyAtIGludmFsaWRSb3dzLFxuICAgICAgaW52YWxpZFJvd3MsXG4gICAgICByb3dTdGF0ZXMsXG4gICAgICBsYXN0VXBkYXRlZDogbmV3IERhdGUoKVxuICAgIH07XG4gICAgXG4gICAgLy8gRW1pdCBuZXcgc3RhdGVcbiAgICB0aGlzLl90YWJsZVZhbGlkYXRpb25TdGF0ZSQubmV4dChuZXdUYWJsZVN0YXRlKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCBjdXJyZW50IHRhYmxlIHZhbGlkYXRpb24gc3RhdGVcbiAgICovXG4gIGdldFRhYmxlVmFsaWRhdGlvblN0YXRlKCk6IFRhYmxlVmFsaWRhdGlvblN0YXRlIHtcbiAgICByZXR1cm4gdGhpcy5fdGFibGVWYWxpZGF0aW9uU3RhdGUkLnZhbHVlO1xuICB9XG4gIFxuICAvKipcbiAgICogU2V0IHRvdGFsIHJvd3MgZm9yIHZhbGlkYXRpb24gc3RhdGUgdHJhY2tpbmdcbiAgICovXG4gIHNldFZhbGlkYXRpb25Sb3dDb3VudCh0b3RhbFJvd3M6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMuX3RhYmxlVmFsaWRhdGlvblN0YXRlJC52YWx1ZTtcbiAgICB0aGlzLl90YWJsZVZhbGlkYXRpb25TdGF0ZSQubmV4dCh7XG4gICAgICAuLi5jdXJyZW50U3RhdGUsXG4gICAgICB0b3RhbFJvd3MsXG4gICAgICBsYXN0VXBkYXRlZDogbmV3IERhdGUoKVxuICAgIH0pO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBTVEFURSBSRVNFVFxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRvIGluaXRpYWwgY29uZmlndXJhdGlvblxuICAgKi9cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5yZXNldFBhZ2luYXRpb24oKTtcbiAgICB0aGlzLnJlc2V0QWxsU29ydGluZygpO1xuICAgIHRoaXMucmVzZXRBbGxGaWx0ZXJzKCk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgcGFnaW5hdGlvbiBvbmx5XG4gICAqL1xuICByZXNldFBhZ2luYXRpb24oKTogdm9pZCB7XG4gICAgdGhpcy5fcGFnaW5hdGlvbiQubmV4dCh7XG4gICAgICBjdXJyZW50UGFnZTogdGhpcy5faW5pdGlhbENvbmZpZy5pbml0aWFsUGFnZSEsXG4gICAgICBwYWdlU2l6ZTogdGhpcy5faW5pdGlhbENvbmZpZy5wYWdlU2l6ZSEsXG4gICAgICB0b3RhbEl0ZW1zOiAwLFxuICAgICAgdG90YWxQYWdlczogMFxuICAgIH0pO1xuICAgIHRoaXMuZW1pdFN0YXRlQ2hhbmdlKCdwYWdpbmF0aW9uJyk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgYWxsIGNvbHVtbiBzb3J0c1xuICAgKi9cbiAgcmVzZXRBbGxTb3J0aW5nKCk6IHZvaWQge1xuICAgIHRoaXMuY2xlYXJBbGxTb3J0aW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgYWxsIGNvbHVtbiBmaWx0ZXJzXG4gICAqL1xuICByZXNldEFsbEZpbHRlcnMoKTogdm9pZCB7XG4gICAgdGhpcy5jbGVhckFsbEZpbHRlcnMoKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gSU5URVJOQUwgTUVUSE9EU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEZpbmQgYSBjb2x1bW4gYnkga2V5XG4gICAqIEBwYXJhbSBjb2x1bW5LZXkgQ29sdW1uIGtleVxuICAgKiBAcmV0dXJucyBDb2x1bW4gY29uZmlnIG9yIHVuZGVmaW5lZFxuICAgKi9cbiAgcHJpdmF0ZSBmaW5kQ29sdW1uKGNvbHVtbktleTogc3RyaW5nKTogQ29sdW1uQ29uZmlnPGFueT4gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9jb2x1bW5zLmZpbmQoY29sID0+IGNvbC5rZXkgPT09IGNvbHVtbktleSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRvdGFsIHBhZ2VzXG4gICAqIEBwYXJhbSB0b3RhbEl0ZW1zIFRvdGFsIG51bWJlciBvZiBpdGVtc1xuICAgKiBAcGFyYW0gcGFnZVNpemUgUGFnZSBzaXplXG4gICAqIEByZXR1cm5zIFRvdGFsIG51bWJlciBvZiBwYWdlc1xuICAgKi9cbiAgcHJpdmF0ZSBjYWxjdWxhdGVUb3RhbFBhZ2VzKHRvdGFsSXRlbXM6IG51bWJlciA9IDAsIHBhZ2VTaXplOiBudW1iZXIgPSAyNSk6IG51bWJlciB7XG4gICAgaWYgKHRvdGFsSXRlbXMgPT09IDAgfHwgcGFnZVNpemUgPT09IDApIHtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICByZXR1cm4gTWF0aC5jZWlsKHRvdGFsSXRlbXMgLyBwYWdlU2l6ZSk7XG4gIH1cblxuICAvKipcbiAgICogRW1pdCBzdGF0ZSBjaGFuZ2UgZXZlbnRcbiAgICogQHBhcmFtIHR5cGUgVHlwZSBvZiBjaGFuZ2VcbiAgICovXG4gIHByaXZhdGUgZW1pdFN0YXRlQ2hhbmdlKHR5cGU6IFRhYmxlU3RhdGVDaGFuZ2VFdmVudFsndHlwZSddKTogdm9pZCB7XG4gICAgY29uc3Qgc3RhdGUgPSB0aGlzLmJ1aWxkU3RhdGVTbmFwc2hvdCgpO1xuICAgIHRoaXMuX3N0YXRlQ2hhbmdlJC5uZXh0KHtcbiAgICAgIHR5cGUsXG4gICAgICBzdGF0ZVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIHN0YXRlIHNuYXBzaG90IGZyb20gY3VycmVudCBzdGF0ZVxuICAgKiBAcmV0dXJucyBTdGF0ZSBzbmFwc2hvdFxuICAgKi9cbiAgcHJpdmF0ZSBidWlsZFN0YXRlU25hcHNob3QoKTogVGFibGVTdGF0ZVNuYXBzaG90IHtcbiAgICByZXR1cm4ge1xuICAgICAgcGFnaW5hdGlvbjogdGhpcy5nZXRQYWdpbmF0aW9uKCksXG4gICAgICBcbiAgICAgIC8vIEJ1aWxkIGZ1bGwgc29ydCBzdGF0ZSB3aXRoIGRpcmVjdGlvbiBhbmQgcHJpb3JpdHlcbiAgICAgIHNvcnRlZENvbHVtbnM6IHRoaXMuX2NvbHVtbnNcbiAgICAgICAgLmZpbHRlcihjb2wgPT4gY29sLnNvcnRFbmFibGVkID09PSB0cnVlKVxuICAgICAgICAubWFwKChjb2wsIGluZGV4KSA9PiAoe1xuICAgICAgICAgIGNvbHVtbktleTogY29sLmtleSxcbiAgICAgICAgICBkaXJlY3Rpb246IGNvbC5zb3J0RGlyZWN0aW9uIHx8IFNvcnREaXJlY3Rpb24uTk9ORSxcbiAgICAgICAgICBwcmlvcml0eTogaW5kZXggIC8vIFNvcnQgb3JkZXIgYmFzZWQgb24gZW5hYmxlbWVudCBvcmRlclxuICAgICAgICB9KSksXG4gICAgICBcbiAgICAgIC8vIEJ1aWxkIGZ1bGwgZmlsdGVyIHN0YXRlIHdpdGggb3BlcmF0b3IgYW5kIHZhbHVlXG4gICAgICBmaWx0ZXJlZENvbHVtbnM6IHRoaXMuX2NvbHVtbnNcbiAgICAgICAgLmZpbHRlcihjb2wgPT4gY29sLmZpbHRlckNvbmZpZz8uZW5hYmxlZCA9PT0gdHJ1ZSlcbiAgICAgICAgLm1hcChjb2wgPT4gKHtcbiAgICAgICAgICBjb2x1bW5LZXk6IGNvbC5rZXksXG4gICAgICAgICAgb3BlcmF0b3I6IGNvbC5maWx0ZXJDb25maWc/Lm9wZXJhdG9yIHx8IEZpbHRlck9wZXJhdG9yLkNPTlRBSU5TLFxuICAgICAgICAgIHZhbHVlOiBjb2wuZmlsdGVyQ29uZmlnPy52YWx1ZSxcbiAgICAgICAgICBlbmFibGVkOiB0cnVlXG4gICAgICAgIH0pKVxuICAgIH07XG4gIH1cbn1cblxuIl19