@firestitch/report 18.9.0 → 18.10.1

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 (186) 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 +20 -7
  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 +45 -8
  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 +37 -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-group-changes.interface.d.ts +7 -0
  41. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  42. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  43. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  44. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  45. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  46. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  47. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  48. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  49. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  50. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  51. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  52. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  53. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  55. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  56. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  57. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  58. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  59. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  60. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  61. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  62. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  63. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  64. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  65. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  66. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  67. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  68. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  69. package/app/reports/interfaces/report.interface.d.ts +27 -16
  70. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  71. package/app/reports/mark-click.d.ts +20 -0
  72. package/app/reports/option-builder.d.ts +12 -1
  73. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  74. package/app/reports/report-date-presets.d.ts +2 -0
  75. package/app/reports/report-filter-items.d.ts +20 -21
  76. package/app/reports/report-tile.d.ts +2 -0
  77. package/app/reports/report-view-config.d.ts +34 -0
  78. package/app/reports/report-view-menu.d.ts +15 -0
  79. package/app/reports/report-viewer-features.d.ts +5 -0
  80. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  81. package/app/reports/services/report-filter-state.service.d.ts +65 -11
  82. package/app/reports/services/report-view.service.d.ts +39 -0
  83. package/app/reports/tile-data-state.d.ts +7 -0
  84. package/app/reports/tile-loads.d.ts +4 -0
  85. package/app/reports/views/report/fs-ai-report.component.d.ts +10 -8
  86. package/app/reports/views/report/report.component.d.ts +6 -0
  87. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  88. package/esm2022/app/reports/canvas-landing-page.mjs +26 -0
  89. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  90. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  91. package/esm2022/app/reports/components/component-list/component-list.component.mjs +11 -5
  92. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +56 -40
  93. package/esm2022/app/reports/components/report-component/report-component.component.mjs +261 -65
  94. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  95. package/esm2022/app/reports/data/report.data.mjs +94 -14
  96. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +106 -51
  97. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +248 -104
  98. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  99. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  100. package/esm2022/app/reports/export/report-export-collector.service.mjs +187 -117
  101. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  102. package/esm2022/app/reports/export/report-pdf.service.mjs +12 -7
  103. package/esm2022/app/reports/export/report-pptx.service.mjs +18 -14
  104. package/esm2022/app/reports/filter-settings-rules.mjs +290 -0
  105. package/esm2022/app/reports/format.mjs +2 -22
  106. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  107. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  108. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  109. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  110. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  111. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  112. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  113. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  114. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  115. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  116. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  117. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  118. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  119. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  120. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  121. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  122. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  123. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  124. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  125. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/report-filter-group-changes.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  138. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  140. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  159. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  160. package/esm2022/app/reports/mark-click.mjs +193 -0
  161. package/esm2022/app/reports/option-builder.mjs +159 -15
  162. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  163. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  164. package/esm2022/app/reports/report-filter-items.mjs +263 -72
  165. package/esm2022/app/reports/report-tile.mjs +12 -0
  166. package/esm2022/app/reports/report-view-config.mjs +587 -0
  167. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  168. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  169. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  170. package/esm2022/app/reports/services/report-filter-state.service.mjs +668 -210
  171. package/esm2022/app/reports/services/report-view.service.mjs +218 -0
  172. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  173. package/esm2022/app/reports/tile-loads.mjs +38 -0
  174. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +194 -127
  175. package/esm2022/app/reports/views/report/report.component.mjs +112 -29
  176. package/esm2022/public_api.mjs +23 -1
  177. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs → firestitch-report-echarts-DHEH_K_q.mjs} +2 -2
  178. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs.map → firestitch-report-echarts-DHEH_K_q.mjs.map} +1 -1
  179. package/fesm2022/{firestitch-report-firestitch-report-CqbXT1gh.mjs → firestitch-report-firestitch-report-ZcHTnNKq.mjs} +8222 -4447
  180. package/fesm2022/firestitch-report-firestitch-report-ZcHTnNKq.mjs.map +1 -0
  181. package/fesm2022/firestitch-report.mjs +1 -1
  182. package/package.json +1 -1
  183. package/public_api.d.ts +22 -0
  184. package/app/reports/report-url-state.d.ts +0 -19
  185. package/esm2022/app/reports/report-url-state.mjs +0 -189
  186. package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +0 -1
