ng-firebase-table-kxp 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/esm2020/lib/components/table/table.component.mjs +776 -0
  2. package/esm2020/lib/firebase-table-kxp-lib.component.mjs +19 -0
  3. package/esm2020/lib/firebase-table-kxp-lib.module.mjs +74 -0
  4. package/esm2020/lib/firebase-table-kxp-lib.service.mjs +14 -0
  5. package/esm2020/lib/services/table.service.mjs +908 -0
  6. package/esm2020/lib/types/Table.mjs +2 -0
  7. package/esm2020/ng-firebase-table-kxp.mjs +5 -0
  8. package/esm2020/public-api.mjs +15 -0
  9. package/fesm2015/ng-firebase-table-kxp.mjs +1811 -0
  10. package/fesm2015/ng-firebase-table-kxp.mjs.map +1 -0
  11. package/fesm2020/ng-firebase-table-kxp.mjs +1784 -0
  12. package/fesm2020/ng-firebase-table-kxp.mjs.map +1 -0
  13. package/index.d.ts +5 -0
  14. package/lib/components/table/table.component.d.ts +111 -0
  15. package/lib/firebase-table-kxp-lib.component.d.ts +5 -0
  16. package/lib/firebase-table-kxp-lib.module.d.ts +21 -0
  17. package/lib/firebase-table-kxp-lib.service.d.ts +6 -0
  18. package/lib/services/table.service.d.ts +70 -0
  19. package/{src/lib/types/Table.ts → lib/types/Table.d.ts} +28 -31
  20. package/package.json +22 -2
  21. package/{src/public-api.ts → public-api.d.ts} +0 -13
  22. package/CHANGELOG.md +0 -88
  23. package/ng-package.json +0 -7
  24. package/src/lib/components/table/table.component.html +0 -555
  25. package/src/lib/components/table/table.component.scss +0 -22
  26. package/src/lib/components/table/table.component.spec.ts +0 -24
  27. package/src/lib/components/table/table.component.ts +0 -917
  28. package/src/lib/firebase-table-kxp-lib.component.spec.ts +0 -23
  29. package/src/lib/firebase-table-kxp-lib.component.ts +0 -15
  30. package/src/lib/firebase-table-kxp-lib.module.ts +0 -45
  31. package/src/lib/firebase-table-kxp-lib.service.spec.ts +0 -16
  32. package/src/lib/firebase-table-kxp-lib.service.ts +0 -9
  33. package/src/lib/services/table.service.spec.ts +0 -16
  34. package/src/lib/services/table.service.ts +0 -1235
  35. package/tsconfig.lib.json +0 -14
  36. package/tsconfig.lib.prod.json +0 -10
  37. package/tsconfig.spec.json +0 -14
