@firestitch/report 18.9.0 → 18.10.0

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 (190) hide show
  1. package/app/reports/anchor-at-point.d.ts +14 -0
  2. package/app/reports/canvas-landing-page.d.ts +2 -0
  3. package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
  4. package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
  5. package/app/reports/components/report-canvas/report-canvas.component.d.ts +3 -0
  6. package/app/reports/components/report-component/report-component.component.d.ts +35 -1
  7. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  8. package/app/reports/data/report.data.d.ts +17 -2
  9. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +18 -3
  10. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  11. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  12. package/app/reports/drill-crumbs.d.ts +12 -0
  13. package/app/reports/export/report-export-collector.service.d.ts +13 -4
  14. package/app/reports/export/report-filter-lines.d.ts +18 -0
  15. package/app/reports/filter-settings-rules.d.ts +33 -0
  16. package/app/reports/format.d.ts +0 -1
  17. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  18. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  19. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  20. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  21. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  22. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  23. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  24. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  25. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  26. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  27. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  28. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  29. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  30. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  31. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  33. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  34. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  35. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  37. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  38. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  39. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  40. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  41. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  43. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  44. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  45. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  46. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  47. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  48. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  49. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  51. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  52. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  53. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  56. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  57. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  58. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  59. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  60. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  61. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  63. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  65. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  66. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  67. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  68. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  69. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  70. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  71. package/app/reports/interfaces/report.interface.d.ts +27 -3
  72. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  73. package/app/reports/mark-click.d.ts +20 -0
  74. package/app/reports/option-builder.d.ts +12 -1
  75. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  76. package/app/reports/report-date-presets.d.ts +2 -0
  77. package/app/reports/report-filter-items.d.ts +27 -22
  78. package/app/reports/report-tile.d.ts +2 -0
  79. package/app/reports/report-url-state.d.ts +27 -10
  80. package/app/reports/report-view-config.d.ts +36 -0
  81. package/app/reports/report-view-menu.d.ts +15 -0
  82. package/app/reports/report-viewer-features.d.ts +5 -0
  83. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  84. package/app/reports/services/report-filter-state.service.d.ts +64 -1
  85. package/app/reports/services/report-view.service.d.ts +51 -0
  86. package/app/reports/tile-data-state.d.ts +7 -0
  87. package/app/reports/tile-loads.d.ts +4 -0
  88. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  89. package/app/reports/views/report/report.component.d.ts +6 -0
  90. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  91. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  92. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  93. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  94. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  95. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +47 -32
  96. package/esm2022/app/reports/components/report-component/report-component.component.mjs +257 -61
  97. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  98. package/esm2022/app/reports/data/report.data.mjs +87 -10
  99. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +106 -51
  100. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  101. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  102. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  103. package/esm2022/app/reports/export/report-export-collector.service.mjs +187 -117
  104. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  105. package/esm2022/app/reports/export/report-pdf.service.mjs +12 -7
  106. package/esm2022/app/reports/export/report-pptx.service.mjs +18 -14
  107. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  108. package/esm2022/app/reports/format.mjs +2 -22
  109. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  110. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  111. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  112. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  113. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  114. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  115. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  116. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  117. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  118. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  119. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  120. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  121. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  122. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  123. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  124. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  125. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  138. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  140. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  164. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  165. package/esm2022/app/reports/mark-click.mjs +193 -0
  166. package/esm2022/app/reports/option-builder.mjs +159 -15
  167. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  168. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  169. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  170. package/esm2022/app/reports/report-tile.mjs +12 -0
  171. package/esm2022/app/reports/report-url-state.mjs +596 -108
  172. package/esm2022/app/reports/report-view-config.mjs +697 -0
  173. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  174. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  175. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  176. package/esm2022/app/reports/services/report-filter-state.service.mjs +697 -62
  177. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  178. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  179. package/esm2022/app/reports/tile-loads.mjs +38 -0
  180. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +177 -46
  181. package/esm2022/app/reports/views/report/report.component.mjs +103 -23
  182. package/esm2022/public_api.mjs +23 -1
  183. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  184. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  185. package/fesm2022/{firestitch-report-firestitch-report-CqbXT1gh.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +9063 -4272
  186. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  187. package/fesm2022/firestitch-report.mjs +1 -1
  188. package/package.json +1 -1
  189. package/public_api.d.ts +22 -0
  190. package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +0 -1
@@ -1,64 +1,247 @@
1
- import { GROUP_BY_ITEM, GROUP_PARAM_PREFIX, dateBoundString, dateFromBound, groupItemName, } from './report-filter-items';
2
- // The report viewer's state in its URL: a pure codec, with no knowledge of a
3
- // loaded report. ReportFilterStateService decides WHAT is carried (only values
4
- // that differ from the authored defaults) and checks what is read back against
5
- // the report; this file only turns values into query params and back.
1
+ import { iso8601 } from '@firestitch/date';
2
+ import { getExcludeName } from '@firestitch/filter';
3
+ import { parseISO } from 'date-fns';
4
+ import { FORMAT_PARAM, GROUP_BY_ITEM, MATCH_ITEM, PERSONAL_VIEW_PARAM, VIEW_PARAM, dateBoundString, groupParamKeys, itemRangeName, } from './report-filter-items';
5
+ import { DRILL_MAX_DEPTH, GROUP_VALUE_MAX_PICKS, REPORT_VIEW_CONFIG_VERSION, isCalendarDay, isChartGranularity, numberFromText, toStoredGroupValue, } from './report-view-config';
6
+ // The report viewer's state in its URL: a pure codec. It knows the report's
7
+ // filter groups only to name their keys; ReportFilterStateService decides
8
+ // WHAT is carried (only values that differ from the link's base) and checks
9
+ // what is read back against the report; this file only turns values into
10
+ // query params and back. Each value below is as the codec writes it; the
11
+ // router percent-encodes it again in the address bar.
6
12
  //
7
- // ?page=7&groupBy=week&g12=last30Days&g15=3,5&g16=2026-01-01..&s31=-create_date&q31=north&h31=notes,total
13
+ // ?page=7&groupBy=week&region=3:North,5:East&excludeStatus=2:Refunded
14
+ // &shippedFrom=2026-01-01T00:00:00-05:00&shippedTo=2026-01-31T00:00:00-05:00
15
+ // &unitsMin=0&unitsMax=50&s31=-create_date&q31=north
16
+ // &h31=notes,total&d44=year:2026-01-01,quarter:2026-07-01&match=any&rv=12&rf=2
8
17
  //
9
- // - g<groupId>: one key per filter group. A dateRange is its relative preset
10
- // name when it carries one, else 'YYYY-MM-DD..YYYY-MM-DD' (either side may be
11
- // empty); a select is its values joined by ','; a keyword is its text. An
12
- // empty value is an explicit clear of a group that has a default.
18
+ // A filter group is written under its fs-filter item's own query keys, so
19
+ // the bar and the link have one syntax. <key> is the group's key, the
20
+ // camelCase of its label ('Region' -> region; groupParamKeys in
21
+ // report-filter-items.ts, which also says what a clash falls back to:
22
+ // region12).
23
+ // - A select: <key>=value:name,... for the values it keeps and
24
+ // exclude<Key>=value:name,... for the values it leaves out. This is
25
+ // fs-filter's own syntax: ',' between picks, ':' between a value and its
26
+ // name, and a ',', ':' or '\' inside either one escaped with '\'. The name
27
+ // is the one the chip showed when the link was written, and is left off
28
+ // while the viewer has not seen it. Only the value is read back: names come
29
+ // from the option list, so a renamed option shows its new name.
30
+ // - A number range: <key>Min and <key>Max, either one open.
31
+ // - A date range: <key>From and <key>To in fs-filter's date format (the
32
+ // day's local midnight with its offset, 2026-01-01T00:00:00-05:00), either
33
+ // one open. Only the day is read back, so a link opens on the same days in
34
+ // every zone. A link never names a preset: a date picker preset only sets
35
+ // the days, and a rolling range (a report's relative default) is not written
36
+ // while it is the link's base, and is written as its days when it must be
37
+ // (the caller turns it into days first; see groupValueParams).
38
+ // - A keyword: <key>=text.
39
+ // An empty value is an explicit clear of a group that has a default: <key>=
40
+ // for a select or a keyword, both ends empty for a range.
41
+ // The other keys:
13
42
  // - s<componentId>: a list's sort column, '-' prefixed when descending.
14
43
  // - q<componentId>: the text in a list's search box.
15
44
  // - h<componentId>: the columns a viewer hid on a list (encodeColumnList).
45
+ // - d<componentId>: a chart's drill path, 'level:value' steps (each part
46
+ // percent-encoded) joined by ','.
16
47
  // - groupBy: the group-by grain (GROUP_BY_ITEM).
48
+ // - match=any: the groups combine with any (absent = all).
49
+ // - rv: the shared view the state is a diff from. rpv: the open personal
50
+ // view, a label only, never a base.
51
+ // - rf=2: the format every link this viewer writes carries.
52
+ // A key this codec does not know is ignored and left in the URL as it is.
17
53
  // The page key is the host's (FsAiReportComponent.pageQueryParam) and is
18
- // written beside these, never by this codec.
19
- // The prefix of a group's value key. Declared beside the filter items, which
20
- // read it too (declaring it here would make the two files import each other);
21
- // re-exported so every codec constant can be imported from the codec.
22
- export { GROUP_PARAM_PREFIX } from './report-filter-items';
54
+ // written beside these, never by this codec. The cross-filter and the rows
55
+ // panel are never in the URL.
56
+ //
57
+ // The keys the codec owns: the tile keys, groupBy, match, rv, rpv, rf, and
58
+ // every key a group of the open report is written under. A write removes an
59
+ // owned key it no longer carries, so a host must not keep its own state
60
+ // under one. A group key comes from a label, so a host param named like one
61
+ // (a group labeled 'Status' owns status and excludeStatus) is the codec's.
62
+ // Only the default page key, 'page', is kept off the groups.
63
+ // The keys of the views and the format. Declared beside the filter items,
64
+ // which keep a group key off them (declaring them here would make the two
65
+ // files import each other); re-exported so every codec constant can be
66
+ // imported from the codec.
67
+ export { FORMAT_PARAM, PERSONAL_VIEW_PARAM, VIEW_PARAM } from './report-filter-items';
23
68
  // The prefix of a list's sort key.
24
69
  export const LIST_SORT_PARAM_PREFIX = 's';
25
- // Between the two days of an encoded fixed date range.
26
- export const DATE_RANGE_SEPARATOR = '..';
27
70
  // The prefix of a list's search key.
28
71
  export const LIST_SEARCH_PARAM_PREFIX = 'q';
29
72
  // The prefix of a list's hidden-columns key.
30
73
  export const LIST_HIDDEN_PARAM_PREFIX = 'h';
31
- // The prefixes of the keys this codec owns, each followed by an id.
32
- const OWNED_PREFIXES = [
33
- GROUP_PARAM_PREFIX, LIST_SORT_PARAM_PREFIX, LIST_SEARCH_PARAM_PREFIX, LIST_HIDDEN_PARAM_PREFIX,
34
- ];
35
- // A key this codec owns: a group value, or a list's sort, search or hidden
36
- // columns. Any such key the snapshot no longer carries is removed from the
37
- // URL, so a host must not keep its own state under a key of this shape (one
38
- // of the prefixes above, then digits).
39
- export const OWNED_PARAM = new RegExp(`^[${OWNED_PREFIXES.join('')}]\\d+$`);
40
- const DAY_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
41
- // The viewer-state params of a URL as raw strings. Keys this codec does not
42
- // own are ignored.
43
- export function readReportUrlParams(params) {
44
- const groups = new Map();
74
+ // The prefix of a chart's drill-path key.
75
+ export const DRILL_PARAM_PREFIX = 'd';
76
+ // The match's key: the report bar's Match item's own name.
77
+ export const MATCH_PARAM = MATCH_ITEM;
78
+ // The format a link this viewer writes carries.
79
+ export const URL_FORMAT = 2;
80
+ // Between a drill step's level and its value.
81
+ export const DRILL_STEP_SEPARATOR = ':';
82
+ // Between a select's picks, and between a pick's value and its name
83
+ // (fs-filter's AutoCompleteChips syntax).
84
+ export const PICK_SEPARATOR = ',';
85
+ export const PICK_NAME_SEPARATOR = ':';
86
+ // Before a ',', ':' or '\' that is part of a pick's value or name.
87
+ const PICK_ESCAPE = '\\';
88
+ // The most characters the codec's params may take in a link (the host's own
89
+ // path and params are not counted).
90
+ export const REPORT_URL_MAX_LENGTH = 2000;
91
+ // Shown once when a link left group values out (ReportUrlWrite.tooLong).
92
+ export const URL_TOO_LONG_MESSAGE = 'This filter is too long for a link; save a view to share it.';
93
+ const MATCH_ANY = 'any';
94
+ // The prefixes of the tile keys this codec owns, each followed by an id.
95
+ const OWNED_PREFIXES = [LIST_SORT_PARAM_PREFIX, LIST_SEARCH_PARAM_PREFIX, LIST_HIDDEN_PARAM_PREFIX, DRILL_PARAM_PREFIX];
96
+ // The keys this codec owns that carry no id and do not depend on the report.
97
+ const OWNED_KEYS = [GROUP_BY_ITEM, MATCH_PARAM, VIEW_PARAM, PERSONAL_VIEW_PARAM, FORMAT_PARAM];
98
+ // A key of one of the prefixes above, followed by its id.
99
+ const ID_PARAM = new RegExp(`^([${OWNED_PREFIXES.join('')}])(\\d+)$`);
100
+ // A key this codec owns whatever the report: a list's sort, search or hidden
101
+ // columns; a chart's drill path; the grain, the match, the two views and the
102
+ // format. The groups' keys are owned too (see the top of this file).
103
+ export const OWNED_PARAM = new RegExp(`^(?:[${OWNED_PREFIXES.join('')}]\\d+|${OWNED_KEYS.join('|')})$`);
104
+ // A link's day: 'yyyy-MM-dd', alone or as the start of fs-filter's date
105
+ // format ('T' and a time and offset after it).
106
+ const LINK_DAY = /^(\d{4}-\d{2}-\d{2})(?:T.*)?$/;
107
+ // The viewer-state params of a URL: the groups' values in their stored shape
108
+ // (null for a group the link clears; read as paramsToViewConfig reads them),
109
+ // the rest as raw strings. Keys this codec does not own are ignored.
110
+ // `groups` is every filter group of the report.
111
+ export function readReportUrlParams(params, groups) {
45
112
  const listSorts = new Map();
46
113
  const listSearches = new Map();
47
114
  const listHidden = new Map();
48
- // Each owned prefix names the map its keys go to; a prefix with no entry
49
- // here is never read as some other kind of state.
115
+ // Each prefix read here names the map its keys go to; a prefix with no
116
+ // entry is never read as some other kind of state.
50
117
  const byPrefix = {
51
- [GROUP_PARAM_PREFIX]: groups,
52
118
  [LIST_SORT_PARAM_PREFIX]: listSorts,
53
119
  [LIST_SEARCH_PARAM_PREFIX]: listSearches,
54
120
  [LIST_HIDDEN_PARAM_PREFIX]: listHidden,
55
121
  };
122
+ const query = {};
56
123
  for (const key of params.keys) {
57
- if (OWNED_PARAM.test(key)) {
58
- byPrefix[key.charAt(0)]?.set(Number(key.slice(1)), params.get(key) ?? '');
124
+ query[key] = params.get(key) ?? '';
125
+ const owned = ID_PARAM.exec(key);
126
+ if (owned) {
127
+ byPrefix[owned[1]]?.set(Number(owned[2]), params.get(key) ?? '');
128
+ }
129
+ }
130
+ return {
131
+ groups: readGroupParams(query, groups),
132
+ listSorts, listSearches, listHidden,
133
+ groupBy: params.get(GROUP_BY_ITEM),
134
+ };
135
+ }
136
+ // The viewer state a link carries, as a view config: its group values (read
137
+ // by each group's type, so a group the report does not have is skipped), the
138
+ // grain, the match and each tile's sort, search, hidden columns and drill
139
+ // path. A param that is unusable is left out. Whether a tile's component and
140
+ // a list's columns exist is the caller's check. `groups` is every filter
141
+ // group of the report.
142
+ export function paramsToViewConfig(params, groups) {
143
+ const config = { v: REPORT_VIEW_CONFIG_VERSION };
144
+ const groupBy = paramText(params[GROUP_BY_ITEM]);
145
+ if (isChartGranularity(groupBy)) {
146
+ config.groupBy = groupBy;
147
+ }
148
+ if (paramText(params[MATCH_PARAM]) === MATCH_ANY) {
149
+ config.match = MATCH_ANY;
150
+ }
151
+ readGroupParams(params, groups).forEach((value, groupId) => {
152
+ config.groups = { ...config.groups, [groupId]: value };
153
+ });
154
+ Object.keys(params).forEach((key) => {
155
+ const owned = ID_PARAM.exec(key);
156
+ const raw = paramText(params[key]);
157
+ if (owned && raw !== null) {
158
+ readTileParam(config, owned[1], Number(owned[2]), raw);
159
+ }
160
+ });
161
+ return config;
162
+ }
163
+ // The params that make a link carry `config`, the views it names, and rf=2.
164
+ // Each group is written under its keys among `groups` (every filter group of
165
+ // the report); a group the report no longer has is left out. `name` names a
166
+ // select's values. Past REPORT_URL_MAX_LENGTH the longest group values are
167
+ // left out (those groups then open at the link's base) and tooLong is set.
168
+ export function viewConfigToParams(config, groups, link = {}, name = () => null) {
169
+ const params = {};
170
+ const keys = groupParamKeys(groups);
171
+ const types = new Map(groups.map((group) => [group.id, group.type]));
172
+ const groupParams = new Set();
173
+ if (config.groupBy) {
174
+ params[GROUP_BY_ITEM] = config.groupBy;
175
+ }
176
+ Object.entries(config.groups ?? {}).forEach(([id, value]) => {
177
+ const groupId = Number(id);
178
+ const key = keys.get(groupId);
179
+ if (key) {
180
+ const written = groupValueParams(types.get(groupId), key, value, (pick) => name(groupId, pick));
181
+ Object.assign(params, written);
182
+ Object.keys(written).forEach((param) => groupParams.add(param));
59
183
  }
184
+ });
185
+ Object.entries(config.tiles ?? {}).forEach(([componentId, tile]) => {
186
+ Object.assign(params, tileParams(Number(componentId), tile));
187
+ });
188
+ if (config.match === MATCH_ANY) {
189
+ params[MATCH_PARAM] = MATCH_ANY;
190
+ }
191
+ if (link.viewId) {
192
+ params[VIEW_PARAM] = String(link.viewId);
60
193
  }
61
- return { groups, listSorts, listSearches, listHidden, groupBy: params.get(GROUP_BY_ITEM) };
194
+ if (link.personalViewId) {
195
+ params[PERSONAL_VIEW_PARAM] = String(link.personalViewId);
196
+ }
197
+ return capReportParams(withFormat(params), groupParams);
198
+ }
199
+ // The views a link names, each a positive id or null.
200
+ export function readReportUrlLink(params) {
201
+ return {
202
+ viewId: positiveId(paramText(params[VIEW_PARAM])),
203
+ personalViewId: positiveId(paramText(params[PERSONAL_VIEW_PARAM])),
204
+ };
205
+ }
206
+ // Whether a link carries viewer state of its own, so it opens on that state
207
+ // rather than on a default view: any owned key but the format marker and the
208
+ // personal view, which is a label only. `groups` is every filter group of
209
+ // the report.
210
+ export function hasReportUrlState(params, groups) {
211
+ const groupKeys = ownedGroupKeys(groups);
212
+ return Object.keys(params).some((key) => ID_PARAM.test(key) || groupKeys.has(key)
213
+ || key === GROUP_BY_ITEM || key === MATCH_PARAM || key === VIEW_PARAM);
214
+ }
215
+ // Every owned key `current` carries, set to null: under the router's 'merge'
216
+ // handling, a write spread over these removes the keys it no longer carries.
217
+ // Keys this codec does not own are left alone. `groups` is every filter
218
+ // group of the report.
219
+ export function reportParamsToClear(current, groups) {
220
+ const groupKeys = ownedGroupKeys(groups);
221
+ const params = {};
222
+ for (const key of current.keys) {
223
+ if (OWNED_PARAM.test(key) || groupKeys.has(key)) {
224
+ params[key] = null;
225
+ }
226
+ }
227
+ return params;
228
+ }
229
+ // The names the select picks in `current` (the URL as it is) carry, so a
230
+ // write can keep a name the viewer's lists have not named yet. Only a write
231
+ // reads these: what the chips show comes from the lists.
232
+ export function urlValueNames(current, groups) {
233
+ const keys = groupParamKeys(groups);
234
+ const names = new Map();
235
+ groups
236
+ .filter((group) => group.type === 'select')
237
+ .forEach((group) => {
238
+ const key = keys.get(group.id);
239
+ const picks = [current.get(key), current.get(getExcludeName(key))]
240
+ .flatMap((raw) => (raw ? decodePickList(raw) : []))
241
+ .filter((pick) => pick.name !== null);
242
+ names.set(group.id, new Map(picks.map((pick) => [pick.value, pick.name])));
243
+ });
244
+ return (groupId, value) => names.get(groupId)?.get(String(value)) ?? null;
62
245
  }
63
246
  // A list's hidden column names as one param value. A name is a query's output
64
247
  // alias, which can hold a comma, so each is percent-encoded before the join.
@@ -71,57 +254,35 @@ export function encodeColumnList(names) {
71
254
  export function decodeColumnList(raw) {
72
255
  return raw.split(',')
73
256
  .filter((item) => item !== '')
74
- .map((item) => {
75
- try {
76
- return decodeURIComponent(item);
77
- }
78
- catch {
79
- return item;
80
- }
81
- });
257
+ .map(decodeItem);
82
258
  }
83
- // A group value read back from its URL param. null is an explicit clear (an
84
- // empty param). undefined means the param is unusable for a group of this type
85
- // (an unknown preset name, a malformed day, a wrong shape) and is ignored.
86
- // `resolveRelative` turns a preset name into today's range for it, or null for
87
- // a name it does not know.
88
- export function decodeFilterValue(type, raw, resolveRelative) {
89
- if (raw === '') {
90
- return null;
91
- }
92
- switch (type) {
93
- case 'dateRange':
94
- return raw.includes(DATE_RANGE_SEPARATOR)
95
- ? decodeFixedRange(raw)
96
- : decodePreset(raw, resolveRelative);
97
- case 'select': {
98
- const values = raw.split(',').filter((value) => value !== '');
99
- return values.length ? { values } : undefined;
100
- }
101
- case 'keyword':
102
- return raw.trim() ? { value: raw } : undefined;
103
- default:
104
- return undefined;
105
- }
106
- }
107
- // A group value as its URL param. The shape says how: a preset name, then a
108
- // date range, then select values, then keyword text. null (a cleared group)
109
- // is the empty param.
110
- export function encodeFilterValue(value) {
259
+ // A group's value in its stored shape as the link's params under the group's
260
+ // key (see the top of this file): days, then a select's values left out, then
261
+ // its values kept, then a number range, then keyword text. null (a cleared
262
+ // group), or a value that holds nothing, is the group's keys, empty. A
263
+ // relative range with no days is not written at all: a link carries days, and
264
+ // only the caller has the report's zone and clock to give them
265
+ // (ReportViewService). `name` names a select's value.
266
+ export function groupValueParams(type, key, value, name = () => null) {
111
267
  if (!value) {
112
- return '';
113
- }
114
- if (value.preset) {
115
- return value.preset;
268
+ return clearParams(type, key);
116
269
  }
117
270
  if (value.start || value.end) {
118
- return [dateBoundString(value.start) ?? '', dateBoundString(value.end) ?? '']
119
- .join(DATE_RANGE_SEPARATOR);
271
+ return rangeParams(type, key, ['from', 'to'], [linkDayText(value.start), linkDayText(value.end)]);
272
+ }
273
+ if (value.excludeValues?.length) {
274
+ return { [getExcludeName(key)]: encodePicks(value.excludeValues, name) };
120
275
  }
121
276
  if (value.values) {
122
- return value.values.map((item) => String(item)).join(',');
277
+ return { [key]: encodePicks(value.values, name) };
123
278
  }
124
- return value.value ?? '';
279
+ if (isNumberEnd(value.min) || isNumberEnd(value.max)) {
280
+ return rangeParams(type, key, ['min', 'max'], [numberEndText(value.min), numberEndText(value.max)]);
281
+ }
282
+ if (value.relative) {
283
+ return {};
284
+ }
285
+ return value.value ? { [key]: value.value } : clearParams(type, key);
125
286
  }
126
287
  export function encodeSort(sort) {
127
288
  return `${sort.direction === 'desc' ? '-' : ''}${sort.column}`;
@@ -135,19 +296,49 @@ export function decodeSort(raw) {
135
296
  ? { column, direction: descending ? 'desc' : 'asc' }
136
297
  : null;
137
298
  }
138
- // The query params that make the URL carry `snapshot`: every snapshot key is
139
- // set, and each owned key (or the grain) that `current` carries but the
140
- // snapshot does not is set to null, which removes it under the router's
141
- // 'merge' handling. Keys this codec does not own are left alone.
142
- export function buildReportUrlParams(snapshot, current) {
143
- const params = {};
144
- for (const key of current.keys) {
145
- if (OWNED_PARAM.test(key) || key === GROUP_BY_ITEM) {
146
- params[key] = null;
299
+ // A drill path as its URL param. A step with no value writes its level only.
300
+ export function encodeDrillPath(path) {
301
+ return path
302
+ .map((step) => (step.value === null || step.value === undefined
303
+ ? encodeURIComponent(step.level)
304
+ : `${encodeURIComponent(step.level)}${DRILL_STEP_SEPARATOR}${encodeURIComponent(String(step.value))}`))
305
+ .join(',');
306
+ }
307
+ // A drill path read back from its URL param: its steps up to the first that
308
+ // is not a time level (the steps before it are kept), at most DRILL_MAX_DEPTH
309
+ // of them. Values come back as text. Whether the path fits the chart is the
310
+ // server's check (it applies the longest valid prefix).
311
+ export function decodeDrillPath(raw) {
312
+ const path = [];
313
+ for (const item of raw.split(',')) {
314
+ const step = decodeDrillStep(item);
315
+ if (!step || path.length === DRILL_MAX_DEPTH) {
316
+ break;
147
317
  }
318
+ path.push(step);
148
319
  }
320
+ return path;
321
+ }
322
+ // The query params that make the URL carry `snapshot`: every snapshot key is
323
+ // set, and each owned key that `current` carries but the snapshot does not is
324
+ // set to null, which removes it under the router's 'merge' handling. Keys
325
+ // this codec does not own are left alone. Each group is written under its
326
+ // keys among `groups` (every filter group of the report). A select's value
327
+ // is named by `name`, else by the name `current` carries for it. A date range
328
+ // is written as the days on screen, never as a preset name.
329
+ export function buildReportUrlParams(snapshot, current, groups, name = () => null) {
330
+ const params = {};
331
+ const keys = groupParamKeys(groups);
332
+ const types = new Map(groups.map((group) => [group.id, group.type]));
333
+ const currentName = urlValueNames(current, groups);
149
334
  snapshot.groups.forEach((value, groupId) => {
150
- params[groupItemName({ id: groupId })] = encodeFilterValue(value);
335
+ const key = keys.get(groupId);
336
+ if (key) {
337
+ const type = types.get(groupId);
338
+ const named = (pick) => name(groupId, pick) ?? currentName(groupId, pick);
339
+ const days = value ? { ...value, preset: undefined } : value;
340
+ Object.assign(params, groupValueParams(type, key, toStoredGroupValue(type, days), named));
341
+ }
151
342
  });
152
343
  snapshot.listSorts.forEach((sort, componentId) => {
153
344
  params[`${LIST_SORT_PARAM_PREFIX}${componentId}`] = encodeSort(sort);
@@ -162,28 +353,325 @@ export function buildReportUrlParams(snapshot, current) {
162
353
  if (snapshot.frequency) {
163
354
  params[GROUP_BY_ITEM] = snapshot.frequency;
164
355
  }
165
- return params;
356
+ return { ...reportParamsToClear(current, groups), ...withFormat(params) };
166
357
  }
167
- // 'YYYY-MM-DD..YYYY-MM-DD', either side optional but not both. Each side must
168
- // be a real calendar day.
169
- function decodeFixedRange(raw) {
170
- const sides = raw.split(DATE_RANGE_SEPARATOR);
171
- if (sides.length !== 2 || (!sides[0] && !sides[1])) {
172
- return undefined;
358
+ // `params` with the format marker, when it carries anything.
359
+ function withFormat(params) {
360
+ return Object.keys(params).length ? { ...params, [FORMAT_PARAM]: String(URL_FORMAT) } : params;
361
+ }
362
+ // Each group's value a link carries, in its stored shape, by group id (null
363
+ // for a group the link clears). A group with no usable param is left out.
364
+ function readGroupParams(params, groups) {
365
+ const keys = groupParamKeys(groups);
366
+ const values = new Map();
367
+ for (const group of groups) {
368
+ const value = readGroupParam(params, group.type, keys.get(group.id));
369
+ if (value !== undefined) {
370
+ values.set(group.id, value);
371
+ }
372
+ }
373
+ return values;
374
+ }
375
+ // One group's value in a link, read from the keys of its type. null is a
376
+ // clear; undefined is no usable value.
377
+ function readGroupParam(params, type, key) {
378
+ switch (type) {
379
+ case 'select':
380
+ return readSelect(params, key);
381
+ case 'dateRange':
382
+ return readDateRange(params, key);
383
+ case 'numberRange':
384
+ return readNumberRange(params, key);
385
+ case 'keyword':
386
+ return readKeyword(params[key]);
387
+ default:
388
+ return undefined;
389
+ }
390
+ }
391
+ // A select's values kept (<key>), else its values left out (exclude<Key>).
392
+ function readSelect(params, key) {
393
+ const kept = paramText(params[key]);
394
+ if (kept !== null) {
395
+ return kept === '' ? null : decodePicks(kept, 'values');
396
+ }
397
+ const excluded = paramText(params[getExcludeName(key)]);
398
+ if (excluded !== null) {
399
+ return excluded === '' ? null : decodePicks(excluded, 'excludeValues');
173
400
  }
174
- const [start, end] = sides.map((side) => side ? decodeDay(side) : null);
401
+ return undefined;
402
+ }
403
+ // A date range's days (<key>From, <key>To), each a real calendar day,
404
+ // either one open but not both.
405
+ function readDateRange(params, key) {
406
+ const ends = readRangeEnds(params, key, ['from', 'to']);
407
+ if (!ends) {
408
+ return ends === null ? null : undefined;
409
+ }
410
+ const [start, end] = ends.map(linkDay);
175
411
  if (start === undefined || end === undefined) {
176
412
  return undefined;
177
413
  }
178
- return { start, end };
414
+ return compactRange(start, end, 'start', 'end');
415
+ }
416
+ // A number range's ends (<key>Min, <key>Max), each a finite number, either
417
+ // one open but not both, and min not above max.
418
+ function readNumberRange(params, key) {
419
+ const ends = readRangeEnds(params, key, ['min', 'max']);
420
+ if (!ends) {
421
+ return ends === null ? null : undefined;
422
+ }
423
+ const [min, max] = ends.map((end) => (end === '' ? null : numberFromText(end)));
424
+ if ((ends[0] !== '' && min === null) || (ends[1] !== '' && max === null) || (min !== null && max !== null && min > max)) {
425
+ return undefined;
426
+ }
427
+ return compactRange(min, max, 'min', 'max');
428
+ }
429
+ // A keyword's text. Blank text is unusable.
430
+ function readKeyword(raw) {
431
+ const text = paramText(raw);
432
+ if (text === null) {
433
+ return undefined;
434
+ }
435
+ if (text === '') {
436
+ return null;
437
+ }
438
+ return text.trim() ? { value: text } : undefined;
179
439
  }
180
- // One side of a fixed range as a local Date, or undefined when it is not a
181
- // real Y-M-D day.
182
- function decodeDay(side) {
183
- return DAY_PATTERN.test(side) ? (dateFromBound(side) ?? undefined) : undefined;
440
+ // A range's two ends as written ('' for one the link leaves open):
441
+ // undefined when the link carries neither key, null when every one it
442
+ // carries is empty (a clear).
443
+ function readRangeEnds(params, key, ends) {
444
+ const [low, high] = ends.map((end) => paramText(params[itemRangeName(key, end)]));
445
+ if (low === null && high === null) {
446
+ return undefined;
447
+ }
448
+ return low || high ? [low ?? '', high ?? ''] : null;
184
449
  }
185
- function decodePreset(name, resolveRelative) {
186
- const range = resolveRelative(name);
187
- return range ? { start: range.start, end: range.end, preset: name } : undefined;
450
+ // The params of a range's ends, the ones it sets only; with neither one
451
+ // usable, the group's clear.
452
+ function rangeParams(type, key, ends, texts) {
453
+ const params = {};
454
+ ends.forEach((end, index) => {
455
+ if (texts[index]) {
456
+ params[itemRangeName(key, end)] = texts[index];
457
+ }
458
+ });
459
+ return Object.keys(params).length ? params : clearParams(type, key);
460
+ }
461
+ // The params of a cleared group: its keys, empty.
462
+ function clearParams(type, key) {
463
+ switch (type) {
464
+ case 'dateRange':
465
+ return { [itemRangeName(key, 'from')]: '', [itemRangeName(key, 'to')]: '' };
466
+ case 'numberRange':
467
+ return { [itemRangeName(key, 'min')]: '', [itemRangeName(key, 'max')]: '' };
468
+ default:
469
+ return { [key]: '' };
470
+ }
471
+ }
472
+ // A stored day in fs-filter's date format: its local midnight with the
473
+ // offset, '' when there is no real day.
474
+ function linkDayText(bound) {
475
+ const day = dateBoundString(bound);
476
+ return day && isCalendarDay(day) ? iso8601(parseISO(day)) : '';
477
+ }
478
+ // The day of a link's date end: null when the end is open (''), undefined
479
+ // when it is not a real calendar day.
480
+ function linkDay(text) {
481
+ if (text === '') {
482
+ return null;
483
+ }
484
+ const day = LINK_DAY.exec(text)?.[1];
485
+ return day && isCalendarDay(day) ? day : undefined;
486
+ }
487
+ // The keys a link carries the groups' values under, by each group's type.
488
+ function ownedGroupKeys(groups) {
489
+ const keys = groupParamKeys(groups);
490
+ return new Set(groups.flatMap((group) => {
491
+ const key = keys.get(group.id);
492
+ switch (group.type) {
493
+ case 'select':
494
+ return [key, getExcludeName(key)];
495
+ case 'dateRange':
496
+ return [itemRangeName(key, 'from'), itemRangeName(key, 'to')];
497
+ case 'numberRange':
498
+ return [itemRangeName(key, 'min'), itemRangeName(key, 'max')];
499
+ default:
500
+ return [key];
501
+ }
502
+ }));
503
+ }
504
+ // One id-keyed param of a tile read into `config`.
505
+ function readTileParam(config, prefix, id, raw) {
506
+ switch (prefix) {
507
+ case LIST_SORT_PARAM_PREFIX:
508
+ setTileState(config, id, 'sort', decodeSort(raw));
509
+ break;
510
+ case LIST_SEARCH_PARAM_PREFIX:
511
+ setTileState(config, id, 'search', raw || null);
512
+ break;
513
+ case LIST_HIDDEN_PARAM_PREFIX:
514
+ setTileState(config, id, 'hidden', nonEmpty(decodeColumnList(raw)));
515
+ break;
516
+ default:
517
+ setTileState(config, id, 'drill', nonEmpty(decodeDrillPath(raw)));
518
+ }
519
+ }
520
+ // Sets one key of a tile's state, creating the tile, unless there is nothing
521
+ // to set.
522
+ function setTileState(config, componentId, key, value) {
523
+ if (value === null) {
524
+ return;
525
+ }
526
+ config.tiles = { ...config.tiles, [componentId]: { ...config.tiles?.[componentId], [key]: value } };
527
+ }
528
+ // The params of one tile's state.
529
+ function tileParams(componentId, tile) {
530
+ const params = {};
531
+ if (tile.sort?.column) {
532
+ params[`${LIST_SORT_PARAM_PREFIX}${componentId}`] = encodeSort(tile.sort);
533
+ }
534
+ // The text as typed: the router percent-encodes it in the URL.
535
+ if (tile.search) {
536
+ params[`${LIST_SEARCH_PARAM_PREFIX}${componentId}`] = tile.search;
537
+ }
538
+ if (tile.hidden?.length) {
539
+ params[`${LIST_HIDDEN_PARAM_PREFIX}${componentId}`] = encodeColumnList(tile.hidden);
540
+ }
541
+ if (tile.drill?.length) {
542
+ params[`${DRILL_PARAM_PREFIX}${componentId}`] = encodeDrillPath(tile.drill);
543
+ }
544
+ return params;
545
+ }
546
+ // `params` within REPORT_URL_MAX_LENGTH: past it, group values (the params
547
+ // named in `groupParams`) are left out, longest first, until the rest fits.
548
+ function capReportParams(params, groupParams) {
549
+ if (queryLength(params) <= REPORT_URL_MAX_LENGTH) {
550
+ return { params, tooLong: false };
551
+ }
552
+ const kept = { ...params };
553
+ const groupKeys = Object.keys(kept)
554
+ .filter((key) => groupParams.has(key))
555
+ .sort((a, b) => queryText(kept[b]).length - queryText(kept[a]).length);
556
+ for (const key of groupKeys) {
557
+ if (queryLength(kept) <= REPORT_URL_MAX_LENGTH) {
558
+ break;
559
+ }
560
+ delete kept[key];
561
+ }
562
+ return { params: kept, tooLong: true };
563
+ }
564
+ // The length of `params` as the router writes them in a query string.
565
+ function queryLength(params) {
566
+ return Object.entries(params)
567
+ .map(([key, value]) => `${queryText(key)}=${queryText(value)}`)
568
+ .join('&')
569
+ .length;
570
+ }
571
+ // Text as the router writes it in a query string (its query encoding):
572
+ // percent-encoded, with '@', ':', '$', ',' and ';' left as they are.
573
+ function queryText(text) {
574
+ return encodeURIComponent(text)
575
+ .replace(/%40/g, '@')
576
+ .replace(/%3A/gi, ':')
577
+ .replace(/%24/g, '$')
578
+ .replace(/%2C/gi, ',')
579
+ .replace(/%3B/gi, ';');
580
+ }
581
+ // A param's text: a repeated key gives its first value.
582
+ function paramText(value) {
583
+ const first = Array.isArray(value) ? value[0] : value;
584
+ return typeof first === 'string' || typeof first === 'number' ? String(first) : null;
585
+ }
586
+ function positiveId(raw) {
587
+ return raw !== null && /^[1-9]\d*$/.test(raw) ? Number(raw) : null;
588
+ }
589
+ function nonEmpty(list) {
590
+ return list.length ? list : null;
591
+ }
592
+ // An item of a list param, percent-decoded; one that does not decode (a
593
+ // hand-edited '%') is kept as written.
594
+ function decodeItem(item) {
595
+ try {
596
+ return decodeURIComponent(item);
597
+ }
598
+ catch {
599
+ return item;
600
+ }
601
+ }
602
+ // Select picks as one param value: value:name for each, the name left off
603
+ // when `name` does not know it, blanks left out.
604
+ function encodePicks(picks, name) {
605
+ return picks
606
+ .filter((pick) => typeof pick === 'string' || typeof pick === 'number' || typeof pick === 'boolean')
607
+ .filter((pick) => String(pick) !== '')
608
+ .map((pick) => {
609
+ const named = name(pick);
610
+ return named ? `${escapePick(String(pick))}${PICK_NAME_SEPARATOR}${escapePick(named)}` : escapePick(String(pick));
611
+ })
612
+ .join(PICK_SEPARATOR);
613
+ }
614
+ // A pick's value or name with each ',', ':' and '\' in it escaped.
615
+ function escapePick(text) {
616
+ return text.replace(/[\\,:]/g, (char) => `${PICK_ESCAPE}${char}`);
617
+ }
618
+ // The picks of a param written as encodePicks writes them, in order: each
619
+ // value and its name (null when the pick has none).
620
+ function decodePickList(raw) {
621
+ const picks = [];
622
+ let parts = [''];
623
+ let escaped = false;
624
+ const endPick = () => picks.push({ value: parts[0], name: parts.length > 1 ? parts[1] : null });
625
+ for (const char of raw) {
626
+ if (escaped) {
627
+ parts[parts.length - 1] += char;
628
+ escaped = false;
629
+ }
630
+ else if (char === PICK_ESCAPE) {
631
+ escaped = true;
632
+ }
633
+ else if (char === PICK_NAME_SEPARATOR && parts.length === 1) {
634
+ parts.push('');
635
+ }
636
+ else if (char === PICK_SEPARATOR) {
637
+ endPick();
638
+ parts = [''];
639
+ }
640
+ else {
641
+ parts[parts.length - 1] += char;
642
+ }
643
+ }
644
+ endPick();
645
+ return picks;
646
+ }
647
+ // A select's values, kept or left out, read from its param, or undefined
648
+ // when there are none or too many.
649
+ function decodePicks(raw, as) {
650
+ const picks = decodePickList(raw)
651
+ .map((pick) => pick.value)
652
+ .filter((value) => value !== '');
653
+ return picks.length && picks.length <= GROUP_VALUE_MAX_PICKS ? { [as]: picks } : undefined;
654
+ }
655
+ // A range's set ends under their keys.
656
+ function compactRange(low, high, lowKey, highKey) {
657
+ return {
658
+ ...(low !== null ? { [lowKey]: low } : {}),
659
+ ...(high !== null ? { [highKey]: high } : {}),
660
+ };
661
+ }
662
+ function isNumberEnd(end) {
663
+ return typeof end === 'number' && Number.isFinite(end);
664
+ }
665
+ function numberEndText(end) {
666
+ return isNumberEnd(end) ? String(end) : '';
667
+ }
668
+ // One 'level:value' step, or null when its level is not a time grain.
669
+ function decodeDrillStep(item) {
670
+ const at = item.indexOf(DRILL_STEP_SEPARATOR);
671
+ const level = decodeItem(at < 0 ? item : item.slice(0, at));
672
+ if (!isChartGranularity(level)) {
673
+ return null;
674
+ }
675
+ return { level, value: at < 0 ? null : decodeItem(item.slice(at + 1)) };
188
676
  }
189
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXVybC1zdGF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9yZXBvcnQtdXJsLXN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUtBLE9BQU8sRUFDTCxhQUFhLEVBQUUsa0JBQWtCLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBRSxhQUFhLEdBQ2pGLE1BQU0sdUJBQXVCLENBQUM7QUFHL0IsNkVBQTZFO0FBQzdFLCtFQUErRTtBQUMvRSwrRUFBK0U7QUFDL0Usc0VBQXNFO0FBQ3RFLEVBQUU7QUFDRiw0R0FBNEc7QUFDNUcsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSxnRkFBZ0Y7QUFDaEYsNEVBQTRFO0FBQzVFLG9FQUFvRTtBQUNwRSx3RUFBd0U7QUFDeEUscURBQXFEO0FBQ3JELDJFQUEyRTtBQUMzRSxpREFBaUQ7QUFDakQseUVBQXlFO0FBQ3pFLDZDQUE2QztBQUU3Qyw2RUFBNkU7QUFDN0UsOEVBQThFO0FBQzlFLHNFQUFzRTtBQUN0RSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUUzRCxtQ0FBbUM7QUFDbkMsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsR0FBRyxDQUFDO0FBRTFDLHVEQUF1RDtBQUN2RCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUM7QUFFekMscUNBQXFDO0FBQ3JDLE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLEdBQUcsQ0FBQztBQUU1Qyw2Q0FBNkM7QUFDN0MsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFDO0FBRTVDLG9FQUFvRTtBQUNwRSxNQUFNLGNBQWMsR0FBRztJQUNyQixrQkFBa0IsRUFBRSxzQkFBc0IsRUFBRSx3QkFBd0IsRUFBRSx3QkFBd0I7Q0FDL0YsQ0FBQztBQUVGLDJFQUEyRTtBQUMzRSwyRUFBMkU7QUFDM0UsNEVBQTRFO0FBQzVFLHVDQUF1QztBQUN2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QUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDbEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFBhcmFtTWFwLCBQYXJhbXMgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuXG5pbXBvcnQge1xuICBGaWx0ZXJHcm91cFZhbHVlLCBSZXBvcnRGaWx0ZXJUeXBlLCBSZXBvcnRTb3J0LCBSZXBvcnRVcmxQYXJhbXMsIFJlcG9ydFVybFNuYXBzaG90LFxufSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQge1xuICBHUk9VUF9CWV9JVEVNLCBHUk9VUF9QQVJBTV9QUkVGSVgsIGRhdGVCb3VuZFN0cmluZywgZGF0ZUZyb21Cb3VuZCwgZ3JvdXBJdGVtTmFtZSxcbn0gZnJvbSAnLi9yZXBvcnQtZmlsdGVyLWl0ZW1zJztcblxuXG4vLyBUaGUgcmVwb3J0IHZpZXdlcidzIHN0YXRlIGluIGl0cyBVUkw6IGEgcHVyZSBjb2RlYywgd2l0aCBubyBrbm93bGVkZ2Ugb2YgYVxuLy8gbG9hZGVkIHJlcG9ydC4gUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIGRlY2lkZXMgV0hBVCBpcyBjYXJyaWVkIChvbmx5IHZhbHVlc1xuLy8gdGhhdCBkaWZmZXIgZnJvbSB0aGUgYXV0aG9yZWQgZGVmYXVsdHMpIGFuZCBjaGVja3Mgd2hhdCBpcyByZWFkIGJhY2sgYWdhaW5zdFxuLy8gdGhlIHJlcG9ydDsgdGhpcyBmaWxlIG9ubHkgdHVybnMgdmFsdWVzIGludG8gcXVlcnkgcGFyYW1zIGFuZCBiYWNrLlxuLy9cbi8vICAgP3BhZ2U9NyZncm91cEJ5PXdlZWsmZzEyPWxhc3QzMERheXMmZzE1PTMsNSZnMTY9MjAyNi0wMS0wMS4uJnMzMT0tY3JlYXRlX2RhdGUmcTMxPW5vcnRoJmgzMT1ub3Rlcyx0b3RhbFxuLy9cbi8vIC0gZzxncm91cElkPjogb25lIGtleSBwZXIgZmlsdGVyIGdyb3VwLiBBIGRhdGVSYW5nZSBpcyBpdHMgcmVsYXRpdmUgcHJlc2V0XG4vLyAgIG5hbWUgd2hlbiBpdCBjYXJyaWVzIG9uZSwgZWxzZSAnWVlZWS1NTS1ERC4uWVlZWS1NTS1ERCcgKGVpdGhlciBzaWRlIG1heSBiZVxuLy8gICBlbXB0eSk7IGEgc2VsZWN0IGlzIGl0cyB2YWx1ZXMgam9pbmVkIGJ5ICcsJzsgYSBrZXl3b3JkIGlzIGl0cyB0ZXh0LiBBblxuLy8gICBlbXB0eSB2YWx1ZSBpcyBhbiBleHBsaWNpdCBjbGVhciBvZiBhIGdyb3VwIHRoYXQgaGFzIGEgZGVmYXVsdC5cbi8vIC0gczxjb21wb25lbnRJZD46IGEgbGlzdCdzIHNvcnQgY29sdW1uLCAnLScgcHJlZml4ZWQgd2hlbiBkZXNjZW5kaW5nLlxuLy8gLSBxPGNvbXBvbmVudElkPjogdGhlIHRleHQgaW4gYSBsaXN0J3Mgc2VhcmNoIGJveC5cbi8vIC0gaDxjb21wb25lbnRJZD46IHRoZSBjb2x1bW5zIGEgdmlld2VyIGhpZCBvbiBhIGxpc3QgKGVuY29kZUNvbHVtbkxpc3QpLlxuLy8gLSBncm91cEJ5OiB0aGUgZ3JvdXAtYnkgZ3JhaW4gKEdST1VQX0JZX0lURU0pLlxuLy8gVGhlIHBhZ2Uga2V5IGlzIHRoZSBob3N0J3MgKEZzQWlSZXBvcnRDb21wb25lbnQucGFnZVF1ZXJ5UGFyYW0pIGFuZCBpc1xuLy8gd3JpdHRlbiBiZXNpZGUgdGhlc2UsIG5ldmVyIGJ5IHRoaXMgY29kZWMuXG5cbi8vIFRoZSBwcmVmaXggb2YgYSBncm91cCdzIHZhbHVlIGtleS4gRGVjbGFyZWQgYmVzaWRlIHRoZSBmaWx0ZXIgaXRlbXMsIHdoaWNoXG4vLyByZWFkIGl0IHRvbyAoZGVjbGFyaW5nIGl0IGhlcmUgd291bGQgbWFrZSB0aGUgdHdvIGZpbGVzIGltcG9ydCBlYWNoIG90aGVyKTtcbi8vIHJlLWV4cG9ydGVkIHNvIGV2ZXJ5IGNvZGVjIGNvbnN0YW50IGNhbiBiZSBpbXBvcnRlZCBmcm9tIHRoZSBjb2RlYy5cbmV4cG9ydCB7IEdST1VQX1BBUkFNX1BSRUZJWCB9IGZyb20gJy4vcmVwb3J0LWZpbHRlci1pdGVtcyc7XG5cbi8vIFRoZSBwcmVmaXggb2YgYSBsaXN0J3Mgc29ydCBrZXkuXG5leHBvcnQgY29uc3QgTElTVF9TT1JUX1BBUkFNX1BSRUZJWCA9ICdzJztcblxuLy8gQmV0d2VlbiB0aGUgdHdvIGRheXMgb2YgYW4gZW5jb2RlZCBmaXhlZCBkYXRlIHJhbmdlLlxuZXhwb3J0IGNvbnN0IERBVEVfUkFOR0VfU0VQQVJBVE9SID0gJy4uJztcblxuLy8gVGhlIHByZWZpeCBvZiBhIGxpc3QncyBzZWFyY2gga2V5LlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX1BBUkFNX1BSRUZJWCA9ICdxJztcblxuLy8gVGhlIHByZWZpeCBvZiBhIGxpc3QncyBoaWRkZW4tY29sdW1ucyBrZXkuXG5leHBvcnQgY29uc3QgTElTVF9ISURERU5fUEFSQU1fUFJFRklYID0gJ2gnO1xuXG4vLyBUaGUgcHJlZml4ZXMgb2YgdGhlIGtleXMgdGhpcyBjb2RlYyBvd25zLCBlYWNoIGZvbGxvd2VkIGJ5IGFuIGlkLlxuY29uc3QgT1dORURfUFJFRklYRVMgPSBbXG4gIEdST1VQX1BBUkFNX1BSRUZJWCwgTElTVF9TT1JUX1BBUkFNX1BSRUZJWCwgTElTVF9TRUFSQ0hfUEFSQU1fUFJFRklYLCBMSVNUX0hJRERFTl9QQVJBTV9QUkVGSVgsXG5dO1xuXG4vLyBBIGtleSB0aGlzIGNvZGVjIG93bnM6IGEgZ3JvdXAgdmFsdWUsIG9yIGEgbGlzdCdzIHNvcnQsIHNlYXJjaCBvciBoaWRkZW5cbi8vIGNvbHVtbnMuIEFueSBzdWNoIGtleSB0aGUgc25hcHNob3Qgbm8gbG9uZ2VyIGNhcnJpZXMgaXMgcmVtb3ZlZCBmcm9tIHRoZVxuLy8gVVJMLCBzbyBhIGhvc3QgbXVzdCBub3Qga2VlcCBpdHMgb3duIHN0YXRlIHVuZGVyIGEga2V5IG9mIHRoaXMgc2hhcGUgKG9uZVxuLy8gb2YgdGhlIHByZWZpeGVzIGFib3ZlLCB0aGVuIGRpZ2l0cykuXG5leHBvcnQgY29uc3QgT1dORURfUEFSQU0gPSBuZXcgUmVnRXhwKGBeWyR7T1dORURfUFJFRklYRVMuam9pbignJyl9XVxcXFxkKyRgKTtcblxuY29uc3QgREFZX1BBVFRFUk4gPSAvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9JC87XG5cbi8vIFRoZSB2aWV3ZXItc3RhdGUgcGFyYW1zIG9mIGEgVVJMIGFzIHJhdyBzdHJpbmdzLiBLZXlzIHRoaXMgY29kZWMgZG9lcyBub3Rcbi8vIG93biBhcmUgaWdub3JlZC5cbmV4cG9ydCBmdW5jdGlvbiByZWFkUmVwb3J0VXJsUGFyYW1zKHBhcmFtczogUGFyYW1NYXApOiBSZXBvcnRVcmxQYXJhbXMge1xuICBjb25zdCBncm91cHMgPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuICBjb25zdCBsaXN0U29ydHMgPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuICBjb25zdCBsaXN0U2VhcmNoZXMgPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuICBjb25zdCBsaXN0SGlkZGVuID0gbmV3IE1hcDxudW1iZXIsIHN0cmluZz4oKTtcbiAgLy8gRWFjaCBvd25lZCBwcmVmaXggbmFtZXMgdGhlIG1hcCBpdHMga2V5cyBnbyB0bzsgYSBwcmVmaXggd2l0aCBubyBlbnRyeVxuICAvLyBoZXJlIGlzIG5ldmVyIHJlYWQgYXMgc29tZSBvdGhlciBraW5kIG9mIHN0YXRlLlxuICBjb25zdCBieVByZWZpeDogUmVjb3JkPHN0cmluZywgTWFwPG51bWJlciwgc3RyaW5nPj4gPSB7XG4gICAgW0dST1VQX1BBUkFNX1BSRUZJWF06IGdyb3VwcyxcbiAgICBbTElTVF9TT1JUX1BBUkFNX1BSRUZJWF06IGxpc3RTb3J0cyxcbiAgICBbTElTVF9TRUFSQ0hfUEFSQU1fUFJFRklYXTogbGlzdFNlYXJjaGVzLFxuICAgIFtMSVNUX0hJRERFTl9QQVJBTV9QUkVGSVhdOiBsaXN0SGlkZGVuLFxuICB9O1xuXG4gIGZvciAoY29uc3Qga2V5IG9mIHBhcmFtcy5rZXlzKSB7XG4gICAgaWYgKE9XTkVEX1BBUkFNLnRlc3Qoa2V5KSkge1xuICAgICAgYnlQcmVmaXhba2V5LmNoYXJBdCgwKV0/LnNldChOdW1iZXIoa2V5LnNsaWNlKDEpKSwgcGFyYW1zLmdldChrZXkpID8/ICcnKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4geyBncm91cHMsIGxpc3RTb3J0cywgbGlzdFNlYXJjaGVzLCBsaXN0SGlkZGVuLCBncm91cEJ5OiBwYXJhbXMuZ2V0KEdST1VQX0JZX0lURU0pIH07XG59XG5cbi8vIEEgbGlzdCdzIGhpZGRlbiBjb2x1bW4gbmFtZXMgYXMgb25lIHBhcmFtIHZhbHVlLiBBIG5hbWUgaXMgYSBxdWVyeSdzIG91dHB1dFxuLy8gYWxpYXMsIHdoaWNoIGNhbiBob2xkIGEgY29tbWEsIHNvIGVhY2ggaXMgcGVyY2VudC1lbmNvZGVkIGJlZm9yZSB0aGUgam9pbi5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVDb2x1bW5MaXN0KG5hbWVzOiByZWFkb25seSBzdHJpbmdbXSk6IHN0cmluZyB7XG4gIHJldHVybiBuYW1lcy5tYXAoKG5hbWUpID0+IGVuY29kZVVSSUNvbXBvbmVudChuYW1lKSkuam9pbignLCcpO1xufVxuXG4vLyBUaGUgY29sdW1uIG5hbWVzIG9mIGEgaGlkZGVuLWNvbHVtbnMgcGFyYW0sIGluIGl0cyBvcmRlci4gRW1wdHkgaXRlbXMgYXJlXG4vLyBkcm9wcGVkLCBhbmQgYW4gaXRlbSB0aGF0IGRvZXMgbm90IGRlY29kZSAoYSBoYW5kLWVkaXRlZCAnJScpIGlzIGtlcHQgYXNcbi8vIHdyaXR0ZW4uIFdoZXRoZXIgYSBuYW1lIGlzIGEgY29sdW1uIG9mIHRoZSBsaXN0IGlzIHRoZSBjYWxsZXIncyBjaGVjay5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVDb2x1bW5MaXN0KHJhdzogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gcmF3LnNwbGl0KCcsJylcbiAgICAuZmlsdGVyKChpdGVtKSA9PiBpdGVtICE9PSAnJylcbiAgICAubWFwKChpdGVtKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KGl0ZW0pO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBpdGVtO1xuICAgICAgfVxuICAgIH0pO1xufVxuXG4vLyBBIGdyb3VwIHZhbHVlIHJlYWQgYmFjayBmcm9tIGl0cyBVUkwgcGFyYW0uIG51bGwgaXMgYW4gZXhwbGljaXQgY2xlYXIgKGFuXG4vLyBlbXB0eSBwYXJhbSkuIHVuZGVmaW5lZCBtZWFucyB0aGUgcGFyYW0gaXMgdW51c2FibGUgZm9yIGEgZ3JvdXAgb2YgdGhpcyB0eXBlXG4vLyAoYW4gdW5rbm93biBwcmVzZXQgbmFtZSwgYSBtYWxmb3JtZWQgZGF5LCBhIHdyb25nIHNoYXBlKSBhbmQgaXMgaWdub3JlZC5cbi8vIGByZXNvbHZlUmVsYXRpdmVgIHR1cm5zIGEgcHJlc2V0IG5hbWUgaW50byB0b2RheSdzIHJhbmdlIGZvciBpdCwgb3IgbnVsbCBmb3Jcbi8vIGEgbmFtZSBpdCBkb2VzIG5vdCBrbm93LlxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUZpbHRlclZhbHVlKFxuICB0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlLFxuICByYXc6IHN0cmluZyxcbiAgcmVzb2x2ZVJlbGF0aXZlOiAobmFtZTogc3RyaW5nKSA9PiB7IHN0YXJ0OiBEYXRlOyBlbmQ6IERhdGUgfSB8IG51bGwsXG4pOiBGaWx0ZXJHcm91cFZhbHVlIHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gIGlmIChyYXcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdkYXRlUmFuZ2UnOlxuICAgICAgcmV0dXJuIHJhdy5pbmNsdWRlcyhEQVRFX1JBTkdFX1NFUEFSQVRPUilcbiAgICAgICAgPyBkZWNvZGVGaXhlZFJhbmdlKHJhdylcbiAgICAgICAgOiBkZWNvZGVQcmVzZXQocmF3LCByZXNvbHZlUmVsYXRpdmUpO1xuXG4gICAgY2FzZSAnc2VsZWN0Jzoge1xuICAgICAgY29uc3QgdmFsdWVzID0gcmF3LnNwbGl0KCcsJykuZmlsdGVyKCh2YWx1ZSkgPT4gdmFsdWUgIT09ICcnKTtcblxuICAgICAgcmV0dXJuIHZhbHVlcy5sZW5ndGggPyB7IHZhbHVlcyB9IDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNhc2UgJ2tleXdvcmQnOlxuICAgICAgcmV0dXJuIHJhdy50cmltKCkgPyB7IHZhbHVlOiByYXcgfSA6IHVuZGVmaW5lZDtcblxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8vIEEgZ3JvdXAgdmFsdWUgYXMgaXRzIFVSTCBwYXJhbS4gVGhlIHNoYXBlIHNheXMgaG93OiBhIHByZXNldCBuYW1lLCB0aGVuIGFcbi8vIGRhdGUgcmFuZ2UsIHRoZW4gc2VsZWN0IHZhbHVlcywgdGhlbiBrZXl3b3JkIHRleHQuIG51bGwgKGEgY2xlYXJlZCBncm91cClcbi8vIGlzIHRoZSBlbXB0eSBwYXJhbS5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVGaWx0ZXJWYWx1ZSh2YWx1ZTogRmlsdGVyR3JvdXBWYWx1ZSB8IG51bGwpOiBzdHJpbmcge1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgaWYgKHZhbHVlLnByZXNldCkge1xuICAgIHJldHVybiB2YWx1ZS5wcmVzZXQ7XG4gIH1cblxuICBpZiAodmFsdWUuc3RhcnQgfHwgdmFsdWUuZW5kKSB7XG4gICAgcmV0dXJuIFtkYXRlQm91bmRTdHJpbmcodmFsdWUuc3RhcnQpID8/ICcnLCBkYXRlQm91bmRTdHJpbmcodmFsdWUuZW5kKSA/PyAnJ11cbiAgICAgIC5qb2luKERBVEVfUkFOR0VfU0VQQVJBVE9SKTtcbiAgfVxuXG4gIGlmICh2YWx1ZS52YWx1ZXMpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWVzLm1hcCgoaXRlbSkgPT4gU3RyaW5nKGl0ZW0pKS5qb2luKCcsJyk7XG4gIH1cblxuICByZXR1cm4gdmFsdWUudmFsdWUgPz8gJyc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVTb3J0KHNvcnQ6IFJlcG9ydFNvcnQpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7c29ydC5kaXJlY3Rpb24gPT09ICdkZXNjJyA/ICctJyA6ICcnfSR7c29ydC5jb2x1bW59YDtcbn1cblxuLy8gQSBsaXN0IHNvcnQgcmVhZCBiYWNrIGZyb20gaXRzIFVSTCBwYXJhbSwgb3IgbnVsbCB3aGVuIGl0IG5hbWVzIG5vIGNvbHVtbi5cbi8vIFdoZXRoZXIgdGhlIGNvbHVtbiBpcyBvbmUgdGhlIGxpc3QgY2FuIHNvcnQgYnkgaXMgdGhlIGNhbGxlcidzIGNoZWNrLlxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVNvcnQocmF3OiBzdHJpbmcpOiBSZXBvcnRTb3J0IHwgbnVsbCB7XG4gIGNvbnN0IGRlc2NlbmRpbmcgPSByYXcuc3RhcnRzV2l0aCgnLScpO1xuICBjb25zdCBjb2x1bW4gPSBkZXNjZW5kaW5nID8gcmF3LnNsaWNlKDEpIDogcmF3O1xuXG4gIHJldHVybiBjb2x1bW5cbiAgICA/IHsgY29sdW1uLCBkaXJlY3Rpb246IGRlc2NlbmRpbmcgPyAnZGVzYycgOiAnYXNjJyB9XG4gICAgOiBudWxsO1xufVxuXG4vLyBUaGUgcXVlcnkgcGFyYW1zIHRoYXQgbWFrZSB0aGUgVVJMIGNhcnJ5IGBzbmFwc2hvdGA6IGV2ZXJ5IHNuYXBzaG90IGtleSBpc1xuLy8gc2V0LCBhbmQgZWFjaCBvd25lZCBrZXkgKG9yIHRoZSBncmFpbikgdGhhdCBgY3VycmVudGAgY2FycmllcyBidXQgdGhlXG4vLyBzbmFwc2hvdCBkb2VzIG5vdCBpcyBzZXQgdG8gbnVsbCwgd2hpY2ggcmVtb3ZlcyBpdCB1bmRlciB0aGUgcm91dGVyJ3Ncbi8vICdtZXJnZScgaGFuZGxpbmcuIEtleXMgdGhpcyBjb2RlYyBkb2VzIG5vdCBvd24gYXJlIGxlZnQgYWxvbmUuXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRSZXBvcnRVcmxQYXJhbXMoc25hcHNob3Q6IFJlcG9ydFVybFNuYXBzaG90LCBjdXJyZW50OiBQYXJhbU1hcCk6IFBhcmFtcyB7XG4gIGNvbnN0IHBhcmFtczogUGFyYW1zID0ge307XG5cbiAgZm9yIChjb25zdCBrZXkgb2YgY3VycmVudC5rZXlzKSB7XG4gICAgaWYgKE9XTkVEX1BBUkFNLnRlc3Qoa2V5KSB8fCBrZXkgPT09IEdST1VQX0JZX0lURU0pIHtcbiAgICAgIHBhcmFtc1trZXldID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICBzbmFwc2hvdC5ncm91cHMuZm9yRWFjaCgodmFsdWUsIGdyb3VwSWQpID0+IHtcbiAgICBwYXJhbXNbZ3JvdXBJdGVtTmFtZSh7IGlkOiBncm91cElkIH0pXSA9IGVuY29kZUZpbHRlclZhbHVlKHZhbHVlKTtcbiAgfSk7XG5cbiAgc25hcHNob3QubGlzdFNvcnRzLmZvckVhY2goKHNvcnQsIGNvbXBvbmVudElkKSA9PiB7XG4gICAgcGFyYW1zW2Ake0xJU1RfU09SVF9QQVJBTV9QUkVGSVh9JHtjb21wb25lbnRJZH1gXSA9IGVuY29kZVNvcnQoc29ydCk7XG4gIH0pO1xuXG4gIC8vIFRoZSB0ZXh0IGFzIHR5cGVkOiB0aGUgcm91dGVyIHBlcmNlbnQtZW5jb2RlcyBpdCBpbiB0aGUgVVJMLlxuICBzbmFwc2hvdC5saXN0U2VhcmNoZXMuZm9yRWFjaCgoc2VhcmNoLCBjb21wb25lbnRJZCkgPT4ge1xuICAgIHBhcmFtc1tgJHtMSVNUX1NFQVJDSF9QQVJBTV9QUkVGSVh9JHtjb21wb25lbnRJZH1gXSA9IHNlYXJjaDtcbiAgfSk7XG5cbiAgc25hcHNob3QubGlzdEhpZGRlbi5mb3JFYWNoKChuYW1lcywgY29tcG9uZW50SWQpID0+IHtcbiAgICBwYXJhbXNbYCR7TElTVF9ISURERU5fUEFSQU1fUFJFRklYfSR7Y29tcG9uZW50SWR9YF0gPSBlbmNvZGVDb2x1bW5MaXN0KG5hbWVzKTtcbiAgfSk7XG5cbiAgaWYgKHNuYXBzaG90LmZyZXF1ZW5jeSkge1xuICAgIHBhcmFtc1tHUk9VUF9CWV9JVEVNXSA9IHNuYXBzaG90LmZyZXF1ZW5jeTtcbiAgfVxuXG4gIHJldHVybiBwYXJhbXM7XG59XG5cbi8vICdZWVlZLU1NLURELi5ZWVlZLU1NLUREJywgZWl0aGVyIHNpZGUgb3B0aW9uYWwgYnV0IG5vdCBib3RoLiBFYWNoIHNpZGUgbXVzdFxuLy8gYmUgYSByZWFsIGNhbGVuZGFyIGRheS5cbmZ1bmN0aW9uIGRlY29kZUZpeGVkUmFuZ2UocmF3OiBzdHJpbmcpOiBGaWx0ZXJHcm91cFZhbHVlIHwgdW5kZWZpbmVkIHtcbiAgY29uc3Qgc2lkZXMgPSByYXcuc3BsaXQoREFURV9SQU5HRV9TRVBBUkFUT1IpO1xuICBpZiAoc2lkZXMubGVuZ3RoICE9PSAyIHx8ICghc2lkZXNbMF0gJiYgIXNpZGVzWzFdKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBbc3RhcnQsIGVuZF0gPSBzaWRlcy5tYXAoKHNpZGUpID0+IHNpZGUgPyBkZWNvZGVEYXkoc2lkZSkgOiBudWxsKTtcbiAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQgfHwgZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcmV0dXJuIHsgc3RhcnQsIGVuZCB9O1xufVxuXG4vLyBPbmUgc2lkZSBvZiBhIGZpeGVkIHJhbmdlIGFzIGEgbG9jYWwgRGF0ZSwgb3IgdW5kZWZpbmVkIHdoZW4gaXQgaXMgbm90IGFcbi8vIHJlYWwgWS1NLUQgZGF5LlxuZnVuY3Rpb24gZGVjb2RlRGF5KHNpZGU6IHN0cmluZyk6IERhdGUgfCB1bmRlZmluZWQge1xuICByZXR1cm4gREFZX1BBVFRFUk4udGVzdChzaWRlKSA/IChkYXRlRnJvbUJvdW5kKHNpZGUpID8/IHVuZGVmaW5lZCkgOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGRlY29kZVByZXNldChcbiAgbmFtZTogc3RyaW5nLFxuICByZXNvbHZlUmVsYXRpdmU6IChuYW1lOiBzdHJpbmcpID0+IHsgc3RhcnQ6IERhdGU7IGVuZDogRGF0ZSB9IHwgbnVsbCxcbik6IEZpbHRlckdyb3VwVmFsdWUgfCB1bmRlZmluZWQge1xuICBjb25zdCByYW5nZSA9IHJlc29sdmVSZWxhdGl2ZShuYW1lKTtcblxuICByZXR1cm4gcmFuZ2UgPyB7IHN0YXJ0OiByYW5nZS5zdGFydCwgZW5kOiByYW5nZS5lbmQsIHByZXNldDogbmFtZSB9IDogdW5kZWZpbmVkO1xufVxuIl19
677
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXVybC1zdGF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9yZXBvcnQtdXJsLXN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMzQyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFcEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQVlwQyxPQUFPLEVBQ0wsWUFBWSxFQUFFLGFBQWEsRUFBZ0IsVUFBVSxFQUFFLG1CQUFtQixFQUFFLFVBQVUsRUFDdEYsZUFBZSxFQUFFLGNBQWMsRUFBRSxhQUFhLEdBQy9DLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUNMLGVBQWUsRUFBRSxxQkFBcUIsRUFBRSwwQkFBMEIsRUFBRSxhQUFhLEVBQUUsa0JBQWtCLEVBQ3JHLGNBQWMsRUFBRSxrQkFBa0IsR0FDbkMsTUFBTSxzQkFBc0IsQ0FBQztBQUc5Qiw0RUFBNEU7QUFDNUUsMEVBQTBFO0FBQzFFLDRFQUE0RTtBQUM1RSx5RUFBeUU7QUFDekUseUVBQXlFO0FBQ3pFLHNEQUFzRDtBQUN0RCxFQUFFO0FBQ0Ysd0VBQXdFO0FBQ3hFLGdGQUFnRjtBQUNoRix3REFBd0Q7QUFDeEQsa0ZBQWtGO0FBQ2xGLEVBQUU7QUFDRiwwRUFBMEU7QUFDMUUsc0VBQXNFO0FBQ3RFLGdFQUFnRTtBQUNoRSxzRUFBc0U7QUFDdEUsYUFBYTtBQUNiLCtEQUErRDtBQUMvRCxzRUFBc0U7QUFDdEUsMkVBQTJFO0FBQzNFLDZFQUE2RTtBQUM3RSwwRUFBMEU7QUFDMUUsOEVBQThFO0FBQzlFLGtFQUFrRTtBQUNsRSw0REFBNEQ7QUFDNUQsd0VBQXdFO0FBQ3hFLDZFQUE2RTtBQUM3RSw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUs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QUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUM5QyxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLEdBQVk7SUFDL0IsT0FBTyxPQUFPLEdBQUcsS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUN6RCxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsR0FBWTtJQUNqQyxPQUFPLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDN0MsQ0FBQztBQUVELHNFQUFzRTtBQUN0RSxTQUFTLGVBQWUsQ0FBQyxJQUFZO0lBQ25DLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUM5QyxNQUFNLEtBQUssR0FBRyxVQUFVLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRTVELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQy9CLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUMxRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGFyYW1NYXAsIFBhcmFtcyB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5cbmltcG9ydCB7IGlzbzg2MDEgfSBmcm9tICdAZmlyZXN0aXRjaC9kYXRlJztcbmltcG9ydCB7IGdldEV4Y2x1ZGVOYW1lIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZmlsdGVyJztcblxuaW1wb3J0IHsgcGFyc2VJU08gfSBmcm9tICdkYXRlLWZucyc7XG5cbmltcG9ydCB7IFJlcG9ydERyaWxsU3RlcCB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtZHJpbGwtc3RlcC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyTWF0Y2ggfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1tYXRjaC50eXBlJztcbmltcG9ydCB7IFJlcG9ydFRpbGVTdGF0ZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdGlsZS1zdGF0ZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0VXJsTGluayB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdXJsLWxpbmsuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlcG9ydFVybFZhbHVlTmFtZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdXJsLXZhbHVlLW5hbWUudHlwZSc7XG5pbXBvcnQgeyBSZXBvcnRVcmxXcml0ZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdXJsLXdyaXRlLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRWaWV3Q29uZmlnIH0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC12aWV3LWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHtcbiAgRmlsdGVyR3JvdXBEZWZhdWx0LCBSZXBvcnRGaWx0ZXJHcm91cCwgUmVwb3J0RmlsdGVyVHlwZSwgUmVwb3J0U29ydCwgUmVwb3J0VXJsUGFyYW1zLCBSZXBvcnRVcmxTbmFwc2hvdCxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHtcbiAgRk9STUFUX1BBUkFNLCBHUk9VUF9CWV9JVEVNLCBJdGVtUmFuZ2VFbmQsIE1BVENIX0lURU0sIFBFUlNPTkFMX1ZJRVdfUEFSQU0sIFZJRVdfUEFSQU0sXG4gIGRhdGVCb3VuZFN0cmluZywgZ3JvdXBQYXJhbUtleXMsIGl0ZW1SYW5nZU5hbWUsXG59IGZyb20gJy4vcmVwb3J0LWZpbHRlci1pdGVtcyc7XG5pbXBvcnQge1xuICBEUklMTF9NQVhfREVQVEgsIEdST1VQX1ZBTFVFX01BWF9QSUNLUywgUkVQT1JUX1ZJRVdfQ09ORklHX1ZFUlNJT04sIGlzQ2FsZW5kYXJEYXksIGlzQ2hhcnRHcmFudWxhcml0eSxcbiAgbnVtYmVyRnJvbVRleHQsIHRvU3RvcmVkR3JvdXBWYWx1ZSxcbn0gZnJvbSAnLi9yZXBvcnQtdmlldy1jb25maWcnO1xuXG5cbi8vIFRoZSByZXBvcnQgdmlld2VyJ3Mgc3RhdGUgaW4gaXRzIFVSTDogYSBwdXJlIGNvZGVjLiBJdCBrbm93cyB0aGUgcmVwb3J0J3Ncbi8vIGZpbHRlciBncm91cHMgb25seSB0byBuYW1lIHRoZWlyIGtleXM7IFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSBkZWNpZGVzXG4vLyBXSEFUIGlzIGNhcnJpZWQgKG9ubHkgdmFsdWVzIHRoYXQgZGlmZmVyIGZyb20gdGhlIGxpbmsncyBiYXNlKSBhbmQgY2hlY2tzXG4vLyB3aGF0IGlzIHJlYWQgYmFjayBhZ2FpbnN0IHRoZSByZXBvcnQ7IHRoaXMgZmlsZSBvbmx5IHR1cm5zIHZhbHVlcyBpbnRvXG4vLyBxdWVyeSBwYXJhbXMgYW5kIGJhY2suIEVhY2ggdmFsdWUgYmVsb3cgaXMgYXMgdGhlIGNvZGVjIHdyaXRlcyBpdDsgdGhlXG4vLyByb3V0ZXIgcGVyY2VudC1lbmNvZGVzIGl0IGFnYWluIGluIHRoZSBhZGRyZXNzIGJhci5cbi8vXG4vLyAgID9wYWdlPTcmZ3JvdXBCeT13ZWVrJnJlZ2lvbj0zOk5vcnRoLDU6RWFzdCZleGNsdWRlU3RhdHVzPTI6UmVmdW5kZWRcbi8vICAgICZzaGlwcGVkRnJvbT0yMDI2LTAxLTAxVDAwOjAwOjAwLTA1OjAwJnNoaXBwZWRUbz0yMDI2LTAxLTMxVDAwOjAwOjAwLTA1OjAwXG4vLyAgICAmdW5pdHNNaW49MCZ1bml0c01heD01MCZzMzE9LWNyZWF0ZV9kYXRlJnEzMT1ub3J0aFxuLy8gICAgJmgzMT1ub3Rlcyx0b3RhbCZkNDQ9eWVhcjoyMDI2LTAxLTAxLHF1YXJ0ZXI6MjAyNi0wNy0wMSZtYXRjaD1hbnkmcnY9MTImcmY9MlxuLy9cbi8vIEEgZmlsdGVyIGdyb3VwIGlzIHdyaXR0ZW4gdW5kZXIgaXRzIGZzLWZpbHRlciBpdGVtJ3Mgb3duIHF1ZXJ5IGtleXMsIHNvXG4vLyB0aGUgYmFyIGFuZCB0aGUgbGluayBoYXZlIG9uZSBzeW50YXguIDxrZXk+IGlzIHRoZSBncm91cCdzIGtleSwgdGhlXG4vLyBjYW1lbENhc2Ugb2YgaXRzIGxhYmVsICgnUmVnaW9uJyAtPiByZWdpb247IGdyb3VwUGFyYW1LZXlzIGluXG4vLyByZXBvcnQtZmlsdGVyLWl0ZW1zLnRzLCB3aGljaCBhbHNvIHNheXMgd2hhdCBhIGNsYXNoIGZhbGxzIGJhY2sgdG86XG4vLyByZWdpb24xMikuXG4vLyAtIEEgc2VsZWN0OiA8a2V5Pj12YWx1ZTpuYW1lLC4uLiBmb3IgdGhlIHZhbHVlcyBpdCBrZWVwcyBhbmRcbi8vICAgZXhjbHVkZTxLZXk+PXZhbHVlOm5hbWUsLi4uIGZvciB0aGUgdmFsdWVzIGl0IGxlYXZlcyBvdXQuIFRoaXMgaXNcbi8vICAgZnMtZmlsdGVyJ3Mgb3duIHN5bnRheDogJywnIGJldHdlZW4gcGlja3MsICc6JyBiZXR3ZWVuIGEgdmFsdWUgYW5kIGl0c1xuLy8gICBuYW1lLCBhbmQgYSAnLCcsICc6JyBvciAnXFwnIGluc2lkZSBlaXRoZXIgb25lIGVzY2FwZWQgd2l0aCAnXFwnLiBUaGUgbmFtZVxuLy8gICBpcyB0aGUgb25lIHRoZSBjaGlwIHNob3dlZCB3aGVuIHRoZSBsaW5rIHdhcyB3cml0dGVuLCBhbmQgaXMgbGVmdCBvZmZcbi8vICAgd2hpbGUgdGhlIHZpZXdlciBoYXMgbm90IHNlZW4gaXQuIE9ubHkgdGhlIHZhbHVlIGlzIHJlYWQgYmFjazogbmFtZXMgY29tZVxuLy8gICBmcm9tIHRoZSBvcHRpb24gbGlzdCwgc28gYSByZW5hbWVkIG9wdGlvbiBzaG93cyBpdHMgbmV3IG5hbWUuXG4vLyAtIEEgbnVtYmVyIHJhbmdlOiA8a2V5Pk1pbiBhbmQgPGtleT5NYXgsIGVpdGhlciBvbmUgb3Blbi5cbi8vIC0gQSBkYXRlIHJhbmdlOiA8a2V5PkZyb20gYW5kIDxrZXk+VG8gaW4gZnMtZmlsdGVyJ3MgZGF0ZSBmb3JtYXQgKHRoZVxuLy8gICBkYXkncyBsb2NhbCBtaWRuaWdodCB3aXRoIGl0cyBvZmZzZXQsIDIwMjYtMDEtMDFUMDA6MDA6MDAtMDU6MDApLCBlaXRoZXJcbi8vICAgb25lIG9wZW4uIE9ubHkgdGhlIGRheSBpcyByZWFkIGJhY2ssIHNvIGEgbGluayBvcGVucyBvbiB0aGUgc2FtZSBkYXlzIGluXG4vLyAgIGV2ZXJ5IHpvbmUuIEEgbGluayBuZXZlciBuYW1lcyBhIHByZXNldDogYSBkYXRlIHBpY2tlciBwcmVzZXQgb25seSBzZXRzXG4vLyAgIHRoZSBkYXlzLCBhbmQgYSByb2xsaW5nIHJhbmdlIChhIHJlcG9ydCdzIHJlbGF0aXZlIGRlZmF1bHQpIGlzIG5vdCB3cml0dGVuXG4vLyAgIHdoaWxlIGl0IGlzIHRoZSBsaW5rJ3MgYmFzZSwgYW5kIGlzIHdyaXR0ZW4gYXMgaXRzIGRheXMgd2hlbiBpdCBtdXN0IGJlXG4vLyAgICh0aGUgY2FsbGVyIHR1cm5zIGl0IGludG8gZGF5cyBmaXJzdDsgc2VlIGdyb3VwVmFsdWVQYXJhbXMpLlxuLy8gLSBBIGtleXdvcmQ6IDxrZXk+PXRleHQuXG4vLyBBbiBlbXB0eSB2YWx1ZSBpcyBhbiBleHBsaWNpdCBjbGVhciBvZiBhIGdyb3VwIHRoYXQgaGFzIGEgZGVmYXVsdDogPGtleT49XG4vLyBmb3IgYSBzZWxlY3Qgb3IgYSBrZXl3b3JkLCBib3RoIGVuZHMgZW1wdHkgZm9yIGEgcmFuZ2UuXG4vLyBUaGUgb3RoZXIga2V5czpcbi8vIC0gczxjb21wb25lbnRJZD46IGEgbGlzdCdzIHNvcnQgY29sdW1uLCAnLScgcHJlZml4ZWQgd2hlbiBkZXNjZW5kaW5nLlxuLy8gLSBxPGNvbXBvbmVudElkPjogdGhlIHRleHQgaW4gYSBsaXN0J3Mgc2VhcmNoIGJveC5cbi8vIC0gaDxjb21wb25lbnRJZD46IHRoZSBjb2x1bW5zIGEgdmlld2VyIGhpZCBvbiBhIGxpc3QgKGVuY29kZUNvbHVtbkxpc3QpLlxuLy8gLSBkPGNvbXBvbmVudElkPjogYSBjaGFydCdzIGRyaWxsIHBhdGgsICdsZXZlbDp2YWx1ZScgc3RlcHMgKGVhY2ggcGFydFxuLy8gICBwZXJjZW50LWVuY29kZWQpIGpvaW5lZCBieSAnLCcuXG4vLyAtIGdyb3VwQnk6IHRoZSBncm91cC1ieSBncmFpbiAoR1JPVVBfQllfSVRFTSkuXG4vLyAtIG1hdGNoPWFueTogdGhlIGdyb3VwcyBjb21iaW5lIHdpdGggYW55IChhYnNlbnQgPSBhbGwpLlxuLy8gLSBydjogdGhlIHNoYXJlZCB2aWV3IHRoZSBzdGF0ZSBpcyBhIGRpZmYgZnJvbS4gcnB2OiB0aGUgb3BlbiBwZXJzb25hbFxuLy8gICB2aWV3LCBhIGxhYmVsIG9ubHksIG5ldmVyIGEgYmFzZS5cbi8vIC0gcmY9MjogdGhlIGZvcm1hdCBldmVyeSBsaW5rIHRoaXMgdmlld2VyIHdyaXRlcyBjYXJyaWVzLlxuLy8gQSBrZXkgdGhpcyBjb2RlYyBkb2VzIG5vdCBrbm93IGlzIGlnbm9yZWQgYW5kIGxlZnQgaW4gdGhlIFVSTCBhcyBpdCBpcy5cbi8vIFRoZSBwYWdlIGtleSBpcyB0aGUgaG9zdCdzIChGc0FpUmVwb3J0Q29tcG9uZW50LnBhZ2VRdWVyeVBhcmFtKSBhbmQgaXNcbi8vIHdyaXR0ZW4gYmVzaWRlIHRoZXNlLCBuZXZlciBieSB0aGlzIGNvZGVjLiBUaGUgY3Jvc3MtZmlsdGVyIGFuZCB0aGUgcm93c1xuLy8gcGFuZWwgYXJlIG5ldmVyIGluIHRoZSBVUkwuXG4vL1xuLy8gVGhlIGtleXMgdGhlIGNvZGVjIG93bnM6IHRoZSB0aWxlIGtleXMsIGdyb3VwQnksIG1hdGNoLCBydiwgcnB2LCByZiwgYW5kXG4vLyBldmVyeSBrZXkgYSBncm91cCBvZiB0aGUgb3BlbiByZXBvcnQgaXMgd3JpdHRlbiB1bmRlci4gQSB3cml0ZSByZW1vdmVzIGFuXG4vLyBvd25lZCBrZXkgaXQgbm8gbG9uZ2VyIGNhcnJpZXMsIHNvIGEgaG9zdCBtdXN0IG5vdCBrZWVwIGl0cyBvd24gc3RhdGVcbi8vIHVuZGVyIG9uZS4gQSBncm91cCBrZXkgY29tZXMgZnJvbSBhIGxhYmVsLCBzbyBhIGhvc3QgcGFyYW0gbmFtZWQgbGlrZSBvbmVcbi8vIChhIGdyb3VwIGxhYmVsZWQgJ1N0YXR1cycgb3ducyBzdGF0dXMgYW5kIGV4Y2x1ZGVTdGF0dXMpIGlzIHRoZSBjb2RlYydzLlxuLy8gT25seSB0aGUgZGVmYXVsdCBwYWdlIGtleSwgJ3BhZ2UnLCBpcyBrZXB0IG9mZiB0aGUgZ3JvdXBzLlxuXG4vLyBUaGUga2V5cyBvZiB0aGUgdmlld3MgYW5kIHRoZSBmb3JtYXQuIERlY2xhcmVkIGJlc2lkZSB0aGUgZmlsdGVyIGl0ZW1zLFxuLy8gd2hpY2gga2VlcCBhIGdyb3VwIGtleSBvZmYgdGhlbSAoZGVjbGFyaW5nIHRoZW0gaGVyZSB3b3VsZCBtYWtlIHRoZSB0d29cbi8vIGZpbGVzIGltcG9ydCBlYWNoIG90aGVyKTsgcmUtZXhwb3J0ZWQgc28gZXZlcnkgY29kZWMgY29uc3RhbnQgY2FuIGJlXG4vLyBpbXBvcnRlZCBmcm9tIHRoZSBjb2RlYy5cbmV4cG9ydCB7IEZPUk1BVF9QQVJBTSwgUEVSU09OQUxfVklFV19QQVJBTSwgVklFV19QQVJBTSB9IGZyb20gJy4vcmVwb3J0LWZpbHRlci1pdGVtcyc7XG5cbi8vIFRoZSBwcmVmaXggb2YgYSBsaXN0J3Mgc29ydCBrZXkuXG5leHBvcnQgY29uc3QgTElTVF9TT1JUX1BBUkFNX1BSRUZJWCA9ICdzJztcblxuLy8gVGhlIHByZWZpeCBvZiBhIGxpc3QncyBzZWFyY2gga2V5LlxuZXhwb3J0IGNvbnN0IExJU1RfU0VBUkNIX1BBUkFNX1BSRUZJWCA9ICdxJztcblxuLy8gVGhlIHByZWZpeCBvZiBhIGxpc3QncyBoaWRkZW4tY29sdW1ucyBrZXkuXG5leHBvcnQgY29uc3QgTElTVF9ISURERU5fUEFSQU1fUFJFRklYID0gJ2gnO1xuXG4vLyBUaGUgcHJlZml4IG9mIGEgY2hhcnQncyBkcmlsbC1wYXRoIGtleS5cbmV4cG9ydCBjb25zdCBEUklMTF9QQVJBTV9QUkVGSVggPSAnZCc7XG5cbi8vIFRoZSBtYXRjaCdzIGtleTogdGhlIHJlcG9ydCBiYXIncyBNYXRjaCBpdGVtJ3Mgb3duIG5hbWUuXG5leHBvcnQgY29uc3QgTUFUQ0hfUEFSQU0gPSBNQVRDSF9JVEVNO1xuXG4vLyBUaGUgZm9ybWF0IGEgbGluayB0aGlzIHZpZXdlciB3cml0ZXMgY2Fycmllcy5cbmV4cG9ydCBjb25zdCBVUkxfRk9STUFUID0gMjtcblxuLy8gQmV0d2VlbiBhIGRyaWxsIHN0ZXAncyBsZXZlbCBhbmQgaXRzIHZhbHVlLlxuZXhwb3J0IGNvbnN0IERSSUxMX1NURVBfU0VQQVJBVE9SID0gJzonO1xuXG4vLyBCZXR3ZWVuIGEgc2VsZWN0J3MgcGlja3MsIGFuZCBiZXR3ZWVuIGEgcGljaydzIHZhbHVlIGFuZCBpdHMgbmFtZVxuLy8gKGZzLWZpbHRlcidzIEF1dG9Db21wbGV0ZUNoaXBzIHN5bnRheCkuXG5leHBvcnQgY29uc3QgUElDS19TRVBBUkFUT1IgPSAnLCc7XG5leHBvcnQgY29uc3QgUElDS19OQU1FX1NFUEFSQVRPUiA9ICc6JztcblxuLy8gQmVmb3JlIGEgJywnLCAnOicgb3IgJ1xcJyB0aGF0IGlzIHBhcnQgb2YgYSBwaWNrJ3MgdmFsdWUgb3IgbmFtZS5cbmNvbnN0IFBJQ0tfRVNDQVBFID0gJ1xcXFwnO1xuXG4vLyBUaGUgbW9zdCBjaGFyYWN0ZXJzIHRoZSBjb2RlYydzIHBhcmFtcyBtYXkgdGFrZSBpbiBhIGxpbmsgKHRoZSBob3N0J3Mgb3duXG4vLyBwYXRoIGFuZCBwYXJhbXMgYXJlIG5vdCBjb3VudGVkKS5cbmV4cG9ydCBjb25zdCBSRVBPUlRfVVJMX01BWF9MRU5HVEggPSAyMDAwO1xuXG4vLyBTaG93biBvbmNlIHdoZW4gYSBsaW5rIGxlZnQgZ3JvdXAgdmFsdWVzIG91dCAoUmVwb3J0VXJsV3JpdGUudG9vTG9uZykuXG5leHBvcnQgY29uc3QgVVJMX1RPT19MT05HX01FU1NBR0UgPSAnVGhpcyBmaWx0ZXIgaXMgdG9vIGxvbmcgZm9yIGEgbGluazsgc2F2ZSBhIHZpZXcgdG8gc2hhcmUgaXQuJztcblxuY29uc3QgTUFUQ0hfQU5ZOiBSZXBvcnRGaWx0ZXJNYXRjaCA9ICdhbnknO1xuXG4vLyBUaGUgcHJlZml4ZXMgb2YgdGhlIHRpbGUga2V5cyB0aGlzIGNvZGVjIG93bnMsIGVhY2ggZm9sbG93ZWQgYnkgYW4gaWQuXG5jb25zdCBPV05FRF9QUkVGSVhFUyA9IFtMSVNUX1NPUlRfUEFSQU1fUFJFRklYLCBMSVNUX1NFQVJDSF9QQVJBTV9QUkVGSVgsIExJU1RfSElEREVOX1BBUkFNX1BSRUZJWCwgRFJJTExfUEFSQU1fUFJFRklYXTtcblxuLy8gVGhlIGtleXMgdGhpcyBjb2RlYyBvd25zIHRoYXQgY2Fycnkgbm8gaWQgYW5kIGRvIG5vdCBkZXBlbmQgb24gdGhlIHJlcG9ydC5cbmNvbnN0IE9XTkVEX0tFWVMgPSBbR1JPVVBfQllfSVRFTSwgTUFUQ0hfUEFSQU0sIFZJRVdfUEFSQU0sIFBFUlNPTkFMX1ZJRVdfUEFSQU0sIEZPUk1BVF9QQVJBTV07XG5cbi8vIEEga2V5IG9mIG9uZSBvZiB0aGUgcHJlZml4ZXMgYWJvdmUsIGZvbGxvd2VkIGJ5IGl0cyBpZC5cbmNvbnN0IElEX1BBUkFNID0gbmV3IFJlZ0V4cChgXihbJHtPV05FRF9QUkVGSVhFUy5qb2luKCcnKX1dKShcXFxcZCspJGApO1xuXG4vLyBBIGtleSB0aGlzIGNvZGVjIG93bnMgd2hhdGV2ZXIgdGhlIHJlcG9ydDogYSBsaXN0J3Mgc29ydCwgc2VhcmNoIG9yIGhpZGRlblxuLy8gY29sdW1uczsgYSBjaGFydCdzIGRyaWxsIHBhdGg7IHRoZSBncmFpbiwgdGhlIG1hdGNoLCB0aGUgdHdvIHZpZXdzIGFuZCB0aGVcbi8vIGZvcm1hdC4gVGhlIGdyb3Vwcycga2V5cyBhcmUgb3duZWQgdG9vIChzZWUgdGhlIHRvcCBvZiB0aGlzIGZpbGUpLlxuZXhwb3J0IGNvbnN0IE9XTkVEX1BBUkFNID0gbmV3IFJlZ0V4cChgXig/Olske09XTkVEX1BSRUZJWEVTLmpvaW4oJycpfV1cXFxcZCt8JHtPV05FRF9LRVlTLmpvaW4oJ3wnKX0pJGApO1xuXG4vLyBBIGxpbmsncyBkYXk6ICd5eXl5LU1NLWRkJywgYWxvbmUgb3IgYXMgdGhlIHN0YXJ0IG9mIGZzLWZpbHRlcidzIGRhdGVcbi8vIGZvcm1hdCAoJ1QnIGFuZCBhIHRpbWUgYW5kIG9mZnNldCBhZnRlciBpdCkuXG5jb25zdCBMSU5LX0RBWSA9IC9eKFxcZHs0fS1cXGR7Mn0tXFxkezJ9KSg/OlQuKik/JC87XG5cbnR5cGUgVXJsR3JvdXAgPSBQaWNrPFJlcG9ydEZpbHRlckdyb3VwLCAnaWQnIHwgJ3R5cGUnIHwgJ2xhYmVsJyB8ICdmaWx0ZXJzJz47XG5cbi8vIFRoZSB2aWV3ZXItc3RhdGUgcGFyYW1zIG9mIGEgVVJMOiB0aGUgZ3JvdXBzJyB2YWx1ZXMgaW4gdGhlaXIgc3RvcmVkIHNoYXBlXG4vLyAobnVsbCBmb3IgYSBncm91cCB0aGUgbGluayBjbGVhcnM7IHJlYWQgYXMgcGFyYW1zVG9WaWV3Q29uZmlnIHJlYWRzIHRoZW0pLFxuLy8gdGhlIHJlc3QgYXMgcmF3IHN0cmluZ3MuIEtleXMgdGhpcyBjb2RlYyBkb2VzIG5vdCBvd24gYXJlIGlnbm9yZWQuXG4vLyBgZ3JvdXBzYCBpcyBldmVyeSBmaWx0ZXIgZ3JvdXAgb2YgdGhlIHJlcG9ydC5cbmV4cG9ydCBmdW5jdGlvbiByZWFkUmVwb3J0VXJsUGFyYW1zKHBhcmFtczogUGFyYW1NYXAsIGdyb3VwczogcmVhZG9ubHkgVXJsR3JvdXBbXSk6IFJlcG9ydFVybFBhcmFtcyB7XG4gIGNvbnN0IGxpc3RTb3J0cyA9IG5ldyBNYXA8bnVtYmVyLCBzdHJpbmc+KCk7XG4gIGNvbnN0IGxpc3RTZWFyY2hlcyA9IG5ldyBNYXA8bnVtYmVyLCBzdHJpbmc+KCk7XG4gIGNvbnN0IGxpc3RIaWRkZW4gPSBuZXcgTWFwPG51bWJlciwgc3RyaW5nPigpO1xuICAvLyBFYWNoIHByZWZpeCByZWFkIGhlcmUgbmFtZXMgdGhlIG1hcCBpdHMga2V5cyBnbyB0bzsgYSBwcmVmaXggd2l0aCBub1xuICAvLyBlbnRyeSBpcyBuZXZlciByZWFkIGFzIHNvbWUgb3RoZXIga2luZCBvZiBzdGF0ZS5cbiAgY29uc3QgYnlQcmVmaXg6IFJlY29yZDxzdHJpbmcsIE1hcDxudW1iZXIsIHN0cmluZz4+ID0ge1xuICAgIFtMSVNUX1NPUlRfUEFSQU1fUFJFRklYXTogbGlzdFNvcnRzLFxuICAgIFtMSVNUX1NFQVJDSF9QQVJBTV9QUkVGSVhdOiBsaXN0U2VhcmNoZXMsXG4gICAgW0xJU1RfSElEREVOX1BBUkFNX1BSRUZJWF06IGxpc3RIaWRkZW4sXG4gIH07XG4gIGNvbnN0IHF1ZXJ5OiBQYXJhbXMgPSB7fTtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBwYXJhbXMua2V5cykge1xuICAgIHF1ZXJ5W2tleV0gPSBwYXJhbXMuZ2V0KGtleSkgPz8gJyc7XG4gICAgY29uc3Qgb3duZWQgPSBJRF9QQVJBTS5leGVjKGtleSk7XG4gICAgaWYgKG93bmVkKSB7XG4gICAgICBieVByZWZpeFtvd25lZFsxXV0/LnNldChOdW1iZXIob3duZWRbMl0pLCBwYXJhbXMuZ2V0KGtleSkgPz8gJycpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZ3JvdXBzOiByZWFkR3JvdXBQYXJhbXMocXVlcnksIGdyb3VwcyksXG4gICAgbGlzdFNvcnRzLCBsaXN0U2VhcmNoZXMsIGxpc3RIaWRkZW4sXG4gICAgZ3JvdXBCeTogcGFyYW1zLmdldChHUk9VUF9CWV9JVEVNKSxcbiAgfTtcbn1cblxuLy8gVGhlIHZpZXdlciBzdGF0ZSBhIGxpbmsgY2FycmllcywgYXMgYSB2aWV3IGNvbmZpZzogaXRzIGdyb3VwIHZhbHVlcyAocmVhZFxuLy8gYnkgZWFjaCBncm91cCdzIHR5cGUsIHNvIGEgZ3JvdXAgdGhlIHJlcG9ydCBkb2VzIG5vdCBoYXZlIGlzIHNraXBwZWQpLCB0aGVcbi8vIGdyYWluLCB0aGUgbWF0Y2ggYW5kIGVhY2ggdGlsZSdzIHNvcnQsIHNlYXJjaCwgaGlkZGVuIGNvbHVtbnMgYW5kIGRyaWxsXG4vLyBwYXRoLiBBIHBhcmFtIHRoYXQgaXMgdW51c2FibGUgaXMgbGVmdCBvdXQuIFdoZXRoZXIgYSB0aWxlJ3MgY29tcG9uZW50IGFuZFxuLy8gYSBsaXN0J3MgY29sdW1ucyBleGlzdCBpcyB0aGUgY2FsbGVyJ3MgY2hlY2suIGBncm91cHNgIGlzIGV2ZXJ5IGZpbHRlclxuLy8gZ3JvdXAgb2YgdGhlIHJlcG9ydC5cbmV4cG9ydCBmdW5jdGlvbiBwYXJhbXNUb1ZpZXdDb25maWcocGFyYW1zOiBQYXJhbXMsIGdyb3VwczogcmVhZG9ubHkgVXJsR3JvdXBbXSk6IFJlcG9ydFZpZXdDb25maWcge1xuICBjb25zdCBjb25maWc6IFJlcG9ydFZpZXdDb25maWcgPSB7IHY6IFJFUE9SVF9WSUVXX0NPTkZJR19WRVJTSU9OIH07XG5cbiAgY29uc3QgZ3JvdXBCeSA9IHBhcmFtVGV4dChwYXJhbXNbR1JPVVBfQllfSVRFTV0pO1xuICBpZiAoaXNDaGFydEdyYW51bGFyaXR5KGdyb3VwQnkpKSB7XG4gICAgY29uZmlnLmdyb3VwQnkgPSBncm91cEJ5O1xuICB9XG5cbiAgaWYgKHBhcmFtVGV4dChwYXJhbXNbTUFUQ0hfUEFSQU1dKSA9PT0gTUFUQ0hfQU5ZKSB7XG4gICAgY29uZmlnLm1hdGNoID0gTUFUQ0hfQU5ZO1xuICB9XG5cbiAgcmVhZEdyb3VwUGFyYW1zKHBhcmFtcywgZ3JvdXBzKS5mb3JFYWNoKCh2YWx1ZSwgZ3JvdXBJZCkgPT4ge1xuICAgIGNvbmZpZy5ncm91cHMgPSB7IC4uLmNvbmZpZy5ncm91cHMsIFtncm91cElkXTogdmFsdWUgfTtcbiAgfSk7XG5cbiAgT2JqZWN0LmtleXMocGFyYW1zKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICBjb25zdCBvd25lZCA9IElEX1BBUkFNLmV4ZWMoa2V5KTtcbiAgICBjb25zdCByYXcgPSBwYXJhbVRleHQocGFyYW1zW2tleV0pO1xuXG4gICAgaWYgKG93bmVkICYmIHJhdyAhPT0gbnVsbCkge1xuICAgICAgcmVhZFRpbGVQYXJhbShjb25maWcsIG93bmVkWzFdLCBOdW1iZXIob3duZWRbMl0pLCByYXcpO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGNvbmZpZztcbn1cblxuLy8gVGhlIHBhcmFtcyB0aGF0IG1ha2UgYSBsaW5rIGNhcnJ5IGBjb25maWdgLCB0aGUgdmlld3MgaXQgbmFtZXMsIGFuZCByZj0yLlxuLy8gRWFjaCBncm91cCBpcyB3cml0dGVuIHVuZGVyIGl0cyBrZXlzIGFtb25nIGBncm91cHNgIChldmVyeSBmaWx0ZXIgZ3JvdXAgb2Zcbi8vIHRoZSByZXBvcnQpOyBhIGdyb3VwIHRoZSByZXBvcnQgbm8gbG9uZ2VyIGhhcyBpcyBsZWZ0IG91dC4gYG5hbWVgIG5hbWVzIGFcbi8vIHNlbGVjdCdzIHZhbHVlcy4gUGFzdCBSRVBPUlRfVVJMX01BWF9MRU5HVEggdGhlIGxvbmdlc3QgZ3JvdXAgdmFsdWVzIGFyZVxuLy8gbGVmdCBvdXQgKHRob3NlIGdyb3VwcyB0aGVuIG9wZW4gYXQgdGhlIGxpbmsncyBiYXNlKSBhbmQgdG9vTG9uZyBpcyBzZXQuXG5leHBvcnQgZnVuY3Rpb24gdmlld0NvbmZpZ1RvUGFyYW1zKFxuICBjb25maWc6IFJlcG9ydFZpZXdDb25maWcsXG4gIGdyb3VwczogcmVhZG9ubHkgVXJsR3JvdXBbXSxcbiAgbGluazogUmVwb3J0VXJsTGluayA9IHt9LFxuICBuYW1lOiBSZXBvcnRVcmxWYWx1ZU5hbWUgPSAoKSA9PiBudWxsLFxuKTogUmVwb3J0VXJsV3JpdGUge1xuICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgY29uc3Qga2V5cyA9IGdyb3VwUGFyYW1LZXlzKGdyb3Vwcyk7XG4gIGNvbnN0IHR5cGVzID0gbmV3IE1hcChncm91cHMubWFwKChncm91cCkgPT4gW2dyb3VwLmlkLCBncm91cC50eXBlXSkpO1xuICBjb25zdCBncm91cFBhcmFtcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIGlmIChjb25maWcuZ3JvdXBCeSkge1xuICAgIHBhcmFtc1tHUk9VUF9CWV9JVEVNXSA9IGNvbmZpZy5ncm91cEJ5O1xuICB9XG5cbiAgT2JqZWN0LmVudHJpZXMoY29uZmlnLmdyb3VwcyA/PyB7fSkuZm9yRWFjaCgoW2lkLCB2YWx1ZV0pID0+IHtcbiAgICBjb25zdCBncm91cElkID0gTnVtYmVyKGlkKTtcbiAgICBjb25zdCBrZXkgPSBrZXlzLmdldChncm91cElkKTtcbiAgICBpZiAoa2V5KSB7XG4gICAgICBjb25zdCB3cml0dGVuID0gZ3JvdXBWYWx1ZVBhcmFtcyh0eXBlcy5nZXQoZ3JvdXBJZCksIGtleSwgdmFsdWUsIChwaWNrKSA9PiBuYW1lKGdyb3VwSWQsIHBpY2spKTtcbiAgICAgIE9iamVjdC5hc3NpZ24ocGFyYW1zLCB3cml0dGVuKTtcbiAgICAgIE9iamVjdC5rZXlzKHdyaXR0ZW4pLmZvckVhY2goKHBhcmFtKSA9PiBncm91cFBhcmFtcy5hZGQocGFyYW0pKTtcbiAgICB9XG4gIH0pO1xuXG4gIE9iamVjdC5lbnRyaWVzKGNvbmZpZy50aWxlcyA/PyB7fSkuZm9yRWFjaCgoW2NvbXBvbmVudElkLCB0aWxlXSkgPT4ge1xuICAgIE9iamVjdC5hc3NpZ24ocGFyYW1zLCB0aWxlUGFyYW1zKE51bWJlcihjb21wb25lbnRJZCksIHRpbGUpKTtcbiAgfSk7XG5cbiAgaWYgKGNvbmZpZy5tYXRjaCA9PT0gTUFUQ0hfQU5ZKSB7XG4gICAgcGFyYW1zW01BVENIX1BBUkFNXSA9IE1BVENIX0FOWTtcbiAgfVxuXG4gIGlmIChsaW5rLnZpZXdJZCkge1xuICAgIHBhcmFtc1tWSUVXX1BBUkFNXSA9IFN0cmluZyhsaW5rLnZpZXdJZCk7XG4gIH1cblxuICBpZiAobGluay5wZXJzb25hbFZpZXdJZCkge1xuICAgIHBhcmFtc1tQRVJTT05BTF9WSUVXX1BBUkFNXSA9IFN0cmluZyhsaW5rLnBlcnNvbmFsVmlld0lkKTtcbiAgfVxuXG4gIHJldHVybiBjYXBSZXBvcnRQYXJhbXMod2l0aEZvcm1hdChwYXJhbXMpLCBncm91cFBhcmFtcyk7XG59XG5cbi8vIFRoZSB2aWV3cyBhIGxpbmsgbmFtZXMsIGVhY2ggYSBwb3NpdGl2ZSBpZCBvciBudWxsLlxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRSZXBvcnRVcmxMaW5rKHBhcmFtczogUGFyYW1zKTogUmVwb3J0VXJsTGluayB7XG4gIHJldHVybiB7XG4gICAgdmlld0lkOiBwb3NpdGl2ZUlkKHBhcmFtVGV4dChwYXJhbXNbVklFV19QQVJBTV0pKSxcbiAgICBwZXJzb25hbFZpZXdJZDogcG9zaXRpdmVJZChwYXJhbVRleHQocGFyYW1zW1BFUlNPTkFMX1ZJRVdfUEFSQU1dKSksXG4gIH07XG59XG5cbi8vIFdoZXRoZXIgYSBsaW5rIGNhcnJpZXMgdmlld2VyIHN0YXRlIG9mIGl0cyBvd24sIHNvIGl0IG9wZW5zIG9uIHRoYXQgc3RhdGVcbi8vIHJhdGhlciB0aGFuIG9uIGEgZGVmYXVsdCB2aWV3OiBhbnkgb3duZWQga2V5IGJ1dCB0aGUgZm9ybWF0IG1hcmtlciBhbmQgdGhlXG4vLyBwZXJzb25hbCB2aWV3LCB3aGljaCBpcyBhIGxhYmVsIG9ubHkuIGBncm91cHNgIGlzIGV2ZXJ5IGZpbHRlciBncm91cCBvZlxuLy8gdGhlIHJlcG9ydC5cbmV4cG9ydCBmdW5jdGlvbiBoYXNSZXBvcnRVcmxTdGF0ZShwYXJhbXM6IFBhcmFtcywgZ3JvdXBzOiByZWFkb25seSBVcmxHcm91cFtdKTogYm9vbGVhbiB7XG4gIGNvbnN0IGdyb3VwS2V5cyA9IG93bmVkR3JvdXBLZXlzKGdyb3Vwcyk7XG5cbiAgcmV0dXJuIE9iamVjdC5rZXlzKHBhcmFtcykuc29tZSgoa2V5KSA9PiBJRF9QQVJBTS50ZXN0KGtleSkgfHwgZ3JvdXBLZXlzLmhhcyhrZXkpXG4gICAgfHwga2V5ID09PSBHUk9VUF9CWV9JVEVNIHx8IGtleSA9PT0gTUFUQ0hfUEFSQU0gfHwga2V5ID09PSBWSUVXX1BBUkFNKTtcbn1cblxuLy8gRXZlcnkgb3duZWQga2V5IGBjdXJyZW50YCBjYXJyaWVzLCBzZXQgdG8gbnVsbDogdW5kZXIgdGhlIHJvdXRlcidzICdtZXJnZSdcbi8vIGhhbmRsaW5nLCBhIHdyaXRlIHNwcmVhZCBvdmVyIHRoZXNlIHJlbW92ZXMgdGhlIGtleXMgaXQgbm8gbG9uZ2VyIGNhcnJpZXMuXG4vLyBLZXlzIHRoaXMgY29kZWMgZG9lcyBub3Qgb3duIGFyZSBsZWZ0IGFsb25lLiBgZ3JvdXBzYCBpcyBldmVyeSBmaWx0ZXJcbi8vIGdyb3VwIG9mIHRoZSByZXBvcnQuXG5leHBvcnQgZnVuY3Rpb24gcmVwb3J0UGFyYW1zVG9DbGVhcihjdXJyZW50OiBQYXJhbU1hcCwgZ3JvdXBzOiByZWFkb25seSBVcmxHcm91cFtdKTogUGFyYW1zIHtcbiAgY29uc3QgZ3JvdXBLZXlzID0gb3duZWRHcm91cEtleXMoZ3JvdXBzKTtcbiAgY29uc3QgcGFyYW1zOiBQYXJhbXMgPSB7fTtcblxuICBmb3IgKGNvbnN0IGtleSBvZiBjdXJyZW50LmtleXMpIHtcbiAgICBpZiAoT1dORURfUEFSQU0udGVzdChrZXkpIHx8IGdyb3VwS2V5cy5oYXMoa2V5KSkge1xuICAgICAgcGFyYW1zW2tleV0gPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwYXJhbXM7XG59XG5cbi8vIFRoZSBuYW1lcyB0aGUgc2VsZWN0IHBpY2tzIGluIGBjdXJyZW50YCAodGhlIFVSTCBhcyBpdCBpcykgY2FycnksIHNvIGFcbi8vIHdyaXRlIGNhbiBrZWVwIGEgbmFtZSB0aGUgdmlld2VyJ3MgbGlzdHMgaGF2ZSBub3QgbmFtZWQgeWV0LiBPbmx5IGEgd3JpdGVcbi8vIHJlYWRzIHRoZXNlOiB3aGF0IHRoZSBjaGlwcyBzaG93IGNvbWVzIGZyb20gdGhlIGxpc3RzLlxuZXhwb3J0IGZ1bmN0aW9uIHVybFZhbHVlTmFtZXMoY3VycmVudDogUGFyYW1NYXAsIGdyb3VwczogcmVhZG9ubHkgVXJsR3JvdXBbXSk6IFJlcG9ydFVybFZhbHVlTmFtZSB7XG4gIGNvbnN0IGtleXMgPSBncm91cFBhcmFtS2V5cyhncm91cHMpO1xuICBjb25zdCBuYW1lcyA9IG5ldyBNYXA8bnVtYmVyLCBNYXA8c3RyaW5nLCBzdHJpbmc+PigpO1xuXG4gIGdyb3Vwc1xuICAgIC5maWx0ZXIoKGdyb3VwKSA9PiBncm91cC50eXBlID09PSAnc2VsZWN0JylcbiAgICAuZm9yRWFjaCgoZ3JvdXApID0+IHtcbiAgICAgIGNvbnN0IGtleSA9IGtleXMuZ2V0KGdyb3VwLmlkKTtcbiAgICAgIGNvbnN0IHBpY2tzID0gW2N1cnJlbnQuZ2V0KGtleSksIGN1cnJlbnQuZ2V0KGdldEV4Y2x1ZGVOYW1lKGtleSkpXVxuICAgICAgICAuZmxhdE1hcCgocmF3KSA9PiAocmF3ID8gZGVjb2RlUGlja0xpc3QocmF3KSA6IFtdKSlcbiAgICAgICAgLmZpbHRlcigocGljaykgPT4gcGljay5uYW1lICE9PSBudWxsKTtcblxuICAgICAgbmFtZXMuc2V0KGdyb3VwLmlkLCBuZXcgTWFwKHBpY2tzLm1hcCgocGljaykgPT4gW3BpY2sudmFsdWUsIHBpY2submFtZV0pKSk7XG4gICAgfSk7XG5cbiAgcmV0dXJuIChncm91cElkLCB2YWx1ZSkgPT4gbmFtZXMuZ2V0KGdyb3VwSWQpPy5nZXQoU3RyaW5nKHZhbHVlKSkgPz8gbnVsbDtcbn1cblxuLy8gQSBsaXN0J3MgaGlkZGVuIGNvbHVtbiBuYW1lcyBhcyBvbmUgcGFyYW0gdmFsdWUuIEEgbmFtZSBpcyBhIHF1ZXJ5J3Mgb3V0cHV0XG4vLyBhbGlhcywgd2hpY2ggY2FuIGhvbGQgYSBjb21tYSwgc28gZWFjaCBpcyBwZXJjZW50LWVuY29kZWQgYmVmb3JlIHRoZSBqb2luLlxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZUNvbHVtbkxpc3QobmFtZXM6IHJlYWRvbmx5IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5hbWVzLm1hcCgobmFtZSkgPT4gZW5jb2RlVVJJQ29tcG9uZW50KG5hbWUpKS5qb2luKCcsJyk7XG59XG5cbi8vIFRoZSBjb2x1bW4gbmFtZXMgb2YgYSBoaWRkZW4tY29sdW1ucyBwYXJhbSwgaW4gaXRzIG9yZGVyLiBFbXB0eSBpdGVtcyBhcmVcbi8vIGRyb3BwZWQsIGFuZCBhbiBpdGVtIHRoYXQgZG9lcyBub3QgZGVjb2RlIChhIGhhbmQtZWRpdGVkICclJykgaXMga2VwdCBhc1xuLy8gd3JpdHRlbi4gV2hldGhlciBhIG5hbWUgaXMgYSBjb2x1bW4gb2YgdGhlIGxpc3QgaXMgdGhlIGNhbGxlcidzIGNoZWNrLlxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZUNvbHVtbkxpc3QocmF3OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiByYXcuc3BsaXQoJywnKVxuICAgIC5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0gIT09ICcnKVxuICAgIC5tYXAoZGVjb2RlSXRlbSk7XG59XG5cbi8vIEEgZ3JvdXAncyB2YWx1ZSBpbiBpdHMgc3RvcmVkIHNoYXBlIGFzIHRoZSBsaW5rJ3MgcGFyYW1zIHVuZGVyIHRoZSBncm91cCdzXG4vLyBrZXkgKHNlZSB0aGUgdG9wIG9mIHRoaXMgZmlsZSk6IGRheXMsIHRoZW4gYSBzZWxlY3QncyB2YWx1ZXMgbGVmdCBvdXQsIHRoZW5cbi8vIGl0cyB2YWx1ZXMga2VwdCwgdGhlbiBhIG51bWJlciByYW5nZSwgdGhlbiBrZXl3b3JkIHRleHQuIG51bGwgKGEgY2xlYXJlZFxuLy8gZ3JvdXApLCBvciBhIHZhbHVlIHRoYXQgaG9sZHMgbm90aGluZywgaXMgdGhlIGdyb3VwJ3Mga2V5cywgZW1wdHkuIEFcbi8vIHJlbGF0aXZlIHJhbmdlIHdpdGggbm8gZGF5cyBpcyBub3Qgd3JpdHRlbiBhdCBhbGw6IGEgbGluayBjYXJyaWVzIGRheXMsIGFuZFxuLy8gb25seSB0aGUgY2FsbGVyIGhhcyB0aGUgcmVwb3J0J3Mgem9uZSBhbmQgY2xvY2sgdG8gZ2l2ZSB0aGVtXG4vLyAoUmVwb3J0Vmlld1NlcnZpY2UpLiBgbmFtZWAgbmFtZXMgYSBzZWxlY3QncyB2YWx1ZS5cbmV4cG9ydCBmdW5jdGlvbiBncm91cFZhbHVlUGFyYW1zKFxuICB0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlIHwgdW5kZWZpbmVkLFxuICBrZXk6IHN0cmluZyxcbiAgdmFsdWU6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwsXG4gIG5hbWU6ICh2YWx1ZTogdW5rbm93bikgPT4gc3RyaW5nIHwgbnVsbCA9ICgpID0+IG51bGwsXG4pOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgaWYgKCF2YWx1ZSkge1xuICAgIHJldHVybiBjbGVhclBhcmFtcyh0eXBlLCBrZXkpO1xuICB9XG5cbiAgaWYgKHZhbHVlLnN0YXJ0IHx8IHZhbHVlLmVuZCkge1xuICAgIHJldHVybiByYW5nZVBhcmFtcyh0eXBlLCBrZXksIFsnZnJvbScsICd0byddLCBbbGlua0RheVRleHQodmFsdWUuc3RhcnQpLCBsaW5rRGF5VGV4dCh2YWx1ZS5lbmQpXSk7XG4gIH1cblxuICBpZiAodmFsdWUuZXhjbHVkZVZhbHVlcz8ubGVuZ3RoKSB7XG4gICAgcmV0dXJuIHsgW2dldEV4Y2x1ZGVOYW1lKGtleSldOiBlbmNvZGVQaWNrcyh2YWx1ZS5leGNsdWRlVmFsdWVzLCBuYW1lKSB9O1xuICB9XG5cbiAgaWYgKHZhbHVlLnZhbHVlcykge1xuICAgIHJldHVybiB7IFtrZXldOiBlbmNvZGVQaWNrcyh2YWx1ZS52YWx1ZXMsIG5hbWUpIH07XG4gIH1cblxuICBpZiAoaXNOdW1iZXJFbmQodmFsdWUubWluKSB8fCBpc051bWJlckVuZCh2YWx1ZS5tYXgpKSB7XG4gICAgcmV0dXJuIHJhbmdlUGFyYW1zKHR5cGUsIGtleSwgWydtaW4nLCAnbWF4J10sIFtudW1iZXJFbmRUZXh0KHZhbHVlLm1pbiksIG51bWJlckVuZFRleHQodmFsdWUubWF4KV0pO1xuICB9XG5cbiAgaWYgKHZhbHVlLnJlbGF0aXZlKSB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG5cbiAgcmV0dXJuIHZhbHVlLnZhbHVlID8geyBba2V5XTogdmFsdWUudmFsdWUgfSA6IGNsZWFyUGFyYW1zKHR5cGUsIGtleSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVTb3J0KHNvcnQ6IFJlcG9ydFNvcnQpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7c29ydC5kaXJlY3Rpb24gPT09ICdkZXNjJyA/ICctJyA6ICcnfSR7c29ydC5jb2x1bW59YDtcbn1cblxuLy8gQSBsaXN0IHNvcnQgcmVhZCBiYWNrIGZyb20gaXRzIFVSTCBwYXJhbSwgb3IgbnVsbCB3aGVuIGl0IG5hbWVzIG5vIGNvbHVtbi5cbi8vIFdoZXRoZXIgdGhlIGNvbHVtbiBpcyBvbmUgdGhlIGxpc3QgY2FuIHNvcnQgYnkgaXMgdGhlIGNhbGxlcidzIGNoZWNrLlxuZXhwb3J0IGZ1bmN0aW9uIGRlY29kZVNvcnQocmF3OiBzdHJpbmcpOiBSZXBvcnRTb3J0IHwgbnVsbCB7XG4gIGNvbnN0IGRlc2NlbmRpbmcgPSByYXcuc3RhcnRzV2l0aCgnLScpO1xuICBjb25zdCBjb2x1bW4gPSBkZXNjZW5kaW5nID8gcmF3LnNsaWNlKDEpIDogcmF3O1xuXG4gIHJldHVybiBjb2x1bW5cbiAgICA/IHsgY29sdW1uLCBkaXJlY3Rpb246IGRlc2NlbmRpbmcgPyAnZGVzYycgOiAnYXNjJyB9XG4gICAgOiBudWxsO1xufVxuXG4vLyBBIGRyaWxsIHBhdGggYXMgaXRzIFVSTCBwYXJhbS4gQSBzdGVwIHdpdGggbm8gdmFsdWUgd3JpdGVzIGl0cyBsZXZlbCBvbmx5LlxuZXhwb3J0IGZ1bmN0aW9uIGVuY29kZURyaWxsUGF0aChwYXRoOiByZWFkb25seSBSZXBvcnREcmlsbFN0ZXBbXSk6IHN0cmluZyB7XG4gIHJldHVybiBwYXRoXG4gICAgLm1hcCgoc3RlcCkgPT4gKHN0ZXAudmFsdWUgPT09IG51bGwgfHwgc3RlcC52YWx1ZSA9PT0gdW5kZWZpbmVkXG4gICAgICA/IGVuY29kZVVSSUNvbXBvbmVudChzdGVwLmxldmVsKVxuICAgICAgOiBgJHtlbmNvZGVVUklDb21wb25lbnQoc3RlcC5sZXZlbCl9JHtEUklMTF9TVEVQX1NFUEFSQVRPUn0ke2VuY29kZVVSSUNvbXBvbmVudChTdHJpbmcoc3RlcC52YWx1ZSkpfWApKVxuICAgIC5qb2luKCcsJyk7XG59XG5cbi8vIEEgZHJpbGwgcGF0aCByZWFkIGJhY2sgZnJvbSBpdHMgVVJMIHBhcmFtOiBpdHMgc3RlcHMgdXAgdG8gdGhlIGZpcnN0IHRoYXRcbi8vIGlzIG5vdCBhIHRpbWUgbGV2ZWwgKHRoZSBzdGVwcyBiZWZvcmUgaXQgYXJlIGtlcHQpLCBhdCBtb3N0IERSSUxMX01BWF9ERVBUSFxuLy8gb2YgdGhlbS4gVmFsdWVzIGNvbWUgYmFjayBhcyB0ZXh0LiBXaGV0aGVyIHRoZSBwYXRoIGZpdHMgdGhlIGNoYXJ0IGlzIHRoZVxuLy8gc2VydmVyJ3MgY2hlY2sgKGl0IGFwcGxpZXMgdGhlIGxvbmdlc3QgdmFsaWQgcHJlZml4KS5cbmV4cG9ydCBmdW5jdGlvbiBkZWNvZGVEcmlsbFBhdGgocmF3OiBzdHJpbmcpOiBSZXBvcnREcmlsbFN0ZXBbXSB7XG4gIGNvbnN0IHBhdGg6IFJlcG9ydERyaWxsU3RlcFtdID0gW107XG5cbiAgZm9yIChjb25zdCBpdGVtIG9mIHJhdy5zcGxpdCgnLCcpKSB7XG4gICAgY29uc3Qgc3RlcCA9IGRlY29kZURyaWxsU3RlcChpdGVtKTtcbiAgICBpZiAoIXN0ZXAgfHwgcGF0aC5sZW5ndGggPT09IERSSUxMX01BWF9ERVBUSCkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcGF0aC5wdXNoKHN0ZXApO1xuICB9XG5cbiAgcmV0dXJuIHBhdGg7XG59XG5cbi8vIFRoZSBxdWVyeSBwYXJhbXMgdGhhdCBtYWtlIHRoZSBVUkwgY2FycnkgYHNuYXBzaG90YDogZXZlcnkgc25hcHNob3Qga2V5IGlzXG4vLyBzZXQsIGFuZCBlYWNoIG93bmVkIGtleSB0aGF0IGBjdXJyZW50YCBjYXJyaWVzIGJ1dCB0aGUgc25hcHNob3QgZG9lcyBub3QgaXNcbi8vIHNldCB0byBudWxsLCB3aGljaCByZW1vdmVzIGl0IHVuZGVyIHRoZSByb3V0ZXIncyAnbWVyZ2UnIGhhbmRsaW5nLiBLZXlzXG4vLyB0aGlzIGNvZGVjIGRvZXMgbm90IG93biBhcmUgbGVmdCBhbG9uZS4gRWFjaCBncm91cCBpcyB3cml0dGVuIHVuZGVyIGl0c1xuLy8ga2V5cyBhbW9uZyBgZ3JvdXBzYCAoZXZlcnkgZmlsdGVyIGdyb3VwIG9mIHRoZSByZXBvcnQpLiBBIHNlbGVjdCdzIHZhbHVlXG4vLyBpcyBuYW1lZCBieSBgbmFtZWAsIGVsc2UgYnkgdGhlIG5hbWUgYGN1cnJlbnRgIGNhcnJpZXMgZm9yIGl0LiBBIGRhdGUgcmFuZ2Vcbi8vIGlzIHdyaXR0ZW4gYXMgdGhlIGRheXMgb24gc2NyZWVuLCBuZXZlciBhcyBhIHByZXNldCBuYW1lLlxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUmVwb3J0VXJsUGFyYW1zKFxuICBzbmFwc2hvdDogUmVwb3J0VXJsU25hcHNob3QsXG4gIGN1cnJlbnQ6IFBhcmFtTWFwLFxuICBncm91cHM6IHJlYWRvbmx5IFVybEdyb3VwW10sXG4gIG5hbWU6IFJlcG9ydFVybFZhbHVlTmFtZSA9ICgpID0+IG51bGwsXG4pOiBQYXJhbXMge1xuICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgY29uc3Qga2V5cyA9IGdyb3VwUGFyYW1LZXlzKGdyb3Vwcyk7XG4gIGNvbnN0IHR5cGVzID0gbmV3IE1hcChncm91cHMubWFwKChncm91cCkgPT4gW2dyb3VwLmlkLCBncm91cC50eXBlXSkpO1xuICBjb25zdCBjdXJyZW50TmFtZSA9IHVybFZhbHVlTmFtZXMoY3VycmVudCwgZ3JvdXBzKTtcblxuICBzbmFwc2hvdC5ncm91cHMuZm9yRWFjaCgodmFsdWUsIGdyb3VwSWQpID0+IHtcbiAgICBjb25zdCBrZXkgPSBrZXlzLmdldChncm91cElkKTtcbiAgICBpZiAoa2V5KSB7XG4gICAgICBjb25zdCB0eXBlID0gdHlwZXMuZ2V0KGdyb3VwSWQpO1xuICAgICAgY29uc3QgbmFtZWQgPSAocGljazogdW5rbm93bikgPT4gbmFtZShncm91cElkLCBwaWNrKSA/PyBjdXJyZW50TmFtZShncm91cElkLCBwaWNrKTtcbiAgICAgIGNvbnN0IGRheXMgPSB2YWx1ZSA/IHsgLi4udmFsdWUsIHByZXNldDogdW5kZWZpbmVkIH0gOiB2YWx1ZTtcbiAgICAgIE9iamVjdC5hc3NpZ24ocGFyYW1zLCBncm91cFZhbHVlUGFyYW1zKHR5cGUsIGtleSwgdG9TdG9yZWRHcm91cFZhbHVlKHR5cGUsIGRheXMpLCBuYW1lZCkpO1xuICAgIH1cbiAgfSk7XG5cbiAgc25hcHNob3QubGlzdFNvcnRzLmZvckVhY2goKHNvcnQsIGNvbXBvbmVudElkKSA9PiB7XG4gICAgcGFyYW1zW2Ake0xJU1RfU09SVF9QQVJBTV9QUkVGSVh9JHtjb21wb25lbnRJZH1gXSA9IGVuY29kZVNvcnQoc29ydCk7XG4gIH0pO1xuXG4gIC8vIFRoZSB0ZXh0IGFzIHR5cGVkOiB0aGUgcm91dGVyIHBlcmNlbnQtZW5jb2RlcyBpdCBpbiB0aGUgVVJMLlxuICBzbmFwc2hvdC5saXN0U2VhcmNoZXMuZm9yRWFjaCgoc2VhcmNoLCBjb21wb25lbnRJZCkgPT4ge1xuICAgIHBhcmFtc1tgJHtMSVNUX1NFQVJDSF9QQVJBTV9QUkVGSVh9JHtjb21wb25lbnRJZH1gXSA9IHNlYXJjaDtcbiAgfSk7XG5cbiAgc25hcHNob3QubGlzdEhpZGRlbi5mb3JFYWNoKChuYW1lcywgY29tcG9uZW50SWQpID0+IHtcbiAgICBwYXJhbXNbYCR7TElTVF9ISURERU5fUEFSQU1fUFJFRklYfSR7Y29tcG9uZW50SWR9YF0gPSBlbmNvZGVDb2x1bW5MaXN0KG5hbWVzKTtcbiAgfSk7XG5cbiAgaWYgKHNuYXBzaG90LmZyZXF1ZW5jeSkge1xuICAgIHBhcmFtc1tHUk9VUF9CWV9JVEVNXSA9IHNuYXBzaG90LmZyZXF1ZW5jeTtcbiAgfVxuXG4gIHJldHVybiB7IC4uLnJlcG9ydFBhcmFtc1RvQ2xlYXIoY3VycmVudCwgZ3JvdXBzKSwgLi4ud2l0aEZvcm1hdChwYXJhbXMpIH07XG59XG5cbi8vIGBwYXJhbXNgIHdpdGggdGhlIGZvcm1hdCBtYXJrZXIsIHdoZW4gaXQgY2FycmllcyBhbnl0aGluZy5cbmZ1bmN0aW9uIHdpdGhGb3JtYXQocGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhwYXJhbXMpLmxlbmd0aCA/IHsgLi4ucGFyYW1zLCBbRk9STUFUX1BBUkFNXTogU3RyaW5nKFVSTF9GT1JNQVQpIH0gOiBwYXJhbXM7XG59XG5cbi8vIEVhY2ggZ3JvdXAncyB2YWx1ZSBhIGxpbmsgY2FycmllcywgaW4gaXRzIHN0b3JlZCBzaGFwZSwgYnkgZ3JvdXAgaWQgKG51bGxcbi8vIGZvciBhIGdyb3VwIHRoZSBsaW5rIGNsZWFycykuIEEgZ3JvdXAgd2l0aCBubyB1c2FibGUgcGFyYW0gaXMgbGVmdCBvdXQuXG5mdW5jdGlvbiByZWFkR3JvdXBQYXJhbXMocGFyYW1zOiBQYXJhbXMsIGdyb3VwczogcmVhZG9ubHkgVXJsR3JvdXBbXSk6IE1hcDxudW1iZXIsIEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGw+IHtcbiAgY29uc3Qga2V5cyA9IGdyb3VwUGFyYW1LZXlzKGdyb3Vwcyk7XG4gIGNvbnN0IHZhbHVlcyA9IG5ldyBNYXA8bnVtYmVyLCBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsPigpO1xuXG4gIGZvciAoY29uc3QgZ3JvdXAgb2YgZ3JvdXBzKSB7XG4gICAgY29uc3QgdmFsdWUgPSByZWFkR3JvdXBQYXJhbShwYXJhbXMsIGdyb3VwLnR5cGUsIGtleXMuZ2V0KGdyb3VwLmlkKSk7XG4gICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhbHVlcy5zZXQoZ3JvdXAuaWQsIHZhbHVlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdmFsdWVzO1xufVxuXG4vLyBPbmUgZ3JvdXAncyB2YWx1ZSBpbiBhIGxpbmssIHJlYWQgZnJvbSB0aGUga2V5cyBvZiBpdHMgdHlwZS4gbnVsbCBpcyBhXG4vLyBjbGVhcjsgdW5kZWZpbmVkIGlzIG5vIHVzYWJsZSB2YWx1ZS5cbmZ1bmN0aW9uIHJlYWRHcm91cFBhcmFtKHBhcmFtczogUGFyYW1zLCB0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlLCBrZXk6IHN0cmluZyk6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwgfCB1bmRlZmluZWQge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdzZWxlY3QnOlxuICAgICAgcmV0dXJuIHJlYWRTZWxlY3QocGFyYW1zLCBrZXkpO1xuXG4gICAgY2FzZSAnZGF0ZVJhbmdlJzpcbiAgICAgIHJldHVybiByZWFkRGF0ZVJhbmdlKHBhcmFtcywga2V5KTtcblxuICAgIGNhc2UgJ251bWJlclJhbmdlJzpcbiAgICAgIHJldHVybiByZWFkTnVtYmVyUmFuZ2UocGFyYW1zLCBrZXkpO1xuXG4gICAgY2FzZSAna2V5d29yZCc6XG4gICAgICByZXR1cm4gcmVhZEtleXdvcmQocGFyYW1zW2tleV0pO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLy8gQSBzZWxlY3QncyB2YWx1ZXMga2VwdCAoPGtleT4pLCBlbHNlIGl0cyB2YWx1ZXMgbGVmdCBvdXQgKGV4Y2x1ZGU8S2V5PikuXG5mdW5jdGlvbiByZWFkU2VsZWN0KHBhcmFtczogUGFyYW1zLCBrZXk6IHN0cmluZyk6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwgfCB1bmRlZmluZWQge1xuICBjb25zdCBrZXB0ID0gcGFyYW1UZXh0KHBhcmFtc1trZXldKTtcbiAgaWYgKGtlcHQgIT09IG51bGwpIHtcbiAgICByZXR1cm4ga2VwdCA9PT0gJycgPyBudWxsIDogZGVjb2RlUGlja3Moa2VwdCwgJ3ZhbHVlcycpO1xuICB9XG5cbiAgY29uc3QgZXhjbHVkZWQgPSBwYXJhbVRleHQocGFyYW1zW2dldEV4Y2x1ZGVOYW1lKGtleSldKTtcbiAgaWYgKGV4Y2x1ZGVkICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIGV4Y2x1ZGVkID09PSAnJyA/IG51bGwgOiBkZWNvZGVQaWNrcyhleGNsdWRlZCwgJ2V4Y2x1ZGVWYWx1ZXMnKTtcbiAgfVxuXG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8vIEEgZGF0ZSByYW5nZSdzIGRheXMgKDxrZXk+RnJvbSwgPGtleT5UbyksIGVhY2ggYSByZWFsIGNhbGVuZGFyIGRheSxcbi8vIGVpdGhlciBvbmUgb3BlbiBidXQgbm90IGJvdGguXG5mdW5jdGlvbiByZWFkRGF0ZVJhbmdlKHBhcmFtczogUGFyYW1zLCBrZXk6IHN0cmluZyk6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwgfCB1bmRlZmluZWQge1xuICBjb25zdCBlbmRzID0gcmVhZFJhbmdlRW5kcyhwYXJhbXMsIGtleSwgWydmcm9tJywgJ3RvJ10pO1xuICBpZiAoIWVuZHMpIHtcbiAgICByZXR1cm4gZW5kcyA9PT0gbnVsbCA/IG51bGwgOiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBbc3RhcnQsIGVuZF0gPSBlbmRzLm1hcChsaW5rRGF5KTtcbiAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQgfHwgZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcmV0dXJuIGNvbXBhY3RSYW5nZShzdGFydCwgZW5kLCAnc3RhcnQnLCAnZW5kJyk7XG59XG5cbi8vIEEgbnVtYmVyIHJhbmdlJ3MgZW5kcyAoPGtleT5NaW4sIDxrZXk+TWF4KSwgZWFjaCBhIGZpbml0ZSBudW1iZXIsIGVpdGhlclxuLy8gb25lIG9wZW4gYnV0IG5vdCBib3RoLCBhbmQgbWluIG5vdCBhYm92ZSBtYXguXG5mdW5jdGlvbiByZWFkTnVtYmVyUmFuZ2UocGFyYW1zOiBQYXJhbXMsIGtleTogc3RyaW5nKTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGVuZHMgPSByZWFkUmFuZ2VFbmRzKHBhcmFtcywga2V5LCBbJ21pbicsICdtYXgnXSk7XG4gIGlmICghZW5kcykge1xuICAgIHJldHVybiBlbmRzID09PSBudWxsID8gbnVsbCA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IFttaW4sIG1heF0gPSBlbmRzLm1hcCgoZW5kKSA9PiAoZW5kID09PSAnJyA/IG51bGwgOiBudW1iZXJGcm9tVGV4dChlbmQpKSk7XG4gIGlmICgoZW5kc1swXSAhPT0gJycgJiYgbWluID09PSBudWxsKSB8fCAoZW5kc1sxXSAhPT0gJycgJiYgbWF4ID09PSBudWxsKSB8fCAobWluICE9PSBudWxsICYmIG1heCAhPT0gbnVsbCAmJiBtaW4gPiBtYXgpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiBjb21wYWN0UmFuZ2UobWluLCBtYXgsICdtaW4nLCAnbWF4Jyk7XG59XG5cbi8vIEEga2V5d29yZCdzIHRleHQuIEJsYW5rIHRleHQgaXMgdW51c2FibGUuXG5mdW5jdGlvbiByZWFkS2V5d29yZChyYXc6IHVua25vd24pOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgdGV4dCA9IHBhcmFtVGV4dChyYXcpO1xuICBpZiAodGV4dCA9PT0gbnVsbCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAodGV4dCA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB0ZXh0LnRyaW0oKSA/IHsgdmFsdWU6IHRleHQgfSA6IHVuZGVmaW5lZDtcbn1cblxuLy8gQSByYW5nZSdzIHR3byBlbmRzIGFzIHdyaXR0ZW4gKCcnIGZvciBvbmUgdGhlIGxpbmsgbGVhdmVzIG9wZW4pOlxuLy8gdW5kZWZpbmVkIHdoZW4gdGhlIGxpbmsgY2FycmllcyBuZWl0aGVyIGtleSwgbnVsbCB3aGVuIGV2ZXJ5IG9uZSBpdFxuLy8gY2FycmllcyBpcyBlbXB0eSAoYSBjbGVhcikuXG5mdW5jdGlvbiByZWFkUmFuZ2VFbmRzKFxuICBwYXJhbXM6IFBhcmFtcyxcbiAga2V5OiBzdHJpbmcsXG4gIGVuZHM6IFtJdGVtUmFuZ2VFbmQsIEl0ZW1SYW5nZUVuZF0sXG4pOiBbc3RyaW5nLCBzdHJpbmddIHwgbnVsbCB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IFtsb3csIGhpZ2hdID0gZW5kcy5tYXAoKGVuZCkgPT4gcGFyYW1UZXh0KHBhcmFtc1tpdGVtUmFuZ2VOYW1lKGtleSwgZW5kKV0pKTtcbiAgaWYgKGxvdyA9PT0gbnVsbCAmJiBoaWdoID09PSBudWxsKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiBsb3cgfHwgaGlnaCA/IFtsb3cgPz8gJycsIGhpZ2ggPz8gJyddIDogbnVsbDtcbn1cblxuLy8gVGhlIHBhcmFtcyBvZiBhIHJhbmdlJ3MgZW5kcywgdGhlIG9uZXMgaXQgc2V0cyBvbmx5OyB3aXRoIG5laXRoZXIgb25lXG4vLyB1c2FibGUsIHRoZSBncm91cCdzIGNsZWFyLlxuZnVuY3Rpb24gcmFuZ2VQYXJhbXMoXG4gIHR5cGU6IFJlcG9ydEZpbHRlclR5cGUgfCB1bmRlZmluZWQsXG4gIGtleTogc3RyaW5nLFxuICBlbmRzOiBbSXRlbVJhbmdlRW5kLCBJdGVtUmFuZ2VFbmRdLFxuICB0ZXh0czogW3N0cmluZywgc3RyaW5nXSxcbik6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgZW5kcy5mb3JFYWNoKChlbmQsIGluZGV4KSA9PiB7XG4gICAgaWYgKHRleHRzW2luZGV4XSkge1xuICAgICAgcGFyYW1zW2l0ZW1SYW5nZU5hbWUoa2V5LCBlbmQpXSA9IHRleHRzW2luZGV4XTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBPYmplY3Qua2V5cyhwYXJhbXMpLmxlbmd0aCA/IHBhcmFtcyA6IGNsZWFyUGFyYW1zKHR5cGUsIGtleSk7XG59XG5cbi8vIFRoZSBwYXJhbXMgb2YgYSBjbGVhcmVkIGdyb3VwOiBpdHMga2V5cywgZW1wdHkuXG5mdW5jdGlvbiBjbGVhclBhcmFtcyh0eXBlOiBSZXBvcnRGaWx0ZXJUeXBlIHwgdW5kZWZpbmVkLCBrZXk6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdkYXRlUmFuZ2UnOlxuICAgICAgcmV0dXJuIHsgW2l0ZW1SYW5nZU5hbWUoa2V5LCAnZnJvbScpXTogJycsIFtpdGVtUmFuZ2VOYW1lKGtleSwgJ3RvJyldOiAnJyB9O1xuXG4gICAgY2FzZSAnbnVtYmVyUmFuZ2UnOlxuICAgICAgcmV0dXJuIHsgW2l0ZW1SYW5nZU5hbWUoa2V5LCAnbWluJyldOiAnJywgW2l0ZW1SYW5nZU5hbWUoa2V5LCAnbWF4JyldOiAnJyB9O1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB7IFtrZXldOiAnJyB9O1xuICB9XG59XG5cbi8vIEEgc3RvcmVkIGRheSBpbiBmcy1maWx0ZXIncyBkYXRlIGZvcm1hdDogaXRzIGxvY2FsIG1pZG5pZ2h0IHdpdGggdGhlXG4vLyBvZmZzZXQsICcnIHdoZW4gdGhlcmUgaXMgbm8gcmVhbCBkYXkuXG5mdW5jdGlvbiBsaW5rRGF5VGV4dChib3VuZDogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHtcbiAgY29uc3QgZGF5ID0gZGF0ZUJvdW5kU3RyaW5nKGJvdW5kKTtcblxuICByZXR1cm4gZGF5ICYmIGlzQ2FsZW5kYXJEYXkoZGF5KSA/IGlzbzg2MDEocGFyc2VJU08oZGF5KSkgOiAnJztcbn1cblxuLy8gVGhlIGRheSBvZiBhIGxpbmsncyBkYXRlIGVuZDogbnVsbCB3aGVuIHRoZSBlbmQgaXMgb3BlbiAoJycpLCB1bmRlZmluZWRcbi8vIHdoZW4gaXQgaXMgbm90IGEgcmVhbCBjYWxlbmRhciBkYXkuXG5mdW5jdGlvbiBsaW5rRGF5KHRleHQ6IHN0cmluZyk6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQge1xuICBpZiAodGV4dCA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IGRheSA9IExJTktfREFZLmV4ZWModGV4dCk/LlsxXTtcblxuICByZXR1cm4gZGF5ICYmIGlzQ2FsZW5kYXJEYXkoZGF5KSA/IGRheSA6IHVuZGVmaW5lZDtcbn1cblxuLy8gVGhlIGtleXMgYSBsaW5rIGNhcnJpZXMgdGhlIGdyb3VwcycgdmFsdWVzIHVuZGVyLCBieSBlYWNoIGdyb3VwJ3MgdHlwZS5cbmZ1bmN0aW9uIG93bmVkR3JvdXBLZXlzKGdyb3VwczogcmVhZG9ubHkgVXJsR3JvdXBbXSk6IFNldDxzdHJpbmc+IHtcbiAgY29uc3Qga2V5cyA9IGdyb3VwUGFyYW1LZXlzKGdyb3Vwcyk7XG5cbiAgcmV0dXJuIG5ldyBTZXQoZ3JvdXBzLmZsYXRNYXAoKGdyb3VwKSA9PiB7XG4gICAgY29uc3Qga2V5ID0ga2V5cy5nZXQoZ3JvdXAuaWQpO1xuXG4gICAgc3dpdGNoIChncm91cC50eXBlKSB7XG4gICAgICBjYXNlICdzZWxlY3QnOlxuICAgICAgICByZXR1cm4gW2tleSwgZ2V0RXhjbHVkZU5hbWUoa2V5KV07XG5cbiAgICAgIGNhc2UgJ2RhdGVSYW5nZSc6XG4gICAgICAgIHJldHVybiBbaXRlbVJhbmdlTmFtZShrZXksICdmcm9tJyksIGl0ZW1SYW5nZU5hbWUoa2V5LCAndG8nKV07XG5cbiAgICAgIGNhc2UgJ251bWJlclJhbmdlJzpcbiAgICAgICAgcmV0dXJuIFtpdGVtUmFuZ2VOYW1lKGtleSwgJ21pbicpLCBpdGVtUmFuZ2VOYW1lKGtleSwgJ21heCcpXTtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIFtrZXldO1xuICAgIH1cbiAgfSkpO1xufVxuXG4vLyBPbmUgaWQta2V5ZWQgcGFyYW0gb2YgYSB0aWxlIHJlYWQgaW50byBgY29uZmlnYC5cbmZ1bmN0aW9uIHJlYWRUaWxlUGFyYW0oXG4gIGNvbmZpZzogUmVwb3J0Vmlld0NvbmZpZyxcbiAgcHJlZml4OiBzdHJpbmcsXG4gIGlkOiBudW1iZXIsXG4gIHJhdzogc3RyaW5nLFxuKTogdm9pZCB7XG4gIHN3aXRjaCAocHJlZml4KSB7XG4gICAgY2FzZSBMSVNUX1NPUlRfUEFSQU1fUFJFRklYOlxuICAgICAgc2V0VGlsZVN0YXRlKGNvbmZpZywgaWQsICdzb3J0JywgZGVjb2RlU29ydChyYXcpKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBMSVNUX1NFQVJDSF9QQVJBTV9QUkVGSVg6XG4gICAgICBzZXRUaWxlU3RhdGUoY29uZmlnLCBpZCwgJ3NlYXJjaCcsIHJhdyB8fCBudWxsKTtcbiAgICAgIGJyZWFrO1xuXG4gICAgY2FzZSBMSVNUX0hJRERFTl9QQVJBTV9QUkVGSVg6XG4gICAgICBzZXRUaWxlU3RhdGUoY29uZmlnLCBpZCwgJ2hpZGRlbicsIG5vbkVtcHR5KGRlY29kZUNvbHVtbkxpc3QocmF3KSkpO1xuICAgICAgYnJlYWs7XG5cbiAgICBkZWZhdWx0OlxuICAgICAgc2V0VGlsZVN0YXRlKGNvbmZpZywgaWQsICdkcmlsbCcsIG5vbkVtcHR5KGRlY29kZURyaWxsUGF0aChyYXcpKSk7XG4gIH1cbn1cblxuLy8gU2V0cyBvbmUga2V5IG9mIGEgdGlsZSdzIHN0YXRlLCBjcmVhdGluZyB0aGUgdGlsZSwgdW5sZXNzIHRoZXJlIGlzIG5vdGhpbmdcbi8vIHRvIHNldC5cbmZ1bmN0aW9uIHNldFRpbGVTdGF0ZTxLIGV4dGVuZHMga2V5b2YgUmVwb3J0VGlsZVN0YXRlPihcbiAgY29uZmlnOiBSZXBvcnRWaWV3Q29uZmlnLFxuICBjb21wb25lbnRJZDogbnVtYmVyLFxuICBrZXk6IEssXG4gIHZhbHVlOiBSZXBvcnRUaWxlU3RhdGVbS10gfCBudWxsLFxuKTogdm9pZCB7XG4gIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbmZpZy50aWxlcyA9IHsgLi4uY29uZmlnLnRpbGVzLCBbY29tcG9uZW50SWRdOiB7IC4uLmNvbmZpZy50aWxlcz8uW2NvbXBvbmVudElkXSwgW2tleV06IHZhbHVlIH0gfTtcbn1cblxuLy8gVGhlIHBhcmFtcyBvZiBvbmUgdGlsZSdzIHN0YXRlLlxuZnVuY3Rpb24gdGlsZVBhcmFtcyhjb21wb25lbnRJZDogbnVtYmVyLCB0aWxlOiBSZXBvcnRUaWxlU3RhdGUpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3QgcGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgaWYgKHRpbGUuc29ydD8uY29sdW1uKSB7XG4gICAgcGFyYW1zW2Ake0xJU1RfU09SVF9QQVJBTV9QUkVGSVh9JHtjb21wb25lbnRJZH1gXSA9IGVuY29kZVNvcnQodGlsZS5zb3J0KTtcbiAgfVxuXG4gIC8vIFRoZSB0ZXh0IGFzIHR5cGVkOiB0aGUgcm91dGVyIHBlcmNlbnQtZW5jb2RlcyBpdCBpbiB0aGUgVVJMLlxuICBpZiAodGlsZS5zZWFyY2gpIHtcbiAgICBwYXJhbXNbYCR7TElTVF9TRUFSQ0hfUEFSQU1fUFJFRklYfSR7Y29tcG9uZW50SWR9YF0gPSB0aWxlLnNlYXJjaDtcbiAgfVxuXG4gIGlmICh0aWxlLmhpZGRlbj8ubGVuZ3RoKSB7XG4gICAgcGFyYW1zW2Ake0xJU1RfSElEREVOX1BBUkFNX1BSRUZJWH0ke2NvbXBvbmVudElkfWBdID0gZW5jb2RlQ29sdW1uTGlzdCh0aWxlLmhpZGRlbik7XG4gIH1cblxuICBpZiAodGlsZS5kcmlsbD8ubGVuZ3RoKSB7XG4gICAgcGFyYW1zW2Ake0RSSUxMX1BBUkFNX1BSRUZJWH0ke2NvbXBvbmVudElkfWBdID0gZW5jb2RlRHJpbGxQYXRoKHRpbGUuZHJpbGwpO1xuICB9XG5cbiAgcmV0dXJuIHBhcmFtcztcbn1cblxuLy8gYHBhcmFtc2Agd2l0aGluIFJFUE9SVF9VUkxfTUFYX0xFTkdUSDogcGFzdCBpdCwgZ3JvdXAgdmFsdWVzICh0aGUgcGFyYW1zXG4vLyBuYW1lZCBpbiBgZ3JvdXBQYXJhbXNgKSBhcmUgbGVmdCBvdXQsIGxvbmdlc3QgZmlyc3QsIHVudGlsIHRoZSByZXN0IGZpdHMuXG5mdW5jdGlvbiBjYXBSZXBvcnRQYXJhbXMocGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCBncm91cFBhcmFtczogUmVhZG9ubHlTZXQ8c3RyaW5nPik6IFJlcG9ydFVybFdyaXRlIHtcbiAgaWYgKHF1ZXJ5TGVuZ3RoKHBhcmFtcykgPD0gUkVQT1JUX1VSTF9NQVhfTEVOR1RIKSB7XG4gICAgcmV0dXJuIHsgcGFyYW1zLCB0b29Mb25nOiBmYWxzZSB9O1xuICB9XG5cbiAgY29uc3Qga2VwdCA9IHsgLi4ucGFyYW1zIH07XG4gIGNvbnN0IGdyb3VwS2V5cyA9IE9iamVjdC5rZXlzKGtlcHQpXG4gICAgLmZpbHRlcigoa2V5KSA9PiBncm91cFBhcmFtcy5oYXMoa2V5KSlcbiAgICAuc29ydCgoYSwgYikgPT4gcXVlcnlUZXh0KGtlcHRbYl0pLmxlbmd0aCAtIHF1ZXJ5VGV4dChrZXB0W2FdKS5sZW5ndGgpO1xuXG4gIGZvciAoY29uc3Qga2V5IG9mIGdyb3VwS2V5cykge1xuICAgIGlmIChxdWVyeUxlbmd0aChrZXB0KSA8PSBSRVBPUlRfVVJMX01BWF9MRU5HVEgpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGRlbGV0ZSBrZXB0W2tleV07XG4gIH1cblxuICByZXR1cm4geyBwYXJhbXM6IGtlcHQsIHRvb0xvbmc6IHRydWUgfTtcbn1cblxuLy8gVGhlIGxlbmd0aCBvZiBgcGFyYW1zYCBhcyB0aGUgcm91dGVyIHdyaXRlcyB0aGVtIGluIGEgcXVlcnkgc3RyaW5nLlxuZnVuY3Rpb24gcXVlcnlMZW5ndGgocGFyYW1zOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogbnVtYmVyIHtcbiAgcmV0dXJuIE9iamVjdC5lbnRyaWVzKHBhcmFtcylcbiAgICAubWFwKChba2V5LCB2YWx1ZV0pID0+IGAke3F1ZXJ5VGV4dChrZXkpfT0ke3F1ZXJ5VGV4dCh2YWx1ZSl9YClcbiAgICAuam9pbignJicpXG4gICAgLmxlbmd0aDtcbn1cblxuLy8gVGV4dCBhcyB0aGUgcm91dGVyIHdyaXRlcyBpdCBpbiBhIHF1ZXJ5IHN0cmluZyAoaXRzIHF1ZXJ5IGVuY29kaW5nKTpcbi8vIHBlcmNlbnQtZW5jb2RlZCwgd2l0aCAnQCcsICc6JywgJyQnLCAnLCcgYW5kICc7JyBsZWZ0IGFzIHRoZXkgYXJlLlxuZnVuY3Rpb24gcXVlcnlUZXh0KHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQodGV4dClcbiAgICAucmVwbGFjZSgvJTQwL2csICdAJylcbiAgICAucmVwbGFjZSgvJTNBL2dpLCAnOicpXG4gICAgLnJlcGxhY2UoLyUyNC9nLCAnJCcpXG4gICAgLnJlcGxhY2UoLyUyQy9naSwgJywnKVxuICAgIC5yZXBsYWNlKC8lM0IvZ2ksICc7Jyk7XG59XG5cbi8vIEEgcGFyYW0ncyB0ZXh0OiBhIHJlcGVhdGVkIGtleSBnaXZlcyBpdHMgZmlyc3QgdmFsdWUuXG5mdW5jdGlvbiBwYXJhbVRleHQodmFsdWU6IHVua25vd24pOiBzdHJpbmcgfCBudWxsIHtcbiAgY29uc3QgZmlyc3QgPSBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlWzBdIDogdmFsdWU7XG5cbiAgcmV0dXJuIHR5cGVvZiBmaXJzdCA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGZpcnN0ID09PSAnbnVtYmVyJyA/IFN0cmluZyhmaXJzdCkgOiBudWxsO1xufVxuXG5mdW5jdGlvbiBwb3NpdGl2ZUlkKHJhdzogc3RyaW5nIHwgbnVsbCk6IG51bWJlciB8IG51bGwge1xuICByZXR1cm4gcmF3ICE9PSBudWxsICYmIC9eWzEtOV1cXGQqJC8udGVzdChyYXcpID8gTnVtYmVyKHJhdykgOiBudWxsO1xufVxuXG5mdW5jdGlvbiBub25FbXB0eTxUPihsaXN0OiBUW10pOiBUW10gfCBudWxsIHtcbiAgcmV0dXJuIGxpc3QubGVuZ3RoID8gbGlzdCA6IG51bGw7XG59XG5cbi8vIEFuIGl0ZW0gb2YgYSBsaXN0IHBhcmFtLCBwZXJjZW50LWRlY29kZWQ7IG9uZSB0aGF0IGRvZXMgbm90IGRlY29kZSAoYVxuLy8gaGFuZC1lZGl0ZWQgJyUnKSBpcyBrZXB0IGFzIHdyaXR0ZW4uXG5mdW5jdGlvbiBkZWNvZGVJdGVtKGl0ZW06IHN0cmluZyk6IHN0cmluZyB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChpdGVtKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIGl0ZW07XG4gIH1cbn1cblxuLy8gU2VsZWN0IHBpY2tzIGFzIG9uZSBwYXJhbSB2YWx1ZTogdmFsdWU6bmFtZSBmb3IgZWFjaCwgdGhlIG5hbWUgbGVmdCBvZmZcbi8vIHdoZW4gYG5hbWVgIGRvZXMgbm90IGtub3cgaXQsIGJsYW5rcyBsZWZ0IG91dC5cbmZ1bmN0aW9uIGVuY29kZVBpY2tzKHBpY2tzOiByZWFkb25seSB1bmtub3duW10sIG5hbWU6ICh2YWx1ZTogdW5rbm93bikgPT4gc3RyaW5nIHwgbnVsbCk6IHN0cmluZyB7XG4gIHJldHVybiBwaWNrc1xuICAgIC5maWx0ZXIoKHBpY2spID0+IHR5cGVvZiBwaWNrID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgcGljayA9PT0gJ251bWJlcicgfHwgdHlwZW9mIHBpY2sgPT09ICdib29sZWFuJylcbiAgICAuZmlsdGVyKChwaWNrKSA9PiBTdHJpbmcocGljaykgIT09ICcnKVxuICAgIC5tYXAoKHBpY2spID0+IHtcbiAgICAgIGNvbnN0IG5hbWVkID0gbmFtZShwaWNrKTtcblxuICAgICAgcmV0dXJuIG5hbWVkID8gYCR7ZXNjYXBlUGljayhTdHJpbmcocGljaykpfSR7UElDS19OQU1FX1NFUEFSQVRPUn0ke2VzY2FwZVBpY2sobmFtZWQpfWAgOiBlc2NhcGVQaWNrKFN0cmluZyhwaWNrKSk7XG4gICAgfSlcbiAgICAuam9pbihQSUNLX1NFUEFSQVRPUik7XG59XG5cbi8vIEEgcGljaydzIHZhbHVlIG9yIG5hbWUgd2l0aCBlYWNoICcsJywgJzonIGFuZCAnXFwnIGluIGl0IGVzY2FwZWQuXG5mdW5jdGlvbiBlc2NhcGVQaWNrKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiB0ZXh0LnJlcGxhY2UoL1tcXFxcLDpdL2csIChjaGFyKSA9PiBgJHtQSUNLX0VTQ0FQRX0ke2NoYXJ9YCk7XG59XG5cbi8vIFRoZSBwaWNrcyBvZiBhIHBhcmFtIHdyaXR0ZW4gYXMgZW5jb2RlUGlja3Mgd3JpdGVzIHRoZW0sIGluIG9yZGVyOiBlYWNoXG4vLyB2YWx1ZSBhbmQgaXRzIG5hbWUgKG51bGwgd2hlbiB0aGUgcGljayBoYXMgbm9uZSkuXG5mdW5jdGlvbiBkZWNvZGVQaWNrTGlzdChyYXc6IHN0cmluZyk6IHsgdmFsdWU6IHN0cmluZzsgbmFtZTogc3RyaW5nIHwgbnVsbCB9W10ge1xuICBjb25zdCBwaWNrczogeyB2YWx1ZTogc3RyaW5nOyBuYW1lOiBzdHJpbmcgfCBudWxsIH1bXSA9IFtdO1xuICBsZXQgcGFydHM6IHN0cmluZ1tdID0gWycnXTtcbiAgbGV0IGVzY2FwZWQgPSBmYWxzZTtcbiAgY29uc3QgZW5kUGljayA9ICgpID0+IHBpY2tzLnB1c2goeyB2YWx1ZTogcGFydHNbMF0sIG5hbWU6IHBhcnRzLmxlbmd0aCA+IDEgPyBwYXJ0c1sxXSA6IG51bGwgfSk7XG5cbiAgZm9yIChjb25zdCBjaGFyIG9mIHJhdykge1xuICAgIGlmIChlc2NhcGVkKSB7XG4gICAgICBwYXJ0c1twYXJ0cy5sZW5ndGggLSAxXSArPSBjaGFyO1xuICAgICAgZXNjYXBlZCA9IGZhbHNlO1xuICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gUElDS19FU0NBUEUpIHtcbiAgICAgIGVzY2FwZWQgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gUElDS19OQU1FX1NFUEFSQVRPUiAmJiBwYXJ0cy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHBhcnRzLnB1c2goJycpO1xuICAgIH0gZWxzZSBpZiAoY2hhciA9PT0gUElDS19TRVBBUkFUT1IpIHtcbiAgICAgIGVuZFBpY2soKTtcbiAgICAgIHBhcnRzID0gWycnXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGFydHNbcGFydHMubGVuZ3RoIC0gMV0gKz0gY2hhcjtcbiAgICB9XG4gIH1cblxuICBlbmRQaWNrKCk7XG5cbiAgcmV0dXJuIHBpY2tzO1xufVxuXG4vLyBBIHNlbGVjdCdzIHZhbHVlcywga2VwdCBvciBsZWZ0IG91dCwgcmVhZCBmcm9tIGl0cyBwYXJhbSwgb3IgdW5kZWZpbmVkXG4vLyB3aGVuIHRoZXJlIGFyZSBub25lIG9yIHRvbyBtYW55LlxuZnVuY3Rpb24gZGVjb2RlUGlja3MocmF3OiBzdHJpbmcsIGFzOiAndmFsdWVzJyB8ICdleGNsdWRlVmFsdWVzJyk6IEZpbHRlckdyb3VwRGVmYXVsdCB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHBpY2tzID0gZGVjb2RlUGlja0xpc3QocmF3KVxuICAgIC5tYXAoKHBpY2spID0+IHBpY2sudmFsdWUpXG4gICAgLmZpbHRlcigodmFsdWUpID0+IHZhbHVlICE9PSAnJyk7XG5cbiAgcmV0dXJuIHBpY2tzLmxlbmd0aCAmJiBwaWNrcy5sZW5ndGggPD0gR1JPVVBfVkFMVUVfTUFYX1BJQ0tTID8geyBbYXNdOiBwaWNrcyB9IDogdW5kZWZpbmVkO1xufVxuXG4vLyBBIHJhbmdlJ3Mgc2V0IGVuZHMgdW5kZXIgdGhlaXIga2V5cy5cbmZ1bmN0aW9uIGNvbXBhY3RSYW5nZTxUPihsb3c6IFQgfCBudWxsLCBoaWdoOiBUIHwgbnVsbCwgbG93S2V5OiBzdHJpbmcsIGhpZ2hLZXk6IHN0cmluZyk6IEZpbHRlckdyb3VwRGVmYXVsdCB7XG4gIHJldHVybiB7XG4gICAgLi4uKGxvdyAhPT0gbnVsbCA/IHsgW2xvd0tleV06IGxvdyB9IDoge30pLFxuICAgIC4uLihoaWdoICE9PSBudWxsID8geyBbaGlnaEtleV06IGhpZ2ggfSA6IHt9KSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gaXNOdW1iZXJFbmQoZW5kOiB1bmtub3duKTogZW5kIGlzIG51bWJlciB7XG4gIHJldHVybiB0eXBlb2YgZW5kID09PSAnbnVtYmVyJyAmJiBOdW1iZXIuaXNGaW5pdGUoZW5kKTtcbn1cblxuZnVuY3Rpb24gbnVtYmVyRW5kVGV4dChlbmQ6IHVua25vd24pOiBzdHJpbmcge1xuICByZXR1cm4gaXNOdW1iZXJFbmQoZW5kKSA/IFN0cmluZyhlbmQpIDogJyc7XG59XG5cbi8vIE9uZSAnbGV2ZWw6dmFsdWUnIHN0ZXAsIG9yIG51bGwgd2hlbiBpdHMgbGV2ZWwgaXMgbm90IGEgdGltZSBncmFpbi5cbmZ1bmN0aW9uIGRlY29kZURyaWxsU3RlcChpdGVtOiBzdHJpbmcpOiBSZXBvcnREcmlsbFN0ZXAgfCBudWxsIHtcbiAgY29uc3QgYXQgPSBpdGVtLmluZGV4T2YoRFJJTExfU1RFUF9TRVBBUkFUT1IpO1xuICBjb25zdCBsZXZlbCA9IGRlY29kZUl0ZW0oYXQgPCAwID8gaXRlbSA6IGl0ZW0uc2xpY2UoMCwgYXQpKTtcblxuICBpZiAoIWlzQ2hhcnRHcmFudWxhcml0eShsZXZlbCkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiB7IGxldmVsLCB2YWx1ZTogYXQgPCAwID8gbnVsbCA6IGRlY29kZUl0ZW0oaXRlbS5zbGljZShhdCArIDEpKSB9O1xufVxuIl19