@@ -0,0 +1,290 @@
1
+ import { RELATIVE_RANGE_NAMES, isRelativeRange } from './report-view-config';
2
+ import { offersExclude } from './report-viewer-features';
3
+ // The Type select's choices. A column that can be either holds both.
4
+ export const FILTER_TYPE_OPTIONS = [
5
+ { value: 'select', name: 'Values' },
6
+ { value: 'numberRange', name: 'Number range' },
7
+ ];
8
+ export const TYPE_LOCKED_TOOLTIP = 'Remove the filter to change its type.';
9
+ export const PAGE_FILTER_TOOLTIP = 'A page filter shows in the page bar only.';
10
+ export const COMPONENT_TOGGLE_TOOLTIP = 'Show on this component';
11
+ // The Default period select's value for a range of fixed days. No relative
12
+ // range is named this.
13
+ export const FIXED_DATES_PERIOD = 'fixed';
14
+ // How many decimals a Default minimum or Default maximum takes.
15
+ export const DEFAULT_BOUND_SCALE = 6;
16
+ // A filter's Name and Label, checked as the server checks them, so a bad one
17
+ // is caught before Save. The name is an identifier: a letter, then letters
18
+ // and digits. That it is unique in the report is the server's to check.
19
+ export const FILTER_NAME_PATTERN = /^[A-Za-z][A-Za-z0-9]*$/;
20
+ export const FILTER_NAME_PATTERN_MESSAGE = 'A name starts with a letter and holds only letters and digits.';
21
+ export const FILTER_NAME_MAX_LENGTH = 50;
22
+ export const FILTER_LABEL_MAX_LENGTH = 200;
23
+ // Every Report bar choice, in the order the select lists them.
24
+ const BAR_PLACEMENT_OPTIONS = [
25
+ { value: 'off', name: 'Off' },
26
+ { value: 'every', name: 'Every page' },
27
+ { value: 'page', name: 'This page only' },
28
+ ];
29
+ // A number with its group commas in place ('1,250.5', '-12,000').
30
+ const GROUPED_DECIMAL = /^-?\d{1,3}(,\d{3})+(\.\d*)?$/;
31
+ // A plain decimal number ('1250.5', '-3', '0', '.5'). Hex, binary, octal,
32
+ // exponents and inner spaces do not match, though Number() reads some.
33
+ const PLAIN_DECIMAL = /^-?(\d+(\.\d*)?|\.\d+)$/;
34
+ // A default range end as typed. An empty field is no end. A number input
35
+ // with a mask hands back text with its group commas ('1,250.5'), so those go
36
+ // before Number() reads it; 0 is an end like any other. Anything that is not
37
+ // a decimal number is no end.
38
+ export function parseDefaultBound(raw) {
39
+ if (typeof raw === 'number') {
40
+ return Number.isFinite(raw) ? raw : null;
41
+ }
42
+ if (typeof raw !== 'string') {
43
+ return null;
44
+ }
45
+ const trimmed = raw.trim();
46
+ const text = GROUPED_DECIMAL.test(trimmed) ? trimmed.replace(/,/g, '') : trimmed;
47
+ if (!PLAIN_DECIMAL.test(text)) {
48
+ return null;
49
+ }
50
+ const value = Number(text);
51
+ return Number.isFinite(value) ? value : null;
52
+ }
53
+ // Why two range ends cannot be saved, in the server's words, or null. An open
54
+ // end is always fine.
55
+ export function boundsError(min, max) {
56
+ if (min === null || max === null || min <= max) {
57
+ return null;
58
+ }
59
+ return `min (${min}) is above max (${max}).`;
60
+ }
61
+ // The Type select of a column on the component settings' Filters tab. It
62
+ // shows when the column can take either type and the server serves number
63
+ // ranges (an older server lists no features). A filter's type cannot change,
64
+ // so it is locked while the column has a filter on this component.
65
+ export function typeSelectState(types, hasFilterOnThisComponent, features) {
66
+ const show = (features ?? []).includes('numberRange')
67
+ && FILTER_TYPE_OPTIONS.every((option) => (types ?? []).includes(option.value));
68
+ if (!show) {
69
+ return { show: false, disabled: false, tooltip: null };
70
+ }
71
+ return {
72
+ show: true,
73
+ disabled: hasFilterOnThisComponent,
74
+ tooltip: hasFilterOnThisComponent ? TYPE_LOCKED_TOOLTIP : null,
75
+ };
76
+ }
77
+ // The levels a new or moved filter can take on a component. This page only
78
+ // needs a server that serves page filters and a component on a page (a
79
+ // header or footer component is on no page).
80
+ export function filterLevelChoices(features, onPage) {
81
+ const levels = ['component', 'report', 'both'];
82
+ return onPage && (features ?? []).includes('pageScope')
83
+ ? [...levels, 'page']
84
+ : levels;
85
+ }
86
+ // The Report bar select's choices for the levels on offer. The choice a row
87
+ // already holds is always listed, so the select never shows blank.
88
+ export function barPlacementOptions(levelChoices, current = 'off') {
89
+ return BAR_PLACEMENT_OPTIONS.filter((option) => {
90
+ switch (option.value) {
91
+ case 'every':
92
+ return levelChoices.includes('report') || levelChoices.includes('both') || current === 'every';
93
+ case 'page':
94
+ return levelChoices.includes('page') || current === 'page';
95
+ default:
96
+ return true;
97
+ }
98
+ });
99
+ }
100
+ // A value's Report bar choices. A value has no strip of its own and its
101
+ // group may be shared, so a pick never lowers the group (the inline values
102
+ // rule): This page only is offered for a new filter, or for a group that is
103
+ // already a page group, never to move a shared group to one page.
104
+ export function valuePlacementOptions(levelChoices, current) {
105
+ const choices = !current || current === 'page'
106
+ ? levelChoices
107
+ : levelChoices.filter((level) => level !== 'page');
108
+ return barPlacementOptions(choices, barPlacement(current));
109
+ }
110
+ // The level a value's filter group ends at after a Report bar pick, or null
111
+ // when the value leaves it. Off unlinks this value alone and the group keeps
112
+ // its other members. A new filter takes the pick's level. Every page raises a
113
+ // strip-only group to both, keeping its strips, and a page group to the
114
+ // report bar. Nothing else moves the group, so a value never lowers it.
115
+ export function valueFilterLevel(placement, current) {
116
+ if (placement === 'off') {
117
+ return null;
118
+ }
119
+ if (!current) {
120
+ return placement === 'page' ? 'page' : 'report';
121
+ }
122
+ if (placement !== 'every') {
123
+ return current;
124
+ }
125
+ switch (current) {
126
+ case 'component':
127
+ return 'both';
128
+ case 'page':
129
+ return 'report';
130
+ default:
131
+ return current;
132
+ }
133
+ }
134
+ // Where a group of a level shows in the report bar. No group (no filter) is
135
+ // off.
136
+ export function barPlacement(level) {
137
+ switch (level) {
138
+ case 'report':
139
+ case 'both':
140
+ return 'every';
141
+ case 'page':
142
+ return 'page';
143
+ default:
144
+ return 'off';
145
+ }
146
+ }
147
+ // Whether a group of a level shows on its components.
148
+ export function shownOnComponent(level) {
149
+ return level === 'component' || level === 'both';
150
+ }
151
+ // The level the two controls of a row ask for, or null when they ask for no
152
+ // filter at all. A page filter shows in its page's bar only, so This page
153
+ // only ignores the This component toggle.
154
+ export function filterLevel(placement, component) {
155
+ switch (placement) {
156
+ case 'page':
157
+ return 'page';
158
+ case 'every':
159
+ return component ? 'both' : 'report';
160
+ default:
161
+ return component ? 'component' : null;
162
+ }
163
+ }
164
+ // The This component toggle of a row: locked while This page only is picked.
165
+ export function componentToggleState(placement) {
166
+ return placement === 'page'
167
+ ? { disabled: true, tooltip: PAGE_FILTER_TOOLTIP }
168
+ : { disabled: false, tooltip: COMPONENT_TOGGLE_TOOLTIP };
169
+ }
170
+ // The groups the report settings' Filters tab lists defaults for: those of
171
+ // the report bar, every page or one, in bar order.
172
+ export function defaultRowGroups(groups) {
173
+ return (groups ?? [])
174
+ .filter((group) => group.level === 'report' || group.level === 'both' || group.level === 'page')
175
+ .sort((a, b) => a.order - b.order);
176
+ }
177
+ // A default row's label: a page group names its page, 'Region (page
178
+ // "Overview")'. A page with no name reads as the canvas names it ('Page 2').
179
+ // A page this report no longer holds adds nothing.
180
+ export function defaultRowLabel(group, pages) {
181
+ const label = group.label || group.filters?.[0]?.filterColumn || 'Filter';
182
+ if (group.level !== 'page') {
183
+ return label;
184
+ }
185
+ const index = (pages ?? []).findIndex((page) => page.id === group.pageId);
186
+ if (index < 0) {
187
+ return label;
188
+ }
189
+ return `${label} (page "${pages[index].name || `Page ${index + 1}`}")`;
190
+ }
191
+ // The Default period select's choices: Fixed dates, then every relative
192
+ // range in the server enum's order, named by `labels`. A stored range this
193
+ // viewer does not know is listed last, so the select still shows it.
194
+ export function defaultPeriodOptions(labels, stored = null) {
195
+ const options = [
196
+ { value: FIXED_DATES_PERIOD, name: 'Fixed dates' },
197
+ ...RELATIVE_RANGE_NAMES.map((relative) => ({ value: relative, name: labels(relative) })),
198
+ ];
199
+ return stored && stored !== FIXED_DATES_PERIOD && !isRelativeRange(stored)
200
+ ? [...options, { value: stored, name: labels(stored) }]
201
+ : options;
202
+ }
203
+ // The Default period a stored date range default opens on: its relative
204
+ // range, else Fixed dates (the days, or none).
205
+ export function defaultPeriod(stored) {
206
+ return stored?.relative && !stored.start && !stored.end
207
+ ? stored.relative
208
+ : FIXED_DATES_PERIOD;
209
+ }
210
+ // A date range default in its stored shape: the relative range picked, else
211
+ // the fixed days, or null when there are none. Never both: the server
212
+ // refuses a relative range with days.
213
+ export function dateRangeDefault(period, start, end) {
214
+ if (period !== FIXED_DATES_PERIOD) {
215
+ return { relative: period };
216
+ }
217
+ if (!start && !end) {
218
+ return null;
219
+ }
220
+ return { ...(start ? { start } : {}), ...(end ? { end } : {}) };
221
+ }
222
+ // A select default in its stored shape: the picks kept, or left out while
223
+ // Exclude these values is on, or null when nothing is picked.
224
+ export function selectDefault(values, exclude) {
225
+ if (!values.length) {
226
+ return null;
227
+ }
228
+ return exclude ? { excludeValues: values } : { values };
229
+ }
230
+ // A number range default in its stored shape from the ends as typed: an
231
+ // open end is left out, 0 is kept, and two open ends are no default.
232
+ export function numberRangeDefault(rawMin, rawMax) {
233
+ const min = parseDefaultBound(rawMin);
234
+ const max = parseDefaultBound(rawMax);
235
+ if (min === null && max === null) {
236
+ return null;
237
+ }
238
+ return { ...(min !== null ? { min } : {}), ...(max !== null ? { max } : {}) };
239
+ }
240
+ // Whether a select group's default row offers Exclude these values: the
241
+ // report bar's rule (offersExclude), so not on a server that does not serve
242
+ // exclude (an older server lists no features) nor on a group with a member
243
+ // that binds several columns (multiColumn). A default that already leaves
244
+ // values out keeps the toggle, so it can be turned off.
245
+ export function showExcludeToggle(group, features) {
246
+ if (group.type === 'select' && group.config?.default?.excludeValues?.length) {
247
+ return true;
248
+ }
249
+ return offersExclude(group, features);
250
+ }
251
+ // A stored or draft default in a stable form for comparing: empty and
252
+ // absent keys are dropped, so a no-op edit does not read as a change. 0 is an
253
+ // end like any other. Nothing left is null.
254
+ export function normalizeDefault(value) {
255
+ if (!value) {
256
+ return null;
257
+ }
258
+ const normalized = {};
259
+ if (value.start) {
260
+ normalized.start = value.start;
261
+ }
262
+ if (value.end) {
263
+ normalized.end = value.end;
264
+ }
265
+ if (value.values?.length) {
266
+ normalized.values = value.values;
267
+ }
268
+ if (value.excludeValues?.length) {
269
+ normalized.excludeValues = value.excludeValues;
270
+ }
271
+ if (typeof value.min === 'number') {
272
+ normalized.min = value.min;
273
+ }
274
+ if (typeof value.max === 'number') {
275
+ normalized.max = value.max;
276
+ }
277
+ if (value.value) {
278
+ normalized.value = value.value;
279
+ }
280
+ if (value.relative) {
281
+ normalized.relative = value.relative;
282
+ }
283
+ return Object.keys(normalized).length ? normalized : null;
284
+ }
285
+ // Whether a row's draft default differs from the group's stored one. Only a
286
+ // changed row is saved.
287
+ export function defaultChanged(stored, draft) {
288
+ return JSON.stringify(normalizeDefault(stored)) !== JSON.stringify(normalizeDefault(draft));
289
+ }
290
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLXNldHRpbmdzLXJ1bGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2ZpbHRlci1zZXR0aW5ncy1ydWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFtQkEsT0FBTyxFQUFFLG9CQUFvQixFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUd6RCxxRUFBcUU7QUFDckUsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQTZDO0lBQzNFLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO0lBQ25DLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFO0NBQy9DLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyx1Q0FBdUMsQ0FBQztBQUMzRSxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRywyQ0FBMkMsQ0FBQztBQUMvRSxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyx3QkFBd0IsQ0FBQztBQUVqRSwyRUFBMkU7QUFDM0UsdUJBQXVCO0FBQ3ZCLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLE9BQU8sQ0FBQztBQUUxQyxnRUFBZ0U7QUFDaEUsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxDQUFDO0FBRXJDLDZFQUE2RTtBQUM3RSwyRUFBMkU7QUFDM0Usd0VBQXdFO0FBQ3hFLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLHdCQUF3QixDQUFDO0FBQzVELE1BQU0sQ0FBQyxNQUFNLDJCQUEyQixHQUFHLGdFQUFnRSxDQUFDO0FBQzVHLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLEVBQUUsQ0FBQztBQUN6QyxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxHQUFHLENBQUM7QUFFM0MsK0RBQStEO0FB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LENBQUMsUUFBUSxFQUFFLENBQUM7UUFDbkIsVUFBVSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUM1RCxDQUFDO0FBRUQsNEVBQTRFO0FBQzVFLHdCQUF3QjtBQUN4QixNQUFNLFVBQVUsY0FBYyxDQUM1QixNQUE2QyxFQUM3QyxLQUE0QztJQUU1QyxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDOUYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSBydWxlcyBiZWhpbmQgdGhlIHR3byBmaWx0ZXIgc2V0dGluZ3MgZGlhbG9ncywga2VwdCBwdXJlIHNvIHRoZSBub2RlXG4vLyBoYXJuZXNzIGNoZWNrcyB0aGVtIHdpdGhvdXQgYSBkaWFsb2cuIFRoZSBjb21wb25lbnQgc2V0dGluZ3MnIEZpbHRlcnMgdGFiXG4vLyByZWFkcyB0aGUgVHlwZSBzZWxlY3QsIHRoZSBSZXBvcnQgYmFyIHNlbGVjdCBhbmQgdGhlIFRoaXMgY29tcG9uZW50IHRvZ2dsZVxuLy8gZnJvbSBoZXJlOyB0aGUgcmVwb3J0IHNldHRpbmdzJyBGaWx0ZXJzIHRhYiByZWFkcyBpdHMgZGVmYXVsdCByb3dzICh0aGVcbi8vIHBlcmlvZCwgdGhlIGV4Y2x1ZGUgdG9nZ2xlLCB0aGUgbnVtYmVyIHJhbmdlIGVuZHMgYW5kIHRoZWlyIGNoZWNrKSBmcm9tXG4vLyBoZXJlLiBUaGUgZGlhbG9ncyBvbmx5IGNhbGwgdGhlc2UuXG5pbXBvcnQgeyBGaWx0ZXJCYXJQbGFjZW1lbnQgfSBmcm9tICcuL2ludGVyZmFjZXMvZmlsdGVyLWJhci1wbGFjZW1lbnQudHlwZSc7XG5pbXBvcnQgeyBGaWx0ZXJDb21wb25lbnRUb2dnbGVTdGF0ZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9maWx0ZXItY29tcG9uZW50LXRvZ2dsZS1zdGF0ZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgRmlsdGVyU2V0dGluZ3NPcHRpb24gfSBmcm9tICcuL2ludGVyZmFjZXMvZmlsdGVyLXNldHRpbmdzLW9wdGlvbi5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgRmlsdGVyVHlwZVNlbGVjdFN0YXRlIH0gZnJvbSAnLi9pbnRlcmZhY2VzL2ZpbHRlci10eXBlLXNlbGVjdC1zdGF0ZS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0Vmlld2VyRmVhdHVyZSB9IGZyb20gJy4vaW50ZXJmYWNlcy9yZXBvcnQtdmlld2VyLWZlYXR1cmUudHlwZSc7XG5pbXBvcnQge1xuICBGaWx0ZXJHcm91cERlZmF1bHQsXG4gIFJlcG9ydEZpbHRlckdyb3VwLFxuICBSZXBvcnRGaWx0ZXJMZXZlbCxcbiAgUmVwb3J0RmlsdGVyVHlwZSxcbiAgUmVwb3J0UGFnZSxcbiAgUmVwb3J0UmVsYXRpdmVSYW5nZSxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUkVMQVRJVkVfUkFOR0VfTkFNRVMsIGlzUmVsYXRpdmVSYW5nZSB9IGZyb20gJy4vcmVwb3J0LXZpZXctY29uZmlnJztcbmltcG9ydCB7IG9mZmVyc0V4Y2x1ZGUgfSBmcm9tICcuL3JlcG9ydC12aWV3ZXItZmVhdHVyZXMnO1xuXG5cbi8vIFRoZSBUeXBlIHNlbGVjdCdzIGNob2ljZXMuIEEgY29sdW1uIHRoYXQgY2FuIGJlIGVpdGhlciBob2xkcyBib3RoLlxuZXhwb3J0IGNvbnN0IEZJTFRFUl9UWVBFX09QVElPTlM6IEZpbHRlclNldHRpbmdzT3B0aW9uPFJlcG9ydEZpbHRlclR5cGU+W10gPSBbXG4gIHsgdmFsdWU6ICdzZWxlY3QnLCBuYW1lOiAnVmFsdWVzJyB9LFxuICB7IHZhbHVlOiAnbnVtYmVyUmFuZ2UnLCBuYW1lOiAnTnVtYmVyIHJhbmdlJyB9LFxuXTtcblxuZXhwb3J0IGNvbnN0IFRZUEVfTE9DS0VEX1RPT0xUSVAgPSAnUmVtb3ZlIHRoZSBmaWx0ZXIgdG8gY2hhbmdlIGl0cyB0eXBlLic7XG5leHBvcnQgY29uc3QgUEFHRV9GSUxURVJfVE9PTFRJUCA9ICdBIHBhZ2UgZmlsdGVyIHNob3dzIGluIHRoZSBwYWdlIGJhciBvbmx5Lic7XG5leHBvcnQgY29uc3QgQ09NUE9ORU5UX1RPR0dMRV9UT09MVElQID0gJ1Nob3cgb24gdGhpcyBjb21wb25lbnQnO1xuXG4vLyBUaGUgRGVmYXVsdCBwZXJpb2Qgc2VsZWN0J3MgdmFsdWUgZm9yIGEgcmFuZ2Ugb2YgZml4ZWQgZGF5cy4gTm8gcmVsYXRpdmVcbi8vIHJhbmdlIGlzIG5hbWVkIHRoaXMuXG5leHBvcnQgY29uc3QgRklYRURfREFURVNfUEVSSU9EID0gJ2ZpeGVkJztcblxuLy8gSG93IG1hbnkgZGVjaW1hbHMgYSBEZWZhdWx0IG1pbmltdW0gb3IgRGVmYXVsdCBtYXhpbXVtIHRha2VzLlxuZXhwb3J0IGNvbnN0IERFRkFVTFRfQk9VTkRfU0NBTEUgPSA2O1xuXG4vLyBBIGZpbHRlcidzIE5hbWUgYW5kIExhYmVsLCBjaGVja2VkIGFzIHRoZSBzZXJ2ZXIgY2hlY2tzIHRoZW0sIHNvIGEgYmFkIG9uZVxuLy8gaXMgY2F1Z2h0IGJlZm9yZSBTYXZlLiBUaGUgbmFtZSBpcyBhbiBpZGVudGlmaWVyOiBhIGxldHRlciwgdGhlbiBsZXR0ZXJzXG4vLyBhbmQgZGlnaXRzLiBUaGF0IGl0IGlzIHVuaXF1ZSBpbiB0aGUgcmVwb3J0IGlzIHRoZSBzZXJ2ZXIncyB0byBjaGVjay5cbmV4cG9ydCBjb25zdCBGSUxURVJfTkFNRV9QQVRURVJOID0gL15bQS1aYS16XVtBLVphLXowLTldKiQvO1xuZXhwb3J0IGNvbnN0IEZJTFRFUl9OQU1FX1BBVFRFUk5fTUVTU0FHRSA9ICdBIG5hbWUgc3RhcnRzIHdpdGggYSBsZXR0ZXIgYW5kIGhvbGRzIG9ubHkgbGV0dGVycyBhbmQgZGlnaXRzLic7XG5leHBvcnQgY29uc3QgRklMVEVSX05BTUVfTUFYX0xFTkdUSCA9IDUwO1xuZXhwb3J0IGNvbnN0IEZJTFRFUl9MQUJFTF9NQVhfTEVOR1RIID0gMjAwO1xuXG4vLyBFdmVyeSBSZXBvcnQgYmFyIGNob2ljZSwgaW4gdGhlIG9yZGVyIHRoZSBzZWxlY3QgbGlzdHMgdGhlbS5cbmNvbnN0IEJBUl9QTEFDRU1FTlRfT1BUSU9OUzogRmlsdGVyU2V0dGluZ3NPcHRpb248RmlsdGVyQmFyUGxhY2VtZW50PltdID0gW1xuICB7IHZhbHVlOiAnb2ZmJywgbmFtZTogJ09mZicgfSxcbiAgeyB2YWx1ZTogJ2V2ZXJ5JywgbmFtZTogJ0V2ZXJ5IHBhZ2UnIH0sXG4gIHsgdmFsdWU6ICdwYWdlJywgbmFtZTogJ1RoaXMgcGFnZSBvbmx5JyB9LFxuXTtcblxuXG4vLyBBIG51bWJlciB3aXRoIGl0cyBncm91cCBjb21tYXMgaW4gcGxhY2UgKCcxLDI1MC41JywgJy0xMiwwMDAnKS5cbmNvbnN0IEdST1VQRURfREVDSU1BTCA9IC9eLT9cXGR7MSwzfSgsXFxkezN9KSsoXFwuXFxkKik/JC87XG4vLyBBIHBsYWluIGRlY2ltYWwgbnVtYmVyICgnMTI1MC41JywgJy0zJywgJzAnLCAnLjUnKS4gSGV4LCBiaW5hcnksIG9jdGFsLFxuLy8gZXhwb25lbnRzIGFuZCBpbm5lciBzcGFjZXMgZG8gbm90IG1hdGNoLCB0aG91Z2ggTnVtYmVyKCkgcmVhZHMgc29tZS5cbmNvbnN0IFBMQUlOX0RFQ0lNQUwgPSAvXi0/KFxcZCsoXFwuXFxkKik/fFxcLlxcZCspJC87XG5cbi8vIEEgZGVmYXVsdCByYW5nZSBlbmQgYXMgdHlwZWQuIEFuIGVtcHR5IGZpZWxkIGlzIG5vIGVuZC4gQSBudW1iZXIgaW5wdXRcbi8vIHdpdGggYSBtYXNrIGhhbmRzIGJhY2sgdGV4dCB3aXRoIGl0cyBncm91cCBjb21tYXMgKCcxLDI1MC41JyksIHNvIHRob3NlIGdvXG4vLyBiZWZvcmUgTnVtYmVyKCkgcmVhZHMgaXQ7IDAgaXMgYW4gZW5kIGxpa2UgYW55IG90aGVyLiBBbnl0aGluZyB0aGF0IGlzIG5vdFxuLy8gYSBkZWNpbWFsIG51bWJlciBpcyBubyBlbmQuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VEZWZhdWx0Qm91bmQocmF3OiB1bmtub3duKTogbnVtYmVyIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgcmF3ID09PSAnbnVtYmVyJykge1xuICAgIHJldHVybiBOdW1iZXIuaXNGaW5pdGUocmF3KSA/IHJhdyA6IG51bGw7XG4gIH1cblxuICBpZiAodHlwZW9mIHJhdyAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IHRyaW1tZWQgPSByYXcudHJpbSgpO1xuICBjb25zdCB0ZXh0ID0gR1JPVVBFRF9ERUNJTUFMLnRlc3QodHJpbW1lZCkgPyB0cmltbWVkLnJlcGxhY2UoLywvZywgJycpIDogdHJpbW1lZDtcbiAgaWYgKCFQTEFJTl9ERUNJTUFMLnRlc3QodGV4dCkpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IHZhbHVlID0gTnVtYmVyKHRleHQpO1xuXG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpID8gdmFsdWUgOiBudWxsO1xufVxuXG4vLyBXaHkgdHdvIHJhbmdlIGVuZHMgY2Fubm90IGJlIHNhdmVkLCBpbiB0aGUgc2VydmVyJ3Mgd29yZHMsIG9yIG51bGwuIEFuIG9wZW5cbi8vIGVuZCBpcyBhbHdheXMgZmluZS5cbmV4cG9ydCBmdW5jdGlvbiBib3VuZHNFcnJvcihtaW46IG51bWJlciB8IG51bGwsIG1heDogbnVtYmVyIHwgbnVsbCk6IHN0cmluZyB8IG51bGwge1xuICBpZiAobWluID09PSBudWxsIHx8IG1heCA9PT0gbnVsbCB8fCBtaW4gPD0gbWF4KSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gYG1pbiAoJHttaW59KSBpcyBhYm92ZSBtYXggKCR7bWF4fSkuYDtcbn1cblxuLy8gVGhlIFR5cGUgc2VsZWN0IG9mIGEgY29sdW1uIG9uIHRoZSBjb21wb25lbnQgc2V0dGluZ3MnIEZpbHRlcnMgdGFiLiBJdFxuLy8gc2hvd3Mgd2hlbiB0aGUgY29sdW1uIGNhbiB0YWtlIGVpdGhlciB0eXBlIGFuZCB0aGUgc2VydmVyIHNlcnZlcyBudW1iZXJcbi8vIHJhbmdlcyAoYW4gb2xkZXIgc2VydmVyIGxpc3RzIG5vIGZlYXR1cmVzKS4gQSBmaWx0ZXIncyB0eXBlIGNhbm5vdCBjaGFuZ2UsXG4vLyBzbyBpdCBpcyBsb2NrZWQgd2hpbGUgdGhlIGNvbHVtbiBoYXMgYSBmaWx0ZXIgb24gdGhpcyBjb21wb25lbnQuXG5leHBvcnQgZnVuY3Rpb24gdHlwZVNlbGVjdFN0YXRlKFxuICB0eXBlczogUmVwb3J0RmlsdGVyVHlwZVtdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbiAgaGFzRmlsdGVyT25UaGlzQ29tcG9uZW50OiBib29sZWFuLFxuICBmZWF0dXJlczogUmVwb3J0Vmlld2VyRmVhdHVyZVtdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbik6IEZpbHRlclR5cGVTZWxlY3RTdGF0ZSB7XG4gIGNvbnN0IHNob3cgPSAoZmVhdHVyZXMgPz8gW10pLmluY2x1ZGVzKCdudW1iZXJSYW5nZScpXG4gICAgJiYgRklMVEVSX1RZUEVfT1BUSU9OUy5ldmVyeSgob3B0aW9uKSA9PiAodHlwZXMgPz8gW10pLmluY2x1ZGVzKG9wdGlvbi52YWx1ZSkpO1xuXG4gIGlmICghc2hvdykge1xuICAgIHJldHVybiB7IHNob3c6IGZhbHNlLCBkaXNhYmxlZDogZmFsc2UsIHRvb2x0aXA6IG51bGwgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgc2hvdzogdHJ1ZSxcbiAgICBkaXNhYmxlZDogaGFzRmlsdGVyT25UaGlzQ29tcG9uZW50LFxuICAgIHRvb2x0aXA6IGhhc0ZpbHRlck9uVGhpc0NvbXBvbmVudCA/IFRZUEVfTE9DS0VEX1RPT0xUSVAgOiBudWxsLFxuICB9O1xufVxuXG4vLyBUaGUgbGV2ZWxzIGEgbmV3IG9yIG1vdmVkIGZpbHRlciBjYW4gdGFrZSBvbiBhIGNvbXBvbmVudC4gVGhpcyBwYWdlIG9ubHlcbi8vIG5lZWRzIGEgc2VydmVyIHRoYXQgc2VydmVzIHBhZ2UgZmlsdGVycyBhbmQgYSBjb21wb25lbnQgb24gYSBwYWdlIChhXG4vLyBoZWFkZXIgb3IgZm9vdGVyIGNvbXBvbmVudCBpcyBvbiBubyBwYWdlKS5cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJMZXZlbENob2ljZXMoXG4gIGZlYXR1cmVzOiBSZXBvcnRWaWV3ZXJGZWF0dXJlW10gfCBudWxsIHwgdW5kZWZpbmVkLFxuICBvblBhZ2U6IGJvb2xlYW4sXG4pOiBSZXBvcnRGaWx0ZXJMZXZlbFtdIHtcbiAgY29uc3QgbGV2ZWxzOiBSZXBvcnRGaWx0ZXJMZXZlbFtdID0gWydjb21wb25lbnQnLCAncmVwb3J0JywgJ2JvdGgnXTtcblxuICByZXR1cm4gb25QYWdlICYmIChmZWF0dXJlcyA/PyBbXSkuaW5jbHVkZXMoJ3BhZ2VTY29wZScpXG4gICAgPyBbLi4ubGV2ZWxzLCAncGFnZSddXG4gICAgOiBsZXZlbHM7XG59XG5cbi8vIFRoZSBSZXBvcnQgYmFyIHNlbGVjdCdzIGNob2ljZXMgZm9yIHRoZSBsZXZlbHMgb24gb2ZmZXIuIFRoZSBjaG9pY2UgYSByb3dcbi8vIGFscmVhZHkgaG9sZHMgaXMgYWx3YXlzIGxpc3RlZCwgc28gdGhlIHNlbGVjdCBuZXZlciBzaG93cyBibGFuay5cbmV4cG9ydCBmdW5jdGlvbiBiYXJQbGFjZW1lbnRPcHRpb25zKFxuICBsZXZlbENob2ljZXM6IFJlcG9ydEZpbHRlckxldmVsW10sXG4gIGN1cnJlbnQ6IEZpbHRlckJhclBsYWNlbWVudCA9ICdvZmYnLFxuKTogRmlsdGVyU2V0dGluZ3NPcHRpb248RmlsdGVyQmFyUGxhY2VtZW50PltdIHtcbiAgcmV0dXJuIEJBUl9QTEFDRU1FTlRfT1BUSU9OUy5maWx0ZXIoKG9wdGlvbikgPT4ge1xuICAgIHN3aXRjaCAob3B0aW9uLnZhbHVlKSB7XG4gICAgICBjYXNlICdldmVyeSc6XG4gICAgICAgIHJldHVybiBsZXZlbENob2ljZXMuaW5jbHVkZXMoJ3JlcG9ydCcpIHx8IGxldmVsQ2hvaWNlcy5pbmNsdWRlcygnYm90aCcpIHx8IGN1cnJlbnQgPT09ICdldmVyeSc7XG4gICAgICBjYXNlICdwYWdlJzpcbiAgICAgICAgcmV0dXJuIGxldmVsQ2hvaWNlcy5pbmNsdWRlcygncGFnZScpIHx8IGN1cnJlbnQgPT09ICdwYWdlJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfSk7XG59XG5cbi8vIEEgdmFsdWUncyBSZXBvcnQgYmFyIGNob2ljZXMuIEEgdmFsdWUgaGFzIG5vIHN0cmlwIG9mIGl0cyBvd24gYW5kIGl0c1xuLy8gZ3JvdXAgbWF5IGJlIHNoYXJlZCwgc28gYSBwaWNrIG5ldmVyIGxvd2VycyB0aGUgZ3JvdXAgKHRoZSBpbmxpbmUgdmFsdWVzXG4vLyBydWxlKTogVGhpcyBwYWdlIG9ubHkgaXMgb2ZmZXJlZCBmb3IgYSBuZXcgZmlsdGVyLCBvciBmb3IgYSBncm91cCB0aGF0IGlzXG4vLyBhbHJlYWR5IGEgcGFnZSBncm91cCwgbmV2ZXIgdG8gbW92ZSBhIHNoYXJlZCBncm91cCB0byBvbmUgcGFnZS5cbmV4cG9ydCBmdW5jdGlvbiB2YWx1ZVBsYWNlbWVudE9wdGlvbnMoXG4gIGxldmVsQ2hvaWNlczogUmVwb3J0RmlsdGVyTGV2ZWxbXSxcbiAgY3VycmVudDogUmVwb3J0RmlsdGVyTGV2ZWwgfCBudWxsIHwgdW5kZWZpbmVkLFxuKTogRmlsdGVyU2V0dGluZ3NPcHRpb248RmlsdGVyQmFyUGxhY2VtZW50PltdIHtcbiAgY29uc3QgY2hvaWNlcyA9ICFjdXJyZW50IHx8IGN1cnJlbnQgPT09ICdwYWdlJ1xuICAgID8gbGV2ZWxDaG9pY2VzXG4gICAgOiBsZXZlbENob2ljZXMuZmlsdGVyKChsZXZlbCkgPT4gbGV2ZWwgIT09ICdwYWdlJyk7XG5cbiAgcmV0dXJuIGJhclBsYWNlbWVudE9wdGlvbnMoY2hvaWNlcywgYmFyUGxhY2VtZW50KGN1cnJlbnQpKTtcbn1cblxuLy8gVGhlIGxldmVsIGEgdmFsdWUncyBmaWx0ZXIgZ3JvdXAgZW5kcyBhdCBhZnRlciBhIFJlcG9ydCBiYXIgcGljaywgb3IgbnVsbFxuLy8gd2hlbiB0aGUgdmFsdWUgbGVhdmVzIGl0LiBPZmYgdW5saW5rcyB0aGlzIHZhbHVlIGFsb25lIGFuZCB0aGUgZ3JvdXAga2VlcHNcbi8vIGl0cyBvdGhlciBtZW1iZXJzLiBBIG5ldyBmaWx0ZXIgdGFrZXMgdGhlIHBpY2sncyBsZXZlbC4gRXZlcnkgcGFnZSByYWlzZXMgYVxuLy8gc3RyaXAtb25seSBncm91cCB0byBib3RoLCBrZWVwaW5nIGl0cyBzdHJpcHMsIGFuZCBhIHBhZ2UgZ3JvdXAgdG8gdGhlXG4vLyByZXBvcnQgYmFyLiBOb3RoaW5nIGVsc2UgbW92ZXMgdGhlIGdyb3VwLCBzbyBhIHZhbHVlIG5ldmVyIGxvd2VycyBpdC5cbmV4cG9ydCBmdW5jdGlvbiB2YWx1ZUZpbHRlckxldmVsKFxuICBwbGFjZW1lbnQ6IEZpbHRlckJhclBsYWNlbWVudCxcbiAgY3VycmVudDogUmVwb3J0RmlsdGVyTGV2ZWwgfCBudWxsIHwgdW5kZWZpbmVkLFxuKTogUmVwb3J0RmlsdGVyTGV2ZWwgfCBudWxsIHtcbiAgaWYgKHBsYWNlbWVudCA9PT0gJ29mZicpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGlmICghY3VycmVudCkge1xuICAgIHJldHVybiBwbGFjZW1lbnQgPT09ICdwYWdlJyA/ICdwYWdlJyA6ICdyZXBvcnQnO1xuICB9XG5cbiAgaWYgKHBsYWNlbWVudCAhPT0gJ2V2ZXJ5Jykge1xuICAgIHJldHVybiBjdXJyZW50O1xuICB9XG5cbiAgc3dpdGNoIChjdXJyZW50KSB7XG4gICAgY2FzZSAnY29tcG9uZW50JzpcbiAgICAgIHJldHVybiAnYm90aCc7XG4gICAgY2FzZSAncGFnZSc6XG4gICAgICByZXR1cm4gJ3JlcG9ydCc7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBjdXJyZW50O1xuICB9XG59XG5cbi8vIFdoZXJlIGEgZ3JvdXAgb2YgYSBsZXZlbCBzaG93cyBpbiB0aGUgcmVwb3J0IGJhci4gTm8gZ3JvdXAgKG5vIGZpbHRlcikgaXNcbi8vIG9mZi5cbmV4cG9ydCBmdW5jdGlvbiBiYXJQbGFjZW1lbnQobGV2ZWw6IFJlcG9ydEZpbHRlckxldmVsIHwgbnVsbCB8IHVuZGVmaW5lZCk6IEZpbHRlckJhclBsYWNlbWVudCB7XG4gIHN3aXRjaCAobGV2ZWwpIHtcbiAgICBjYXNlICdyZXBvcnQnOlxuICAgIGNhc2UgJ2JvdGgnOlxuICAgICAgcmV0dXJuICdldmVyeSc7XG4gICAgY2FzZSAncGFnZSc6XG4gICAgICByZXR1cm4gJ3BhZ2UnO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gJ29mZic7XG4gIH1cbn1cblxuLy8gV2hldGhlciBhIGdyb3VwIG9mIGEgbGV2ZWwgc2hvd3Mgb24gaXRzIGNvbXBvbmVudHMuXG5leHBvcnQgZnVuY3Rpb24gc2hvd25PbkNvbXBvbmVudChsZXZlbDogUmVwb3J0RmlsdGVyTGV2ZWwgfCBudWxsIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gIHJldHVybiBsZXZlbCA9PT0gJ2NvbXBvbmVudCcgfHwgbGV2ZWwgPT09ICdib3RoJztcbn1cblxuLy8gVGhlIGxldmVsIHRoZSB0d28gY29udHJvbHMgb2YgYSByb3cgYXNrIGZvciwgb3IgbnVsbCB3aGVuIHRoZXkgYXNrIGZvciBub1xuLy8gZmlsdGVyIGF0IGFsbC4gQSBwYWdlIGZpbHRlciBzaG93cyBpbiBpdHMgcGFnZSdzIGJhciBvbmx5LCBzbyBUaGlzIHBhZ2Vcbi8vIG9ubHkgaWdub3JlcyB0aGUgVGhpcyBjb21wb25lbnQgdG9nZ2xlLlxuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlckxldmVsKHBsYWNlbWVudDogRmlsdGVyQmFyUGxhY2VtZW50LCBjb21wb25lbnQ6IGJvb2xlYW4pOiBSZXBvcnRGaWx0ZXJMZXZlbCB8IG51bGwge1xuICBzd2l0Y2ggKHBsYWNlbWVudCkge1xuICAgIGNhc2UgJ3BhZ2UnOlxuICAgICAgcmV0dXJuICdwYWdlJztcbiAgICBjYXNlICdldmVyeSc6XG4gICAgICByZXR1cm4gY29tcG9uZW50ID8gJ2JvdGgnIDogJ3JlcG9ydCc7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBjb21wb25lbnQgPyAnY29tcG9uZW50JyA6IG51bGw7XG4gIH1cbn1cblxuLy8gVGhlIFRoaXMgY29tcG9uZW50IHRvZ2dsZSBvZiBhIHJvdzogbG9ja2VkIHdoaWxlIFRoaXMgcGFnZSBvbmx5IGlzIHBpY2tlZC5cbmV4cG9ydCBmdW5jdGlvbiBjb21wb25lbnRUb2dnbGVTdGF0ZShwbGFjZW1lbnQ6IEZpbHRlckJhclBsYWNlbWVudCk6IEZpbHRlckNvbXBvbmVudFRvZ2dsZVN0YXRlIHtcbiAgcmV0dXJuIHBsYWNlbWVudCA9PT0gJ3BhZ2UnXG4gICAgPyB7IGRpc2FibGVkOiB0cnVlLCB0b29sdGlwOiBQQUdFX0ZJTFRFUl9UT09MVElQIH1cbiAgICA6IHsgZGlzYWJsZWQ6IGZhbHNlLCB0b29sdGlwOiBDT01QT05FTlRfVE9HR0xFX1RPT0xUSVAgfTtcbn1cblxuLy8gVGhlIGdyb3VwcyB0aGUgcmVwb3J0IHNldHRpbmdzJyBGaWx0ZXJzIHRhYiBsaXN0cyBkZWZhdWx0cyBmb3I6IHRob3NlIG9mXG4vLyB0aGUgcmVwb3J0IGJhciwgZXZlcnkgcGFnZSBvciBvbmUsIGluIGJhciBvcmRlci5cbmV4cG9ydCBmdW5jdGlvbiBkZWZhdWx0Um93R3JvdXBzKGdyb3VwczogUmVwb3J0RmlsdGVyR3JvdXBbXSB8IG51bGwgfCB1bmRlZmluZWQpOiBSZXBvcnRGaWx0ZXJHcm91cFtdIHtcbiAgcmV0dXJuIChncm91cHMgPz8gW10pXG4gICAgLmZpbHRlcigoZ3JvdXApID0+IGdyb3VwLmxldmVsID09PSAncmVwb3J0JyB8fCBncm91cC5sZXZlbCA9PT0gJ2JvdGgnIHx8IGdyb3VwLmxldmVsID09PSAncGFnZScpXG4gICAgLnNvcnQoKGEsIGIpID0+IGEub3JkZXIgLSBiLm9yZGVyKTtcbn1cblxuLy8gQSBkZWZhdWx0IHJvdydzIGxhYmVsOiBhIHBhZ2UgZ3JvdXAgbmFtZXMgaXRzIHBhZ2UsICdSZWdpb24gKHBhZ2Vcbi8vIFwiT3ZlcnZpZXdcIiknLiBBIHBhZ2Ugd2l0aCBubyBuYW1lIHJlYWRzIGFzIHRoZSBjYW52YXMgbmFtZXMgaXQgKCdQYWdlIDInKS5cbi8vIEEgcGFnZSB0aGlzIHJlcG9ydCBubyBsb25nZXIgaG9sZHMgYWRkcyBub3RoaW5nLlxuZXhwb3J0IGZ1bmN0aW9uIGRlZmF1bHRSb3dMYWJlbChncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsIHBhZ2VzOiBSZXBvcnRQYWdlW10gfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHtcbiAgY29uc3QgbGFiZWwgPSBncm91cC5sYWJlbCB8fCBncm91cC5maWx0ZXJzPy5bMF0/LmZpbHRlckNvbHVtbiB8fCAnRmlsdGVyJztcblxuICBpZiAoZ3JvdXAubGV2ZWwgIT09ICdwYWdlJykge1xuICAgIHJldHVybiBsYWJlbDtcbiAgfVxuXG4gIGNvbnN0IGluZGV4ID0gKHBhZ2VzID8/IFtdKS5maW5kSW5kZXgoKHBhZ2UpID0+IHBhZ2UuaWQgPT09IGdyb3VwLnBhZ2VJZCk7XG4gIGlmIChpbmRleCA8IDApIHtcbiAgICByZXR1cm4gbGFiZWw7XG4gIH1cblxuICByZXR1cm4gYCR7bGFiZWx9IChwYWdlIFwiJHtwYWdlc1tpbmRleF0ubmFtZSB8fCBgUGFnZSAke2luZGV4ICsgMX1gfVwiKWA7XG59XG5cbi8vIFRoZSBEZWZhdWx0IHBlcmlvZCBzZWxlY3QncyBjaG9pY2VzOiBGaXhlZCBkYXRlcywgdGhlbiBldmVyeSByZWxhdGl2ZVxuLy8gcmFuZ2UgaW4gdGhlIHNlcnZlciBlbnVtJ3Mgb3JkZXIsIG5hbWVkIGJ5IGBsYWJlbHNgLiBBIHN0b3JlZCByYW5nZSB0aGlzXG4vLyB2aWV3ZXIgZG9lcyBub3Qga25vdyBpcyBsaXN0ZWQgbGFzdCwgc28gdGhlIHNlbGVjdCBzdGlsbCBzaG93cyBpdC5cbmV4cG9ydCBmdW5jdGlvbiBkZWZhdWx0UGVyaW9kT3B0aW9ucyhcbiAgbGFiZWxzOiAocmVsYXRpdmU6IFJlcG9ydFJlbGF0aXZlUmFuZ2UpID0+IHN0cmluZyxcbiAgc3RvcmVkOiBzdHJpbmcgfCBudWxsID0gbnVsbCxcbik6IEZpbHRlclNldHRpbmdzT3B0aW9uW10ge1xuICBjb25zdCBvcHRpb25zOiBGaWx0ZXJTZXR0aW5nc09wdGlvbltdID0gW1xuICAgIHsgdmFsdWU6IEZJWEVEX0RBVEVTX1BFUklPRCwgbmFtZTogJ0ZpeGVkIGRhdGVzJyB9LFxuICAgIC4uLlJFTEFUSVZFX1JBTkdFX05BTUVTLm1hcCgocmVsYXRpdmUpID0+ICh7IHZhbHVlOiByZWxhdGl2ZSwgbmFtZTogbGFiZWxzKHJlbGF0aXZlKSB9KSksXG4gIF07XG5cbiAgcmV0dXJuIHN0b3JlZCAmJiBzdG9yZWQgIT09IEZJWEVEX0RBVEVTX1BFUklPRCAmJiAhaXNSZWxhdGl2ZVJhbmdlKHN0b3JlZClcbiAgICA/IFsuLi5vcHRpb25zLCB7IHZhbHVlOiBzdG9yZWQsIG5hbWU6IGxhYmVscyhzdG9yZWQgYXMgUmVwb3J0UmVsYXRpdmVSYW5nZSkgfV1cbiAgICA6IG9wdGlvbnM7XG59XG5cbi8vIFRoZSBEZWZhdWx0IHBlcmlvZCBhIHN0b3JlZCBkYXRlIHJhbmdlIGRlZmF1bHQgb3BlbnMgb246IGl0cyByZWxhdGl2ZVxuLy8gcmFuZ2UsIGVsc2UgRml4ZWQgZGF0ZXMgKHRoZSBkYXlzLCBvciBub25lKS5cbmV4cG9ydCBmdW5jdGlvbiBkZWZhdWx0UGVyaW9kKHN0b3JlZDogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIHJldHVybiBzdG9yZWQ/LnJlbGF0aXZlICYmICFzdG9yZWQuc3RhcnQgJiYgIXN0b3JlZC5lbmRcbiAgICA/IHN0b3JlZC5yZWxhdGl2ZVxuICAgIDogRklYRURfREFURVNfUEVSSU9EO1xufVxuXG4vLyBBIGRhdGUgcmFuZ2UgZGVmYXVsdCBpbiBpdHMgc3RvcmVkIHNoYXBlOiB0aGUgcmVsYXRpdmUgcmFuZ2UgcGlja2VkLCBlbHNlXG4vLyB0aGUgZml4ZWQgZGF5cywgb3IgbnVsbCB3aGVuIHRoZXJlIGFyZSBub25lLiBOZXZlciBib3RoOiB0aGUgc2VydmVyXG4vLyByZWZ1c2VzIGEgcmVsYXRpdmUgcmFuZ2Ugd2l0aCBkYXlzLlxuZXhwb3J0IGZ1bmN0aW9uIGRhdGVSYW5nZURlZmF1bHQoXG4gIHBlcmlvZDogc3RyaW5nLFxuICBzdGFydDogc3RyaW5nIHwgbnVsbCxcbiAgZW5kOiBzdHJpbmcgfCBudWxsLFxuKTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB7XG4gIGlmIChwZXJpb2QgIT09IEZJWEVEX0RBVEVTX1BFUklPRCkge1xuICAgIHJldHVybiB7IHJlbGF0aXZlOiBwZXJpb2QgfTtcbiAgfVxuXG4gIGlmICghc3RhcnQgJiYgIWVuZCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHsgLi4uKHN0YXJ0ID8geyBzdGFydCB9IDoge30pLCAuLi4oZW5kID8geyBlbmQgfSA6IHt9KSB9O1xufVxuXG4vLyBBIHNlbGVjdCBkZWZhdWx0IGluIGl0cyBzdG9yZWQgc2hhcGU6IHRoZSBwaWNrcyBrZXB0LCBvciBsZWZ0IG91dCB3aGlsZVxuLy8gRXhjbHVkZSB0aGVzZSB2YWx1ZXMgaXMgb24sIG9yIG51bGwgd2hlbiBub3RoaW5nIGlzIHBpY2tlZC5cbmV4cG9ydCBmdW5jdGlvbiBzZWxlY3REZWZhdWx0KHZhbHVlczogdW5rbm93bltdLCBleGNsdWRlOiBib29sZWFuKTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB7XG4gIGlmICghdmFsdWVzLmxlbmd0aCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIGV4Y2x1ZGUgPyB7IGV4Y2x1ZGVWYWx1ZXM6IHZhbHVlcyB9IDogeyB2YWx1ZXMgfTtcbn1cblxuLy8gQSBudW1iZXIgcmFuZ2UgZGVmYXVsdCBpbiBpdHMgc3RvcmVkIHNoYXBlIGZyb20gdGhlIGVuZHMgYXMgdHlwZWQ6IGFuXG4vLyBvcGVuIGVuZCBpcyBsZWZ0IG91dCwgMCBpcyBrZXB0LCBhbmQgdHdvIG9wZW4gZW5kcyBhcmUgbm8gZGVmYXVsdC5cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJSYW5nZURlZmF1bHQocmF3TWluOiB1bmtub3duLCByYXdNYXg6IHVua25vd24pOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHtcbiAgY29uc3QgbWluID0gcGFyc2VEZWZhdWx0Qm91bmQocmF3TWluKTtcbiAgY29uc3QgbWF4ID0gcGFyc2VEZWZhdWx0Qm91bmQocmF3TWF4KTtcblxuICBpZiAobWluID09PSBudWxsICYmIG1heCA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHsgLi4uKG1pbiAhPT0gbnVsbCA/IHsgbWluIH0gOiB7fSksIC4uLihtYXggIT09IG51bGwgPyB7IG1heCB9IDoge30pIH07XG59XG5cbi8vIFdoZXRoZXIgYSBzZWxlY3QgZ3JvdXAncyBkZWZhdWx0IHJvdyBvZmZlcnMgRXhjbHVkZSB0aGVzZSB2YWx1ZXM6IHRoZVxuLy8gcmVwb3J0IGJhcidzIHJ1bGUgKG9mZmVyc0V4Y2x1ZGUpLCBzbyBub3Qgb24gYSBzZXJ2ZXIgdGhhdCBkb2VzIG5vdCBzZXJ2ZVxuLy8gZXhjbHVkZSAoYW4gb2xkZXIgc2VydmVyIGxpc3RzIG5vIGZlYXR1cmVzKSBub3Igb24gYSBncm91cCB3aXRoIGEgbWVtYmVyXG4vLyB0aGF0IGJpbmRzIHNldmVyYWwgY29sdW1ucyAobXVsdGlDb2x1bW4pLiBBIGRlZmF1bHQgdGhhdCBhbHJlYWR5IGxlYXZlc1xuLy8gdmFsdWVzIG91dCBrZWVwcyB0aGUgdG9nZ2xlLCBzbyBpdCBjYW4gYmUgdHVybmVkIG9mZi5cbmV4cG9ydCBmdW5jdGlvbiBzaG93RXhjbHVkZVRvZ2dsZShcbiAgZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLFxuICBmZWF0dXJlczogUmVwb3J0Vmlld2VyRmVhdHVyZVtdIHwgbnVsbCB8IHVuZGVmaW5lZCxcbik6IGJvb2xlYW4ge1xuICBpZiAoZ3JvdXAudHlwZSA9PT0gJ3NlbGVjdCcgJiYgZ3JvdXAuY29uZmlnPy5kZWZhdWx0Py5leGNsdWRlVmFsdWVzPy5sZW5ndGgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBvZmZlcnNFeGNsdWRlKGdyb3VwLCBmZWF0dXJlcyk7XG59XG5cbi8vIEEgc3RvcmVkIG9yIGRyYWZ0IGRlZmF1bHQgaW4gYSBzdGFibGUgZm9ybSBmb3IgY29tcGFyaW5nOiBlbXB0eSBhbmRcbi8vIGFic2VudCBrZXlzIGFyZSBkcm9wcGVkLCBzbyBhIG5vLW9wIGVkaXQgZG9lcyBub3QgcmVhZCBhcyBhIGNoYW5nZS4gMCBpcyBhblxuLy8gZW5kIGxpa2UgYW55IG90aGVyLiBOb3RoaW5nIGxlZnQgaXMgbnVsbC5cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVEZWZhdWx0KHZhbHVlOiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHwgdW5kZWZpbmVkKTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB7XG4gIGlmICghdmFsdWUpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0IG5vcm1hbGl6ZWQ6IEZpbHRlckdyb3VwRGVmYXVsdCA9IHt9O1xuICBpZiAodmFsdWUuc3RhcnQpIHtcbiAgICBub3JtYWxpemVkLnN0YXJ0ID0gdmFsdWUuc3RhcnQ7XG4gIH1cbiAgaWYgKHZhbHVlLmVuZCkge1xuICAgIG5vcm1hbGl6ZWQuZW5kID0gdmFsdWUuZW5kO1xuICB9XG4gIGlmICh2YWx1ZS52YWx1ZXM/Lmxlbmd0aCkge1xuICAgIG5vcm1hbGl6ZWQudmFsdWVzID0gdmFsdWUudmFsdWVzO1xuICB9XG4gIGlmICh2YWx1ZS5leGNsdWRlVmFsdWVzPy5sZW5ndGgpIHtcbiAgICBub3JtYWxpemVkLmV4Y2x1ZGVWYWx1ZXMgPSB2YWx1ZS5leGNsdWRlVmFsdWVzO1xuICB9XG4gIGlmICh0eXBlb2YgdmFsdWUubWluID09PSAnbnVtYmVyJykge1xuICAgIG5vcm1hbGl6ZWQubWluID0gdmFsdWUubWluO1xuICB9XG4gIGlmICh0eXBlb2YgdmFsdWUubWF4ID09PSAnbnVtYmVyJykge1xuICAgIG5vcm1hbGl6ZWQubWF4ID0gdmFsdWUubWF4O1xuICB9XG4gIGlmICh2YWx1ZS52YWx1ZSkge1xuICAgIG5vcm1hbGl6ZWQudmFsdWUgPSB2YWx1ZS52YWx1ZTtcbiAgfVxuICBpZiAodmFsdWUucmVsYXRpdmUpIHtcbiAgICBub3JtYWxpemVkLnJlbGF0aXZlID0gdmFsdWUucmVsYXRpdmU7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmtleXMobm9ybWFsaXplZCkubGVuZ3RoID8gbm9ybWFsaXplZCA6IG51bGw7XG59XG5cbi8vIFdoZXRoZXIgYSByb3cncyBkcmFmdCBkZWZhdWx0IGRpZmZlcnMgZnJvbSB0aGUgZ3JvdXAncyBzdG9yZWQgb25lLiBPbmx5IGFcbi8vIGNoYW5nZWQgcm93IGlzIHNhdmVkLlxuZXhwb3J0IGZ1bmN0aW9uIGRlZmF1bHRDaGFuZ2VkKFxuICBzdG9yZWQ6IEZpbHRlckdyb3VwRGVmYXVsdCB8IG51bGwgfCB1bmRlZmluZWQsXG4gIGRyYWZ0OiBGaWx0ZXJHcm91cERlZmF1bHQgfCBudWxsIHwgdW5kZWZpbmVkLFxuKTogYm9vbGVhbiB7XG4gIHJldHVybiBKU09OLnN0cmluZ2lmeShub3JtYWxpemVEZWZhdWx0KHN0b3JlZCkpICE9PSBKU09OLnN0cmluZ2lmeShub3JtYWxpemVEZWZhdWx0KGRyYWZ0KSk7XG59XG4iXX0=