@@ -0,0 +1,908 @@
1
+ import { Injectable, Optional } from '@angular/core';
2
+ import firebase from 'firebase/compat/app';
3
+ import { firstValueFrom } from 'rxjs';
4
+ import * as moment from 'moment';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/fire/compat/firestore";
7
+ import * as i2 from "@angular/material/dialog";
8
+ import * as i3 from "ngx-toastr";
9
+ export class TableService {
10
+ constructor(ngFire, dialog, toastr) {
11
+ this.ngFire = ngFire;
12
+ this.dialog = dialog;
13
+ this.toastr = toastr;
14
+ this.operators = {
15
+ '==': (a, b) => a === b,
16
+ '!=': (a, b) => a !== b,
17
+ '>': (a, b) => a > b,
18
+ '<': (a, b) => a < b,
19
+ '>=': (a, b) => a >= b,
20
+ '<=': (a, b) => a <= b,
21
+ includes: (a, b) => a.includes(b),
22
+ };
23
+ }
24
+ async getItems(collection) {
25
+ try {
26
+ const querySnapshot = await collection.get();
27
+ return querySnapshot.docs.map((doc) => {
28
+ return { ...doc.data(), id: doc.id };
29
+ });
30
+ }
31
+ catch (error) {
32
+ console.warn('Collection não encontrada:', error);
33
+ return [];
34
+ }
35
+ }
36
+ async executeQuery(params) {
37
+ if (params.filterFn) {
38
+ // Lógica com filtro no cliente (filterFn)
39
+ const BATCH_FETCH_SIZE = params.batchSize;
40
+ const GOAL_SIZE = params.batchSize + 1;
41
+ if (params.navigation === 'forward' || params.navigation === 'reload') {
42
+ if (params.navigation === 'reload' && params.doc) {
43
+ params.doc.lastDoc = null;
44
+ }
45
+ let lastDocCursor = params.doc ? params.doc.lastDoc : null;
46
+ let pageResults = [];
47
+ let allFetchedDocs = [];
48
+ let hasMoreDocsInDb = true;
49
+ while (pageResults.length < GOAL_SIZE && hasMoreDocsInDb) {
50
+ let query = this.ngFire.collection(params.collection).ref;
51
+ query = this.applyFilters(query, params.arrange, params.conditions);
52
+ if (lastDocCursor) {
53
+ query = query.startAfter(lastDocCursor);
54
+ }
55
+ query = query.limit(BATCH_FETCH_SIZE);
56
+ const snapshot = await query.get();
57
+ if (snapshot.empty) {
58
+ hasMoreDocsInDb = false;
59
+ break;
60
+ }
61
+ lastDocCursor = snapshot.docs[snapshot.docs.length - 1];
62
+ allFetchedDocs.push(...snapshot.docs);
63
+ const batchUsers = snapshot.docs
64
+ .map((doc) => ({
65
+ id: doc.id,
66
+ ...doc.data(),
67
+ }))
68
+ .filter(params.filterFn);
69
+ pageResults.push(...batchUsers);
70
+ if (snapshot.size < BATCH_FETCH_SIZE) {
71
+ hasMoreDocsInDb = false;
72
+ }
73
+ }
74
+ const hasNextPage = pageResults.length > params.batchSize;
75
+ const finalItems = pageResults.slice(0, params.batchSize);
76
+ const firstDocOfPage = allFetchedDocs.find((doc) => doc.id === finalItems[0]?.id) || null;
77
+ const lastDocOfPage = allFetchedDocs.find((doc) => doc.id === finalItems[finalItems.length - 1]?.id) || null;
78
+ return {
79
+ items: finalItems,
80
+ filterLength: null,
81
+ firstDoc: firstDocOfPage,
82
+ lastDoc: lastDocOfPage,
83
+ hasNextPage: hasNextPage,
84
+ hasPreviousPage: !!(params.doc && params.doc.lastDoc) &&
85
+ params.navigation !== 'reload',
86
+ currentClientPageIndex: undefined,
87
+ };
88
+ }
89
+ // Lógica para trás (backward)
90
+ else if (params.navigation === 'backward') {
91
+ if (!params.doc || !params.doc.firstDoc) {
92
+ return {
93
+ items: [],
94
+ filterLength: null,
95
+ firstDoc: null,
96
+ lastDoc: null,
97
+ hasNextPage: true,
98
+ hasPreviousPage: false,
99
+ currentClientPageIndex: undefined,
100
+ };
101
+ }
102
+ let pageResults = [];
103
+ let allFetchedDocs = [];
104
+ let hasMoreDocsInDb = true;
105
+ let boundaryDoc = params.doc.firstDoc;
106
+ while (pageResults.length < GOAL_SIZE && hasMoreDocsInDb) {
107
+ let query = this.ngFire.collection(params.collection).ref;
108
+ query = this.applyFilters(query, params.arrange, params.conditions);
109
+ query = query.endBefore(boundaryDoc);
110
+ query = query.limitToLast(BATCH_FETCH_SIZE);
111
+ const snapshot = await query.get();
112
+ if (snapshot.empty) {
113
+ hasMoreDocsInDb = false;
114
+ break;
115
+ }
116
+ boundaryDoc = snapshot.docs[0];
117
+ allFetchedDocs = [...snapshot.docs, ...allFetchedDocs];
118
+ const batchUsers = snapshot.docs
119
+ .map((doc) => ({
120
+ id: doc.id,
121
+ ...doc.data(),
122
+ }))
123
+ .filter(params.filterFn);
124
+ pageResults = [...batchUsers, ...pageResults];
125
+ if (snapshot.size < BATCH_FETCH_SIZE) {
126
+ hasMoreDocsInDb = false;
127
+ }
128
+ }
129
+ const finalItems = pageResults.slice(0, params.batchSize);
130
+ const firstDocOfPage = allFetchedDocs.find((doc) => doc.id === finalItems[0]?.id) || null;
131
+ const lastDocOfPage = allFetchedDocs.find((doc) => doc.id === finalItems[finalItems.length - 1]?.id) || null;
132
+ return {
133
+ items: finalItems,
134
+ filterLength: null,
135
+ firstDoc: firstDocOfPage,
136
+ lastDoc: lastDocOfPage,
137
+ hasNextPage: true,
138
+ currentClientPageIndex: undefined,
139
+ };
140
+ }
141
+ }
142
+ else {
143
+ let items = [];
144
+ let docs = [];
145
+ let hasNextPage = false;
146
+ let filterLength = null;
147
+ let query = this.ngFire.collection(params.collection).ref;
148
+ if (params.conditions) {
149
+ params.conditions.forEach((c) => {
150
+ if (c.operator === '!=') {
151
+ query = query.orderBy(c.firestoreProperty);
152
+ }
153
+ });
154
+ }
155
+ query = this.applyFilters(query, params.arrange, params.conditions);
156
+ if (params.navigation === 'reload') {
157
+ query = query.limit(params.batchSize + 1);
158
+ if (params.doc && params.doc.firstDoc) {
159
+ query = query.startAt(params.doc.firstDoc);
160
+ }
161
+ }
162
+ else if (params.navigation === 'forward') {
163
+ query = query.limit(params.batchSize + 1);
164
+ if (params.doc && params.doc.lastDoc) {
165
+ query = query.startAfter(params.doc.lastDoc);
166
+ }
167
+ }
168
+ else {
169
+ // backward
170
+ query = query.limitToLast(params.batchSize + 1);
171
+ if (params.doc && params.doc.firstDoc) {
172
+ query = query.endBefore(params.doc.firstDoc);
173
+ }
174
+ }
175
+ const itemCol = await query.get();
176
+ itemCol.docs.forEach((doc) => docs.push(doc));
177
+ const itemPromises = docs.map(async (item) => {
178
+ const itemData = item.data();
179
+ items.push({ id: item.id, ...itemData });
180
+ });
181
+ let lastDoc = docs[docs.length - 1] || null;
182
+ let firstDoc = docs[0];
183
+ if ((items.length > params.batchSize && params.navigation === 'forward') ||
184
+ (params.navigation === 'reload' && items.length > params.batchSize)) {
185
+ lastDoc = docs[docs.length - 2] || null;
186
+ items.pop();
187
+ hasNextPage = true;
188
+ }
189
+ if (items.length > params.batchSize && params.navigation === 'backward') {
190
+ firstDoc = docs[1];
191
+ items.shift();
192
+ hasNextPage = true;
193
+ }
194
+ await Promise.all(itemPromises);
195
+ return {
196
+ items,
197
+ filterLength,
198
+ lastDoc,
199
+ firstDoc,
200
+ hasNextPage,
201
+ currentClientPageIndex: undefined,
202
+ };
203
+ }
204
+ // Fallback para garantir que sempre retornamos algo
205
+ return {
206
+ items: [],
207
+ filterLength: null,
208
+ firstDoc: null,
209
+ lastDoc: null,
210
+ hasNextPage: false,
211
+ currentClientPageIndex: undefined,
212
+ };
213
+ }
214
+ applyFilters(query, arrange, conditions) {
215
+ if (conditions) {
216
+ conditions.map((cond) => {
217
+ query = query.where(cond.firestoreProperty, cond.operator, cond.dashProperty);
218
+ });
219
+ }
220
+ let hasFilterSpecificOrderBy = false;
221
+ let appliedOrderByField = null;
222
+ const equalsFilters = arrange.filters.filter((f) => f.arrange === 'equals' && f.filter);
223
+ const otherFilters = arrange.filters.filter((f) => f.arrange !== 'equals');
224
+ const equalsGroupedByProperty = equalsFilters.reduce((acc, current) => {
225
+ const prop = current.filter.property;
226
+ if (!acc[prop]) {
227
+ acc[prop] = [];
228
+ }
229
+ acc[prop].push(current.filter.filtering);
230
+ return acc;
231
+ }, {});
232
+ for (const prop in equalsGroupedByProperty) {
233
+ const values = equalsGroupedByProperty[prop];
234
+ if (values.length > 0) {
235
+ query = query.where(prop, 'in', values);
236
+ }
237
+ }
238
+ otherFilters.forEach((filterItem) => {
239
+ // Aplicar filtragem por busca
240
+ if (filterItem.filter?.filtering &&
241
+ filterItem.filter?.property !== '' &&
242
+ filterItem.arrange === 'filter') {
243
+ query = query
244
+ .where(filterItem.filter.property, '>=', filterItem.filter.filtering.trim().toUpperCase())
245
+ .where(filterItem.filter.property, '<=', filterItem.filter.filtering.trim().toUpperCase() + '\uf8ff');
246
+ if (!hasFilterSpecificOrderBy) {
247
+ query = query.orderBy(filterItem.filter.property);
248
+ hasFilterSpecificOrderBy = true;
249
+ appliedOrderByField = filterItem.filter.property;
250
+ }
251
+ }
252
+ // Aplicar filtro do tipo "filterByDate"
253
+ if (filterItem.dateFilter && filterItem.arrange === 'filterByDate') {
254
+ query = query
255
+ .where(arrange.sortBy.field, '>=', filterItem.dateFilter.initial)
256
+ .where(arrange.sortBy.field, '<=', filterItem.dateFilter.final);
257
+ if (!hasFilterSpecificOrderBy) {
258
+ query = query.orderBy(arrange.sortBy.field);
259
+ hasFilterSpecificOrderBy = true;
260
+ appliedOrderByField = arrange.sortBy.field;
261
+ }
262
+ }
263
+ });
264
+ // Aplicar sortBy
265
+ if (arrange.sortBy && arrange.sortBy.field && arrange.sortBy.order) {
266
+ if (appliedOrderByField !== arrange.sortBy.field) {
267
+ query = query.orderBy(arrange.sortBy.field, arrange.sortBy.order);
268
+ }
269
+ }
270
+ return query;
271
+ }
272
+ /**
273
+ * Detecta se a query vai precisar de index composto e deve usar fallback client-side
274
+ */
275
+ shouldUseClientSideFallback(params) {
276
+ const hasConditions = params.conditions && params.conditions.length > 0;
277
+ const hasArrangeFilters = params.arrange?.filters && params.arrange.filters.length > 0;
278
+ const hasSortBy = params.arrange?.sortBy?.field;
279
+ if (params.filterFn) {
280
+ return false;
281
+ }
282
+ if (hasConditions && hasArrangeFilters && hasSortBy) {
283
+ return true;
284
+ }
285
+ if (hasConditions && hasArrangeFilters) {
286
+ return true;
287
+ }
288
+ if (hasArrangeFilters && params.arrange.filters.length > 1 && hasSortBy) {
289
+ return true;
290
+ }
291
+ return false;
292
+ }
293
+ async getPaginated(params) {
294
+ // Detectar preventivamente se deve usar fallback
295
+ if (this.shouldUseClientSideFallback(params)) {
296
+ await this.trackMissingIndexPreventive(params.collection, params.arrange, params.conditions);
297
+ const result = await this.executeClientSideQuery(params);
298
+ console.log('📊 [TABLE] Resultados paginados via fallback client-side:', {
299
+ totalItems: result.filterLength,
300
+ returnedItems: result.items.length,
301
+ hasNextPage: result.hasNextPage,
302
+ currentPage: (result.currentClientPageIndex || 0) + 1,
303
+ });
304
+ return result;
305
+ }
306
+ try {
307
+ const result = await this.executeQuery(params);
308
+ console.log('📊 [TABLE] Resultados paginados via Firestore:', {
309
+ totalItems: result.filterLength || 'N/A',
310
+ returnedItems: result.items.length,
311
+ hasNextPage: result.hasNextPage,
312
+ });
313
+ return result;
314
+ }
315
+ catch (error) {
316
+ if (error && error.code === 'failed-precondition') {
317
+ await this.trackMissingIndex(error, params.collection, params.arrange, params.conditions);
318
+ const result = await this.executeClientSideQuery(params);
319
+ console.log('📊 [TABLE] Resultados paginados via fallback (erro de index):', {
320
+ totalItems: result.filterLength,
321
+ returnedItems: result.items.length,
322
+ hasNextPage: result.hasNextPage,
323
+ currentPage: (result.currentClientPageIndex || 0) + 1,
324
+ });
325
+ return result;
326
+ }
327
+ else if (error && error.code === 'invalid-argument') {
328
+ await this.trackMissingIndex(error, params.collection, params.arrange, params.conditions);
329
+ const result = await this.executeClientSideQuery(params);
330
+ console.log('📊 [TABLE] Resultados paginados via fallback (argumento inválido):', {
331
+ totalItems: result.filterLength,
332
+ returnedItems: result.items.length,
333
+ hasNextPage: result.hasNextPage,
334
+ currentPage: (result.currentClientPageIndex || 0) + 1,
335
+ });
336
+ return result;
337
+ }
338
+ else {
339
+ throw error;
340
+ }
341
+ }
342
+ }
343
+ async executeClientSideQuery(params) {
344
+ // Otimizar usando pelo menos uma cláusula .where() quando possível
345
+ let query = this.ngFire.collection(params.collection).ref;
346
+ let appliedCondition = null;
347
+ let hasAppliedWhereClause = false;
348
+ // Primeiro, tenta aplicar condições simples
349
+ if (params.conditions && params.conditions.length > 0) {
350
+ const simpleCondition = params.conditions.find((cond) => ['==', '>', '<', '>=', '<='].includes(cond.operator));
351
+ if (simpleCondition) {
352
+ query = query.where(simpleCondition.firestoreProperty, simpleCondition.operator, simpleCondition.dashProperty);
353
+ appliedCondition = simpleCondition;
354
+ hasAppliedWhereClause = true;
355
+ }
356
+ }
357
+ // Se não há condições disponíveis, tenta aplicar filtros do arrange
358
+ let appliedFirestoreFilter = null;
359
+ if (!hasAppliedWhereClause && params.arrange?.filters) {
360
+ const equalsFilter = params.arrange.filters.find((f) => f.arrange === 'equals' && f.filter?.filtering);
361
+ if (equalsFilter && equalsFilter.filter) {
362
+ query = query.where(equalsFilter.filter.property, '==', equalsFilter.filter.filtering);
363
+ hasAppliedWhereClause = true;
364
+ appliedFirestoreFilter = equalsFilter;
365
+ }
366
+ else {
367
+ const otherFilter = params.arrange.filters.find((f) => (f.arrange === 'filter' &&
368
+ f.filter?.filtering &&
369
+ f.filter?.property) ||
370
+ (f.arrange === 'filterByDate' &&
371
+ f.dateFilter?.initial &&
372
+ f.dateFilter?.final));
373
+ if (otherFilter) {
374
+ if (otherFilter.arrange === 'filter' && otherFilter.filter) {
375
+ const filterValue = otherFilter.filter.filtering
376
+ .trim()
377
+ .toUpperCase();
378
+ query = query
379
+ .where(otherFilter.filter.property, '>=', filterValue)
380
+ .where(otherFilter.filter.property, '<=', filterValue + '\uf8ff');
381
+ hasAppliedWhereClause = true;
382
+ appliedFirestoreFilter = otherFilter;
383
+ }
384
+ else if (otherFilter.arrange === 'filterByDate' &&
385
+ otherFilter.dateFilter &&
386
+ params.arrange.sortBy?.field) {
387
+ query = query
388
+ .where(params.arrange.sortBy.field, '>=', otherFilter.dateFilter.initial)
389
+ .where(params.arrange.sortBy.field, '<=', otherFilter.dateFilter.final);
390
+ hasAppliedWhereClause = true;
391
+ appliedFirestoreFilter = otherFilter;
392
+ }
393
+ }
394
+ }
395
+ }
396
+ const allDocsSnapshot = await query.get();
397
+ let items = allDocsSnapshot.docs.map((doc) => ({
398
+ id: doc.id,
399
+ ...doc.data(),
400
+ }));
401
+ // Aplicar condições restantes
402
+ if (params.conditions) {
403
+ const remainingConditions = params.conditions.filter((cond) => cond !== appliedCondition);
404
+ if (remainingConditions.length > 0) {
405
+ const operators = this.operators;
406
+ items = items.filter((item) => {
407
+ return remainingConditions.every((cond) => {
408
+ const operatorFn = operators[cond.operator];
409
+ return operatorFn
410
+ ? operatorFn(item[cond.firestoreProperty], cond.dashProperty)
411
+ : false;
412
+ });
413
+ });
414
+ }
415
+ }
416
+ const { filters, sortBy } = params.arrange;
417
+ // Track which filter was already applied in Firestore to avoid double filtering
418
+ if (hasAppliedWhereClause && !appliedCondition && params.arrange?.filters) {
419
+ const equalsFilter = params.arrange.filters.find((f) => f.arrange === 'equals' && f.filter?.filtering);
420
+ if (equalsFilter) {
421
+ appliedFirestoreFilter = equalsFilter;
422
+ }
423
+ else {
424
+ appliedFirestoreFilter = params.arrange.filters.find((f) => (f.arrange === 'filter' &&
425
+ f.filter?.filtering &&
426
+ f.filter?.property) ||
427
+ (f.arrange === 'filterByDate' &&
428
+ f.dateFilter?.initial &&
429
+ f.dateFilter?.final));
430
+ }
431
+ }
432
+ const equalsFilters = filters.filter((f) => f.arrange === 'equals');
433
+ const otherFilters = filters.filter((f) => f.arrange !== 'equals');
434
+ const remainingEqualsFilters = equalsFilters.filter((f) => f !== appliedFirestoreFilter);
435
+ if (remainingEqualsFilters.length > 0) {
436
+ items = items.filter((item) => {
437
+ return remainingEqualsFilters.every((f) => item[f.filter.property] === f.filter.filtering);
438
+ });
439
+ }
440
+ otherFilters.forEach((filterItem) => {
441
+ if (appliedFirestoreFilter === filterItem) {
442
+ return;
443
+ }
444
+ if (filterItem.arrange === 'filter' &&
445
+ filterItem.filter?.filtering &&
446
+ filterItem.filter?.property) {
447
+ const filterValue = String(filterItem.filter.filtering)
448
+ .trim()
449
+ .toLowerCase();
450
+ items = items.filter((item) => {
451
+ const itemValue = String(item[filterItem.filter.property]).toLowerCase();
452
+ return itemValue.includes(filterValue);
453
+ });
454
+ }
455
+ if (filterItem.arrange === 'filterByDate' &&
456
+ filterItem.dateFilter?.initial &&
457
+ filterItem.dateFilter?.final &&
458
+ sortBy.field) {
459
+ items = items.filter((item) => {
460
+ try {
461
+ const fieldValue = item[sortBy.field];
462
+ if (!fieldValue) {
463
+ return false;
464
+ }
465
+ let itemDate;
466
+ if (typeof fieldValue.toDate === 'function') {
467
+ itemDate = fieldValue.toDate();
468
+ }
469
+ else if (fieldValue instanceof Date) {
470
+ itemDate = fieldValue;
471
+ }
472
+ else if (typeof fieldValue === 'string') {
473
+ itemDate = new Date(fieldValue);
474
+ if (isNaN(itemDate.getTime())) {
475
+ return false;
476
+ }
477
+ }
478
+ else if (typeof fieldValue === 'number') {
479
+ itemDate = new Date(fieldValue);
480
+ }
481
+ else {
482
+ return false;
483
+ }
484
+ return (itemDate >= filterItem.dateFilter.initial &&
485
+ itemDate <= filterItem.dateFilter.final);
486
+ }
487
+ catch (error) {
488
+ console.warn('Erro ao processar filtro de data para o item:', item.id, error);
489
+ return false;
490
+ }
491
+ });
492
+ }
493
+ });
494
+ // Aplicar filterFn se existir
495
+ if (params.filterFn) {
496
+ items = items.filter(params.filterFn);
497
+ }
498
+ if (sortBy && sortBy.field && sortBy.order) {
499
+ items.sort((a, b) => {
500
+ const valA = a[sortBy.field];
501
+ const valB = b[sortBy.field];
502
+ if (valA < valB) {
503
+ return sortBy.order === 'asc' ? -1 : 1;
504
+ }
505
+ if (valA > valB) {
506
+ return sortBy.order === 'asc' ? 1 : -1;
507
+ }
508
+ return 0;
509
+ });
510
+ }
511
+ // Paginação
512
+ let currentClientPageIndex = 0;
513
+ if (params.navigation === 'reload') {
514
+ currentClientPageIndex = params.clientPageIndex || 0;
515
+ }
516
+ else if (params.navigation === 'forward') {
517
+ currentClientPageIndex = (params.clientPageIndex || 0) + 1;
518
+ }
519
+ else if (params.navigation === 'backward') {
520
+ currentClientPageIndex = Math.max(0, (params.clientPageIndex || 0) - 1);
521
+ }
522
+ const pageSize = params.batchSize;
523
+ const startIndex = currentClientPageIndex * pageSize;
524
+ const endIndex = startIndex + pageSize;
525
+ const paginatedItems = items.slice(startIndex, endIndex);
526
+ const totalPages = Math.ceil(items.length / pageSize);
527
+ const hasNextPage = currentClientPageIndex < totalPages - 1;
528
+ const hasPreviousPage = currentClientPageIndex > 0;
529
+ return {
530
+ items: paginatedItems,
531
+ filterLength: items.length,
532
+ lastDoc: null,
533
+ firstDoc: null,
534
+ hasNextPage: hasNextPage,
535
+ hasPreviousPage: hasPreviousPage,
536
+ currentClientPageIndex: currentClientPageIndex,
537
+ totalPages: totalPages,
538
+ };
539
+ }
540
+ async getItemsData(collection, arrange, conditions = undefined) {
541
+ try {
542
+ let query = this.ngFire.collection(collection).ref;
543
+ query = this.applyFilters(query, arrange, conditions);
544
+ const snapshot = await query.get();
545
+ return await Promise.all(snapshot.docs.map(async (doc) => {
546
+ const data = doc.data();
547
+ const id = doc.id;
548
+ return {
549
+ id,
550
+ ...data,
551
+ };
552
+ }));
553
+ }
554
+ catch (e) {
555
+ throw e;
556
+ }
557
+ }
558
+ async deleteIndex(id, col, dialogComponent) {
559
+ const dialogRef = this.dialog.open(dialogComponent, {
560
+ data: {
561
+ title: 'Você realmente deseja deletar esse item?',
562
+ description: 'Essa ação é irreversível.',
563
+ },
564
+ });
565
+ const result = await firstValueFrom(dialogRef.afterClosed());
566
+ if (!result === true) {
567
+ return false;
568
+ }
569
+ try {
570
+ const batch = this.ngFire.firestore.batch();
571
+ const docRef = this.ngFire.collection(col).doc(id);
572
+ const docSnapshot = (await firstValueFrom(docRef.get()));
573
+ const doc = docSnapshot.data();
574
+ batch.delete(docRef.ref);
575
+ if (doc && typeof doc.index === 'number') {
576
+ await this.reindex(doc.index, col, batch);
577
+ }
578
+ await batch.commit();
579
+ this.toastr.success('Item excluído com sucesso!');
580
+ return true;
581
+ }
582
+ catch (e) {
583
+ const error = e;
584
+ console.error('Erro ao deletar item:', error);
585
+ this.toastr.error('Erro ao deletar item.');
586
+ return false;
587
+ }
588
+ }
589
+ async reindex(index, col, batch) {
590
+ try {
591
+ const snapshot = (await firstValueFrom(this.ngFire.collection(col).get()));
592
+ const docs = snapshot.docs;
593
+ for (let doc of docs) {
594
+ const data = doc.data();
595
+ if (data && typeof data.index === 'number' && data.index > index) {
596
+ data.index--;
597
+ const docRef = this.ngFire.collection(col).doc(doc.id).ref;
598
+ batch.update(docRef, data);
599
+ }
600
+ }
601
+ }
602
+ catch (error) {
603
+ console.error('Erro ao reindexar:', error);
604
+ }
605
+ return;
606
+ }
607
+ dateFormatValidator() {
608
+ return (control) => {
609
+ if (!control.value) {
610
+ return null;
611
+ }
612
+ const dateStr = control.value.trim();
613
+ const datePattern = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/;
614
+ if (!datePattern.test(dateStr)) {
615
+ return { invalidFormat: true };
616
+ }
617
+ const parts = dateStr.split('/');
618
+ const day = parts[0].padStart(2, '0');
619
+ const month = parts[1].padStart(2, '0');
620
+ const year = parts[2];
621
+ const normalizedDate = `${day}/${month}/${year}`;
622
+ const date = moment(normalizedDate, 'DD/MM/YYYY', true);
623
+ if (!date.isValid()) {
624
+ return { invalidDate: true };
625
+ }
626
+ return null;
627
+ };
628
+ }
629
+ async updateIndex(index, id, col) {
630
+ await this.ngFire.collection(col).doc(id).update({ index });
631
+ }
632
+ /**
633
+ * Extrai o link de criação de índice da mensagem de erro do Firestore
634
+ */
635
+ extractIndexLink(error) {
636
+ if (!error || !error.message)
637
+ return null;
638
+ const linkMatch = error.message.match(/(https:\/\/console\.firebase\.google\.com\/[^\s]+)/);
639
+ return linkMatch ? linkMatch[1] : null;
640
+ }
641
+ /**
642
+ * Rastreia índices ausentes ao usar fallback preventivo
643
+ */
644
+ async trackMissingIndexPreventive(collection, arrange, conditions = undefined) {
645
+ try {
646
+ const querySignature = this.generateQuerySignature(collection, arrange, conditions);
647
+ const docId = `${collection}_${querySignature}`;
648
+ const indexLink = this.generateIndexLink(collection, arrange, conditions);
649
+ const indexInstructions = this.generateIndexInstructions(collection, arrange, conditions);
650
+ const trackingData = {
651
+ collection,
652
+ indexLink,
653
+ indexInstructions,
654
+ arrange: {
655
+ sortBy: arrange.sortBy,
656
+ filters: arrange.filters?.map((f) => ({
657
+ arrange: f.arrange,
658
+ property: f.filter?.property || null,
659
+ dateField: f.arrange === 'filterByDate' ? arrange.sortBy?.field : null,
660
+ })) || [],
661
+ },
662
+ conditions: conditions?.map((c) => ({
663
+ property: c.firestoreProperty,
664
+ operator: c.operator,
665
+ })) || [],
666
+ errorMessage: `Fallback preventivo usado para a collection ${collection}. A query exigiria índice composto.`,
667
+ updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
668
+ };
669
+ console.log('📄 [INDEX LINK] Dados que serão salvos no documento:', {
670
+ docId,
671
+ collection: trackingData.collection,
672
+ indexLink: trackingData.indexLink,
673
+ arrange: trackingData.arrange,
674
+ conditions: trackingData.conditions,
675
+ errorMessage: trackingData.errorMessage,
676
+ });
677
+ const docRef = this.ngFire.collection('missingIndexes').doc(docId);
678
+ const doc = await docRef.get().toPromise();
679
+ if (doc && doc.exists) {
680
+ await docRef.update({
681
+ count: firebase.firestore.FieldValue.increment(1),
682
+ updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
683
+ lastError: trackingData.errorMessage,
684
+ });
685
+ }
686
+ else {
687
+ await docRef.set({
688
+ ...trackingData,
689
+ count: 1,
690
+ createdAt: firebase.firestore.FieldValue.serverTimestamp(),
691
+ });
692
+ }
693
+ }
694
+ catch (trackingError) {
695
+ console.warn('Falha ao rastrear fallback preventivo:', trackingError);
696
+ }
697
+ }
698
+ /**
699
+ * Gera uma assinatura única para uma query
700
+ */
701
+ generateQuerySignature(collection, arrange, conditions = undefined) {
702
+ const signature = {
703
+ collection,
704
+ sortBy: arrange.sortBy,
705
+ filters: arrange.filters?.map((f) => ({
706
+ arrange: f.arrange,
707
+ property: f.filter?.property || null,
708
+ })) || [],
709
+ conditions: conditions?.map((c) => ({
710
+ property: c.firestoreProperty,
711
+ operator: c.operator,
712
+ })) || [],
713
+ };
714
+ return btoa(JSON.stringify(signature))
715
+ .replace(/[^a-zA-Z0-9]/g, '')
716
+ .substring(0, 20);
717
+ }
718
+ /**
719
+ * Gera instruções claras para criar o índice manualmente
720
+ */
721
+ generateIndexInstructions(collection, arrange, conditions = undefined) {
722
+ const instructions = {
723
+ summary: '',
724
+ collection: collection,
725
+ fields: [],
726
+ queryExample: '',
727
+ stepByStep: [],
728
+ notes: [],
729
+ };
730
+ const fields = [];
731
+ if (conditions && conditions.length > 0) {
732
+ conditions.forEach((condition) => {
733
+ if (condition.firestoreProperty) {
734
+ fields.push({
735
+ field: condition.firestoreProperty,
736
+ order: 'Ascending',
737
+ type: 'WHERE clause',
738
+ operator: condition.operator,
739
+ description: `Filtrar por ${condition.firestoreProperty} usando operador ${condition.operator}`,
740
+ });
741
+ }
742
+ });
743
+ }
744
+ if (arrange.filters && arrange.filters.length > 0) {
745
+ arrange.filters.forEach((filter) => {
746
+ if (filter.filter?.property) {
747
+ fields.push({
748
+ field: filter.filter.property,
749
+ order: 'Ascending',
750
+ type: 'WHERE clause (filter)',
751
+ operator: filter.arrange === 'filter' ? 'CONTAINS' : 'RANGE',
752
+ description: `Filtrar por ${filter.filter.property} usando filtro ${filter.arrange}`,
753
+ });
754
+ }
755
+ });
756
+ }
757
+ if (arrange.sortBy?.field) {
758
+ fields.push({
759
+ field: arrange.sortBy.field,
760
+ order: arrange.sortBy.order === 'desc' ? 'Descending' : 'Ascending',
761
+ type: 'ORDER BY clause',
762
+ operator: 'N/A',
763
+ description: `Ordenar resultados por ${arrange.sortBy.field} em ordem ${arrange.sortBy.order}`,
764
+ });
765
+ }
766
+ instructions.fields = fields;
767
+ const fieldNames = fields.map((f) => f.field).join(' + ');
768
+ instructions.summary = `Criar índice composto para ${collection}: ${fieldNames}`;
769
+ let queryExample = `db.collection('${collection}')`;
770
+ fields.forEach((field, index) => {
771
+ if (field.type.includes('WHERE')) {
772
+ if (field.operator === '==') {
773
+ queryExample += `\n .where('${field.field}', '==', 'value')`;
774
+ }
775
+ else if (field.operator === 'CONTAINS') {
776
+ queryExample += `\n .where('${field.field}', '>=', 'searchText')`;
777
+ }
778
+ else {
779
+ queryExample += `\n .where('${field.field}', '${field.operator}', 'value')`;
780
+ }
781
+ }
782
+ });
783
+ const orderByField = fields.find((f) => f.type.includes('ORDER BY'));
784
+ if (orderByField) {
785
+ queryExample += `\n .orderBy('${orderByField.field}', '${orderByField.order.toLowerCase()}')`;
786
+ }
787
+ instructions.queryExample = queryExample;
788
+ instructions.stepByStep = [
789
+ '1. Ir para Firebase Console → Firestore → Indexes',
790
+ '2. Clicar em "Create Index"',
791
+ `3. Definir Collection ID: ${collection}`,
792
+ '4. Configurar campos nesta ORDEM EXATA:',
793
+ ...fields.map((field, index) => ` ${index + 1}. Campo: ${field.field}, Order: ${field.order}, Array: No`),
794
+ '5. Definir Query scopes: Collection',
795
+ '6. Clicar em "Create" e aguardar conclusão',
796
+ ];
797
+ instructions.notes = [
798
+ '⚠️ A ordem dos campos é CRÍTICA - deve corresponder exatamente à ordem da query',
799
+ '⚠️ As cláusulas WHERE devem vir ANTES do campo ORDER BY',
800
+ '⚠️ Este índice só funcionará para queries com esta combinação EXATA de campos',
801
+ '⚠️ A criação do índice pode levar vários minutos',
802
+ ];
803
+ return instructions;
804
+ }
805
+ /**
806
+ * Gera um link de índice baseado na estrutura da query
807
+ */
808
+ generateIndexLink(collection, arrange, conditions = undefined) {
809
+ try {
810
+ const indexFields = [];
811
+ if (conditions && conditions.length > 0) {
812
+ conditions.forEach((condition) => {
813
+ if (condition.firestoreProperty) {
814
+ indexFields.push(condition.firestoreProperty);
815
+ }
816
+ });
817
+ }
818
+ if (arrange.filters && arrange.filters.length > 0) {
819
+ arrange.filters.forEach((filter) => {
820
+ if (filter.filter?.property) {
821
+ indexFields.push(filter.filter.property);
822
+ }
823
+ });
824
+ }
825
+ if (arrange.sortBy?.field) {
826
+ indexFields.push(arrange.sortBy.field);
827
+ }
828
+ if (indexFields.length > 1) {
829
+ const baseUrl = 'https://console.firebase.google.com/project/toppayy-dev/firestore/indexes';
830
+ const queryParams = new URLSearchParams({
831
+ create_composite: `collection=${collection}&fields=${indexFields.join(',')}`,
832
+ });
833
+ const finalLink = `${baseUrl}?${queryParams.toString()}`;
834
+ return finalLink;
835
+ }
836
+ return null;
837
+ }
838
+ catch (error) {
839
+ console.warn('Falha ao gerar link de índice:', error);
840
+ return null;
841
+ }
842
+ }
843
+ async trackMissingIndex(error, collection, arrange, conditions = undefined) {
844
+ try {
845
+ const indexLink = this.extractIndexLink(error);
846
+ if (!indexLink)
847
+ return;
848
+ const linkHash = btoa(indexLink)
849
+ .replace(/[^a-zA-Z0-9]/g, '')
850
+ .substring(0, 20);
851
+ const docId = `${collection}_${linkHash}`;
852
+ const indexInstructions = this.generateIndexInstructions(collection, arrange, conditions);
853
+ const trackingData = {
854
+ collection,
855
+ indexLink,
856
+ indexInstructions,
857
+ arrange: {
858
+ sortBy: arrange.sortBy,
859
+ filters: arrange.filters?.map((f) => ({
860
+ arrange: f.arrange,
861
+ property: f.filter?.property || null,
862
+ dateField: f.arrange === 'filterByDate' ? arrange.sortBy?.field : null,
863
+ })) || [],
864
+ },
865
+ conditions: conditions?.map((c) => ({
866
+ property: c.firestoreProperty,
867
+ operator: c.operator,
868
+ })) || [],
869
+ errorMessage: error.message,
870
+ updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
871
+ };
872
+ const docRef = this.ngFire.collection('missingIndexes').doc(docId);
873
+ const doc = await docRef.get().toPromise();
874
+ if (doc && doc.exists) {
875
+ await docRef.update({
876
+ count: firebase.firestore.FieldValue.increment(1),
877
+ updatedAt: firebase.firestore.FieldValue.serverTimestamp(),
878
+ lastError: error.message,
879
+ });
880
+ }
881
+ else {
882
+ await docRef.set({
883
+ ...trackingData,
884
+ count: 1,
885
+ createdAt: firebase.firestore.FieldValue.serverTimestamp(),
886
+ });
887
+ }
888
+ }
889
+ catch (trackingError) {
890
+ console.warn('Falha ao rastrear índice ausente:', trackingError);
891
+ }
892
+ }
893
+ }
894
+ TableService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TableService, deps: [{ token: i1.AngularFirestore, optional: true }, { token: i2.MatDialog, optional: true }, { token: i3.ToastrService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
895
+ TableService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TableService, providedIn: 'root' });
896
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TableService, decorators: [{
897
+ type: Injectable,
898
+ args: [{
899
+ providedIn: 'root',
900
+ }]
901
+ }], ctorParameters: function () { return [{ type: i1.AngularFirestore, decorators: [{
902
+ type: Optional
903
+ }] }, { type: i2.MatDialog, decorators: [{
904
+ type: Optional
905
+ }] }, { type: i3.ToastrService, decorators: [{
906
+ type: Optional
907
+ }] }]; } });
908
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLWZpcmViYXNlLXRhYmxlLWt4cC9zcmMvbGliL3NlcnZpY2VzL3RhYmxlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFNckQsT0FBTyxRQUFRLE1BQU0scUJBQXFCLENBQUM7QUFFM0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUl0QyxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQzs7Ozs7QUFnQmpDLE1BQU0sT0FBTyxZQUFZO0lBQ3ZCLFlBQ3NCLE1BQXdCLEVBQ3hCLE1BQWlCLEVBQ2pCLE1BQXFCO1FBRnJCLFdBQU0sR0FBTixNQUFNLENBQWtCO1FBQ3hCLFdBQU0sR0FBTixNQUFNLENBQVc7UUFDakIsV0FBTSxHQUFOLE1BQU0sQ0FBZTtRQWd2QnBDLGNBQVMsR0FBRztZQUNqQixJQUFJLEVBQUUsQ0FBQyxDQUFNLEVBQUUsQ0FBTSxFQUFXLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQztZQUMxQyxJQUFJLEVBQUUsQ0FBQyxDQUFNLEVBQUUsQ0FBTSxFQUFXLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQztZQUMxQyxHQUFHLEVBQUUsQ0FBQyxDQUFNLEVBQUUsQ0FBTSxFQUFXLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUN2QyxHQUFHLEVBQUUsQ0FBQyxDQUFNLEVBQUUsQ0FBTSxFQUFXLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUN2QyxJQUFJLEVBQUUsQ0FBQyxDQUFNLEVBQUUsQ0FBTSxFQUFXLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUN6QyxJQUFJLEVBQUUsQ0FBQyxDQUFNLEVBQUUsQ0FBTSxFQUFXLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUN6QyxR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Q1YsVUFBVSxFQUFFLE1BQU07aUJBQ25COzswQkFHSSxRQUFROzswQkFDUixRQUFROzswQkFDUixRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgT3B0aW9uYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEFuZ3VsYXJGaXJlc3RvcmUsXG4gIENvbGxlY3Rpb25SZWZlcmVuY2UsXG4gIFF1ZXJ5RG9jdW1lbnRTbmFwc2hvdCxcbn0gZnJvbSAnQGFuZ3VsYXIvZmlyZS9jb21wYXQvZmlyZXN0b3JlJztcbmltcG9ydCBmaXJlYmFzZSBmcm9tICdmaXJlYmFzZS9jb21wYXQvYXBwJztcbmltcG9ydCB7IEFycmFuZ2UsIENvbmRpdGlvbiwgUGFnaW5hdGlvbiB9IGZyb20gJy4uL3R5cGVzL1RhYmxlJztcbmltcG9ydCB7IGZpcnN0VmFsdWVGcm9tIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBNYXREaWFsb2cgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHsgVG9hc3RyU2VydmljZSB9IGZyb20gJ25neC10b2FzdHInO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBWYWxpZGF0b3JGbiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCAqIGFzIG1vbWVudCBmcm9tICdtb21lbnQnO1xuXG5pbnRlcmZhY2UgUGFnaW5hdGlvblJlc3VsdCB7XG4gIGl0ZW1zOiBhbnlbXTtcbiAgZmlsdGVyTGVuZ3RoOiBudW1iZXIgfCBudWxsO1xuICBmaXJzdERvYzogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5RG9jdW1lbnRTbmFwc2hvdDx1bmtub3duPiB8IG51bGw7XG4gIGxhc3REb2M6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeURvY3VtZW50U25hcHNob3Q8dW5rbm93bj4gfCBudWxsO1xuICBoYXNOZXh0UGFnZTogYm9vbGVhbjtcbiAgaGFzUHJldmlvdXNQYWdlPzogYm9vbGVhbjtcbiAgY3VycmVudENsaWVudFBhZ2VJbmRleD86IG51bWJlcjtcbiAgdG90YWxQYWdlcz86IG51bWJlcjtcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIFRhYmxlU2VydmljZSB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgbmdGaXJlOiBBbmd1bGFyRmlyZXN0b3JlLFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgZGlhbG9nOiBNYXREaWFsb2csXG4gICAgQE9wdGlvbmFsKCkgcHJpdmF0ZSB0b2FzdHI6IFRvYXN0clNlcnZpY2VcbiAgKSB7fVxuXG4gIGFzeW5jIGdldEl0ZW1zKGNvbGxlY3Rpb246IENvbGxlY3Rpb25SZWZlcmVuY2U8dW5rbm93bj4pOiBQcm9taXNlPGFueVtdPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHF1ZXJ5U25hcHNob3QgPSBhd2FpdCBjb2xsZWN0aW9uLmdldCgpO1xuICAgICAgcmV0dXJuIHF1ZXJ5U25hcHNob3QuZG9jcy5tYXAoXG4gICAgICAgIChkb2M6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeURvY3VtZW50U25hcHNob3Q8dW5rbm93bj4pID0+IHtcbiAgICAgICAgICByZXR1cm4geyAuLi4oZG9jLmRhdGEoKSBhcyBhbnkpLCBpZDogZG9jLmlkIH07XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUud2FybignQ29sbGVjdGlvbiBuw6NvIGVuY29udHJhZGE6JywgZXJyb3IpO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZXhlY3V0ZVF1ZXJ5KHBhcmFtczogUGFnaW5hdGlvbik6IFByb21pc2U8UGFnaW5hdGlvblJlc3VsdD4ge1xuICAgIGlmIChwYXJhbXMuZmlsdGVyRm4pIHtcbiAgICAgIC8vIEzDs2dpY2EgY29tIGZpbHRybyBubyBjbGllbnRlIChmaWx0ZXJGbilcbiAgICAgIGNvbnN0IEJBVENIX0ZFVENIX1NJWkUgPSBwYXJhbXMuYmF0Y2hTaXplO1xuICAgICAgY29uc3QgR09BTF9TSVpFID0gcGFyYW1zLmJhdGNoU2l6ZSArIDE7XG5cbiAgICAgIGlmIChwYXJhbXMubmF2aWdhdGlvbiA9PT0gJ2ZvcndhcmQnIHx8IHBhcmFtcy5uYXZpZ2F0aW9uID09PSAncmVsb2FkJykge1xuICAgICAgICBpZiAocGFyYW1zLm5hdmlnYXRpb24gPT09ICdyZWxvYWQnICYmIHBhcmFtcy5kb2MpIHtcbiAgICAgICAgICBwYXJhbXMuZG9jLmxhc3REb2MgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGxhc3REb2NDdXJzb3I6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeURvY3VtZW50U25hcHNob3Q8dW5rbm93bj4gfCBudWxsID1cbiAgICAgICAgICBwYXJhbXMuZG9jID8gcGFyYW1zLmRvYy5sYXN0RG9jIDogbnVsbDtcbiAgICAgICAgbGV0IHBhZ2VSZXN1bHRzOiBhbnlbXSA9IFtdO1xuICAgICAgICBsZXQgYWxsRmV0Y2hlZERvY3M6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeURvY3VtZW50U25hcHNob3Q8dW5rbm93bj5bXSA9XG4gICAgICAgICAgW107XG4gICAgICAgIGxldCBoYXNNb3JlRG9jc0luRGIgPSB0cnVlO1xuXG4gICAgICAgIHdoaWxlIChwYWdlUmVzdWx0cy5sZW5ndGggPCBHT0FMX1NJWkUgJiYgaGFzTW9yZURvY3NJbkRiKSB7XG4gICAgICAgICAgbGV0IHF1ZXJ5OiBmaXJlYmFzZS5maXJlc3RvcmUuUXVlcnk8dW5rbm93bj4gPSB0aGlzLm5nRmlyZS5jb2xsZWN0aW9uKFxuICAgICAgICAgICAgcGFyYW1zLmNvbGxlY3Rpb25cbiAgICAgICAgICApLnJlZjtcbiAgICAgICAgICBxdWVyeSA9IHRoaXMuYXBwbHlGaWx0ZXJzKHF1ZXJ5LCBwYXJhbXMuYXJyYW5nZSwgcGFyYW1zLmNvbmRpdGlvbnMpO1xuXG4gICAgICAgICAgaWYgKGxhc3REb2NDdXJzb3IpIHtcbiAgICAgICAgICAgIHF1ZXJ5ID0gcXVlcnkuc3RhcnRBZnRlcihsYXN0RG9jQ3Vyc29yKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcXVlcnkgPSBxdWVyeS5saW1pdChCQVRDSF9GRVRDSF9TSVpFKTtcblxuICAgICAgICAgIGNvbnN0IHNuYXBzaG90ID0gYXdhaXQgcXVlcnkuZ2V0KCk7XG5cbiAgICAgICAgICBpZiAoc25hcHNob3QuZW1wdHkpIHtcbiAgICAgICAgICAgIGhhc01vcmVEb2NzSW5EYiA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbGFzdERvY0N1cnNvciA9IHNuYXBzaG90LmRvY3Nbc25hcHNob3QuZG9jcy5sZW5ndGggLSAxXTtcbiAgICAgICAgICBhbGxGZXRjaGVkRG9jcy5wdXNoKC4uLnNuYXBzaG90LmRvY3MpO1xuXG4gICAgICAgICAgY29uc3QgYmF0Y2hVc2VycyA9IHNuYXBzaG90LmRvY3NcbiAgICAgICAgICAgIC5tYXAoKGRvYzogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5RG9jdW1lbnRTbmFwc2hvdDx1bmtub3duPikgPT4gKHtcbiAgICAgICAgICAgICAgaWQ6IGRvYy5pZCxcbiAgICAgICAgICAgICAgLi4uKGRvYy5kYXRhKCkgYXMgYW55KSxcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgLmZpbHRlcihwYXJhbXMuZmlsdGVyRm4pO1xuXG4gICAgICAgICAgcGFnZVJlc3VsdHMucHVzaCguLi5iYXRjaFVzZXJzKTtcblxuICAgICAgICAgIGlmIChzbmFwc2hvdC5zaXplIDwgQkFUQ0hfRkVUQ0hfU0laRSkge1xuICAgICAgICAgICAgaGFzTW9yZURvY3NJbkRiID0gZmFsc2U7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaGFzTmV4dFBhZ2UgPSBwYWdlUmVzdWx0cy5sZW5ndGggPiBwYXJhbXMuYmF0Y2hTaXplO1xuICAgICAgICBjb25zdCBmaW5hbEl0ZW1zID0gcGFnZVJlc3VsdHMuc2xpY2UoMCwgcGFyYW1zLmJhdGNoU2l6ZSk7XG5cbiAgICAgICAgY29uc3QgZmlyc3REb2NPZlBhZ2UgPVxuICAgICAgICAgIGFsbEZldGNoZWREb2NzLmZpbmQoXG4gICAgICAgICAgICAoZG9jOiBmaXJlYmFzZS5maXJlc3RvcmUuUXVlcnlEb2N1bWVudFNuYXBzaG90PHVua25vd24+KSA9PlxuICAgICAgICAgICAgICBkb2MuaWQgPT09IGZpbmFsSXRlbXNbMF0/LmlkXG4gICAgICAgICAgKSB8fCBudWxsO1xuICAgICAgICBjb25zdCBsYXN0RG9jT2ZQYWdlID1cbiAgICAgICAgICBhbGxGZXRjaGVkRG9jcy5maW5kKFxuICAgICAgICAgICAgKGRvYzogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5RG9jdW1lbnRTbmFwc2hvdDx1bmtub3duPikgPT5cbiAgICAgICAgICAgICAgZG9jLmlkID09PSBmaW5hbEl0ZW1zW2ZpbmFsSXRlbXMubGVuZ3RoIC0gMV0/LmlkXG4gICAgICAgICAgKSB8fCBudWxsO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgaXRlbXM6IGZpbmFsSXRlbXMsXG4gICAgICAgICAgZmlsdGVyTGVuZ3RoOiBudWxsLFxuICAgICAgICAgIGZpcnN0RG9jOiBmaXJzdERvY09mUGFnZSxcbiAgICAgICAgICBsYXN0RG9jOiBsYXN0RG9jT2ZQYWdlLFxuICAgICAgICAgIGhhc05leHRQYWdlOiBoYXNOZXh0UGFnZSxcbiAgICAgICAgICBoYXNQcmV2aW91c1BhZ2U6XG4gICAgICAgICAgICAhIShwYXJhbXMuZG9jICYmIHBhcmFtcy5kb2MubGFzdERvYykgJiZcbiAgICAgICAgICAgIHBhcmFtcy5uYXZpZ2F0aW9uICE9PSAncmVsb2FkJyxcbiAgICAgICAgICBjdXJyZW50Q2xpZW50UGFnZUluZGV4OiB1bmRlZmluZWQsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICAvLyBMw7NnaWNhIHBhcmEgdHLDoXMgKGJhY2t3YXJkKVxuICAgICAgZWxzZSBpZiAocGFyYW1zLm5hdmlnYXRpb24gPT09ICdiYWNrd2FyZCcpIHtcbiAgICAgICAgaWYgKCFwYXJhbXMuZG9jIHx8ICFwYXJhbXMuZG9jLmZpcnN0RG9jKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGl0ZW1zOiBbXSxcbiAgICAgICAgICAgIGZpbHRlckxlbmd0aDogbnVsbCxcbiAgICAgICAgICAgIGZpcnN0RG9jOiBudWxsLFxuICAgICAgICAgICAgbGFzdERvYzogbnVsbCxcbiAgICAgICAgICAgIGhhc05leHRQYWdlOiB0cnVlLFxuICAgICAgICAgICAgaGFzUHJldmlvdXNQYWdlOiBmYWxzZSxcbiAgICAgICAgICAgIGN1cnJlbnRDbGllbnRQYWdlSW5kZXg6IHVuZGVmaW5lZCxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHBhZ2VSZXN1bHRzOiBhbnlbXSA9IFtdO1xuICAgICAgICBsZXQgYWxsRmV0Y2hlZERvY3M6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeURvY3VtZW50U25hcHNob3Q8dW5rbm93bj5bXSA9XG4gICAgICAgICAgW107XG4gICAgICAgIGxldCBoYXNNb3JlRG9jc0luRGIgPSB0cnVlO1xuXG4gICAgICAgIGxldCBib3VuZGFyeURvYyA9IHBhcmFtcy5kb2MuZmlyc3REb2M7XG5cbiAgICAgICAgd2hpbGUgKHBhZ2VSZXN1bHRzLmxlbmd0aCA8IEdPQUxfU0laRSAmJiBoYXNNb3JlRG9jc0luRGIpIHtcbiAgICAgICAgICBsZXQgcXVlcnk6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeTx1bmtub3duPiA9IHRoaXMubmdGaXJlLmNvbGxlY3Rpb24oXG4gICAgICAgICAgICBwYXJhbXMuY29sbGVjdGlvblxuICAgICAgICAgICkucmVmO1xuXG4gICAgICAgICAgcXVlcnkgPSB0aGlzLmFwcGx5RmlsdGVycyhxdWVyeSwgcGFyYW1zLmFycmFuZ2UsIHBhcmFtcy5jb25kaXRpb25zKTtcblxuICAgICAgICAgIHF1ZXJ5ID0gcXVlcnkuZW5kQmVmb3JlKGJvdW5kYXJ5RG9jKTtcbiAgICAgICAgICBxdWVyeSA9IHF1ZXJ5LmxpbWl0VG9MYXN0KEJBVENIX0ZFVENIX1NJWkUpO1xuXG4gICAgICAgICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBxdWVyeS5nZXQoKTtcblxuICAgICAgICAgIGlmIChzbmFwc2hvdC5lbXB0eSkge1xuICAgICAgICAgICAgaGFzTW9yZURvY3NJbkRiID0gZmFsc2U7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBib3VuZGFyeURvYyA9IHNuYXBzaG90LmRvY3NbMF0gYXMgYW55O1xuXG4gICAgICAgICAgYWxsRmV0Y2hlZERvY3MgPSBbLi4uc25hcHNob3QuZG9jcywgLi4uYWxsRmV0Y2hlZERvY3NdO1xuXG4gICAgICAgICAgY29uc3QgYmF0Y2hVc2VycyA9IHNuYXBzaG90LmRvY3NcbiAgICAgICAgICAgIC5tYXAoKGRvYzogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5RG9jdW1lbnRTbmFwc2hvdDx1bmtub3duPikgPT4gKHtcbiAgICAgICAgICAgICAgaWQ6IGRvYy5pZCxcbiAgICAgICAgICAgICAgLi4uKGRvYy5kYXRhKCkgYXMgYW55KSxcbiAgICAgICAgICAgIH0pKVxuICAgICAgICAgICAgLmZpbHRlcihwYXJhbXMuZmlsdGVyRm4pO1xuXG4gICAgICAgICAgcGFnZVJlc3VsdHMgPSBbLi4uYmF0Y2hVc2VycywgLi4ucGFnZVJlc3VsdHNdO1xuXG4gICAgICAgICAgaWYgKHNuYXBzaG90LnNpemUgPCBCQVRDSF9GRVRDSF9TSVpFKSB7XG4gICAgICAgICAgICBoYXNNb3JlRG9jc0luRGIgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmaW5hbEl0ZW1zID0gcGFnZVJlc3VsdHMuc2xpY2UoMCwgcGFyYW1zLmJhdGNoU2l6ZSk7XG5cbiAgICAgICAgY29uc3QgZmlyc3REb2NPZlBhZ2UgPVxuICAgICAgICAgIGFsbEZldGNoZWREb2NzLmZpbmQoXG4gICAgICAgICAgICAoZG9jOiBmaXJlYmFzZS5maXJlc3RvcmUuUXVlcnlEb2N1bWVudFNuYXBzaG90PHVua25vd24+KSA9PlxuICAgICAgICAgICAgICBkb2MuaWQgPT09IGZpbmFsSXRlbXNbMF0/LmlkXG4gICAgICAgICAgKSB8fCBudWxsO1xuICAgICAgICBjb25zdCBsYXN0RG9jT2ZQYWdlID1cbiAgICAgICAgICBhbGxGZXRjaGVkRG9jcy5maW5kKFxuICAgICAgICAgICAgKGRvYzogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5RG9jdW1lbnRTbmFwc2hvdDx1bmtub3duPikgPT5cbiAgICAgICAgICAgICAgZG9jLmlkID09PSBmaW5hbEl0ZW1zW2ZpbmFsSXRlbXMubGVuZ3RoIC0gMV0/LmlkXG4gICAgICAgICAgKSB8fCBudWxsO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgaXRlbXM6IGZpbmFsSXRlbXMsXG4gICAgICAgICAgZmlsdGVyTGVuZ3RoOiBudWxsLFxuICAgICAgICAgIGZpcnN0RG9jOiBmaXJzdERvY09mUGFnZSxcbiAgICAgICAgICBsYXN0RG9jOiBsYXN0RG9jT2ZQYWdlLFxuICAgICAgICAgIGhhc05leHRQYWdlOiB0cnVlLFxuICAgICAgICAgIGN1cnJlbnRDbGllbnRQYWdlSW5kZXg6IHVuZGVmaW5lZCxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IGl0ZW1zOiBhbnlbXSA9IFtdO1xuICAgICAgbGV0IGRvY3M6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeURvY3VtZW50U25hcHNob3Q8dW5rbm93bj5bXSA9IFtdO1xuICAgICAgbGV0IGhhc05leHRQYWdlID0gZmFsc2U7XG4gICAgICBsZXQgZmlsdGVyTGVuZ3RoOiBudWxsIHwgbnVtYmVyID0gbnVsbDtcblxuICAgICAgbGV0IHF1ZXJ5OiBmaXJlYmFzZS5maXJlc3RvcmUuUXVlcnk8dW5rbm93bj4gPSB0aGlzLm5nRmlyZS5jb2xsZWN0aW9uKFxuICAgICAgICBwYXJhbXMuY29sbGVjdGlvblxuICAgICAgKS5yZWY7XG5cbiAgICAgIGlmIChwYXJhbXMuY29uZGl0aW9ucykge1xuICAgICAgICBwYXJhbXMuY29uZGl0aW9ucy5mb3JFYWNoKChjOiBDb25kaXRpb24pID0+IHtcbiAgICAgICAgICBpZiAoYy5vcGVyYXRvciA9PT0gJyE9Jykge1xuICAgICAgICAgICAgcXVlcnkgPSBxdWVyeS5vcmRlckJ5KGMuZmlyZXN0b3JlUHJvcGVydHkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHF1ZXJ5ID0gdGhpcy5hcHBseUZpbHRlcnMocXVlcnksIHBhcmFtcy5hcnJhbmdlLCBwYXJhbXMuY29uZGl0aW9ucyk7XG5cbiAgICAgIGlmIChwYXJhbXMubmF2aWdhdGlvbiA9PT0gJ3JlbG9hZCcpIHtcbiAgICAgICAgcXVlcnkgPSBxdWVyeS5saW1pdChwYXJhbXMuYmF0Y2hTaXplICsgMSk7XG4gICAgICAgIGlmIChwYXJhbXMuZG9jICYmIHBhcmFtcy5kb2MuZmlyc3REb2MpIHtcbiAgICAgICAgICBxdWVyeSA9IHF1ZXJ5LnN0YXJ0QXQocGFyYW1zLmRvYy5maXJzdERvYyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAocGFyYW1zLm5hdmlnYXRpb24gPT09ICdmb3J3YXJkJykge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5LmxpbWl0KHBhcmFtcy5iYXRjaFNpemUgKyAxKTtcblxuICAgICAgICBpZiAocGFyYW1zLmRvYyAmJiBwYXJhbXMuZG9jLmxhc3REb2MpIHtcbiAgICAgICAgICBxdWVyeSA9IHF1ZXJ5LnN0YXJ0QWZ0ZXIocGFyYW1zLmRvYy5sYXN0RG9jKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gYmFja3dhcmRcbiAgICAgICAgcXVlcnkgPSBxdWVyeS5saW1pdFRvTGFzdChwYXJhbXMuYmF0Y2hTaXplICsgMSk7XG4gICAgICAgIGlmIChwYXJhbXMuZG9jICYmIHBhcmFtcy5kb2MuZmlyc3REb2MpIHtcbiAgICAgICAgICBxdWVyeSA9IHF1ZXJ5LmVuZEJlZm9yZShwYXJhbXMuZG9jLmZpcnN0RG9jKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBpdGVtQ29sID0gYXdhaXQgcXVlcnkuZ2V0KCk7XG4gICAgICBpdGVtQ29sLmRvY3MuZm9yRWFjaChcbiAgICAgICAgKGRvYzogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5RG9jdW1lbnRTbmFwc2hvdDx1bmtub3duPikgPT5cbiAgICAgICAgICBkb2NzLnB1c2goZG9jKVxuICAgICAgKTtcbiAgICAgIGNvbnN0IGl0ZW1Qcm9taXNlcyA9IGRvY3MubWFwKFxuICAgICAgICBhc3luYyAoaXRlbTogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5RG9jdW1lbnRTbmFwc2hvdDx1bmtub3duPikgPT4ge1xuICAgICAgICAgIGNvbnN0IGl0ZW1EYXRhID0gaXRlbS5kYXRhKCkgYXMgYW55O1xuICAgICAgICAgIGl0ZW1zLnB1c2goeyBpZDogaXRlbS5pZCwgLi4uaXRlbURhdGEgfSk7XG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIGxldCBsYXN0RG9jOiBmaXJlYmFzZS5maXJlc3RvcmUuUXVlcnlEb2N1bWVudFNuYXBzaG90PHVua25vd24+IHwgbnVsbCA9XG4gICAgICAgIGRvY3NbZG9jcy5sZW5ndGggLSAxXSB8fCBudWxsO1xuICAgICAgbGV0IGZpcnN0RG9jOiBmaXJlYmFzZS5maXJlc3RvcmUuUXVlcnlEb2N1bWVudFNuYXBzaG90PHVua25vd24+IHwgbnVsbCA9XG4gICAgICAgIGRvY3NbMF07XG5cbiAgICAgIGlmIChcbiAgICAgICAgKGl0ZW1zLmxlbmd0aCA+IHBhcmFtcy5iYXRjaFNpemUgJiYgcGFyYW1zLm5hdmlnYXRpb24gPT09ICdmb3J3YXJkJykgfHxcbiAgICAgICAgKHBhcmFtcy5uYXZpZ2F0aW9uID09PSAncmVsb2FkJyAmJiBpdGVtcy5sZW5ndGggPiBwYXJhbXMuYmF0Y2hTaXplKVxuICAgICAgKSB7XG4gICAgICAgIGxhc3REb2MgPSBkb2NzW2RvY3MubGVuZ3RoIC0gMl0gfHwgbnVsbDtcbiAgICAgICAgaXRlbXMucG9wKCk7XG4gICAgICAgIGhhc05leHRQYWdlID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChpdGVtcy5sZW5ndGggPiBwYXJhbXMuYmF0Y2hTaXplICYmIHBhcmFtcy5uYXZpZ2F0aW9uID09PSAnYmFja3dhcmQnKSB7XG4gICAgICAgIGZpcnN0RG9jID0gZG9jc1sxXTtcbiAgICAgICAgaXRlbXMuc2hpZnQoKTtcbiAgICAgICAgaGFzTmV4dFBhZ2UgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChpdGVtUHJvbWlzZXMpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaXRlbXMsXG4gICAgICAgIGZpbHRlckxlbmd0aCxcbiAgICAgICAgbGFzdERvYyxcbiAgICAgICAgZmlyc3REb2MsXG4gICAgICAgIGhhc05leHRQYWdlLFxuICAgICAgICBjdXJyZW50Q2xpZW50UGFnZUluZGV4OiB1bmRlZmluZWQsXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEZhbGxiYWNrIHBhcmEgZ2FyYW50aXIgcXVlIHNlbXByZSByZXRvcm5hbW9zIGFsZ29cbiAgICByZXR1cm4ge1xuICAgICAgaXRlbXM6IFtdLFxuICAgICAgZmlsdGVyTGVuZ3RoOiBudWxsLFxuICAgICAgZmlyc3REb2M6IG51bGwsXG4gICAgICBsYXN0RG9jOiBudWxsLFxuICAgICAgaGFzTmV4dFBhZ2U6IGZhbHNlLFxuICAgICAgY3VycmVudENsaWVudFBhZ2VJbmRleDogdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cblxuICBhcHBseUZpbHRlcnMoXG4gICAgcXVlcnk6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeTx1bmtub3duPixcbiAgICBhcnJhbmdlOiBBcnJhbmdlLFxuICAgIGNvbmRpdGlvbnM6IENvbmRpdGlvbltdIHwgdW5kZWZpbmVkXG4gICk6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeTx1bmtub3duPiB7XG4gICAgaWYgKGNvbmRpdGlvbnMpIHtcbiAgICAgIGNvbmRpdGlvbnMubWFwKChjb25kOiBDb25kaXRpb24pID0+IHtcbiAgICAgICAgcXVlcnkgPSBxdWVyeS53aGVyZShcbiAgICAgICAgICBjb25kLmZpcmVzdG9yZVByb3BlcnR5LFxuICAgICAgICAgIGNvbmQub3BlcmF0b3IsXG4gICAgICAgICAgY29uZC5kYXNoUHJvcGVydHlcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGxldCBoYXNGaWx0ZXJTcGVjaWZpY09yZGVyQnkgPSBmYWxzZTtcbiAgICBsZXQgYXBwbGllZE9yZGVyQnlGaWVsZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICBjb25zdCBlcXVhbHNGaWx0ZXJzID0gYXJyYW5nZS5maWx0ZXJzLmZpbHRlcihcbiAgICAgIChmOiBhbnkpID0+IGYuYXJyYW5nZSA9PT0gJ2VxdWFscycgJiYgZi5maWx0ZXJcbiAgICApO1xuICAgIGNvbnN0IG90aGVyRmlsdGVycyA9IGFycmFuZ2UuZmlsdGVycy5maWx0ZXIoXG4gICAgICAoZjogYW55KSA9PiBmLmFycmFuZ2UgIT09ICdlcXVhbHMnXG4gICAgKTtcblxuICAgIGNvbnN0IGVxdWFsc0dyb3VwZWRCeVByb3BlcnR5ID0gZXF1YWxzRmlsdGVycy5yZWR1Y2UoXG4gICAgICAoYWNjOiBhbnksIGN1cnJlbnQ6IGFueSkgPT4ge1xuICAgICAgICBjb25zdCBwcm9wID0gY3VycmVudC5maWx0ZXIucHJvcGVydHk7XG4gICAgICAgIGlmICghYWNjW3Byb3BdKSB7XG4gICAgICAgICAgYWNjW3Byb3BdID0gW107XG4gICAgICAgIH1cbiAgICAgICAgYWNjW3Byb3BdLnB1c2goY3VycmVudC5maWx0ZXIuZmlsdGVyaW5nKTtcbiAgICAgICAgcmV0dXJuIGFjYztcbiAgICAgIH0sXG4gICAgICB7fVxuICAgICk7XG5cbiAgICBmb3IgKGNvbnN0IHByb3AgaW4gZXF1YWxzR3JvdXBlZEJ5UHJvcGVydHkpIHtcbiAgICAgIGNvbnN0IHZhbHVlcyA9IGVxdWFsc0dyb3VwZWRCeVByb3BlcnR5W3Byb3BdO1xuICAgICAgaWYgKHZhbHVlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIHF1ZXJ5ID0gcXVlcnkud2hlcmUocHJvcCwgJ2luJywgdmFsdWVzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBvdGhlckZpbHRlcnMuZm9yRWFjaCgoZmlsdGVySXRlbTogYW55KSA9PiB7XG4gICAgICAvLyBBcGxpY2FyIGZpbHRyYWdlbSBwb3IgYnVzY2FcbiAgICAgIGlmIChcbiAgICAgICAgZmlsdGVySXRlbS5maWx0ZXI/LmZpbHRlcmluZyAmJlxuICAgICAgICBmaWx0ZXJJdGVtLmZpbHRlcj8ucHJvcGVydHkgIT09ICcnICYmXG4gICAgICAgIGZpbHRlckl0ZW0uYXJyYW5nZSA9PT0gJ2ZpbHRlcidcbiAgICAgICkge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5XG4gICAgICAgICAgLndoZXJlKFxuICAgICAgICAgICAgZmlsdGVySXRlbS5maWx0ZXIucHJvcGVydHksXG4gICAgICAgICAgICAnPj0nLFxuICAgICAgICAgICAgZmlsdGVySXRlbS5maWx0ZXIuZmlsdGVyaW5nLnRyaW0oKS50b1VwcGVyQ2FzZSgpXG4gICAgICAgICAgKVxuICAgICAgICAgIC53aGVyZShcbiAgICAgICAgICAgIGZpbHRlckl0ZW0uZmlsdGVyLnByb3BlcnR5LFxuICAgICAgICAgICAgJzw9JyxcbiAgICAgICAgICAgIGZpbHRlckl0ZW0uZmlsdGVyLmZpbHRlcmluZy50cmltKCkudG9VcHBlckNhc2UoKSArICdcXHVmOGZmJ1xuICAgICAgICAgICk7XG4gICAgICAgIGlmICghaGFzRmlsdGVyU3BlY2lmaWNPcmRlckJ5KSB7XG4gICAgICAgICAgcXVlcnkgPSBxdWVyeS5vcmRlckJ5KGZpbHRlckl0ZW0uZmlsdGVyLnByb3BlcnR5KTtcbiAgICAgICAgICBoYXNGaWx0ZXJTcGVjaWZpY09yZGVyQnkgPSB0cnVlO1xuICAgICAgICAgIGFwcGxpZWRPcmRlckJ5RmllbGQgPSBmaWx0ZXJJdGVtLmZpbHRlci5wcm9wZXJ0eTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBBcGxpY2FyIGZpbHRybyBkbyB0aXBvIFwiZmlsdGVyQnlEYXRlXCJcbiAgICAgIGlmIChmaWx0ZXJJdGVtLmRhdGVGaWx0ZXIgJiYgZmlsdGVySXRlbS5hcnJhbmdlID09PSAnZmlsdGVyQnlEYXRlJykge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5XG4gICAgICAgICAgLndoZXJlKGFycmFuZ2Uuc29ydEJ5LmZpZWxkLCAnPj0nLCBmaWx0ZXJJdGVtLmRhdGVGaWx0ZXIuaW5pdGlhbClcbiAgICAgICAgICAud2hlcmUoYXJyYW5nZS5zb3J0QnkuZmllbGQsICc8PScsIGZpbHRlckl0ZW0uZGF0ZUZpbHRlci5maW5hbCk7XG4gICAgICAgIGlmICghaGFzRmlsdGVyU3BlY2lmaWNPcmRlckJ5KSB7XG4gICAgICAgICAgcXVlcnkgPSBxdWVyeS5vcmRlckJ5KGFycmFuZ2Uuc29ydEJ5LmZpZWxkKTtcbiAgICAgICAgICBoYXNGaWx0ZXJTcGVjaWZpY09yZGVyQnkgPSB0cnVlO1xuICAgICAgICAgIGFwcGxpZWRPcmRlckJ5RmllbGQgPSBhcnJhbmdlLnNvcnRCeS5maWVsZDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gQXBsaWNhciBzb3J0QnlcbiAgICBpZiAoYXJyYW5nZS5zb3J0QnkgJiYgYXJyYW5nZS5zb3J0QnkuZmllbGQgJiYgYXJyYW5nZS5zb3J0Qnkub3JkZXIpIHtcbiAgICAgIGlmIChhcHBsaWVkT3JkZXJCeUZpZWxkICE9PSBhcnJhbmdlLnNvcnRCeS5maWVsZCkge1xuICAgICAgICBxdWVyeSA9IHF1ZXJ5Lm9yZGVyQnkoYXJyYW5nZS5zb3J0QnkuZmllbGQsIGFycmFuZ2Uuc29ydEJ5Lm9yZGVyKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHF1ZXJ5O1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVjdGEgc2UgYSBxdWVyeSB2YWkgcHJlY2lzYXIgZGUgaW5kZXggY29tcG9zdG8gZSBkZXZlIHVzYXIgZmFsbGJhY2sgY2xpZW50LXNpZGVcbiAgICovXG4gIHByaXZhdGUgc2hvdWxkVXNlQ2xpZW50U2lkZUZhbGxiYWNrKHBhcmFtczogUGFnaW5hdGlvbik6IGJvb2xlYW4ge1xuICAgIGNvbnN0IGhhc0NvbmRpdGlvbnMgPSBwYXJhbXMuY29uZGl0aW9ucyAmJiBwYXJhbXMuY29uZGl0aW9ucy5sZW5ndGggPiAwO1xuICAgIGNvbnN0IGhhc0FycmFuZ2VGaWx0ZXJzID1cbiAgICAgIHBhcmFtcy5hcnJhbmdlPy5maWx0ZXJzICYmIHBhcmFtcy5hcnJhbmdlLmZpbHRlcnMubGVuZ3RoID4gMDtcbiAgICBjb25zdCBoYXNTb3J0QnkgPSBwYXJhbXMuYXJyYW5nZT8uc29ydEJ5Py5maWVsZDtcblxuICAgIGlmIChwYXJhbXMuZmlsdGVyRm4pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoaGFzQ29uZGl0aW9ucyAmJiBoYXNBcnJhbmdlRmlsdGVycyAmJiBoYXNTb3J0QnkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGlmIChoYXNDb25kaXRpb25zICYmIGhhc0FycmFuZ2VGaWx0ZXJzKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoaGFzQXJyYW5nZUZpbHRlcnMgJiYgcGFyYW1zLmFycmFuZ2UuZmlsdGVycy5sZW5ndGggPiAxICYmIGhhc1NvcnRCeSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgYXN5bmMgZ2V0UGFnaW5hdGVkKHBhcmFtczogUGFnaW5hdGlvbik6IFByb21pc2U8UGFnaW5hdGlvblJlc3VsdD4ge1xuICAgIC8vIERldGVjdGFyIHByZXZlbnRpdmFtZW50ZSBzZSBkZXZlIHVzYXIgZmFsbGJhY2tcbiAgICBpZiAodGhpcy5zaG91bGRVc2VDbGllbnRTaWRlRmFsbGJhY2socGFyYW1zKSkge1xuICAgICAgYXdhaXQgdGhpcy50cmFja01pc3NpbmdJbmRleFByZXZlbnRpdmUoXG4gICAgICAgIHBhcmFtcy5jb2xsZWN0aW9uLFxuICAgICAgICBwYXJhbXMuYXJyYW5nZSxcbiAgICAgICAgcGFyYW1zLmNvbmRpdGlvbnNcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZXhlY3V0ZUNsaWVudFNpZGVRdWVyeShwYXJhbXMpO1xuICAgICAgY29uc29sZS5sb2coJ/Cfk4ogW1RBQkxFXSBSZXN1bHRhZG9zIHBhZ2luYWRvcyB2aWEgZmFsbGJhY2sgY2xpZW50LXNpZGU6Jywge1xuICAgICAgICB0b3RhbEl0ZW1zOiByZXN1bHQuZmlsdGVyTGVuZ3RoLFxuICAgICAgICByZXR1cm5lZEl0ZW1zOiByZXN1bHQuaXRlbXMubGVuZ3RoLFxuICAgICAgICBoYXNOZXh0UGFnZTogcmVzdWx0Lmhhc05leHRQYWdlLFxuICAgICAgICBjdXJyZW50UGFnZTogKHJlc3VsdC5jdXJyZW50Q2xpZW50UGFnZUluZGV4IHx8IDApICsgMSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5leGVjdXRlUXVlcnkocGFyYW1zKTtcbiAgICAgIGNvbnNvbGUubG9nKCfwn5OKIFtUQUJMRV0gUmVzdWx0YWRvcyBwYWdpbmFkb3MgdmlhIEZpcmVzdG9yZTonLCB7XG4gICAgICAgIHRvdGFsSXRlbXM6IHJlc3VsdC5maWx0ZXJMZW5ndGggfHwgJ04vQScsXG4gICAgICAgIHJldHVybmVkSXRlbXM6IHJlc3VsdC5pdGVtcy5sZW5ndGgsXG4gICAgICAgIGhhc05leHRQYWdlOiByZXN1bHQuaGFzTmV4dFBhZ2UsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xuICAgICAgaWYgKGVycm9yICYmIGVycm9yLmNvZGUgPT09ICdmYWlsZWQtcHJlY29uZGl0aW9uJykge1xuICAgICAgICBhd2FpdCB0aGlzLnRyYWNrTWlzc2luZ0luZGV4KFxuICAgICAgICAgIGVycm9yLFxuICAgICAgICAgIHBhcmFtcy5jb2xsZWN0aW9uLFxuICAgICAgICAgIHBhcmFtcy5hcnJhbmdlLFxuICAgICAgICAgIHBhcmFtcy5jb25kaXRpb25zXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5leGVjdXRlQ2xpZW50U2lkZVF1ZXJ5KHBhcmFtcyk7XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICfwn5OKIFtUQUJMRV0gUmVzdWx0YWRvcyBwYWdpbmFkb3MgdmlhIGZhbGxiYWNrIChlcnJvIGRlIGluZGV4KTonLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIHRvdGFsSXRlbXM6IHJlc3VsdC5maWx0ZXJMZW5ndGgsXG4gICAgICAgICAgICByZXR1cm5lZEl0ZW1zOiByZXN1bHQuaXRlbXMubGVuZ3RoLFxuICAgICAgICAgICAgaGFzTmV4dFBhZ2U6IHJlc3VsdC5oYXNOZXh0UGFnZSxcbiAgICAgICAgICAgIGN1cnJlbnRQYWdlOiAocmVzdWx0LmN1cnJlbnRDbGllbnRQYWdlSW5kZXggfHwgMCkgKyAxLFxuICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH0gZWxzZSBpZiAoZXJyb3IgJiYgZXJyb3IuY29kZSA9PT0gJ2ludmFsaWQtYXJndW1lbnQnKSB7XG4gICAgICAgIGF3YWl0IHRoaXMudHJhY2tNaXNzaW5nSW5kZXgoXG4gICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgcGFyYW1zLmNvbGxlY3Rpb24sXG4gICAgICAgICAgcGFyYW1zLmFycmFuZ2UsXG4gICAgICAgICAgcGFyYW1zLmNvbmRpdGlvbnNcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmV4ZWN1dGVDbGllbnRTaWRlUXVlcnkocGFyYW1zKTtcbiAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgJ/Cfk4ogW1RBQkxFXSBSZXN1bHRhZG9zIHBhZ2luYWRvcyB2aWEgZmFsbGJhY2sgKGFyZ3VtZW50byBpbnbDoWxpZG8pOicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgdG90YWxJdGVtczogcmVzdWx0LmZpbHRlckxlbmd0aCxcbiAgICAgICAgICAgIHJldHVybmVkSXRlbXM6IHJlc3VsdC5pdGVtcy5sZW5ndGgsXG4gICAgICAgICAgICBoYXNOZXh0UGFnZTogcmVzdWx0Lmhhc05leHRQYWdlLFxuICAgICAgICAgICAgY3VycmVudFBhZ2U6IChyZXN1bHQuY3VycmVudENsaWVudFBhZ2VJbmRleCB8fCAwKSArIDEsXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZXhlY3V0ZUNsaWVudFNpZGVRdWVyeShwYXJhbXM6IFBhZ2luYXRpb24pOiBQcm9taXNlPFBhZ2luYXRpb25SZXN1bHQ+IHtcbiAgICAvLyBPdGltaXphciB1c2FuZG8gcGVsbyBtZW5vcyB1bWEgY2zDoXVzdWxhIC53aGVyZSgpIHF1YW5kbyBwb3Nzw612ZWxcbiAgICBsZXQgcXVlcnk6IGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeTx1bmtub3duPiA9IHRoaXMubmdGaXJlLmNvbGxlY3Rpb24oXG4gICAgICBwYXJhbXMuY29sbGVjdGlvblxuICAgICkucmVmO1xuXG4gICAgbGV0IGFwcGxpZWRDb25kaXRpb246IENvbmRpdGlvbiB8IG51bGwgPSBudWxsO1xuICAgIGxldCBoYXNBcHBsaWVkV2hlcmVDbGF1c2UgPSBmYWxzZTtcblxuICAgIC8vIFByaW1laXJvLCB0ZW50YSBhcGxpY2FyIGNvbmRpw6fDtWVzIHNpbXBsZXNcbiAgICBpZiAocGFyYW1zLmNvbmRpdGlvbnMgJiYgcGFyYW1zLmNvbmRpdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3Qgc2ltcGxlQ29uZGl0aW9uID0gcGFyYW1zLmNvbmRpdGlvbnMuZmluZCgoY29uZDogQ29uZGl0aW9uKSA9PlxuICAgICAgICBbJz09JywgJz4nLCAnPCcsICc+PScsICc8PSddLmluY2x1ZGVzKGNvbmQub3BlcmF0b3IpXG4gICAgICApO1xuXG4gICAgICBpZiAoc2ltcGxlQ29uZGl0aW9uKSB7XG4gICAgICAgIHF1ZXJ5ID0gcXVlcnkud2hlcmUoXG4gICAgICAgICAgc2ltcGxlQ29uZGl0aW9uLmZpcmVzdG9yZVByb3BlcnR5LFxuICAgICAgICAgIHNpbXBsZUNvbmRpdGlvbi5vcGVyYXRvcixcbiAgICAgICAgICBzaW1wbGVDb25kaXRpb24uZGFzaFByb3BlcnR5XG4gICAgICAgICk7XG4gICAgICAgIGFwcGxpZWRDb25kaXRpb24gPSBzaW1wbGVDb25kaXRpb247XG4gICAgICAgIGhhc0FwcGxpZWRXaGVyZUNsYXVzZSA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gU2UgbsOjbyBow6EgY29uZGnDp8O1ZXMgZGlzcG9uw612ZWlzLCB0ZW50YSBhcGxpY2FyIGZpbHRyb3MgZG8gYXJyYW5nZVxuICAgIGxldCBhcHBsaWVkRmlyZXN0b3JlRmlsdGVyOiBhbnkgPSBudWxsO1xuICAgIGlmICghaGFzQXBwbGllZFdoZXJlQ2xhdXNlICYmIHBhcmFtcy5hcnJhbmdlPy5maWx0ZXJzKSB7XG4gICAgICBjb25zdCBlcXVhbHNGaWx0ZXIgPSBwYXJhbXMuYXJyYW5nZS5maWx0ZXJzLmZpbmQoXG4gICAgICAgIChmOiBhbnkpID0+IGYuYXJyYW5nZSA9PT0gJ2VxdWFscycgJiYgZi5maWx0ZXI/LmZpbHRlcmluZ1xuICAgICAgKTtcblxuICAgICAgaWYgKGVxdWFsc0ZpbHRlciAmJiBlcXVhbHNGaWx0ZXIuZmlsdGVyKSB7XG4gICAgICAgIHF1ZXJ5ID0gcXVlcnkud2hlcmUoXG4gICAgICAgICAgZXF1YWxzRmlsdGVyLmZpbHRlci5wcm9wZXJ0eSxcbiAgICAgICAgICAnPT0nLFxuICAgICAgICAgIGVxdWFsc0ZpbHRlci5maWx0ZXIuZmlsdGVyaW5nXG4gICAgICAgICk7XG4gICAgICAgIGhhc0FwcGxpZWRXaGVyZUNsYXVzZSA9IHRydWU7XG4gICAgICAgIGFwcGxpZWRGaXJlc3RvcmVGaWx0ZXIgPSBlcXVhbHNGaWx0ZXI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBvdGhlckZpbHRlciA9IHBhcmFtcy5hcnJhbmdlLmZpbHRlcnMuZmluZChcbiAgICAgICAgICAoZjogYW55KSA9PlxuICAgICAgICAgICAgKGYuYXJyYW5nZSA9PT0gJ2ZpbHRlcicgJiZcbiAgICAgICAgICAgICAgZi5maWx0ZXI/LmZpbHRlcmluZyAmJlxuICAgICAgICAgICAgICBmLmZpbHRlcj8ucHJvcGVydHkpIHx8XG4gICAgICAgICAgICAoZi5hcnJhbmdlID09PSAnZmlsdGVyQnlEYXRlJyAmJlxuICAgICAgICAgICAgICBmLmRhdGVGaWx0ZXI/LmluaXRpYWwgJiZcbiAgICAgICAgICAgICAgZi5kYXRlRmlsdGVyPy5maW5hbClcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAob3RoZXJGaWx0ZXIpIHtcbiAgICAgICAgICBpZiAob3RoZXJGaWx0ZXIuYXJyYW5nZSA9PT0gJ2ZpbHRlcicgJiYgb3RoZXJGaWx0ZXIuZmlsdGVyKSB7XG4gICAgICAgICAgICBjb25zdCBmaWx0ZXJWYWx1ZSA9IG90aGVyRmlsdGVyLmZpbHRlci5maWx0ZXJpbmdcbiAgICAgICAgICAgICAgLnRyaW0oKVxuICAgICAgICAgICAgICAudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIHF1ZXJ5ID0gcXVlcnlcbiAgICAgICAgICAgICAgLndoZXJlKG90aGVyRmlsdGVyLmZpbHRlci5wcm9wZXJ0eSwgJz49JywgZmlsdGVyVmFsdWUpXG4gICAgICAgICAgICAgIC53aGVyZShvdGhlckZpbHRlci5maWx0ZXIucHJvcGVydHksICc8PScsIGZpbHRlclZhbHVlICsgJ1xcdWY4ZmYnKTtcbiAgICAgICAgICAgIGhhc0FwcGxpZWRXaGVyZUNsYXVzZSA9IHRydWU7XG4gICAgICAgICAgICBhcHBsaWVkRmlyZXN0b3JlRmlsdGVyID0gb3RoZXJGaWx0ZXI7XG4gICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgIG90aGVyRmlsdGVyLmFycmFuZ2UgPT09ICdmaWx0ZXJCeURhdGUnICYmXG4gICAgICAgICAgICBvdGhlckZpbHRlci5kYXRlRmlsdGVyICYmXG4gICAgICAgICAgICBwYXJhbXMuYXJyYW5nZS5zb3J0Qnk/LmZpZWxkXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBxdWVyeSA9IHF1ZXJ5XG4gICAgICAgICAgICAgIC53aGVyZShcbiAgICAgICAgICAgICAgICBwYXJhbXMuYXJyYW5nZS5zb3J0QnkuZmllbGQsXG4gICAgICAgICAgICAgICAgJz49JyxcbiAgICAgICAgICAgICAgICBvdGhlckZpbHRlci5kYXRlRmlsdGVyLmluaXRpYWxcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAud2hlcmUoXG4gICAgICAgICAgICAgICAgcGFyYW1zLmFycmFuZ2Uuc29ydEJ5LmZpZWxkLFxuICAgICAgICAgICAgICAgICc8PScsXG4gICAgICAgICAgICAgICAgb3RoZXJGaWx0ZXIuZGF0ZUZpbHRlci5maW5hbFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgaGFzQXBwbGllZFdoZXJlQ2xhdXNlID0gdHJ1ZTtcbiAgICAgICAgICAgIGFwcGxpZWRGaXJlc3RvcmVGaWx0ZXIgPSBvdGhlckZpbHRlcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBhbGxEb2NzU25hcHNob3QgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgICBsZXQgaXRlbXMgPSBhbGxEb2NzU25hcHNob3QuZG9jcy5tYXAoXG4gICAgICAoZG9jOiBmaXJlYmFzZS5maXJlc3RvcmUuUXVlcnlEb2N1bWVudFNuYXBzaG90PHVua25vd24+KSA9PiAoe1xuICAgICAgICBpZDogZG9jLmlkLFxuICAgICAgICAuLi4oZG9jLmRhdGEoKSBhcyBhbnkpLFxuICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gQXBsaWNhciBjb25kacOnw7VlcyByZXN0YW50ZXNcbiAgICBpZiAocGFyYW1zLmNvbmRpdGlvbnMpIHtcbiAgICAgIGNvbnN0IHJlbWFpbmluZ0NvbmRpdGlvbnMgPSBwYXJhbXMuY29uZGl0aW9ucy5maWx0ZXIoXG4gICAgICAgIChjb25kOiBDb25kaXRpb24pID0+IGNvbmQgIT09IGFwcGxpZWRDb25kaXRpb25cbiAgICAgICk7XG4gICAgICBpZiAocmVtYWluaW5nQ29uZGl0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbnN0IG9wZXJhdG9ycyA9IHRoaXMub3BlcmF0b3JzO1xuICAgICAgICBpdGVtcyA9IGl0ZW1zLmZpbHRlcigoaXRlbTogYW55KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHJlbWFpbmluZ0NvbmRpdGlvbnMuZXZlcnkoKGNvbmQ6IENvbmRpdGlvbikgPT4ge1xuICAgICAgICAgICAgY29uc3Qgb3BlcmF0b3JGbiA9XG4gICAgICAgICAgICAgIG9wZXJhdG9yc1tjb25kLm9wZXJhdG9yIGFzIGtleW9mIHR5cGVvZiBvcGVyYXRvcnNdO1xuICAgICAgICAgICAgcmV0dXJuIG9wZXJhdG9yRm5cbiAgICAgICAgICAgICAgPyBvcGVyYXRvckZuKGl0ZW1bY29uZC5maXJlc3RvcmVQcm9wZXJ0eV0sIGNvbmQuZGFzaFByb3BlcnR5KVxuICAgICAgICAgICAgICA6IGZhbHNlO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB7IGZpbHRlcnMsIHNvcnRCeSB9ID0gcGFyYW1zLmFycmFuZ2U7XG5cbiAgICAvLyBUcmFjayB3aGljaCBmaWx0ZXIgd2FzIGFscmVhZHkgYXBwbGllZCBpbiBGaXJlc3RvcmUgdG8gYXZvaWQgZG91YmxlIGZpbHRlcmluZ1xuICAgIGlmIChoYXNBcHBsaWVkV2hlcmVDbGF1c2UgJiYgIWFwcGxpZWRDb25kaXRpb24gJiYgcGFyYW1zLmFycmFuZ2U/LmZpbHRlcnMpIHtcbiAgICAgIGNvbnN0IGVxdWFsc0ZpbHRlciA9IHBhcmFtcy5hcnJhbmdlLmZpbHRlcnMuZmluZChcbiAgICAgICAgKGY6IGFueSkgPT4gZi5hcnJhbmdlID09PSAnZXF1YWxzJyAmJiBmLmZpbHRlcj8uZmlsdGVyaW5nXG4gICAgICApO1xuICAgICAgaWYgKGVxdWFsc0ZpbHRlcikge1xuICAgICAgICBhcHBsaWVkRmlyZXN0b3JlRmlsdGVyID0gZXF1YWxzRmlsdGVyO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXBwbGllZEZpcmVzdG9yZUZpbHRlciA9IHBhcmFtcy5hcnJhbmdlLmZpbHRlcnMuZmluZChcbiAgICAgICAgICAoZjogYW55KSA9PlxuICAgICAgICAgICAgKGYuYXJyYW5nZSA9PT0gJ2ZpbHRlcicgJiZcbiAgICAgICAgICAgICAgZi5maWx0ZXI/LmZpbHRlcmluZyAmJlxuICAgICAgICAgICAgICBmLmZpbHRlcj8ucHJvcGVydHkpIHx8XG4gICAgICAgICAgICAoZi5hcnJhbmdlID09PSAnZmlsdGVyQnlEYXRlJyAmJlxuICAgICAgICAgICAgICBmLmRhdGVGaWx0ZXI/LmluaXRpYWwgJiZcbiAgICAgICAgICAgICAgZi5kYXRlRmlsdGVyPy5maW5hbClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBlcXVhbHNGaWx0ZXJzID0gZmlsdGVycy5maWx0ZXIoKGY6IGFueSkgPT4gZi5hcnJhbmdlID09PSAnZXF1YWxzJyk7XG4gICAgY29uc3Qgb3RoZXJGaWx0ZXJzID0gZmlsdGVycy5maWx0ZXIoKGY6IGFueSkgPT4gZi5hcnJhbmdlICE9PSAnZXF1YWxzJyk7XG5cbiAgICBjb25zdCByZW1haW5pbmdFcXVhbHNGaWx0ZXJzID0gZXF1YWxzRmlsdGVycy5maWx0ZXIoXG4gICAgICAoZjogYW55KSA9PiBmICE9PSBhcHBsaWVkRmlyZXN0b3JlRmlsdGVyXG4gICAgKTtcbiAgICBpZiAocmVtYWluaW5nRXF1YWxzRmlsdGVycy5sZW5ndGggPiAwKSB7XG4gICAgICBpdGVtcyA9IGl0ZW1zLmZpbHRlcigoaXRlbTogYW55KSA9PiB7XG4gICAgICAgIHJldHVybiByZW1haW5pbmdFcXVhbHNGaWx0ZXJzLmV2ZXJ5KFxuICAgICAgICAgIChmOiBhbnkpID0+IGl0ZW1bZi5maWx0ZXIucHJvcGVydHldID09PSBmLmZpbHRlci5maWx0ZXJpbmdcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIG90aGVyRmlsdGVycy5mb3JFYWNoKChmaWx0ZXJJdGVtOiBhbnkpID0+IHtcbiAgICAgIGlmIChhcHBsaWVkRmlyZXN0b3JlRmlsdGVyID09PSBmaWx0ZXJJdGVtKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBmaWx0ZXJJdGVtLmFycmFuZ2UgPT09ICdmaWx0ZXInICYmXG4gICAgICAgIGZpbHRlckl0ZW0uZmlsdGVyPy5maWx0ZXJpbmcgJiZcbiAgICAgICAgZmlsdGVySXRlbS5maWx0ZXI/LnByb3BlcnR5XG4gICAgICApIHtcbiAgICAgICAgY29uc3QgZmlsdGVyVmFsdWUgPSBTdHJpbmcoZmlsdGVySXRlbS5maWx0ZXIuZmlsdGVyaW5nKVxuICAgICAgICAgIC50cmltKClcbiAgICAgICAgICAudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgaXRlbXMgPSBpdGVtcy5maWx0ZXIoKGl0ZW06IGFueSkgPT4ge1xuICAgICAgICAgIGNvbnN0IGl0ZW1WYWx1ZSA9IFN0cmluZyhcbiAgICAgICAgICAgIGl0ZW1bZmlsdGVySXRlbS5maWx0ZXIucHJvcGVydHldXG4gICAgICAgICAgKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgIHJldHVybiBpdGVtVmFsdWUuaW5jbHVkZXMoZmlsdGVyVmFsdWUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKFxuICAgICAgICBmaWx0ZXJJdGVtLmFycmFuZ2UgPT09ICdmaWx0ZXJCeURhdGUnICYmXG4gICAgICAgIGZpbHRlckl0ZW0uZGF0ZUZpbHRlcj8uaW5pdGlhbCAmJlxuICAgICAgICBmaWx0ZXJJdGVtLmRhdGVGaWx0ZXI/LmZpbmFsICYmXG4gICAgICAgIHNvcnRCeS5maWVsZFxuICAgICAgKSB7XG4gICAgICAgIGl0ZW1zID0gaXRlbXMuZmlsdGVyKChpdGVtOiBhbnkpID0+IHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgZmllbGRWYWx1ZSA9IGl0ZW1bc29ydEJ5LmZpZWxkXTtcblxuICAgICAgICAgICAgaWYgKCFmaWVsZFZhbHVlKSB7XG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IGl0ZW1EYXRlO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBmaWVsZFZhbHVlLnRvRGF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICBpdGVtRGF0ZSA9IGZpZWxkVmFsdWUudG9EYXRlKCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGZpZWxkVmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgICAgICAgIGl0ZW1EYXRlID0gZmllbGRWYWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGZpZWxkVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGl0ZW1EYXRlID0gbmV3IERhdGUoZmllbGRWYWx1ZSk7XG4gICAgICAgICAgICAgIGlmIChpc05hTihpdGVtRGF0ZS5nZXRUaW1lKCkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmaWVsZFZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICBpdGVtRGF0ZSA9IG5ldyBEYXRlKGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICBpdGVtRGF0ZSA+PSBmaWx0ZXJJdGVtLmRhdGVGaWx0ZXIuaW5pdGlhbCAmJlxuICAgICAgICAgICAgICBpdGVtRGF0ZSA8PSBmaWx0ZXJJdGVtLmRhdGVGaWx0ZXIuZmluYWxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgJ0Vycm8gYW8gcHJvY2Vzc2FyIGZpbHRybyBkZSBkYXRhIHBhcmEgbyBpdGVtOicsXG4gICAgICAgICAgICAgIGl0ZW0uaWQsXG4gICAgICAgICAgICAgIGVycm9yXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBBcGxpY2FyIGZpbHRlckZuIHNlIGV4aXN0aXJcbiAgICBpZiAocGFyYW1zLmZpbHRlckZuKSB7XG4gICAgICBpdGVtcyA9IGl0ZW1zLmZpbHRlcihwYXJhbXMuZmlsdGVyRm4pO1xuICAgIH1cblxuICAgIGlmIChzb3J0QnkgJiYgc29ydEJ5LmZpZWxkICYmIHNvcnRCeS5vcmRlcikge1xuICAgICAgaXRlbXMuc29ydCgoYTogYW55LCBiOiBhbnkpID0+IHtcbiAgICAgICAgY29uc3QgdmFsQSA9IGFbc29ydEJ5LmZpZWxkXTtcbiAgICAgICAgY29uc3QgdmFsQiA9IGJbc29ydEJ5LmZpZWxkXTtcblxuICAgICAgICBpZiAodmFsQSA8IHZhbEIpIHtcbiAgICAgICAgICByZXR1cm4gc29ydEJ5Lm9yZGVyID09PSAnYXNjJyA/IC0xIDogMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsQSA+IHZhbEIpIHtcbiAgICAgICAgICByZXR1cm4gc29ydEJ5Lm9yZGVyID09PSAnYXNjJyA/IDEgOiAtMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIFBhZ2luYcOnw6NvXG4gICAgbGV0IGN1cnJlbnRDbGllbnRQYWdlSW5kZXggPSAwO1xuXG4gICAgaWYgKHBhcmFtcy5uYXZpZ2F0aW9uID09PSAncmVsb2FkJykge1xuICAgICAgY3VycmVudENsaWVudFBhZ2VJbmRleCA9IHBhcmFtcy5jbGllbnRQYWdlSW5kZXggfHwgMDtcbiAgICB9IGVsc2UgaWYgKHBhcmFtcy5uYXZpZ2F0aW9uID09PSAnZm9yd2FyZCcpIHtcbiAgICAgIGN1cnJlbnRDbGllbnRQYWdlSW5kZXggPSAocGFyYW1zLmNsaWVudFBhZ2VJbmRleCB8fCAwKSArIDE7XG4gICAgfSBlbHNlIGlmIChwYXJhbXMubmF2aWdhdGlvbiA9PT0gJ2JhY2t3YXJkJykge1xuICAgICAgY3VycmVudENsaWVudFBhZ2VJbmRleCA9IE1hdGgubWF4KDAsIChwYXJhbXMuY2xpZW50UGFnZUluZGV4IHx8IDApIC0gMSk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFnZVNpemUgPSBwYXJhbXMuYmF0Y2hTaXplO1xuICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBjdXJyZW50Q2xpZW50UGFnZUluZGV4ICogcGFnZVNpemU7XG4gICAgY29uc3QgZW5kSW5kZXggPSBzdGFydEluZGV4ICsgcGFnZVNpemU7XG4gICAgY29uc3QgcGFnaW5hdGVkSXRlbXMgPSBpdGVtcy5zbGljZShzdGFydEluZGV4LCBlbmRJbmRleCk7XG5cbiAgICBjb25zdCB0b3RhbFBhZ2VzID0gTWF0aC5jZWlsKGl0ZW1zLmxlbmd0aCAvIHBhZ2VTaXplKTtcbiAgICBjb25zdCBoYXNOZXh0UGFnZSA9IGN1cnJlbnRDbGllbnRQYWdlSW5kZXggPCB0b3RhbFBhZ2VzIC0gMTtcbiAgICBjb25zdCBoYXNQcmV2aW91c1BhZ2UgPSBjdXJyZW50Q2xpZW50UGFnZUluZGV4ID4gMDtcblxuICAgIHJldHVybiB7XG4gICAgICBpdGVtczogcGFnaW5hdGVkSXRlbXMsXG4gICAgICBmaWx0ZXJMZW5ndGg6IGl0ZW1zLmxlbmd0aCxcbiAgICAgIGxhc3REb2M6IG51bGwsXG4gICAgICBmaXJzdERvYzogbnVsbCxcbiAgICAgIGhhc05leHRQYWdlOiBoYXNOZXh0UGFnZSxcbiAgICAgIGhhc1ByZXZpb3VzUGFnZTogaGFzUHJldmlvdXNQYWdlLFxuICAgICAgY3VycmVudENsaWVudFBhZ2VJbmRleDogY3VycmVudENsaWVudFBhZ2VJbmRleCxcbiAgICAgIHRvdGFsUGFnZXM6IHRvdGFsUGFnZXMsXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIGdldEl0ZW1zRGF0YShcbiAgICBjb2xsZWN0aW9uOiBzdHJpbmcsXG4gICAgYXJyYW5nZTogQXJyYW5nZSxcbiAgICBjb25kaXRpb25zOiBDb25kaXRpb25bXSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZFxuICApOiBQcm9taXNlPGFueVtdPiB7XG4gICAgdHJ5IHtcbiAgICAgIGxldCBxdWVyeTogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5PHVua25vd24+ID1cbiAgICAgICAgdGhpcy5uZ0ZpcmUuY29sbGVjdGlvbihjb2xsZWN0aW9uKS5yZWY7XG5cbiAgICAgIHF1ZXJ5ID0gdGhpcy5hcHBseUZpbHRlcnMocXVlcnksIGFycmFuZ2UsIGNvbmRpdGlvbnMpO1xuICAgICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBxdWVyeS5nZXQoKTtcbiAgICAgIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgc25hcHNob3QuZG9jcy5tYXAoXG4gICAgICAgICAgYXN5bmMgKGRvYzogZmlyZWJhc2UuZmlyZXN0b3JlLlF1ZXJ5RG9jdW1lbnRTbmFwc2hvdDx1bmtub3duPikgPT4ge1xuICAgICAgICAgICAgY29uc3QgZGF0YSA9IGRvYy5kYXRhKCkgYXMgYW55O1xuICAgICAgICAgICAgY29uc3QgaWQgPSBkb2MuaWQ7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAgLi4uZGF0YSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgfVxuICAgICAgICApXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG9wZXJhdG9ycyA9IHtcbiAgICAnPT0nOiAoYTogYW55LCBiOiBhbnkpOiBib29sZWFuID0+IGEgPT09IGIsXG4gICAgJyE9JzogKGE6IGFueSwgYjogYW55KTogYm9vbGVhbiA9PiBhICE9PSBiLFxuICAgICc+JzogKGE6IGFueSwgYjogYW55KTogYm9vbGVhbiA9PiBhID4gYixcbiAgICAnPCc6IChhOiBhbnksIGI6IGFueSk6IGJvb2xlYW4gPT4gYSA8IGIsXG4gICAgJz49JzogKGE6IGFueSwgYjogYW55KTogYm9vbGVhbiA9PiBhID49IGIsXG4gICAgJzw9JzogKGE6IGFueSwgYjogYW55KTogYm9vbGVhbiA9PiBhIDw9IGIsXG4gICAgaW5jbHVkZXM6IChhOiBhbnksIGI6IGFueSk6IGFueSA9PiBhLmluY2x1ZGVzKGIpLFxuICB9O1xuXG4gIGFzeW5jIGRlbGV0ZUluZGV4KFxuICAgIGlkOiBzdHJpbmcsXG4gICAgY29sOiBzdHJpbmcsXG4gICAgZGlhbG9nQ29tcG9uZW50OiBhbnlcbiAgKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihkaWFsb2dDb21wb25lbnQsIHtcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgdGl0bGU6ICdWb2PDqiByZWFsbWVudGUgZGVzZWphIGRlbGV0YXIgZXNzZSBpdGVtPycsXG4gICAgICAgIGRlc2NyaXB0aW9uOiAnRXNzYSBhw6fDo28gw6kgaXJyZXZlcnPDrXZlbC4nLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGZpcnN0VmFsdWVGcm9tKGRpYWxvZ1JlZi5hZnRlckNsb3NlZCgpKTtcbiAgICBpZiAoIXJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBiYXRjaCA9IHRoaXMubmdGaXJlLmZpcmVzdG9yZS5iYXRjaCgpO1xuXG4gICAgICBjb25zdCBkb2NSZWYgPSB0aGlzLm5nRmlyZS5jb2xsZWN0aW9uKGNvbCkuZG9jKGlkKTtcbiAgICAgIGNvbnN0IGRvY1NuYXBzaG90ID0gKGF3YWl0IGZpcnN0VmFsdWVGcm9tKFxuICAgICAgICBkb2NSZWYuZ2V0KClcbiAgICAgICkpIGFzIGZpcmViYXNlLmZpcmVzdG9yZS5Eb2N1bWVudFNuYXBzaG90PHVua25vd24+O1xuICAgICAgY29uc3QgZG9jID0gZG9jU25hcHNob3QuZGF0YSgpIGFzIGFueTtcbiAgICAgIGJhdGNoLmRlbGV0ZShkb2NSZWYucmVmKTtcbiAgICAgIGlmIChkb2MgJiYgdHlwZW9mIGRvYy5pbmRleCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5yZWluZGV4KGRvYy5pbmRleCwgY29sLCBiYXRjaCk7XG4gICAgICB9XG4gICAgICBhd2FpdCBiYXRjaC5jb21taXQoKTtcblxuICAgICAgdGhpcy50b2FzdHIuc3VjY2VzcygnSXRlbSBleGNsdcOtZG8gY29tIHN1Y2Vzc28hJyk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBjb25zdCBlcnJvciA9IGUgYXMgYW55O1xuICAgICAgY29uc29sZS5lcnJvcignRXJybyBhbyBkZWxldGFyIGl0ZW06JywgZXJyb3IpO1xuICAgICAgdGhpcy50b2FzdHIuZXJyb3IoJ0Vycm8gYW8gZGVsZXRhciBpdGVtLicpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHJlaW5kZXgoXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBjb2w6IHN0cmluZyxcbiAgICBiYXRjaDogZmlyZWJhc2UuZmlyZXN0b3JlLldyaXRlQmF0Y2hcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHNuYXBzaG90ID0gKGF3YWl0IGZpcnN0VmFsdWVGcm9tKFxuICAgICAgICB0aGlzLm5nRmlyZS5jb2xsZWN0aW9uKGNvbCkuZ2V0KClcbiAgICAgICkpIGFzIGZpcmViYXNlLmZpcmVzdG9yZS5RdWVyeVNuYXBzaG90PHVua25vd24+O1xuICAgICAgY29uc3QgZG9jcyA9IHNuYXBzaG90LmRvY3M7XG4gICAgICBmb3IgKGxldCBkb2Mgb2YgZG9jcykge1xuICAgICAgICBjb25zdCBkYXRhID0gZG9jLmRhdGEoKSBhcyBhbnk7XG4gICAgICAgIGlmIChkYXRhICYmIHR5cGVvZiBkYXRhLmluZGV4ID09PSAnbnVtYmVyJyAmJiBkYXRhLmluZGV4ID4gaW5kZXgpIHtcbiAgICAgICAgICBkYXRhLmluZGV4LS07XG4gICAgICAgICAgY29uc3QgZG9jUmVmID0gdGhpcy5uZ0ZpcmUuY29sbGVjdGlvbihjb2wpLmRvYyhkb2MuaWQpLnJlZjtcbiAgICAgICAgICBiYXRjaC51cGRhdGUoZG9jUmVmLCBkYXRhKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvIGFvIHJlaW5kZXhhcjonLCBlcnJvcik7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuXG4gIGRhdGVGb3JtYXRWYWxpZGF0b3IoKTogVmFsaWRhdG9yRm4ge1xuICAgIHJldHVybiAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKTogeyBba2V5OiBzdHJpbmddOiBhbnkgfSB8IG51bGwgPT4ge1xuICAgICAgaWYgKCFjb250cm9sLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBkYXRlU3RyID0gY29udHJvbC52YWx1ZS50cmltKCk7XG4gICAgICBjb25zdCBkYXRlUGF0dGVybiA9IC9eKFxcZHsxLDJ9KVxcLyhcXGR7MSwyfSlcXC8oXFxkezR9KSQvO1xuXG4gICAgICBpZiAoIWRhdGVQYXR0ZXJuLnRlc3QoZGF0ZVN0cikpIHtcbiAgICAgICAgcmV0dXJuIHsgaW52YWxpZEZvcm1hdDogdHJ1ZSB9O1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJ0cyA9IGRhdGVTdHIuc3BsaXQoJy8nKTtcbiAgICAgIGNvbnN0IGRheSA9IHBhcnRzWzBdLnBhZFN0YXJ0KDIsICcwJyk7XG4gICAgICBjb25zdCBtb250aCA9IHBhcnRzWzFdLnBhZFN0YXJ0KDIsICcwJyk7XG4gICAgICBjb25zdCB5ZWFyID0gcGFydHNbMl07XG4gICAgICBjb25zdCBub3JtYWxpemVkRGF0ZSA9IGAke2RheX0vJHttb250aH0vJHt5ZWFyfWA7XG5cbiAgICAgIGNvbnN0IGRhdGUgPSBtb21lbnQobm9ybWFsaXplZERhdGUsICdERC9NTS9ZWVlZJywgdHJ1ZSk7XG5cbiAgICAgIGlmICghZGF0ZS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIHsgaW52YWxpZERhdGU6IHRydWUgfTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIHVwZGF0ZUluZGV4KGluZGV4OiBudW1iZXIsIGlkOiBzdHJpbmcsIGNvbDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5uZ0ZpcmUuY29sbGVjdGlvbihjb2wpLmRvYyhpZCkudXBkYXRlKHsgaW5kZXggfSk7XG4gIH1cblxuICAvKipcbiAgICogRXh0cmFpIG8gbGluayBkZSBjcmlhw6fDo28gZGUgw61uZGljZSBkYSBtZW5zYWdlbSBkZSBlcnJvIGRvIEZpcmVzdG9yZVxuICAgKi9cbiAgcHJpdmF0ZSBleHRyYWN0SW5kZXhMaW5rKGVycm9yOiBhbnkpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBpZiAoIWVycm9yIHx8ICFlcnJvci5tZXNzYWdlKSByZXR1cm4gbnVsbDtcblxuICAgIGNvbnN0IGxpbmtNYXRjaCA9IGVycm9yLm1lc3NhZ2UubWF0Y2goXG4gICAgICAvKGh0dHBzOlxcL1xcL2NvbnNvbGVcXC5maXJlYmFzZVxcLmdvb2dsZVxcLmNvbVxcL1teXFxzXSspL1xuICAgICk7XG4gICAgcmV0dXJuIGxpbmtNYXRjaCA/IGxpbmtNYXRjaFsxXSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmFzdHJlaWEgw61uZGljZXMgYXVzZW50ZXMgYW8gdXNhciBmYWxsYmFjayBwcmV2ZW50aXZvXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHRyYWNrTWlzc2luZ0luZGV4UHJldmVudGl2ZShcbiAgICBjb2xsZWN0aW9uOiBzdHJpbmcsXG4gICAgYXJyYW5nZTogQXJyYW5nZSxcbiAgICBjb25kaXRpb25zOiBDb25kaXRpb25bXSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcXVlcnlTaWduYXR1cmUgPSB0aGlzLmdlbmVyYXRlUXVlcnlTaWduYXR1cmUoXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIGFycmFuZ2UsXG4gICAgICAgIGNvbmRpdGlvbnNcbiAgICAgICk7XG4gICAgICBjb25zdCBkb2NJZCA9IGAke2NvbGxlY3Rpb259XyR7cXVlcnlTaWduYXR1cmV9YDtcblxuICAgICAgY29uc3QgaW5kZXhMaW5rID0gdGhpcy5nZW5lcmF0ZUluZGV4TGluayhjb2xsZWN0aW9uLCBhcnJhbmdlLCBjb25kaXRpb25zKTtcblxuICAgICAgY29uc3QgaW5kZXhJbnN0cnVjdGlvbnMgPSB0aGlzLmdlbmVyYXRlSW5kZXhJbnN0cnVjdGlvbnMoXG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIGFycmFuZ2UsXG4gICAgICAgIGNvbmRpdGlvbnNcbiAgICAgICk7XG5cbiAgICAgIGNvbnN0IHRyYWNraW5nRGF0YTogYW55ID0ge1xuICAgICAgICBjb2xsZWN0aW9uLFxuICAgICAgICBpbmRleExpbmssXG4gICAgICAgIGluZGV4SW5zdHJ1Y3Rpb25zLFxuICAgICAgICBhcnJhbmdlOiB7XG4gICAgICAgICAgc29ydEJ5OiBhcnJhbmdlLnNvcnRCeSxcbiAgICAgICAgICBmaWx0ZXJzOlxuICAgICAgICAgICAgYXJyYW5nZS5maWx0ZXJzPy5tYXAoKGY6IGFueSkgPT4gKHtcbiAgICAgICAgICAgICAgYXJyYW5nZTogZi5hcnJhbmdlLFxuICAgICAgICAgICAgICBwcm9wZXJ0eTogZi5maWx0ZXI/LnByb3BlcnR5IHx8IG51bGwsXG4gICAgICAgICAgICAgIGRhdGVGaWVsZDpcbiAgICAgICAgICAgICAgICBmLmFycmFuZ2UgPT09ICdmaWx0ZXJCeURhdGUnID8gYXJyYW5nZS5zb3J0Qnk/LmZpZWxkIDogbnVsbCxcbiAgICAgICAgICAgIH0pKSB8fCBbXSxcbiAgICAgICAgfSxcbiAgICAgICAgY29uZGl0aW9uczpcbiAgICAgICAgICBjb25kaXRpb25zPy5tYXAoKGM6IENvbmRpdGlvbikgPT4gKHtcbiAgICAgICAgICAgIHByb3BlcnR5OiBjLmZpcmVzdG9yZVByb3BlcnR5LFxuICAgICAgICAgICAgb3BlcmF0b3I6IGMub3BlcmF0b3IsXG4gICAgICAgICAgfSkpIHx8IFtdLFxuICAgICAgICBlcnJvck1lc3NhZ2U6IGBGYWxsYmFjayBwcmV2ZW50aXZvIHVzYWRvIHBhcmEgYSBjb2xsZWN0aW9uICR7Y29sbGVjdGlvbn0uIEEgcXVlcnkgZXhpZ2lyaWEgw61uZGljZSBjb21wb3N0by5gLFxuICAgICAgICB1cGRhdGVkQXQ6IGZpcmViYXNlLmZpcmVzdG9yZS5GaWVsZFZhbHVlLnNlcnZlclRpbWVzdGFtcCgpLFxuICAgICAgfTtcblxuICAgICAgY29uc29sZS5sb2coJ/Cfk4QgW0lOREVYIExJTktdIERhZG9zIHF1ZSBzZXLDo28gc2Fsdm9zIG5vIGRvY3VtZW50bzonLCB7XG4gICAgICAgIGRvY0lkLFxuICAgICAgICBjb2xsZWN0aW9uOiB0cmFja2luZ0RhdGEuY29sbGVjdGlvbixcbiAgICAgICAgaW5kZXhMaW5rOiB0cmFja2luZ0RhdGEuaW5kZXhMaW5rLFxuICAgICAgICBhcnJhbmdlOiB0cmFja2luZ0RhdGEuYXJyYW5nZSxcbiAgICAgICAgY29uZGl0aW9uczogdHJhY2tpbmdEYXRhLmNvbmRpdGlvbnMsXG4gICAgICAgIGVycm9yTWVzc2FnZTogdHJhY2tpbmdEYXRhLmVycm9yTWVzc2FnZSxcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBkb2NSZWYgPSB0aGlzLm5nRmlyZS5jb2xsZWN0aW9uKCdtaXNzaW5nSW5kZXhlcycpLmRvYyhkb2NJZCk7XG4gICAgICBjb25zdCBkb2MgPSBhd2FpdCBkb2NSZWYuZ2V0KCkudG9Qcm9taXNlKCk7XG5cbiAgICAgIGlmIChkb2MgJiYgZG9jLmV4aXN0cykge1xuICAgICAgICBhd2FpdCBkb2NSZWYudXBkYXRlKHtcbiAgICAgICAgICBjb3VudDogZmlyZWJhc2UuZmlyZXN0b3JlLkZpZWxkVmFsdWUuaW5jcmVtZW50KDEpLFxuICAgICAgICAgIHVwZGF0ZWRBdDogZmlyZWJhc2UuZmlyZXN0b3JlLkZpZWxkVmFsdWUuc2VydmVyVGltZXN0YW1wKCksXG4gICAgICAgICAgbGFzdEVycm9yOiB0cmFja2luZ0RhdGEuZXJyb3JNZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IGRvY1JlZi5zZXQoe1xuICAgICAgICAgIC4uLnRyYWNraW5nRGF0YSxcbiAgICAgICAgICBjb3VudDogMSxcbiAgICAgICAgICBjcmVhdGVkQXQ6IGZpcmViYXNlLmZpcmVzdG9yZS5GaWVsZFZhbHVlLnNlcnZlclRpbWVzdGFtcCgpLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGNhdGNoICh0cmFja2luZ0Vycm9yKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ0ZhbGhhIGFvIHJhc3RyZWFyIGZhbGxiYWNrIHByZXZlbnRpdm86JywgdHJhY2tpbmdFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdlcmEgdW1hIGFzc2luYXR1cmEgw7puaWNhIHBhcmEgdW1hIHF1ZXJ5XG4gICAqL1xuICBwcml2YXRlIGdlbmVyYXRlUXVlcnlTaWduYXR1cmUoXG4gICAgY29sbGVjdGlvbjogc3RyaW5nLFxuICAgIGFycmFuZ2U6IEFycmFuZ2UsXG4gICAgY29uZGl0aW9uczogQ29uZGl0aW9uW10gfCB1bmRlZmluZWQgPSB1bmRlZmluZWRcbiAgKTogc3RyaW5nIHtcbiAgICBjb25zdCBzaWduYXR1cmUgPSB7XG4gICAgICBjb2xsZWN0aW9uLFxuICAgICAgc29ydEJ5OiBhcnJhbmdlLnNvcnRCeSxcbiAgICAgIGZpbHRlcnM6XG4gICAgICAgIGFycmFuZ2UuZmlsdGVycz8ubWFwKChmOiBhbnkpID0+ICh7XG4gICAgICAgICAgYXJyYW5nZTogZi5hcnJhbmdlLFxuICAgICAgICAgIHByb3BlcnR5OiBmLmZpbHRlcj8ucHJvcGVydHkgfHwgbnVsbCxcbiAgICAgICAgfSkpIHx8IFtdLFxuICAgICAgY29uZGl0aW9uczpcbiAgICAgICAgY29uZGl0aW9ucz8ubWFwKChjOiBDb25kaXRpb24pID0+ICh7XG4gICAgICAgICAgcHJvcGVydHk6IGMuZmlyZXN0b3JlUHJvcGVydHksXG4gICAgICAgICAgb3BlcmF0b3I6IGMub3BlcmF0b3IsXG4gICAgICAgIH0pKSB8fCBbXSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIGJ0b2EoSlNPTi5zdHJpbmdpZnkoc2lnbmF0dXJlKSlcbiAgICAgIC5yZXBsYWNlKC9bXmEtekEtWjAtOV0vZywgJycpXG4gICAgICAuc3Vic3RyaW5nKDAsIDIwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXJhIGluc3RydcOnw7VlcyBjbGFyYXMgcGFyYSBjcmlhciBvIMOtbmRpY2UgbWFudWFsbWVudGVcbiAgICovXG4gIHByaXZhdGUgZ2VuZXJhdGVJbmRleEluc3RydWN0aW9ucyhcbiAgICBjb2xsZWN0aW9uOiBzdHJpbmcsXG4gICAgYXJyYW5nZTogQXJyYW5nZSxcbiAgICBjb25kaXRpb25zOiBDb25kaXRpb25bXSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZFxuICApOiBhbnkge1xuICAgIGNvbnN0IGluc3RydWN0aW9uczogYW55ID0ge1xuICAgICAgc3VtbWFyeTogJycsXG4gICAgICBjb2xsZWN0aW9uOiBjb2xsZWN0aW9uLFxuICAgICAgZmllbGRzOiBbXSBhcyBhbnlbXSxcbiAgICAgIHF1ZXJ5RXhhbXBsZTogJycsXG4gICAgICBzdGVwQnlTdGVwOiBbXSBhcyBzdHJpbmdbXSxcbiAgICAgIG5vdGVzOiBbXSBhcyBzdHJpbmdbXSxcbiAgICB9O1xuXG4gICAgY29uc3QgZmllbGRzOiBhbnlbXSA9IFtdO1xuXG4gICAgaWYgKGNvbmRpdGlvbnMgJiYgY29uZGl0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25kaXRpb25zLmZvckVhY2goKGNvbmRpdGlvbjogQ29uZGl0aW9uKSA9PiB7XG4gICAgICAgIGlmIChjb25kaXRpb24uZmlyZXN0b3JlUHJvcGVydHkpIHtcbiAgICAgICAgICBmaWVsZHMucHVzaCh7XG4gICAgICAgICAgICBmaWVsZDogY29uZGl0aW9uLmZpcmVzdG9yZVByb3BlcnR5LFxuICAgICAgICAgICAgb3JkZXI6ICdBc2NlbmRpbmcnLFxuICAgICAgICAgICAgdHlwZTogJ1dIRVJFIGNsYXVzZScsXG4gICAgICAgICAgICBvcGVyYXRvcjogY29uZGl0aW9uLm9wZXJhdG9yLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IGBGaWx0cmFyIHBvciAke2NvbmRpdGlvbi5maXJlc3RvcmVQcm9wZXJ0eX0gdXNhbmRvIG9wZXJhZG9yICR7Y29uZGl0aW9uLm9wZXJhdG9yfWAsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChhcnJhbmdlLmZpbHRlcnMgJiYgYXJyYW5nZS5maWx0ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGFycmFuZ2UuZmlsdGVycy5mb3JFYWNoKChmaWx0ZXI6IGFueSkgPT4ge1xuICAgICAgICBpZiAoZmlsdGVyLmZpbHRlcj8ucHJvcGVydHkpIHtcbiAgICAgICAgICBmaWVsZHMucHVzaCh7XG4gICAgICAgICAgICBmaWVsZDogZmlsdGVyLmZpbHRlci5wcm9wZXJ0eSxcbiAgICAgICAgICAgIG9yZGVyOiAnQXNjZW5kaW5nJyxcbiAgICAgICAgICAgIHR5cGU6ICdXSEVSRSBjbGF1c2UgKGZpbHRlciknLFxuICAgICAgICAgICAgb3BlcmF0b3I6IGZpbHRlci5hcnJhbmdlID09PSAnZmlsdGVyJyA/ICdDT05UQUlOUycgOiAnUkFOR0UnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IGBGaWx0cmFyIHBvciAke2ZpbHRlci5maWx0ZXIucHJvcGVydHl9IHVzYW5kbyBmaWx0cm8gJHtmaWx0ZXIuYXJyYW5nZX1gLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoYXJyYW5nZS5zb3J0Qnk/LmZpZWxkKSB7XG4gICAgICBmaWVsZHMucHVzaCh7XG4gICAgICAgIGZpZWxkOiBhcnJhbmdlLnNvcnRCeS5maWVsZCxcbiAgICAgICAgb3JkZXI6IGFycmFuZ2Uuc29ydEJ5Lm9yZGVyID09PSAnZGVzYycgPyAnRGVzY2VuZGluZycgOiAnQXNjZW5kaW5nJyxcbiAgICAgICAgdHlwZTogJ09SREVSIEJZIGNsYXVzZScsXG4gICAgICAgIG9wZXJhdG9yOiAnTi9BJyxcbiAgICAgICAgZGVzY3JpcHRpb246IGBPcmRlbmFyIHJlc3VsdGFkb3MgcG9yICR7YXJyYW5nZS5zb3J0QnkuZmllbGR9IGVtIG9yZGVtICR7YXJyYW5nZS5zb3J0Qnkub3JkZXJ9YCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGluc3RydWN0aW9ucy5maWVsZHMgPSBmaWVsZHM7XG5cbiAgICBjb25zdCBmaWVsZE5hbWVzID0gZmllbGRzLm1hcCgoZjogYW55KSA9PiBmLmZpZWxkKS5qb2luKCcgKyAnKTtcbiAgICBpbnN0cnVjdGlvbnMuc3VtbWFyeSA9IGBDcmlhciDDrW5kaWNlIGNvbXBvc3RvIHBhcmEgJHtjb2xsZWN0aW9ufTogJHtmaWVsZE5hbWVzfWA7XG5cbiAgICBsZXQgcXVlcnlFeGFtcGxlID0gYGRiLmNvbGxlY3Rpb24oJyR7Y29sbGVjdGlvbn0nKWA7XG5cbiAgICBmaWVsZHMuZm9yRWFjaCgoZmllbGQ6IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgaWYgKGZpZWxkLnR5cGUuaW5jbHVkZXMoJ1dIRVJFJykpIHtcbiAgICAgICAgaWYgKGZpZWxkLm9wZXJhdG9yID09PSAnPT0nKSB7XG4gICAgICAgICAgcXVlcnlFeGFtcGxlICs9IGBcXG4gIC53aGVyZSgnJHtmaWVsZC5maWVsZH0nLCAnPT0nLCAndmFsdWUnKWA7XG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGQub3BlcmF0b3IgPT09ICdDT05UQUlOUycpIHtcbiAgICAgICAgICBxdWVyeUV4YW1wbGUgKz0gYFxcbiAgLndoZXJlKCcke2ZpZWxkLmZpZWxkfScsICc+PScsICdzZWFyY2hUZXh0JylgO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHF1ZXJ5RXhhbXBsZSArPSBgXFxuICAud2hlcmUoJyR7ZmllbGQuZmllbGR9JywgJyR7ZmllbGQub3BlcmF0b3J9JywgJ3ZhbHVlJylgO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb25zdCBvcmRlckJ5RmllbGQgPSBmaWVsZHMuZmluZCgoZjogYW55KSA9PiBmLnR5cGUuaW5jbHVkZXMoJ09SREVSIEJZJykpO1xuICAgIGlmIChvcmRlckJ5RmllbGQpIHtcbiAgICAgIHF1ZXJ5RXhhbXBsZSArPSBgXFxuICAub3JkZXJCeSgnJHtcbiAgICAgICAgb3JkZXJCeUZpZWxkLmZpZWxkXG4gICAgICB9JywgJyR7b3JkZXJCeUZpZWxkLm9yZGVyLnRvTG93ZXJDYXNlKCl9JylgO1xuICAgIH1cblxuICAgIGluc3RydWN0aW9ucy5xdWVyeUV4YW1wbGUgPSBxdWVyeUV4YW1wbGU7XG5cbiAgICBpbnN0cnVjdGlvbnMuc3RlcEJ5U3RlcCA9IFtcbiAgICAgICcxLiBJciBwYXJhIEZpcmViYXNlIENvbnNvbGUg4oaSIEZpcmVzdG9yZSDihpIgSW5kZXhlcycsXG4gICAgICAnMi4gQ2xpY2FyIGVtIFwiQ3JlYXRlIEluZGV4XCInLFxuICAgICAgYDMuIERlZmluaXIgQ29sbGVjdGlvbiBJRDogJHtjb2xsZWN0aW9ufWAsXG4gICAgICAnNC4gQ29uZmlndXJhciBjYW1wb3MgbmVzdGEgT1JERU0gRVhBVEE6JyxcbiAgICAgIC4uLmZpZWxkcy5tYXAoXG4gICAgICAgIChmaWVsZDogYW55LCBpbmRleDogbnVtYmVyKSA9PlxuICAgICAgICAgIGAgICAke2luZGV4ICsgMX0uIENhbXBvOiAke2ZpZWxkLmZpZWxkfSwgT3JkZXI6ICR7XG4gICAgICAgICAgICBmaWVsZC5vcmRlclxuICAgICAgICAgIH0sIEFycmF5OiBOb2BcbiAgICAgICksXG4gICAgICAnNS4gRGVmaW5pciBRdWVyeSBzY29wZXM6IENvbGxlY3Rpb24nLFxuICAgICAgJzYuIENsaWNhciBlbSBcIkNyZWF0ZVwiIGUgYWd1YXJkYXIgY29uY2x1c8OjbycsXG4gICAgXTtcblxuICAgIGluc3RydWN0aW9ucy5ub3RlcyA9IFtcbiAgICAgICfimqDvuI8gQSBvcmRlbSBkb3MgY2FtcG9zIMOpIENSw41USUNBIC0gZGV2ZSBjb3JyZXNwb25kZXIgZXhhdGFtZW50ZSDDoCBvcmRlbSBkYSBxdWVyeScsXG4gICAgICAn4pqg77iPIEFzIGNsw6F1c3VsYXMgV0hFUkUgZGV2ZW0gdmlyIEFOVEVTIGRvIGNhbXBvIE9SREVSIEJZJyxcbiAgICAgICfimqDvuI8gRXN0ZSDDrW5kaWNlIHPDsyBmdW5jaW9uYXLDoSBwYXJhIHF1ZXJpZXMgY29tIGVzdGEgY29tYmluYcOnw6NvIEVYQVRBIGRlIGNhbXBvcycsXG4gICAgICAn4pqg77iPIEEgY3JpYcOnw6NvIGRvIMOtbmRpY2UgcG9kZSBsZXZhciB2w6FyaW9zIG1pbnV0b3MnLFxuICAgIF07XG5cbiAgICByZXR1cm4gaW5zdHJ1Y3Rpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlcmEgdW0gbGluayBkZSDDrW5kaWNlIGJhc2VhZG8gbmEgZXN0cnV0dXJhIGRhIHF1ZXJ5XG4gICAqL1xuICBwcml2YXRlIGdlbmVyYXRlSW5kZXhMaW5rKFxuICAgIGNvbGxlY3Rpb246IHN0cmluZyxcbiAgICBhcnJhbmdlOiBBcnJhbmdlLFxuICAgIGNvbmRpdGlvbnM6IENvbmRpdGlvbltdIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkXG4gICk6IHN0cmluZyB8IG51bGwge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpbmRleEZpZWxkczogc3RyaW5nW10gPSBbXTtcblxuICAgICAgaWYgKGNvbmRpdGlvbnMgJiYgY29uZGl0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGNvbmRpdGlvbnMuZm9yRWFjaCgoY29uZGl0aW9uOiBDb25kaXRpb24pID0+IHtcbiAgICAgICAgICBpZiAoY29uZGl0aW9uLmZpcmVzdG9yZVByb3BlcnR5KSB7XG4gICAgICAgICAgICBpbmRleEZpZWxkcy5wdXNoKGNvbmRpdGlvbi5maXJlc3RvcmVQcm9wZXJ0eSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFycmFuZ2UuZmlsdGVycyAmJiBhcnJhbmdlLmZpbHRlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICBhcnJhbmdlLmZpbHRlcnMuZm9yRWFjaCgoZmlsdGVyOiBhbnkpID0+IHtcbiAgICAgICAgICBpZiAoZmlsdGVyLmZpbHRlcj8ucHJvcGVydHkpIHtcbiAgICAgICAgICAgIGluZGV4RmllbGRzLnB1c2goZmlsdGVyLmZpbHRlci5wcm9wZXJ0eSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFycmFuZ2Uuc29ydEJ5Py5maWVsZCkge1xuICAgICAgICBpbmRleEZpZWxkcy5wdXNoKGFycmFuZ2Uuc29ydEJ5LmZpZWxkKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGluZGV4RmllbGRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgY29uc3QgYmFzZVVybCA9XG4gICAgICAgICAgJ2h0dHBzOi8vY29uc29sZS5maXJlYmFzZS5nb29nbGUuY29tL3Byb2plY3QvdG9wcGF5eS1kZXYvZmlyZXN0b3JlL2luZGV4ZXMnO1xuICAgICAgICBjb25zdCBxdWVyeVBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoe1xuICAgICAgICAgIGNyZWF0ZV9jb21wb3NpdGU6IGBjb2xsZWN0aW9uPSR7Y29sbGVjdGlvbn0mZmllbGRzPSR7aW5kZXhGaWVsZHMuam9pbihcbiAgICAgICAgICAgICcsJ1xuICAgICAgICAgICl9YCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgZmluYWxMaW5rID0gYCR7YmFzZVVybH0/JHtxdWVyeVBhcmFtcy50b1N0cmluZygpfWA7XG4gICAgICAgIHJldHVybiBmaW5hbExpbms7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ0ZhbGhhIGFvIGdlcmFyIGxpbmsgZGUgw61uZGljZTonLCBlcnJvcik7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHRyYWNrTWlzc2luZ0luZGV4KFxuICAgIGVycm9yOiBhbnksXG4gICAgY29sbGVjdGlvbjogc3RyaW5nLFxuICAgIGFycmFuZ2U6IEFycmFuZ2UsXG4gICAgY29uZGl0aW9uczogQ29uZGl0aW9uW10gfCB1bmRlZmluZWQgPSB1bmRlZmluZWRcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGluZGV4TGluayA9IHRoaXMuZXh0cmFjdEluZGV4TGluayhlcnJvcik7XG4gICAgICBpZiAoIWluZGV4TGluaykgcmV0dXJuO1xuXG4gICAgICBjb25zdCBsaW5rSGFzaCA9IGJ0b2EoaW5kZXhMaW5rKVxuICAgICAgICAucmVwbGFjZSgvW15hLXpBLVowLTldL2csICcnKVxuICAgICAgICAuc3Vic3RyaW5nKDAsIDIwKTtcbiAgICAgIGNvbnN0IGRvY0lkID0gYCR7Y29sbGVjdGlvbn1fJHtsaW5rSGFzaH1gO1xuXG4gICAgICBjb25zdCBpbmRleEluc3RydWN0aW9ucyA9IHRoaXMuZ2VuZXJhdGVJbmRleEluc3RydWN0aW9ucyhcbiAgICAgICAgY29sbGVjdGlvbixcbiAgICAgICAgYXJyYW5nZSxcbiAgICAgICAgY29uZGl0aW9uc1xuICAgICAgKTtcblxuICAgICAgY29uc3QgdHJhY2tpbmdEYXRhOiBhbnkgPSB7XG4gICAgICAgIGNvbGxlY3Rpb24sXG4gICAgICAgIGluZGV4TGluayxcbiAgICAgICAgaW5kZXhJbnN0cnVjdGlvbnMsXG4gICAgICAgIGFycmFuZ2U6IHtcbiAgICAgICAgICBzb3J0Qnk6IGFycmFuZ2Uuc29ydEJ5LFxuICAgICAgICAgIGZpbHRlcnM6XG4gICAgICAgICAgICBhcnJhbmdlLmZpbHRlcnM/Lm1hcCgoZjogYW55KSA9PiAoe1xuICAgICAgICAgICAgICBhcnJhbmdlOiBmLmFycmFuZ2UsXG4gICAgICAgICAgICAgIHByb3BlcnR5OiBmLmZpbHRlcj8ucHJvcGVydHkgfHwgbnVsbCxcbiAgICAgICAgICAgICAgZGF0ZUZpZWxkOlxuICAgICAgICAgICAgICAgIGYuYXJyYW5nZSA9PT0gJ2ZpbHRlckJ5RGF0ZScgPyBhcnJhbmdlLnNvcnRCeT8uZmllbGQgOiBudWxsLFxuICAgICAgICAgICAgfSkpIHx8IFtdLFxuICAgICAgICB9LFxuICAgICAgICBjb25kaXRpb25zOlxuICAgICAgICAgIGNvbmRpdGlvbnM/Lm1hcCgoYzogQ29uZGl0aW9uKSA9PiAoe1xuICAgICAgICAgICAgcHJvcGVydHk6IGMuZmlyZXN0b3JlUHJvcGVydHksXG4gICAgICAgICAgICBvcGVyYXRvcjogYy5vcGVyYXRvcixcbiAgICAgICAgICB9KSkgfHwgW10sXG4gICAgICAgIGVycm9yTWVzc2FnZTogZXJyb3IubWVzc2FnZSxcbiAgICAgICAgdXBkYXRlZEF0OiBmaXJlYmFzZS5maXJlc3RvcmUuRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgIH07XG5cbiAgICAgIGNvbnN0IGRvY1JlZiA9IHRoaXMubmdGaXJlLmNvbGxlY3Rpb24oJ21pc3NpbmdJbmRleGVzJykuZG9jKGRvY0lkKTtcbiAgICAgIGNvbnN0IGRvYyA9IGF3YWl0IGRvY1JlZi5nZXQoKS50b1Byb21pc2UoKTtcblxuICAgICAgaWYgKGRvYyAmJiBkb2MuZXhpc3RzKSB7XG4gICAgICAgIGF3YWl0IGRvY1JlZi51cGRhdGUoe1xuICAgICAgICAgIGNvdW50OiBmaXJlYmFzZS5maXJlc3RvcmUuRmllbGRWYWx1ZS5pbmNyZW1lbnQoMSksXG4gICAgICAgICAgdXBkYXRlZEF0OiBmaXJlYmFzZS5maXJlc3RvcmUuRmllbGRWYWx1ZS5zZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICAgICBsYXN0RXJyb3I6IGVycm9yLm1lc3NhZ2UsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgZG9jUmVmLnNldCh7XG4gICAgICAgICAgLi4udHJhY2tpbmdEYXRhLFxuICAgICAgICAgIGNvdW50OiAxLFxuICAgICAgICAgIGNyZWF0ZWRBdDogZmlyZWJhc2UuZmlyZXN0b3JlLkZpZWxkVmFsdWUuc2VydmVyVGltZXN0YW1wKCksXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKHRyYWNraW5nRXJyb3IpIHtcbiAgICAgIGNvbnNvbGUud2FybignRmFsaGEgYW8gcmFzdHJlYXIgw61uZGljZSBhdXNlbnRlOicsIHRyYWNraW5nRXJyb3IpO1xuICAgIH1cbiAgfVxufVxuIl19