@firestitch/report 18.8.1 → 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 (208) 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/component-text/component-text.component.d.ts +47 -2
  6. package/app/reports/components/component-text/value-embed.plugin.d.ts +67 -0
  7. package/app/reports/components/report-canvas/report-canvas.component.d.ts +37 -9
  8. package/app/reports/components/report-component/report-component.component.d.ts +45 -2
  9. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  10. package/app/reports/data/report.data.d.ts +18 -2
  11. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +25 -2
  12. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  13. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  14. package/app/reports/drill-crumbs.d.ts +12 -0
  15. package/app/reports/enums/report-value-formula.enum.d.ts +6 -0
  16. package/app/reports/export/report-export-collector.service.d.ts +35 -4
  17. package/app/reports/export/report-export.service.d.ts +3 -1
  18. package/app/reports/export/report-filter-lines.d.ts +18 -0
  19. package/app/reports/export/report-pdf.service.d.ts +18 -2
  20. package/app/reports/export/report-pptx.service.d.ts +15 -2
  21. package/app/reports/export/report-text-layout.service.d.ts +35 -0
  22. package/app/reports/filter-settings-rules.d.ts +33 -0
  23. package/app/reports/format.d.ts +2 -1
  24. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  25. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  26. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  27. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  28. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  29. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  30. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  31. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  33. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  34. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  35. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  37. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  38. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  39. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  40. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  41. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  43. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  44. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  45. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  46. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  47. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  48. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  49. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  51. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  52. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  53. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  56. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  57. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  58. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  59. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  60. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  61. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  63. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  65. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  66. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  67. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  68. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  69. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  70. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  71. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  72. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  73. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  74. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  75. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  76. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  77. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  78. package/app/reports/interfaces/report.interface.d.ts +48 -5
  79. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  80. package/app/reports/layout.d.ts +2 -0
  81. package/app/reports/mark-click.d.ts +20 -0
  82. package/app/reports/option-builder.d.ts +12 -1
  83. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  84. package/app/reports/report-date-presets.d.ts +2 -0
  85. package/app/reports/report-filter-items.d.ts +27 -22
  86. package/app/reports/report-tile.d.ts +2 -0
  87. package/app/reports/report-url-state.d.ts +27 -10
  88. package/app/reports/report-view-config.d.ts +36 -0
  89. package/app/reports/report-view-menu.d.ts +15 -0
  90. package/app/reports/report-viewer-features.d.ts +5 -0
  91. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  92. package/app/reports/services/report-filter-state.service.d.ts +65 -2
  93. package/app/reports/services/report-view.service.d.ts +51 -0
  94. package/app/reports/text.d.ts +50 -0
  95. package/app/reports/tile-data-state.d.ts +7 -0
  96. package/app/reports/tile-loads.d.ts +4 -0
  97. package/app/reports/values.d.ts +17 -0
  98. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  99. package/app/reports/views/report/report.component.d.ts +6 -0
  100. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  101. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  102. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  103. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  104. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  105. package/esm2022/app/reports/components/component-text/component-text.component.mjs +213 -16
  106. package/esm2022/app/reports/components/component-text/value-embed.plugin.mjs +484 -0
  107. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +296 -55
  108. package/esm2022/app/reports/components/report-component/report-component.component.mjs +318 -76
  109. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  110. package/esm2022/app/reports/data/report.data.mjs +103 -8
  111. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +210 -44
  112. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  113. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  114. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  115. package/esm2022/app/reports/enums/report-value-formula.enum.mjs +14 -0
  116. package/esm2022/app/reports/export/report-export-collector.service.mjs +299 -125
  117. package/esm2022/app/reports/export/report-export.service.mjs +57 -19
  118. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  119. package/esm2022/app/reports/export/report-pdf.service.mjs +315 -71
  120. package/esm2022/app/reports/export/report-pptx.service.mjs +293 -71
  121. package/esm2022/app/reports/export/report-text-layout.service.mjs +241 -0
  122. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  123. package/esm2022/app/reports/format.mjs +13 -30
  124. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  125. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  138. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  140. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  164. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  165. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  166. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  167. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  168. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  169. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  170. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  171. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  172. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  173. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  174. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  175. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  176. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  177. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  178. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  179. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  180. package/esm2022/app/reports/layout.mjs +11 -1
  181. package/esm2022/app/reports/mark-click.mjs +193 -0
  182. package/esm2022/app/reports/option-builder.mjs +159 -15
  183. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  184. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  185. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  186. package/esm2022/app/reports/report-tile.mjs +12 -0
  187. package/esm2022/app/reports/report-url-state.mjs +596 -108
  188. package/esm2022/app/reports/report-view-config.mjs +697 -0
  189. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  190. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  191. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  192. package/esm2022/app/reports/services/report-filter-state.service.mjs +715 -71
  193. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  194. package/esm2022/app/reports/text.mjs +293 -85
  195. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  196. package/esm2022/app/reports/tile-loads.mjs +38 -0
  197. package/esm2022/app/reports/values.mjs +183 -0
  198. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +180 -46
  199. package/esm2022/app/reports/views/report/report.component.mjs +106 -23
  200. package/esm2022/public_api.mjs +24 -1
  201. package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  202. package/fesm2022/{firestitch-report-echarts-CFnbJx44.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  203. package/fesm2022/{firestitch-report-firestitch-report-CSylkyko.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +11315 -4201
  204. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  205. package/fesm2022/firestitch-report.mjs +1 -1
  206. package/package.json +1 -1
  207. package/public_api.d.ts +23 -0
  208. package/fesm2022/firestitch-report-firestitch-report-CSylkyko.mjs.map +0 -1
@@ -0,0 +1,127 @@
1
+ import { isMatchAnyGroup } from './report-filter-items';
2
+ import { isTile } from './report-tile';
3
+ import { isChartGranularity } from './report-view-config';
4
+ // Whether a component is a chart on a time x-axis: the only component the
5
+ // report's group-by grain applies to. A deliberate mirror of the server's
6
+ // ReportQueryRunner::_isTimeSeriesChart, which is canonical and drops the
7
+ // grain for every other component; kept so a product pinned to an older
8
+ // framework does not re-bucket a non-time chart.
9
+ export function isTimeSeriesChart(component) {
10
+ return component.type === 'chart' && component.config?.xAxis?.kind === 'time';
11
+ }
12
+ // The interaction state one tile's data request carries, read off a view
13
+ // document of the screen (the state service's snapshot()): the group-by grain
14
+ // for a time-series chart, a list's sort, search and hidden columns, a
15
+ // chart's drill path, and, while the groups match 'any', the groups that
16
+ // combine (matchAnyGroupIds). The tile on screen, its CSV, the PDF and
17
+ // PowerPoint collector and the zip all build their state here, so a file
18
+ // always holds what the screen shows. A list's paging is the caller's. Never
19
+ // sets unchangedIfUnreached: that belongs to an on-screen refetch alone.
20
+ //
21
+ // A drill path and the grain may both be sent: the server lets the drilled
22
+ // level win, and a server that does not drill keeps the grain.
23
+ export function tileDataState(report, component, snapshot) {
24
+ const state = {};
25
+ if (!isTile(component)) {
26
+ return state;
27
+ }
28
+ const tile = snapshot.tiles?.[component.id];
29
+ if (isTimeSeriesChart(component) && isChartGranularity(snapshot.groupBy)) {
30
+ state.frequency = snapshot.groupBy;
31
+ }
32
+ if (component.type === 'list') {
33
+ if (tile?.sort?.column) {
34
+ state.sort = { ...tile.sort };
35
+ }
36
+ if (tile?.search) {
37
+ state.search = tile.search;
38
+ }
39
+ if (tile?.hidden?.length) {
40
+ state.hiddenColumns = [...tile.hidden];
41
+ }
42
+ }
43
+ if (component.type === 'chart' && tile?.drill?.length) {
44
+ state.drill = tile.drill.map((step) => ({ ...step }));
45
+ }
46
+ const matchAnyGroupIds = tileMatchAnyGroupIds(report, component, snapshot);
47
+ if (matchAnyGroupIds.length) {
48
+ state.matchAnyGroupIds = matchAnyGroupIds;
49
+ }
50
+ return state;
51
+ }
52
+ // Each tile's state for the zip export (tileDataState), by component id: the
53
+ // tiles of every page, or of `pageId` alone. The zip holds no header or
54
+ // footer tile. A tile with nothing to send is left out, so an untouched report
55
+ // sends no states at all.
56
+ export function zipExportStates(report, snapshot, pageId = null) {
57
+ const states = {};
58
+ (report.pages ?? [])
59
+ .filter((page) => !pageId || page.id === pageId)
60
+ .flatMap((page) => page.components ?? [])
61
+ .forEach((component) => {
62
+ const state = tileDataState(report, component, snapshot);
63
+ if (Object.keys(state).length) {
64
+ states[component.id] = state;
65
+ }
66
+ });
67
+ return states;
68
+ }
69
+ // The groups a tile's 'any' combines, in id order: while the snapshot's
70
+ // match is 'any', every eligible group that holds a value. A group the tile
71
+ // has no member of is listed too, so the server can tell a tile that cannot
72
+ // test every group (it then applies none of them and says so). A page group
73
+ // counts only for the tiles of its own page: it is in the report bar of no
74
+ // other page. A header or footer tile is a tile of the page on screen.
75
+ function tileMatchAnyGroupIds(report, component, snapshot) {
76
+ if (!report) {
77
+ return [];
78
+ }
79
+ return matchAnyGroupIdsOnPage(report, tilePageId(report, component, snapshot), snapshot);
80
+ }
81
+ // The groups a layer's inline values combine (the page values request's
82
+ // matchAnyGroupIds), by the tile rule (tileDataState): while the snapshot's
83
+ // match is 'any', every eligible group that holds a value, in id order. A
84
+ // value has no member of some of them, and the server then applies none of
85
+ // them to it, as it does for such a tile. `layerId` is the page the values
86
+ // sit on; the header and footer's values (any other id) are values of the
87
+ // page on screen, as a header or footer tile is.
88
+ export function valuesMatchAnyGroupIds(report, layerId, snapshot) {
89
+ if (!report) {
90
+ return [];
91
+ }
92
+ const page = (report.pages ?? []).find((candidate) => candidate.id === layerId);
93
+ return matchAnyGroupIdsOnPage(report, page?.id ?? snapshot.pageId ?? null, snapshot);
94
+ }
95
+ // While the snapshot's match is 'any': the eligible groups of the report bar
96
+ // on `pageId` that hold a value, in id order.
97
+ function matchAnyGroupIdsOnPage(report, pageId, snapshot) {
98
+ if (snapshot.match !== 'any') {
99
+ return [];
100
+ }
101
+ return (report.filterGroups ?? [])
102
+ .filter((group) => isMatchAnyGroup(group, pageId) && holdsValue(snapshot.groups?.[group.id]))
103
+ .map((group) => group.id)
104
+ .sort((a, b) => a - b);
105
+ }
106
+ // The page a tile is drawn on: its own page, or, for a header or footer
107
+ // tile, the page on screen. Null when neither is known. An inline value's
108
+ // page is the page whose values hold it, the same way.
109
+ export function tilePageId(report, component, snapshot) {
110
+ const page = (report.pages ?? [])
111
+ .find((candidate) => [...(candidate.components ?? []), ...(candidate.values ?? [])]
112
+ .some((item) => item.id === component.id));
113
+ return page?.id ?? snapshot.pageId ?? null;
114
+ }
115
+ // Whether a group's stored value holds something a request sends: picks to
116
+ // keep or leave out, text, or a number range end (0 is an end).
117
+ function holdsValue(value) {
118
+ if (!value) {
119
+ return false;
120
+ }
121
+ return !!value.values?.length
122
+ || !!value.excludeValues?.length
123
+ || (typeof value.value === 'string' && !!value.value.trim())
124
+ || Number.isFinite(value.min)
125
+ || Number.isFinite(value.max);
126
+ }
127
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGlsZS1kYXRhLXN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL3RpbGUtZGF0YS1zdGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFPQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUcxRCwwRUFBMEU7QUFDMUUsMEVBQTBFO0FBQzFFLDBFQUEwRTtBQUMxRSx3RUFBd0U7QUFDeEUsaURBQWlEO0FBQ2pELE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxTQUEwQjtJQUMxRCxPQUFPLFNBQVMsQ0FBQyxJQUFJLEtBQUssT0FBTyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksS0FBSyxNQUFNLENBQUM7QUFDaEYsQ0FBQztBQUdELHlFQUF5RTtBQUN6RSw4RUFBOEU7QUFDOUUsdUVBQXVFO0FBQ3ZFLHlFQUF5RTtBQUN6RSx1RUFBdUU7QUFDdkUseUVBQXlFO0FBQ3pFLDZFQUE2RTtBQUM3RSx5RUFBeUU7QUFDekUsRUFBRTtBQUNGLDJFQUEyRTtBQUMzRSwrREFBK0Q7QUFDL0QsTUFBTSxVQUFVLGFBQWEsQ0FDM0IsTUFBcUIsRUFDckIsU0FBMEIsRUFDMUIsUUFBMEI7SUFFMUIsTUFBTSxLQUFLLEdBQXVCLEVBQUUsQ0FBQztJQUVyQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDdkIsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUU1QyxJQUFJLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxJQUFJLGtCQUFrQixDQUFDLFFBQVEs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Jy4vaW50ZXJmYWNlcy9yZXBvcnQtdmlldy1jb25maWcuaW50ZXJmYWNlJztcbmltcG9ydCB7XG4gIENvbXBvbmVudERhdGFTdGF0ZSxcbiAgRmlsdGVyR3JvdXBEZWZhdWx0LFxuICBSZXBvcnQsXG4gIFJlcG9ydENvbXBvbmVudCxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgaXNNYXRjaEFueUdyb3VwIH0gZnJvbSAnLi9yZXBvcnQtZmlsdGVyLWl0ZW1zJztcbmltcG9ydCB7IGlzVGlsZSB9IGZyb20gJy4vcmVwb3J0LXRpbGUnO1xuaW1wb3J0IHsgaXNDaGFydEdyYW51bGFyaXR5IH0gZnJvbSAnLi9yZXBvcnQtdmlldy1jb25maWcnO1xuXG5cbi8vIFdoZXRoZXIgYSBjb21wb25lbnQgaXMgYSBjaGFydCBvbiBhIHRpbWUgeC1heGlzOiB0aGUgb25seSBjb21wb25lbnQgdGhlXG4vLyByZXBvcnQncyBncm91cC1ieSBncmFpbiBhcHBsaWVzIHRvLiBBIGRlbGliZXJhdGUgbWlycm9yIG9mIHRoZSBzZXJ2ZXInc1xuLy8gUmVwb3J0UXVlcnlSdW5uZXI6Ol9pc1RpbWVTZXJpZXNDaGFydCwgd2hpY2ggaXMgY2Fub25pY2FsIGFuZCBkcm9wcyB0aGVcbi8vIGdyYWluIGZvciBldmVyeSBvdGhlciBjb21wb25lbnQ7IGtlcHQgc28gYSBwcm9kdWN0IHBpbm5lZCB0byBhbiBvbGRlclxuLy8gZnJhbWV3b3JrIGRvZXMgbm90IHJlLWJ1Y2tldCBhIG5vbi10aW1lIGNoYXJ0LlxuZXhwb3J0IGZ1bmN0aW9uIGlzVGltZVNlcmllc0NoYXJ0KGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50KTogYm9vbGVhbiB7XG4gIHJldHVybiBjb21wb25lbnQudHlwZSA9PT0gJ2NoYXJ0JyAmJiBjb21wb25lbnQuY29uZmlnPy54QXhpcz8ua2luZCA9PT0gJ3RpbWUnO1xufVxuXG5cbi8vIFRoZSBpbnRlcmFjdGlvbiBzdGF0ZSBvbmUgdGlsZSdzIGRhdGEgcmVxdWVzdCBjYXJyaWVzLCByZWFkIG9mZiBhIHZpZXdcbi8vIGRvY3VtZW50IG9mIHRoZSBzY3JlZW4gKHRoZSBzdGF0ZSBzZXJ2aWNlJ3Mgc25hcHNob3QoKSk6IHRoZSBncm91cC1ieSBncmFpblxuLy8gZm9yIGEgdGltZS1zZXJpZXMgY2hhcnQsIGEgbGlzdCdzIHNvcnQsIHNlYXJjaCBhbmQgaGlkZGVuIGNvbHVtbnMsIGFcbi8vIGNoYXJ0J3MgZHJpbGwgcGF0aCwgYW5kLCB3aGlsZSB0aGUgZ3JvdXBzIG1hdGNoICdhbnknLCB0aGUgZ3JvdXBzIHRoYXRcbi8vIGNvbWJpbmUgKG1hdGNoQW55R3JvdXBJZHMpLiBUaGUgdGlsZSBvbiBzY3JlZW4sIGl0cyBDU1YsIHRoZSBQREYgYW5kXG4vLyBQb3dlclBvaW50IGNvbGxlY3RvciBhbmQgdGhlIHppcCBhbGwgYnVpbGQgdGhlaXIgc3RhdGUgaGVyZSwgc28gYSBmaWxlXG4vLyBhbHdheXMgaG9sZHMgd2hhdCB0aGUgc2NyZWVuIHNob3dzLiBBIGxpc3QncyBwYWdpbmcgaXMgdGhlIGNhbGxlcidzLiBOZXZlclxuLy8gc2V0cyB1bmNoYW5nZWRJZlVucmVhY2hlZDogdGhhdCBiZWxvbmdzIHRvIGFuIG9uLXNjcmVlbiByZWZldGNoIGFsb25lLlxuLy9cbi8vIEEgZHJpbGwgcGF0aCBhbmQgdGhlIGdyYWluIG1heSBib3RoIGJlIHNlbnQ6IHRoZSBzZXJ2ZXIgbGV0cyB0aGUgZHJpbGxlZFxuLy8gbGV2ZWwgd2luLCBhbmQgYSBzZXJ2ZXIgdGhhdCBkb2VzIG5vdCBkcmlsbCBrZWVwcyB0aGUgZ3JhaW4uXG5leHBvcnQgZnVuY3Rpb24gdGlsZURhdGFTdGF0ZShcbiAgcmVwb3J0OiBSZXBvcnQgfCBudWxsLFxuICBjb21wb25lbnQ6IFJlcG9ydENvbXBvbmVudCxcbiAgc25hcHNob3Q6IFJlcG9ydFZpZXdDb25maWcsXG4pOiBDb21wb25lbnREYXRhU3RhdGUge1xuICBjb25zdCBzdGF0ZTogQ29tcG9uZW50RGF0YVN0YXRlID0ge307XG5cbiAgaWYgKCFpc1RpbGUoY29tcG9uZW50KSkge1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIGNvbnN0IHRpbGUgPSBzbmFwc2hvdC50aWxlcz8uW2NvbXBvbmVudC5pZF07XG5cbiAgaWYgKGlzVGltZVNlcmllc0NoYXJ0KGNvbXBvbmVudCkgJiYgaXNDaGFydEdyYW51bGFyaXR5KHNuYXBzaG90Lmdyb3VwQnkpKSB7XG4gICAgc3RhdGUuZnJlcXVlbmN5ID0gc25hcHNob3QuZ3JvdXBCeTtcbiAgfVxuXG4gIGlmIChjb21wb25lbnQudHlwZSA9PT0gJ2xpc3QnKSB7XG4gICAgaWYgKHRpbGU/LnNvcnQ/LmNvbHVtbikge1xuICAgICAgc3RhdGUuc29ydCA9IHsgLi4udGlsZS5zb3J0IH07XG4gICAgfVxuICAgIGlmICh0aWxlPy5zZWFyY2gpIHtcbiAgICAgIHN0YXRlLnNlYXJjaCA9IHRpbGUuc2VhcmNoO1xuICAgIH1cbiAgICBpZiAodGlsZT8uaGlkZGVuPy5sZW5ndGgpIHtcbiAgICAgIHN0YXRlLmhpZGRlbkNvbHVtbnMgPSBbLi4udGlsZS5oaWRkZW5dO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjb21wb25lbnQudHlwZSA9PT0gJ2NoYXJ0JyAmJiB0aWxlPy5kcmlsbD8ubGVuZ3RoKSB7XG4gICAgc3RhdGUuZHJpbGwgPSB0aWxlLmRyaWxsLm1hcCgoc3RlcCkgPT4gKHsgLi4uc3RlcCB9KSk7XG4gIH1cblxuICBjb25zdCBtYXRjaEFueUdyb3VwSWRzID0gdGlsZU1hdGNoQW55R3JvdXBJZHMocmVwb3J0LCBjb21wb25lbnQsIHNuYXBzaG90KTtcbiAgaWYgKG1hdGNoQW55R3JvdXBJZHMubGVuZ3RoKSB7XG4gICAgc3RhdGUubWF0Y2hBbnlHcm91cElkcyA9IG1hdGNoQW55R3JvdXBJZHM7XG4gIH1cblxuICByZXR1cm4gc3RhdGU7XG59XG5cblxuLy8gRWFjaCB0aWxlJ3Mgc3RhdGUgZm9yIHRoZSB6aXAgZXhwb3J0ICh0aWxlRGF0YVN0YXRlKSwgYnkgY29tcG9uZW50IGlkOiB0aGVcbi8vIHRpbGVzIG9mIGV2ZXJ5IHBhZ2UsIG9yIG9mIGBwYWdlSWRgIGFsb25lLiBUaGUgemlwIGhvbGRzIG5vIGhlYWRlciBvclxuLy8gZm9vdGVyIHRpbGUuIEEgdGlsZSB3aXRoIG5vdGhpbmcgdG8gc2VuZCBpcyBsZWZ0IG91dCwgc28gYW4gdW50b3VjaGVkIHJlcG9ydFxuLy8gc2VuZHMgbm8gc3RhdGVzIGF0IGFsbC5cbmV4cG9ydCBmdW5jdGlvbiB6aXBFeHBvcnRTdGF0ZXMoXG4gIHJlcG9ydDogUmVwb3J0LFxuICBzbmFwc2hvdDogUmVwb3J0Vmlld0NvbmZpZyxcbiAgcGFnZUlkOiBudW1iZXIgfCBudWxsID0gbnVsbCxcbik6IFJlY29yZDxudW1iZXIsIENvbXBvbmVudERhdGFTdGF0ZT4ge1xuICBjb25zdCBzdGF0ZXM6IFJlY29yZDxudW1iZXIsIENvbXBvbmVudERhdGFTdGF0ZT4gPSB7fTtcblxuICAocmVwb3J0LnBhZ2VzID8/IFtdKVxuICAgIC5maWx0ZXIoKHBhZ2UpID0+ICFwYWdlSWQgfHwgcGFnZS5pZCA9PT0gcGFnZUlkKVxuICAgIC5mbGF0TWFwKChwYWdlKSA9PiBwYWdlLmNvbXBvbmVudHMgPz8gW10pXG4gICAgLmZvckVhY2goKGNvbXBvbmVudCkgPT4ge1xuICAgICAgY29uc3Qgc3RhdGUgPSB0aWxlRGF0YVN0YXRlKHJlcG9ydCwgY29tcG9uZW50LCBzbmFwc2hvdCk7XG5cbiAgICAgIGlmIChPYmplY3Qua2V5cyhzdGF0ZSkubGVuZ3RoKSB7XG4gICAgICAgIHN0YXRlc1tjb21wb25lbnQuaWRdID0gc3RhdGU7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgcmV0dXJuIHN0YXRlcztcbn1cblxuXG4vLyBUaGUgZ3JvdXBzIGEgdGlsZSdzICdhbnknIGNvbWJpbmVzLCBpbiBpZCBvcmRlcjogd2hpbGUgdGhlIHNuYXBzaG90J3Ncbi8vIG1hdGNoIGlzICdhbnknLCBldmVyeSBlbGlnaWJsZSBncm91cCB0aGF0IGhvbGRzIGEgdmFsdWUuIEEgZ3JvdXAgdGhlIHRpbGVcbi8vIGhhcyBubyBtZW1iZXIgb2YgaXMgbGlzdGVkIHRvbywgc28gdGhlIHNlcnZlciBjYW4gdGVsbCBhIHRpbGUgdGhhdCBjYW5ub3Rcbi8vIHRlc3QgZXZlcnkgZ3JvdXAgKGl0IHRoZW4gYXBwbGllcyBub25lIG9mIHRoZW0gYW5kIHNheXMgc28pLiBBIHBhZ2UgZ3JvdXBcbi8vIGNvdW50cyBvbmx5IGZvciB0aGUgdGlsZXMgb2YgaXRzIG93biBwYWdlOiBpdCBpcyBpbiB0aGUgcmVwb3J0IGJhciBvZiBub1xuLy8gb3RoZXIgcGFnZS4gQSBoZWFkZXIgb3IgZm9vdGVyIHRpbGUgaXMgYSB0aWxlIG9mIHRoZSBwYWdlIG9uIHNjcmVlbi5cbmZ1bmN0aW9uIHRpbGVNYXRjaEFueUdyb3VwSWRzKHJlcG9ydDogUmVwb3J0IHwgbnVsbCwgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQsIHNuYXBzaG90OiBSZXBvcnRWaWV3Q29uZmlnKTogbnVtYmVyW10ge1xuICBpZiAoIXJlcG9ydCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiBtYXRjaEFueUdyb3VwSWRzT25QYWdlKHJlcG9ydCwgdGlsZVBhZ2VJZChyZXBvcnQsIGNvbXBvbmVudCwgc25hcHNob3QpLCBzbmFwc2hvdCk7XG59XG5cblxuLy8gVGhlIGdyb3VwcyBhIGxheWVyJ3MgaW5saW5lIHZhbHVlcyBjb21iaW5lICh0aGUgcGFnZSB2YWx1ZXMgcmVxdWVzdCdzXG4vLyBtYXRjaEFueUdyb3VwSWRzKSwgYnkgdGhlIHRpbGUgcnVsZSAodGlsZURhdGFTdGF0ZSk6IHdoaWxlIHRoZSBzbmFwc2hvdCdzXG4vLyBtYXRjaCBpcyAnYW55JywgZXZlcnkgZWxpZ2libGUgZ3JvdXAgdGhhdCBob2xkcyBhIHZhbHVlLCBpbiBpZCBvcmRlci4gQVxuLy8gdmFsdWUgaGFzIG5vIG1lbWJlciBvZiBzb21lIG9mIHRoZW0sIGFuZCB0aGUgc2VydmVyIHRoZW4gYXBwbGllcyBub25lIG9mXG4vLyB0aGVtIHRvIGl0LCBhcyBpdCBkb2VzIGZvciBzdWNoIGEgdGlsZS4gYGxheWVySWRgIGlzIHRoZSBwYWdlIHRoZSB2YWx1ZXNcbi8vIHNpdCBvbjsgdGhlIGhlYWRlciBhbmQgZm9vdGVyJ3MgdmFsdWVzIChhbnkgb3RoZXIgaWQpIGFyZSB2YWx1ZXMgb2YgdGhlXG4vLyBwYWdlIG9uIHNjcmVlbiwgYXMgYSBoZWFkZXIgb3IgZm9vdGVyIHRpbGUgaXMuXG5leHBvcnQgZnVuY3Rpb24gdmFsdWVzTWF0Y2hBbnlHcm91cElkcyhcbiAgcmVwb3J0OiBSZXBvcnQgfCBudWxsLFxuICBsYXllcklkOiBudW1iZXIgfCBudWxsLFxuICBzbmFwc2hvdDogUmVwb3J0Vmlld0NvbmZpZyxcbik6IG51bWJlcltdIHtcbiAgaWYgKCFyZXBvcnQpIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBwYWdlID0gKHJlcG9ydC5wYWdlcyA/PyBbXSkuZmluZCgoY2FuZGlkYXRlKSA9PiBjYW5kaWRhdGUuaWQgPT09IGxheWVySWQpO1xuXG4gIHJldHVybiBtYXRjaEFueUdyb3VwSWRzT25QYWdlKHJlcG9ydCwgcGFnZT8uaWQgPz8gc25hcHNob3QucGFnZUlkID8/IG51bGwsIHNuYXBzaG90KTtcbn1cblxuXG4vLyBXaGlsZSB0aGUgc25hcHNob3QncyBtYXRjaCBpcyAnYW55JzogdGhlIGVsaWdpYmxlIGdyb3VwcyBvZiB0aGUgcmVwb3J0IGJhclxuLy8gb24gYHBhZ2VJZGAgdGhhdCBob2xkIGEgdmFsdWUsIGluIGlkIG9yZGVyLlxuZnVuY3Rpb24gbWF0Y2hBbnlHcm91cElkc09uUGFnZShyZXBvcnQ6IFJlcG9ydCwgcGFnZUlkOiBudW1iZXIgfCBudWxsLCBzbmFwc2hvdDogUmVwb3J0Vmlld0NvbmZpZyk6IG51bWJlcltdIHtcbiAgaWYgKHNuYXBzaG90Lm1hdGNoICE9PSAnYW55Jykge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiAocmVwb3J0LmZpbHRlckdyb3VwcyA/PyBbXSlcbiAgICAuZmlsdGVyKChncm91cCkgPT4gaXNNYXRjaEFueUdyb3VwKGdyb3VwLCBwYWdlSWQpICYmIGhvbGRzVmFsdWUoc25hcHNob3QuZ3JvdXBzPy5bZ3JvdXAuaWRdKSlcbiAgICAubWFwKChncm91cCkgPT4gZ3JvdXAuaWQpXG4gICAgLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcbn1cblxuXG4vLyBUaGUgcGFnZSBhIHRpbGUgaXMgZHJhd24gb246IGl0cyBvd24gcGFnZSwgb3IsIGZvciBhIGhlYWRlciBvciBmb290ZXJcbi8vIHRpbGUsIHRoZSBwYWdlIG9uIHNjcmVlbi4gTnVsbCB3aGVuIG5laXRoZXIgaXMga25vd24uIEFuIGlubGluZSB2YWx1ZSdzXG4vLyBwYWdlIGlzIHRoZSBwYWdlIHdob3NlIHZhbHVlcyBob2xkIGl0LCB0aGUgc2FtZSB3YXkuXG5leHBvcnQgZnVuY3Rpb24gdGlsZVBhZ2VJZChyZXBvcnQ6IFJlcG9ydCwgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQsIHNuYXBzaG90OiBSZXBvcnRWaWV3Q29uZmlnKTogbnVtYmVyIHwgbnVsbCB7XG4gIGNvbnN0IHBhZ2UgPSAocmVwb3J0LnBhZ2VzID8/IFtdKVxuICAgIC5maW5kKChjYW5kaWRhdGUpID0+IFsuLi4oY2FuZGlkYXRlLmNvbXBvbmVudHMgPz8gW10pLCAuLi4oY2FuZGlkYXRlLnZhbHVlcyA/PyBbXSldXG4gICAgICAuc29tZSgoaXRlbSkgPT4gaXRlbS5pZCA9PT0gY29tcG9uZW50LmlkKSk7XG5cbiAgcmV0dXJuIHBhZ2U/LmlkID8/IHNuYXBzaG90LnBhZ2VJZCA/PyBudWxsO1xufVxuXG5cbi8vIFdoZXRoZXIgYSBncm91cCdzIHN0b3JlZCB2YWx1ZSBob2xkcyBzb21ldGhpbmcgYSByZXF1ZXN0IHNlbmRzOiBwaWNrcyB0b1xuLy8ga2VlcCBvciBsZWF2ZSBvdXQsIHRleHQsIG9yIGEgbnVtYmVyIHJhbmdlIGVuZCAoMCBpcyBhbiBlbmQpLlxuZnVuY3Rpb24gaG9sZHNWYWx1ZSh2YWx1ZTogRmlsdGVyR3JvdXBEZWZhdWx0IHwgbnVsbCB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuICEhdmFsdWUudmFsdWVzPy5sZW5ndGhcbiAgICB8fCAhIXZhbHVlLmV4Y2x1ZGVWYWx1ZXM/Lmxlbmd0aFxuICAgIHx8ICh0eXBlb2YgdmFsdWUudmFsdWUgPT09ICdzdHJpbmcnICYmICEhdmFsdWUudmFsdWUudHJpbSgpKVxuICAgIHx8IE51bWJlci5pc0Zpbml0ZSh2YWx1ZS5taW4pXG4gICAgfHwgTnVtYmVyLmlzRmluaXRlKHZhbHVlLm1heCk7XG59XG4iXX0=
@@ -0,0 +1,38 @@
1
+ import { catchError, filter, map, merge, of, switchMap, timer } from 'rxjs';
2
+ // A sweep of changes (a few filters set in a row, every value of an applied
3
+ // view) settles for this long before a tile refetches, so the sweep costs one
4
+ // request, not one per change.
5
+ export const TILE_REFRESH_DEBOUNCE_MS = 300;
6
+ // A tile's data as one stream: the first load at once, then one load per
7
+ // settled burst of refresh triggers.
8
+ //
9
+ // - Each trigger starts over (switchMap): it cancels the wait for the one
10
+ // before it and the request in flight, then waits for the sweep to settle.
11
+ // So an answer to an older request never lands, not even while the next
12
+ // load still waits, and the bar stays on until the settled load answers.
13
+ // - Each load notes the state version it was sent under (stateVersion), and
14
+ // its answer is dropped when the version has moved since. apply() and
15
+ // resetToBase() move the version and announce a full change together, so
16
+ // the load for the new state is already on its way.
17
+ // - A failed load ends only itself: its message comes through as the answer,
18
+ // and the next trigger loads again.
19
+ export function tileLoads(refresh$, load, version) {
20
+ return merge(of(0), refresh$.pipe(map(() => TILE_REFRESH_DEBOUNCE_MS)))
21
+ .pipe(switchMap((wait) => (wait ? timer(wait) : of(0))
22
+ .pipe(switchMap(() => oneLoad(load, version)))));
23
+ }
24
+ // One request: its answer, or its failure as a message, dropped when the
25
+ // state version moved while it was out.
26
+ function oneLoad(load, version) {
27
+ const sentAt = version();
28
+ return load()
29
+ .pipe(map((data) => ({ data, error: null })), catchError((error) => of({ data: null, error: loadErrorMessage(error) })), filter(() => version() === sentAt));
30
+ }
31
+ // What a failed request says: the server's message, else the error's own,
32
+ // else a plain fallback.
33
+ function loadErrorMessage(error) {
34
+ const failure = error;
35
+ const message = failure?.error?.message ?? failure?.message;
36
+ return typeof message === 'string' && message ? message : 'Failed to load data';
37
+ }
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGlsZS1sb2Fkcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy90aWxlLWxvYWRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBYyxVQUFVLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFLeEYsNEVBQTRFO0FBQzVFLDhFQUE4RTtBQUM5RSwrQkFBK0I7QUFDL0IsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsR0FBRyxDQUFDO0FBRTVDLHlFQUF5RTtBQUN6RSxxQ0FBcUM7QUFDckMsRUFBRTtBQUNGLDBFQUEwRTtBQUMxRSw2RUFBNkU7QUFDN0UsMEVBQTBFO0FBQzFFLDJFQUEyRTtBQUMzRSw0RUFBNEU7QUFDNUUsd0VBQXdFO0FBQ3hFLDJFQUEyRTtBQUMzRSxzREFBc0Q7QUFDdEQsNkVBQTZFO0FBQzdFLHNDQUFzQztBQUN0QyxNQUFNLFVBQVUsU0FBUyxDQUN2QixRQUE2QixFQUM3QixJQUF5QixFQUN6QixPQUFxQjtJQUVyQixPQUFPLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDO1NBQ3BFLElBQUksQ0FDSCxTQUFTLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUM3QyxJQUFJLENBQ0gsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FDeEMsQ0FBQyxDQUNMLENBQUM7QUFDTixDQUFDO0FBRUQseUVBQXlFO0FBQ3pFLHdDQUF3QztBQUN4QyxTQUFTLE9BQU8sQ0FBSSxJQUF5QixFQUFFLE9BQXFCO0lBQ2xFLE1BQU0sTUFBTSxHQUFHLE9BQU8sRUFBRSxDQUFDO0lBRXpCLE9BQU8sSUFBSSxFQUFFO1NBQ1YsSUFBSSxDQUNILEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBcUIsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFDekQsVUFBVSxDQUFDLENBQUMsS0FBYyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQW9CLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQ3JHLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxNQUFNLENBQUMsQ0FDbkMsQ0FBQztBQUNOLENBQUM7QUFFRCwwRUFBMEU7QUFDMUUseUJBQXlCO0FBQ3pCLFNBQVMsZ0JBQWdCLENBQUMsS0FBYztJQUN0QyxNQUFNLE9BQU8sR0FBRyxLQUFvRSxDQUFDO0lBQ3JGLE1BQU0sT0FBTyxHQUFHLE9BQU8sRUFBRSxLQUFLLEVBQUUsT0FBTyxJQUFJLE9BQU8sRUFBRSxPQUFPLENBQUM7SUFFNUQsT0FBTyxPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLHFCQUFxQixDQUFDO0FBQ2xGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPYnNlcnZhYmxlLCBjYXRjaEVycm9yLCBmaWx0ZXIsIG1hcCwgbWVyZ2UsIG9mLCBzd2l0Y2hNYXAsIHRpbWVyIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFRpbGVMb2FkUmVzdWx0IH0gZnJvbSAnLi9pbnRlcmZhY2VzL3RpbGUtbG9hZC1yZXN1bHQuaW50ZXJmYWNlJztcblxuXG4vLyBBIHN3ZWVwIG9mIGNoYW5nZXMgKGEgZmV3IGZpbHRlcnMgc2V0IGluIGEgcm93LCBldmVyeSB2YWx1ZSBvZiBhbiBhcHBsaWVkXG4vLyB2aWV3KSBzZXR0bGVzIGZvciB0aGlzIGxvbmcgYmVmb3JlIGEgdGlsZSByZWZldGNoZXMsIHNvIHRoZSBzd2VlcCBjb3N0cyBvbmVcbi8vIHJlcXVlc3QsIG5vdCBvbmUgcGVyIGNoYW5nZS5cbmV4cG9ydCBjb25zdCBUSUxFX1JFRlJFU0hfREVCT1VOQ0VfTVMgPSAzMDA7XG5cbi8vIEEgdGlsZSdzIGRhdGEgYXMgb25lIHN0cmVhbTogdGhlIGZpcnN0IGxvYWQgYXQgb25jZSwgdGhlbiBvbmUgbG9hZCBwZXJcbi8vIHNldHRsZWQgYnVyc3Qgb2YgcmVmcmVzaCB0cmlnZ2Vycy5cbi8vXG4vLyAtIEVhY2ggdHJpZ2dlciBzdGFydHMgb3ZlciAoc3dpdGNoTWFwKTogaXQgY2FuY2VscyB0aGUgd2FpdCBmb3IgdGhlIG9uZVxuLy8gICBiZWZvcmUgaXQgYW5kIHRoZSByZXF1ZXN0IGluIGZsaWdodCwgdGhlbiB3YWl0cyBmb3IgdGhlIHN3ZWVwIHRvIHNldHRsZS5cbi8vICAgU28gYW4gYW5zd2VyIHRvIGFuIG9sZGVyIHJlcXVlc3QgbmV2ZXIgbGFuZHMsIG5vdCBldmVuIHdoaWxlIHRoZSBuZXh0XG4vLyAgIGxvYWQgc3RpbGwgd2FpdHMsIGFuZCB0aGUgYmFyIHN0YXlzIG9uIHVudGlsIHRoZSBzZXR0bGVkIGxvYWQgYW5zd2Vycy5cbi8vIC0gRWFjaCBsb2FkIG5vdGVzIHRoZSBzdGF0ZSB2ZXJzaW9uIGl0IHdhcyBzZW50IHVuZGVyIChzdGF0ZVZlcnNpb24pLCBhbmRcbi8vICAgaXRzIGFuc3dlciBpcyBkcm9wcGVkIHdoZW4gdGhlIHZlcnNpb24gaGFzIG1vdmVkIHNpbmNlLiBhcHBseSgpIGFuZFxuLy8gICByZXNldFRvQmFzZSgpIG1vdmUgdGhlIHZlcnNpb24gYW5kIGFubm91bmNlIGEgZnVsbCBjaGFuZ2UgdG9nZXRoZXIsIHNvXG4vLyAgIHRoZSBsb2FkIGZvciB0aGUgbmV3IHN0YXRlIGlzIGFscmVhZHkgb24gaXRzIHdheS5cbi8vIC0gQSBmYWlsZWQgbG9hZCBlbmRzIG9ubHkgaXRzZWxmOiBpdHMgbWVzc2FnZSBjb21lcyB0aHJvdWdoIGFzIHRoZSBhbnN3ZXIsXG4vLyAgIGFuZCB0aGUgbmV4dCB0cmlnZ2VyIGxvYWRzIGFnYWluLlxuZXhwb3J0IGZ1bmN0aW9uIHRpbGVMb2FkczxUPihcbiAgcmVmcmVzaCQ6IE9ic2VydmFibGU8dW5rbm93bj4sXG4gIGxvYWQ6ICgpID0+IE9ic2VydmFibGU8VD4sXG4gIHZlcnNpb246ICgpID0+IG51bWJlcixcbik6IE9ic2VydmFibGU8VGlsZUxvYWRSZXN1bHQ8VD4+IHtcbiAgcmV0dXJuIG1lcmdlKG9mKDApLCByZWZyZXNoJC5waXBlKG1hcCgoKSA9PiBUSUxFX1JFRlJFU0hfREVCT1VOQ0VfTVMpKSlcbiAgICAucGlwZShcbiAgICAgIHN3aXRjaE1hcCgod2FpdCkgPT4gKHdhaXQgPyB0aW1lcih3YWl0KSA6IG9mKDApKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gb25lTG9hZChsb2FkLCB2ZXJzaW9uKSksXG4gICAgICAgICkpLFxuICAgICk7XG59XG5cbi8vIE9uZSByZXF1ZXN0OiBpdHMgYW5zd2VyLCBvciBpdHMgZmFpbHVyZSBhcyBhIG1lc3NhZ2UsIGRyb3BwZWQgd2hlbiB0aGVcbi8vIHN0YXRlIHZlcnNpb24gbW92ZWQgd2hpbGUgaXQgd2FzIG91dC5cbmZ1bmN0aW9uIG9uZUxvYWQ8VD4obG9hZDogKCkgPT4gT2JzZXJ2YWJsZTxUPiwgdmVyc2lvbjogKCkgPT4gbnVtYmVyKTogT2JzZXJ2YWJsZTxUaWxlTG9hZFJlc3VsdDxUPj4ge1xuICBjb25zdCBzZW50QXQgPSB2ZXJzaW9uKCk7XG5cbiAgcmV0dXJuIGxvYWQoKVxuICAgIC5waXBlKFxuICAgICAgbWFwKChkYXRhKTogVGlsZUxvYWRSZXN1bHQ8VD4gPT4gKHsgZGF0YSwgZXJyb3I6IG51bGwgfSkpLFxuICAgICAgY2F0Y2hFcnJvcigoZXJyb3I6IHVua25vd24pID0+IG9mPFRpbGVMb2FkUmVzdWx0PFQ+Pih7IGRhdGE6IG51bGwsIGVycm9yOiBsb2FkRXJyb3JNZXNzYWdlKGVycm9yKSB9KSksXG4gICAgICBmaWx0ZXIoKCkgPT4gdmVyc2lvbigpID09PSBzZW50QXQpLFxuICAgICk7XG59XG5cbi8vIFdoYXQgYSBmYWlsZWQgcmVxdWVzdCBzYXlzOiB0aGUgc2VydmVyJ3MgbWVzc2FnZSwgZWxzZSB0aGUgZXJyb3IncyBvd24sXG4vLyBlbHNlIGEgcGxhaW4gZmFsbGJhY2suXG5mdW5jdGlvbiBsb2FkRXJyb3JNZXNzYWdlKGVycm9yOiB1bmtub3duKTogc3RyaW5nIHtcbiAgY29uc3QgZmFpbHVyZSA9IGVycm9yIGFzIHsgZXJyb3I/OiB7IG1lc3NhZ2U/OiB1bmtub3duIH07IG1lc3NhZ2U/OiB1bmtub3duIH0gfCBudWxsO1xuICBjb25zdCBtZXNzYWdlID0gZmFpbHVyZT8uZXJyb3I/Lm1lc3NhZ2UgPz8gZmFpbHVyZT8ubWVzc2FnZTtcblxuICByZXR1cm4gdHlwZW9mIG1lc3NhZ2UgPT09ICdzdHJpbmcnICYmIG1lc3NhZ2UgPyBtZXNzYWdlIDogJ0ZhaWxlZCB0byBsb2FkIGRhdGEnO1xufVxuIl19
@@ -0,0 +1,183 @@
1
+ import { ReportValueFormula } from './enums/report-value-formula.enum';
2
+ import { formatOutputValue } from './format';
3
+ import { VALUE_EMPTY_TEXT, VALUE_TOKEN_PATTERN } from './text';
4
+ // Live values inside text blocks: which values a page's text shows, and what
5
+ // each token reads as. A value belongs to a page (the master for a header or
6
+ // footer) and is listed in its `values`, never in its components. Pure, so the
7
+ // canvas and both exports fill a block's tokens the same way.
8
+ // No value keys: what a text block is told other blocks show when nothing
9
+ // says otherwise. Shared, and typed read-only so no caller fills it.
10
+ export const NO_VALUE_KEYS = Object.freeze(new Set());
11
+ // The keys an html's {{value.<key>}} tokens name: lowercased, each once, in
12
+ // the order they first appear.
13
+ export function valueKeys(html) {
14
+ const keys = Array.from((html ?? '').matchAll(VALUE_TOKEN_PATTERN), (match) => match[1].toLowerCase());
15
+ return [...new Set(keys)];
16
+ }
17
+ // The key a value's tokens name, as they are compared: lowercase.
18
+ export function valueKey(component) {
19
+ return String(component.config?.key ?? '').toLowerCase();
20
+ }
21
+ // The keys a formula value reads (config.formula.of), as they are compared:
22
+ // lowercase. None for a query value.
23
+ export function operandKeys(value) {
24
+ const of = value.config?.formula?.of;
25
+ return Array.isArray(of) ? of.map((key) => String(key).toLowerCase()) : [];
26
+ }
27
+ // The values some text shows, in id order: what the server reads for the
28
+ // page. A key held by two values (a race between two writes) is the newest
29
+ // one's, as server-side.
30
+ export function shownValues(values, texts) {
31
+ const shown = new Set(texts.flatMap((text) => valueKeys(text.config?.html)));
32
+ const ordered = byId(values);
33
+ const newest = new Map(ordered.map((value) => [valueKey(value), value]));
34
+ return ordered.filter((value) => shown.has(valueKey(value)) && newest.get(valueKey(value)) === value);
35
+ }
36
+ // The keys a layer reads when its text shows `shown`: those keys, and the
37
+ // operands of each shown formula, one level deep. It mirrors the server's
38
+ // ReportTextValues::getReadKeys, and is used only for the editor's notice: the
39
+ // server's own read set decides which numbers come back.
40
+ export function readKeys(shown, values) {
41
+ const keys = new Set(shown);
42
+ // Over a copy of the shown keys, so an operand added here is not expanded.
43
+ [...keys].forEach((key) => {
44
+ (values[key]?.reads ?? []).forEach((read) => keys.add(read));
45
+ });
46
+ return keys;
47
+ }
48
+ // What each of a layer's values reads as, by key, for its text's tokens and
49
+ // chips. Every value is listed, shown or not, so a pasted chip keeps its name.
50
+ // A value reads as loading until the layer's numbers have arrived (`results`
51
+ // is null until then) and while a request still on its way asks for it
52
+ // (`loading`, by id): a number on screen is always the current request's. A
53
+ // value with no row, or whose row failed, has no text (the em dash).
54
+ export function textValues(values, results, format, loading = new Set()) {
55
+ const filled = {};
56
+ byId(values).forEach((value) => {
57
+ const key = valueKey(value);
58
+ const name = value.title || key;
59
+ const row = results?.rows.get(value.id);
60
+ const reads = formulaReads(value);
61
+ if (!results || loading.has(value.id)) {
62
+ filled[key] = { name, loading: true, ...reads };
63
+ }
64
+ else if (row && !row.error) {
65
+ filled[key] = { name, text: formatValueText(value, row, values, format), ...reads };
66
+ }
67
+ else {
68
+ filled[key] = { name, ...reads };
69
+ }
70
+ });
71
+ return filled;
72
+ }
73
+ // A value's number as its token reads it, on the canvas and in both exports,
74
+ // through the formatOutputValue KPI cards and list cells use. A query value
75
+ // that shows a comparison output, and a formula, are written by their role: a
76
+ // change or a percent change is signed (unless the formula's `signed` says
77
+ // otherwise), and a change in points carries no ' pp', as the words around
78
+ // the token carry the unit. A change or a sum with no format of its own takes
79
+ // its first operand's, and a ratio reads a percent format as a 0-1 fraction.
80
+ // A row with an error reads as the em dash.
81
+ export function formatValueText(value, row, layerValues, ctx) {
82
+ if (row.error) {
83
+ return VALUE_EMPTY_TEXT;
84
+ }
85
+ const formula = value.config?.formula ?? null;
86
+ const output = row.role || formula
87
+ ? {
88
+ measure: valueKey(value),
89
+ kind: 'value',
90
+ role: row.role ?? null,
91
+ offset: null,
92
+ window: false,
93
+ rank: null,
94
+ share: null,
95
+ }
96
+ : null;
97
+ const context = formula?.op === ReportValueFormula.Ratio ? { ...ctx, ratioPercent: true } : ctx;
98
+ return formatOutputValue(row.value, output, value.config?.measure, context, {
99
+ empty: VALUE_EMPTY_TEXT,
100
+ measureSpec: operandSpec(formula, layerValues),
101
+ signed: formula?.signed ?? undefined,
102
+ pointsUnit: false,
103
+ }).text;
104
+ }
105
+ // The keys of the values that came back without a number to show: no row for
106
+ // them, or a row with an error. What an export's gate names as failed.
107
+ export function failedValueKeys(values, rows) {
108
+ const failed = values
109
+ .filter((value) => {
110
+ const row = rows.get(value.id);
111
+ return !row || !!row.error;
112
+ })
113
+ .map(valueKey);
114
+ return [...new Set(failed)];
115
+ }
116
+ // Whether two token value sets read the same, so a recomputed set that changed
117
+ // nothing a token shows does not repaint every block.
118
+ export function sameTextValues(a, b) {
119
+ if (a === b) {
120
+ return true;
121
+ }
122
+ if (!a || !b) {
123
+ return false;
124
+ }
125
+ const keys = Object.keys(a);
126
+ return keys.length === Object.keys(b).length
127
+ && keys.every((key) => {
128
+ const other = b[key];
129
+ return !!other
130
+ && a[key].name === other.name
131
+ && a[key].text === other.text
132
+ && !!a[key].loading === !!other.loading
133
+ && (a[key].reads ?? []).join(',') === (other.reads ?? []).join(',');
134
+ });
135
+ }
136
+ // Every component of the report, values included: what owns a filter. A value
137
+ // is never drawn, but its filters are the report's like any other.
138
+ export function reportComponents(report) {
139
+ if (!report) {
140
+ return [];
141
+ }
142
+ return [
143
+ ...(report.pages ?? []).flatMap((page) => [...(page.components ?? []), ...(page.values ?? [])]),
144
+ ...(report.master?.components ?? []),
145
+ ...(report.master?.values ?? []),
146
+ ];
147
+ }
148
+ // The value keys each layer holds, by page id and master id. A key that leaves
149
+ // its layer between two loads of the report is a value that was deleted.
150
+ export function layerValueKeys(report) {
151
+ const layers = new Map();
152
+ (report?.pages ?? []).forEach((page) => {
153
+ layers.set(page.id, new Set((page.values ?? []).map(valueKey)));
154
+ });
155
+ if (report?.master) {
156
+ layers.set(report.master.id, new Set((report.master.values ?? []).map(valueKey)));
157
+ }
158
+ return layers;
159
+ }
160
+ // Whether a component is drawn on the canvas. A value only ever reads inside
161
+ // text, so one that leaks into a layer's components is still never drawn.
162
+ export function isDrawn(component) {
163
+ return component.type !== 'value';
164
+ }
165
+ function byId(values) {
166
+ return [...values].sort((a, b) => a.id - b.id);
167
+ }
168
+ // A formula value's operand keys, lowercase, as its TextValue carries them.
169
+ // Nothing for a query value.
170
+ function formulaReads(value) {
171
+ return Array.isArray(value.config?.formula?.of) ? { reads: operandKeys(value) } : {};
172
+ }
173
+ // The format a change or a sum is written in when it names none of its own:
174
+ // its first operand's measure, from the newest value on the layer holding that
175
+ // key. Nothing for any other value, whose own format is all it reads.
176
+ function operandSpec(formula, layerValues) {
177
+ if (formula?.op !== ReportValueFormula.Change && formula?.op !== ReportValueFormula.Sum) {
178
+ return undefined;
179
+ }
180
+ const first = String(formula.of?.[0] ?? '').toLowerCase();
181
+ return byId(layerValues).filter((value) => valueKey(value) === first).pop()?.config?.measure;
182
+ }
183
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsdWVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL3ZhbHVlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUN2RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFVN0MsT0FBTyxFQUFhLGdCQUFnQixFQUFFLG1CQUFtQixFQUFFLE1BQU0sUUFBUSxDQUFDO0FBRzFFLDZFQUE2RTtBQUM3RSw2RUFBNkU7QUFDN0UsK0VBQStFO0FBQy9FLDhEQUE4RDtBQUU5RCwwRUFBMEU7QUFDMUUscUVBQXFFO0FBQ3JFLE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBd0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEdBQUcsRUFBVSxDQUFDLENBQUM7QUFFbkYsNEVBQTRFO0FBQzVFLCtCQUErQjtBQUMvQixNQUFNLFVBQVUsU0FBUyxDQUFDLElBQStCO0lBQ3ZELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBRXZHLE9BQU8sQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDNUIsQ0FBQztBQUVELGtFQUFrRTtBQUNsRSxNQUFNLFVBQVUsUUFBUSxDQUFDLFNBQTBCO0lBQ2pELE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0FBQzNELENBQUM7QUFFRCw0RUFBNEU7QUFDNUUscUNBQXFDO0FBQ3JDLE1BQU0sVUFBVSxXQUFXLENBQUMsS0FBc0I7SUFDaEQsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDO0lBRXJDLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUM3RSxDQUFDO0FBRUQseUVBQXlFO0FBQ3pFLDJFQUEyRTtBQUMzRSx5QkFBeUI7QUFDekIsTUFBTSxVQUFVLFdBQVcsQ0FBQyxNQUF5QixFQUFFLEtBQXdCO0lBQzdFLE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3RSxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0IsTUFBTSxNQUFNLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBRXpFLE9BQU8sT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDO0FBQ3hHLENBQUM7QUFFRCwwRUFBMEU7QUFDMUUsMEVBQTBFO0FBQzFFLCtFQUErRTtBQUMvRSx5REFBeUQ7QUFDekQsTUFBTSxVQUFVLFFBQVEsQ0FBQyxLQUF1QixFQUFFLE1BQWlDO0lBQ2pGLE1BQU0sSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTVCLDJFQUEyRTtJQUMzRSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDeEIsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQy9ELENBQUMsQ0FBQyxDQUFDO0lBRUgsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSw2RUFBNkU7QUFDN0UsdUVBQXVFO0FBQ3ZFLDRFQUE0RTtBQUM1RSxxRUFBcUU7QUFDckUsTUFBTSxVQUFVLFVBQVUsQ0FDeEIsTUFBeUIsRUFDekIsT0FBOEQsRUFDOUQsTUFBMkIsRUFDM0IsVUFBK0IsSUFBSSxHQUFHLEVBQUU7SUFFeEMsTUFBTSxNQUFNLEdBQThCLEVBQUUsQ0FBQztJQUU3QyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDN0IsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVCLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxLQUFLLElBQUksR0FBRyxDQUFDO1FBQ2hDLE1BQU0sR0FBRyxHQUFHLE9BQU8sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN4QyxNQUFNLEtBQUssR0FBRyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFbEMsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUM7UUFDbEQsQ0FBQzthQUFNLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQzdCLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsZUFBZSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUM7UUFDdEYsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQztRQUNuQyxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBRUQsNkVBQTZFO0FBQzdFLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFDOUUsMkVBQTJFO0FBQzNFLDJFQUEyRTtBQUMzRSw4RUFBOEU7QUFDOUUsNkVBQTZFO0FBQzdFLDRDQUE0QztBQUM1QyxNQUFNLFVBQVUsZUFBZSxDQUM3QixLQUFzQixFQUN0QixHQUFvQixFQUNwQixXQUE4QixFQUM5QixHQUF3QjtJQUV4QixJQUFJLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNkLE9BQU8sZ0JBQWdCLENBQUM7SUFDMUIsQ0FBQztJQUVELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsT0FBTyxJQUFJLElBQUksQ0FBQztJQUM5QyxNQUFNLE1BQU0sR0FBc0IsR0FBRyxDQUFDLElBQUksSUFBSSxPQUFPO1FBQ25ELENBQUMsQ0FBQztZQUNBLE9BQU8sRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDO1lBQ3hCLElBQUksRUFBRSxPQUFPO1lBQ2IsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksSUFBSTtZQUN0QixNQUFNLEVBQUUsSUFBSTtZQUNaLE1BQU0sRUFBRSxLQUFLO1lBQ2IsSUFBSSxFQUFFLElBQUk7WUFDVixLQUFLLEVBQUUsSUFBSTtTQUNaO1FBQ0QsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNULE1BQU0sT0FBTyxHQUFHLE9BQU8sRUFBRSxFQUFFLEtBQUssa0JBQWtCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsR0FBRyxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0lBRWhHLE9BQU8saUJBQWlCLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFO1FBQzFFLEtBQUssRUFBRSxnQkFBZ0I7UUFDdkIsV0FBVyxFQUFFLFdBQVcsQ0FBQyxPQUFPLEVBQUUsV0FBVyxDQUFDO1FBQzlDLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxJQUFJLFNBQVM7UUFDcEMsVUFBVSxFQUFFLEtBQUs7S0FDbEIsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUNWLENBQUM7QUFFRCw2RUFBNkU7QUFDN0UsdUVBQXVFO0FBQ3ZFLE1BQU0sVUFBVSxlQUFlLENBQzdCLE1BQXlCLEVBQ3pCLElBQTBDO0lBRTFDLE1BQU0sTUFBTSxHQUFHLE1BQU07U0FDbEIsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDaEIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFL0IsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztJQUM3QixDQUFDLENBQUM7U0FDRCxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7SUFFakIsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztBQUM5QixDQUFDO0FBRUQsK0VBQStFO0FBQy9FLHNEQUFzRDtBQUN0RCxNQUFNLFVBQVUsY0FBYyxDQUM1QixDQUF3QyxFQUN4QyxDQUF3QztJQUV4QyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNaLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNiLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFFNUIsT0FBTyxJQUFJLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTTtXQUN2QyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDcEIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBRXJCLE9BQU8sQ0FBQyxDQUFDLEtBQUs7bUJBQ1QsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsSUFBSTttQkFDMUIsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsSUFBSTttQkFDMUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEtBQUssQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPO21CQUNwQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDeEUsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDO0FBRUQsOEVBQThFO0FBQzlFLG1FQUFtRTtBQUNuRSxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsTUFBcUI7SUFDcEQsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ1osT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQsT0FBTztRQUNMLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUMsRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQy9GLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLFVBQVUsSUFBSSxFQUFFLENBQUM7UUFDcEMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsTUFBTSxJQUFJLEVBQUUsQ0FBQztLQUNqQyxDQUFDO0FBQ0osQ0FBQztBQUVELCtFQUErRTtBQUMvRSx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLGNBQWMsQ0FBQyxNQUFxQjtJQUNsRCxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBdUIsQ0FBQztJQUU5QyxDQUFDLE1BQU0sRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7UUFDckMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDbkIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxJQUFJLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDcEYsQ0FBQztJQUVELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCw2RUFBNkU7QUFDN0UsMEVBQTBFO0FBQzFFLE1BQU0sVUFBVSxPQUFPLENBQUMsU0FBMEI7SUFDaEQsT0FBTyxTQUFTLENBQUMsSUFBSSxLQUFLLE9BQU8sQ0FBQztBQUNwQyxDQUFDO0FBRUQsU0FBUyxJQUFJLENBQUMsTUFBeUI7SUFDckMsT0FBTyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDakQsQ0FBQztBQUVELDRFQUE0RTtBQUM1RSw2QkFBNkI7QUFDN0IsU0FBUyxZQUFZLENBQUMsS0FBc0I7SUFDMUMsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxXQUFXLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0FBQ3ZGLENBQUM7QUFFRCw0RUFBNEU7QUFDNUUsK0VBQStFO0FBQy9FLHNFQUFzRTtBQUN0RSxTQUFTLFdBQVcsQ0FDbEIsT0FBa0MsRUFDbEMsV0FBOEI7SUFFOUIsSUFBSSxPQUFPLEVBQUUsRUFBRSxLQUFLLGtCQUFrQixDQUFDLE1BQU0sSUFBSSxPQUFPLEVBQUUsRUFBRSxLQUFLLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3hGLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBRTFELE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLE1BQU0sRUFBRSxPQUFPLENBQUM7QUFDL0YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFJlcG9ydFZhbHVlRm9ybXVsYSB9IGZyb20gJy4vZW51bXMvcmVwb3J0LXZhbHVlLWZvcm11bGEuZW51bSc7XG5pbXBvcnQgeyBmb3JtYXRPdXRwdXRWYWx1ZSB9IGZyb20gJy4vZm9ybWF0JztcbmltcG9ydCB7XG4gIE51bWJlckZvcm1hdFNwZWMsXG4gIE91dHB1dE1ldGEsXG4gIFJlcG9ydCxcbiAgUmVwb3J0Q29tcG9uZW50LFxuICBSZXBvcnRGb3JtYXRDb250ZXh0LFxuICBSZXBvcnRQYWdlVmFsdWUsXG4gIFZhbHVlRm9ybXVsYUNvbmZpZyxcbn0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgVGV4dFZhbHVlLCBWQUxVRV9FTVBUWV9URVhULCBWQUxVRV9UT0tFTl9QQVRURVJOIH0gZnJvbSAnLi90ZXh0JztcblxuXG4vLyBMaXZlIHZhbHVlcyBpbnNpZGUgdGV4dCBibG9ja3M6IHdoaWNoIHZhbHVlcyBhIHBhZ2UncyB0ZXh0IHNob3dzLCBhbmQgd2hhdFxuLy8gZWFjaCB0b2tlbiByZWFkcyBhcy4gQSB2YWx1ZSBiZWxvbmdzIHRvIGEgcGFnZSAodGhlIG1hc3RlciBmb3IgYSBoZWFkZXIgb3Jcbi8vIGZvb3RlcikgYW5kIGlzIGxpc3RlZCBpbiBpdHMgYHZhbHVlc2AsIG5ldmVyIGluIGl0cyBjb21wb25lbnRzLiBQdXJlLCBzbyB0aGVcbi8vIGNhbnZhcyBhbmQgYm90aCBleHBvcnRzIGZpbGwgYSBibG9jaydzIHRva2VucyB0aGUgc2FtZSB3YXkuXG5cbi8vIE5vIHZhbHVlIGtleXM6IHdoYXQgYSB0ZXh0IGJsb2NrIGlzIHRvbGQgb3RoZXIgYmxvY2tzIHNob3cgd2hlbiBub3RoaW5nXG4vLyBzYXlzIG90aGVyd2lzZS4gU2hhcmVkLCBhbmQgdHlwZWQgcmVhZC1vbmx5IHNvIG5vIGNhbGxlciBmaWxscyBpdC5cbmV4cG9ydCBjb25zdCBOT19WQUxVRV9LRVlTOiBSZWFkb25seVNldDxzdHJpbmc+ID0gT2JqZWN0LmZyZWV6ZShuZXcgU2V0PHN0cmluZz4oKSk7XG5cbi8vIFRoZSBrZXlzIGFuIGh0bWwncyB7e3ZhbHVlLjxrZXk+fX0gdG9rZW5zIG5hbWU6IGxvd2VyY2FzZWQsIGVhY2ggb25jZSwgaW5cbi8vIHRoZSBvcmRlciB0aGV5IGZpcnN0IGFwcGVhci5cbmV4cG9ydCBmdW5jdGlvbiB2YWx1ZUtleXMoaHRtbDogc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZ1tdIHtcbiAgY29uc3Qga2V5cyA9IEFycmF5LmZyb20oKGh0bWwgPz8gJycpLm1hdGNoQWxsKFZBTFVFX1RPS0VOX1BBVFRFUk4pLCAobWF0Y2gpID0+IG1hdGNoWzFdLnRvTG93ZXJDYXNlKCkpO1xuXG4gIHJldHVybiBbLi4ubmV3IFNldChrZXlzKV07XG59XG5cbi8vIFRoZSBrZXkgYSB2YWx1ZSdzIHRva2VucyBuYW1lLCBhcyB0aGV5IGFyZSBjb21wYXJlZDogbG93ZXJjYXNlLlxuZXhwb3J0IGZ1bmN0aW9uIHZhbHVlS2V5KGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50KTogc3RyaW5nIHtcbiAgcmV0dXJuIFN0cmluZyhjb21wb25lbnQuY29uZmlnPy5rZXkgPz8gJycpLnRvTG93ZXJDYXNlKCk7XG59XG5cbi8vIFRoZSBrZXlzIGEgZm9ybXVsYSB2YWx1ZSByZWFkcyAoY29uZmlnLmZvcm11bGEub2YpLCBhcyB0aGV5IGFyZSBjb21wYXJlZDpcbi8vIGxvd2VyY2FzZS4gTm9uZSBmb3IgYSBxdWVyeSB2YWx1ZS5cbmV4cG9ydCBmdW5jdGlvbiBvcGVyYW5kS2V5cyh2YWx1ZTogUmVwb3J0Q29tcG9uZW50KTogc3RyaW5nW10ge1xuICBjb25zdCBvZiA9IHZhbHVlLmNvbmZpZz8uZm9ybXVsYT8ub2Y7XG5cbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkob2YpID8gb2YubWFwKChrZXkpID0+IFN0cmluZyhrZXkpLnRvTG93ZXJDYXNlKCkpIDogW107XG59XG5cbi8vIFRoZSB2YWx1ZXMgc29tZSB0ZXh0IHNob3dzLCBpbiBpZCBvcmRlcjogd2hhdCB0aGUgc2VydmVyIHJlYWRzIGZvciB0aGVcbi8vIHBhZ2UuIEEga2V5IGhlbGQgYnkgdHdvIHZhbHVlcyAoYSByYWNlIGJldHdlZW4gdHdvIHdyaXRlcykgaXMgdGhlIG5ld2VzdFxuLy8gb25lJ3MsIGFzIHNlcnZlci1zaWRlLlxuZXhwb3J0IGZ1bmN0aW9uIHNob3duVmFsdWVzKHZhbHVlczogUmVwb3J0Q29tcG9uZW50W10sIHRleHRzOiBSZXBvcnRDb21wb25lbnRbXSk6IFJlcG9ydENvbXBvbmVudFtdIHtcbiAgY29uc3Qgc2hvd24gPSBuZXcgU2V0KHRleHRzLmZsYXRNYXAoKHRleHQpID0+IHZhbHVlS2V5cyh0ZXh0LmNvbmZpZz8uaHRtbCkpKTtcbiAgY29uc3Qgb3JkZXJlZCA9IGJ5SWQodmFsdWVzKTtcbiAgY29uc3QgbmV3ZXN0ID0gbmV3IE1hcChvcmRlcmVkLm1hcCgodmFsdWUpID0+IFt2YWx1ZUtleSh2YWx1ZSksIHZhbHVlXSkpO1xuXG4gIHJldHVybiBvcmRlcmVkLmZpbHRlcigodmFsdWUpID0+IHNob3duLmhhcyh2YWx1ZUtleSh2YWx1ZSkpICYmIG5ld2VzdC5nZXQodmFsdWVLZXkodmFsdWUpKSA9PT0gdmFsdWUpO1xufVxuXG4vLyBUaGUga2V5cyBhIGxheWVyIHJlYWRzIHdoZW4gaXRzIHRleHQgc2hvd3MgYHNob3duYDogdGhvc2Uga2V5cywgYW5kIHRoZVxuLy8gb3BlcmFuZHMgb2YgZWFjaCBzaG93biBmb3JtdWxhLCBvbmUgbGV2ZWwgZGVlcC4gSXQgbWlycm9ycyB0aGUgc2VydmVyJ3Ncbi8vIFJlcG9ydFRleHRWYWx1ZXM6OmdldFJlYWRLZXlzLCBhbmQgaXMgdXNlZCBvbmx5IGZvciB0aGUgZWRpdG9yJ3Mgbm90aWNlOiB0aGVcbi8vIHNlcnZlcidzIG93biByZWFkIHNldCBkZWNpZGVzIHdoaWNoIG51bWJlcnMgY29tZSBiYWNrLlxuZXhwb3J0IGZ1bmN0aW9uIHJlYWRLZXlzKHNob3duOiBJdGVyYWJsZTxzdHJpbmc+LCB2YWx1ZXM6IFJlY29yZDxzdHJpbmcsIFRleHRWYWx1ZT4pOiBTZXQ8c3RyaW5nPiB7XG4gIGNvbnN0IGtleXMgPSBuZXcgU2V0KHNob3duKTtcblxuICAvLyBPdmVyIGEgY29weSBvZiB0aGUgc2hvd24ga2V5cywgc28gYW4gb3BlcmFuZCBhZGRlZCBoZXJlIGlzIG5vdCBleHBhbmRlZC5cbiAgWy4uLmtleXNdLmZvckVhY2goKGtleSkgPT4ge1xuICAgICh2YWx1ZXNba2V5XT8ucmVhZHMgPz8gW10pLmZvckVhY2goKHJlYWQpID0+IGtleXMuYWRkKHJlYWQpKTtcbiAgfSk7XG5cbiAgcmV0dXJuIGtleXM7XG59XG5cbi8vIFdoYXQgZWFjaCBvZiBhIGxheWVyJ3MgdmFsdWVzIHJlYWRzIGFzLCBieSBrZXksIGZvciBpdHMgdGV4dCdzIHRva2VucyBhbmRcbi8vIGNoaXBzLiBFdmVyeSB2YWx1ZSBpcyBsaXN0ZWQsIHNob3duIG9yIG5vdCwgc28gYSBwYXN0ZWQgY2hpcCBrZWVwcyBpdHMgbmFtZS5cbi8vIEEgdmFsdWUgcmVhZHMgYXMgbG9hZGluZyB1bnRpbCB0aGUgbGF5ZXIncyBudW1iZXJzIGhhdmUgYXJyaXZlZCAoYHJlc3VsdHNgXG4vLyBpcyBudWxsIHVudGlsIHRoZW4pIGFuZCB3aGlsZSBhIHJlcXVlc3Qgc3RpbGwgb24gaXRzIHdheSBhc2tzIGZvciBpdFxuLy8gKGBsb2FkaW5nYCwgYnkgaWQpOiBhIG51bWJlciBvbiBzY3JlZW4gaXMgYWx3YXlzIHRoZSBjdXJyZW50IHJlcXVlc3Qncy4gQVxuLy8gdmFsdWUgd2l0aCBubyByb3csIG9yIHdob3NlIHJvdyBmYWlsZWQsIGhhcyBubyB0ZXh0ICh0aGUgZW0gZGFzaCkuXG5leHBvcnQgZnVuY3Rpb24gdGV4dFZhbHVlcyhcbiAgdmFsdWVzOiBSZXBvcnRDb21wb25lbnRbXSxcbiAgcmVzdWx0czogeyByb3dzOiBSZWFkb25seU1hcDxudW1iZXIsIFJlcG9ydFBhZ2VWYWx1ZT4gfSB8IG51bGwsXG4gIGZvcm1hdDogUmVwb3J0Rm9ybWF0Q29udGV4dCxcbiAgbG9hZGluZzogUmVhZG9ubHlTZXQ8bnVtYmVyPiA9IG5ldyBTZXQoKSxcbik6IFJlY29yZDxzdHJpbmcsIFRleHRWYWx1ZT4ge1xuICBjb25zdCBmaWxsZWQ6IFJlY29yZDxzdHJpbmcsIFRleHRWYWx1ZT4gPSB7fTtcblxuICBieUlkKHZhbHVlcykuZm9yRWFjaCgodmFsdWUpID0+IHtcbiAgICBjb25zdCBrZXkgPSB2YWx1ZUtleSh2YWx1ZSk7XG4gICAgY29uc3QgbmFtZSA9IHZhbHVlLnRpdGxlIHx8IGtleTtcbiAgICBjb25zdCByb3cgPSByZXN1bHRzPy5yb3dzLmdldCh2YWx1ZS5pZCk7XG4gICAgY29uc3QgcmVhZHMgPSBmb3JtdWxhUmVhZHModmFsdWUpO1xuXG4gICAgaWYgKCFyZXN1bHRzIHx8IGxvYWRpbmcuaGFzKHZhbHVlLmlkKSkge1xuICAgICAgZmlsbGVkW2tleV0gPSB7IG5hbWUsIGxvYWRpbmc6IHRydWUsIC4uLnJlYWRzIH07XG4gICAgfSBlbHNlIGlmIChyb3cgJiYgIXJvdy5lcnJvcikge1xuICAgICAgZmlsbGVkW2tleV0gPSB7IG5hbWUsIHRleHQ6IGZvcm1hdFZhbHVlVGV4dCh2YWx1ZSwgcm93LCB2YWx1ZXMsIGZvcm1hdCksIC4uLnJlYWRzIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGZpbGxlZFtrZXldID0geyBuYW1lLCAuLi5yZWFkcyB9O1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGZpbGxlZDtcbn1cblxuLy8gQSB2YWx1ZSdzIG51bWJlciBhcyBpdHMgdG9rZW4gcmVhZHMgaXQsIG9uIHRoZSBjYW52YXMgYW5kIGluIGJvdGggZXhwb3J0cyxcbi8vIHRocm91Z2ggdGhlIGZvcm1hdE91dHB1dFZhbHVlIEtQSSBjYXJkcyBhbmQgbGlzdCBjZWxscyB1c2UuIEEgcXVlcnkgdmFsdWVcbi8vIHRoYXQgc2hvd3MgYSBjb21wYXJpc29uIG91dHB1dCwgYW5kIGEgZm9ybXVsYSwgYXJlIHdyaXR0ZW4gYnkgdGhlaXIgcm9sZTogYVxuLy8gY2hhbmdlIG9yIGEgcGVyY2VudCBjaGFuZ2UgaXMgc2lnbmVkICh1bmxlc3MgdGhlIGZvcm11bGEncyBgc2lnbmVkYCBzYXlzXG4vLyBvdGhlcndpc2UpLCBhbmQgYSBjaGFuZ2UgaW4gcG9pbnRzIGNhcnJpZXMgbm8gJyBwcCcsIGFzIHRoZSB3b3JkcyBhcm91bmRcbi8vIHRoZSB0b2tlbiBjYXJyeSB0aGUgdW5pdC4gQSBjaGFuZ2Ugb3IgYSBzdW0gd2l0aCBubyBmb3JtYXQgb2YgaXRzIG93biB0YWtlc1xuLy8gaXRzIGZpcnN0IG9wZXJhbmQncywgYW5kIGEgcmF0aW8gcmVhZHMgYSBwZXJjZW50IGZvcm1hdCBhcyBhIDAtMSBmcmFjdGlvbi5cbi8vIEEgcm93IHdpdGggYW4gZXJyb3IgcmVhZHMgYXMgdGhlIGVtIGRhc2guXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0VmFsdWVUZXh0KFxuICB2YWx1ZTogUmVwb3J0Q29tcG9uZW50LFxuICByb3c6IFJlcG9ydFBhZ2VWYWx1ZSxcbiAgbGF5ZXJWYWx1ZXM6IFJlcG9ydENvbXBvbmVudFtdLFxuICBjdHg6IFJlcG9ydEZvcm1hdENvbnRleHQsXG4pOiBzdHJpbmcge1xuICBpZiAocm93LmVycm9yKSB7XG4gICAgcmV0dXJuIFZBTFVFX0VNUFRZX1RFWFQ7XG4gIH1cblxuICBjb25zdCBmb3JtdWxhID0gdmFsdWUuY29uZmlnPy5mb3JtdWxhID8/IG51bGw7XG4gIGNvbnN0IG91dHB1dDogT3V0cHV0TWV0YSB8IG51bGwgPSByb3cucm9sZSB8fCBmb3JtdWxhXG4gICAgPyB7XG4gICAgICBtZWFzdXJlOiB2YWx1ZUtleSh2YWx1ZSksXG4gICAgICBraW5kOiAndmFsdWUnLFxuICAgICAgcm9sZTogcm93LnJvbGUgPz8gbnVsbCxcbiAgICAgIG9mZnNldDogbnVsbCxcbiAgICAgIHdpbmRvdzogZmFsc2UsXG4gICAgICByYW5rOiBudWxsLFxuICAgICAgc2hhcmU6IG51bGwsXG4gICAgfVxuICAgIDogbnVsbDtcbiAgY29uc3QgY29udGV4dCA9IGZvcm11bGE/Lm9wID09PSBSZXBvcnRWYWx1ZUZvcm11bGEuUmF0aW8gPyB7IC4uLmN0eCwgcmF0aW9QZXJjZW50OiB0cnVlIH0gOiBjdHg7XG5cbiAgcmV0dXJuIGZvcm1hdE91dHB1dFZhbHVlKHJvdy52YWx1ZSwgb3V0cHV0LCB2YWx1ZS5jb25maWc/Lm1lYXN1cmUsIGNvbnRleHQsIHtcbiAgICBlbXB0eTogVkFMVUVfRU1QVFlfVEVYVCxcbiAgICBtZWFzdXJlU3BlYzogb3BlcmFuZFNwZWMoZm9ybXVsYSwgbGF5ZXJWYWx1ZXMpLFxuICAgIHNpZ25lZDogZm9ybXVsYT8uc2lnbmVkID8/IHVuZGVmaW5lZCxcbiAgICBwb2ludHNVbml0OiBmYWxzZSxcbiAgfSkudGV4dDtcbn1cblxuLy8gVGhlIGtleXMgb2YgdGhlIHZhbHVlcyB0aGF0IGNhbWUgYmFjayB3aXRob3V0IGEgbnVtYmVyIHRvIHNob3c6IG5vIHJvdyBmb3Jcbi8vIHRoZW0sIG9yIGEgcm93IHdpdGggYW4gZXJyb3IuIFdoYXQgYW4gZXhwb3J0J3MgZ2F0ZSBuYW1lcyBhcyBmYWlsZWQuXG5leHBvcnQgZnVuY3Rpb24gZmFpbGVkVmFsdWVLZXlzKFxuICB2YWx1ZXM6IFJlcG9ydENvbXBvbmVudFtdLFxuICByb3dzOiBSZWFkb25seU1hcDxudW1iZXIsIFJlcG9ydFBhZ2VWYWx1ZT4sXG4pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGZhaWxlZCA9IHZhbHVlc1xuICAgIC5maWx0ZXIoKHZhbHVlKSA9PiB7XG4gICAgICBjb25zdCByb3cgPSByb3dzLmdldCh2YWx1ZS5pZCk7XG5cbiAgICAgIHJldHVybiAhcm93IHx8ICEhcm93LmVycm9yO1xuICAgIH0pXG4gICAgLm1hcCh2YWx1ZUtleSk7XG5cbiAgcmV0dXJuIFsuLi5uZXcgU2V0KGZhaWxlZCldO1xufVxuXG4vLyBXaGV0aGVyIHR3byB0b2tlbiB2YWx1ZSBzZXRzIHJlYWQgdGhlIHNhbWUsIHNvIGEgcmVjb21wdXRlZCBzZXQgdGhhdCBjaGFuZ2VkXG4vLyBub3RoaW5nIGEgdG9rZW4gc2hvd3MgZG9lcyBub3QgcmVwYWludCBldmVyeSBibG9jay5cbmV4cG9ydCBmdW5jdGlvbiBzYW1lVGV4dFZhbHVlcyhcbiAgYTogUmVjb3JkPHN0cmluZywgVGV4dFZhbHVlPiB8IHVuZGVmaW5lZCxcbiAgYjogUmVjb3JkPHN0cmluZywgVGV4dFZhbHVlPiB8IHVuZGVmaW5lZCxcbik6IGJvb2xlYW4ge1xuICBpZiAoYSA9PT0gYikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgaWYgKCFhIHx8ICFiKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgY29uc3Qga2V5cyA9IE9iamVjdC5rZXlzKGEpO1xuXG4gIHJldHVybiBrZXlzLmxlbmd0aCA9PT0gT2JqZWN0LmtleXMoYikubGVuZ3RoXG4gICAgJiYga2V5cy5ldmVyeSgoa2V5KSA9PiB7XG4gICAgICBjb25zdCBvdGhlciA9IGJba2V5XTtcblxuICAgICAgcmV0dXJuICEhb3RoZXJcbiAgICAgICAgJiYgYVtrZXldLm5hbWUgPT09IG90aGVyLm5hbWVcbiAgICAgICAgJiYgYVtrZXldLnRleHQgPT09IG90aGVyLnRleHRcbiAgICAgICAgJiYgISFhW2tleV0ubG9hZGluZyA9PT0gISFvdGhlci5sb2FkaW5nXG4gICAgICAgICYmIChhW2tleV0ucmVhZHMgPz8gW10pLmpvaW4oJywnKSA9PT0gKG90aGVyLnJlYWRzID8/IFtdKS5qb2luKCcsJyk7XG4gICAgfSk7XG59XG5cbi8vIEV2ZXJ5IGNvbXBvbmVudCBvZiB0aGUgcmVwb3J0LCB2YWx1ZXMgaW5jbHVkZWQ6IHdoYXQgb3ducyBhIGZpbHRlci4gQSB2YWx1ZVxuLy8gaXMgbmV2ZXIgZHJhd24sIGJ1dCBpdHMgZmlsdGVycyBhcmUgdGhlIHJlcG9ydCdzIGxpa2UgYW55IG90aGVyLlxuZXhwb3J0IGZ1bmN0aW9uIHJlcG9ydENvbXBvbmVudHMocmVwb3J0OiBSZXBvcnQgfCBudWxsKTogUmVwb3J0Q29tcG9uZW50W10ge1xuICBpZiAoIXJlcG9ydCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIHJldHVybiBbXG4gICAgLi4uKHJlcG9ydC5wYWdlcyA/PyBbXSkuZmxhdE1hcCgocGFnZSkgPT4gWy4uLihwYWdlLmNvbXBvbmVudHMgPz8gW10pLCAuLi4ocGFnZS52YWx1ZXMgPz8gW10pXSksXG4gICAgLi4uKHJlcG9ydC5tYXN0ZXI/LmNvbXBvbmVudHMgPz8gW10pLFxuICAgIC4uLihyZXBvcnQubWFzdGVyPy52YWx1ZXMgPz8gW10pLFxuICBdO1xufVxuXG4vLyBUaGUgdmFsdWUga2V5cyBlYWNoIGxheWVyIGhvbGRzLCBieSBwYWdlIGlkIGFuZCBtYXN0ZXIgaWQuIEEga2V5IHRoYXQgbGVhdmVzXG4vLyBpdHMgbGF5ZXIgYmV0d2VlbiB0d28gbG9hZHMgb2YgdGhlIHJlcG9ydCBpcyBhIHZhbHVlIHRoYXQgd2FzIGRlbGV0ZWQuXG5leHBvcnQgZnVuY3Rpb24gbGF5ZXJWYWx1ZUtleXMocmVwb3J0OiBSZXBvcnQgfCBudWxsKTogTWFwPG51bWJlciwgU2V0PHN0cmluZz4+IHtcbiAgY29uc3QgbGF5ZXJzID0gbmV3IE1hcDxudW1iZXIsIFNldDxzdHJpbmc+PigpO1xuXG4gIChyZXBvcnQ/LnBhZ2VzID8/IFtdKS5mb3JFYWNoKChwYWdlKSA9PiB7XG4gICAgbGF5ZXJzLnNldChwYWdlLmlkLCBuZXcgU2V0KChwYWdlLnZhbHVlcyA/PyBbXSkubWFwKHZhbHVlS2V5KSkpO1xuICB9KTtcblxuICBpZiAocmVwb3J0Py5tYXN0ZXIpIHtcbiAgICBsYXllcnMuc2V0KHJlcG9ydC5tYXN0ZXIuaWQsIG5ldyBTZXQoKHJlcG9ydC5tYXN0ZXIudmFsdWVzID8/IFtdKS5tYXAodmFsdWVLZXkpKSk7XG4gIH1cblxuICByZXR1cm4gbGF5ZXJzO1xufVxuXG4vLyBXaGV0aGVyIGEgY29tcG9uZW50IGlzIGRyYXduIG9uIHRoZSBjYW52YXMuIEEgdmFsdWUgb25seSBldmVyIHJlYWRzIGluc2lkZVxuLy8gdGV4dCwgc28gb25lIHRoYXQgbGVha3MgaW50byBhIGxheWVyJ3MgY29tcG9uZW50cyBpcyBzdGlsbCBuZXZlciBkcmF3bi5cbmV4cG9ydCBmdW5jdGlvbiBpc0RyYXduKGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50KTogYm9vbGVhbiB7XG4gIHJldHVybiBjb21wb25lbnQudHlwZSAhPT0gJ3ZhbHVlJztcbn1cblxuZnVuY3Rpb24gYnlJZCh2YWx1ZXM6IFJlcG9ydENvbXBvbmVudFtdKTogUmVwb3J0Q29tcG9uZW50W10ge1xuICByZXR1cm4gWy4uLnZhbHVlc10uc29ydCgoYSwgYikgPT4gYS5pZCAtIGIuaWQpO1xufVxuXG4vLyBBIGZvcm11bGEgdmFsdWUncyBvcGVyYW5kIGtleXMsIGxvd2VyY2FzZSwgYXMgaXRzIFRleHRWYWx1ZSBjYXJyaWVzIHRoZW0uXG4vLyBOb3RoaW5nIGZvciBhIHF1ZXJ5IHZhbHVlLlxuZnVuY3Rpb24gZm9ybXVsYVJlYWRzKHZhbHVlOiBSZXBvcnRDb21wb25lbnQpOiBQaWNrPFRleHRWYWx1ZSwgJ3JlYWRzJz4ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZS5jb25maWc/LmZvcm11bGE/Lm9mKSA/IHsgcmVhZHM6IG9wZXJhbmRLZXlzKHZhbHVlKSB9IDoge307XG59XG5cbi8vIFRoZSBmb3JtYXQgYSBjaGFuZ2Ugb3IgYSBzdW0gaXMgd3JpdHRlbiBpbiB3aGVuIGl0IG5hbWVzIG5vbmUgb2YgaXRzIG93bjpcbi8vIGl0cyBmaXJzdCBvcGVyYW5kJ3MgbWVhc3VyZSwgZnJvbSB0aGUgbmV3ZXN0IHZhbHVlIG9uIHRoZSBsYXllciBob2xkaW5nIHRoYXRcbi8vIGtleS4gTm90aGluZyBmb3IgYW55IG90aGVyIHZhbHVlLCB3aG9zZSBvd24gZm9ybWF0IGlzIGFsbCBpdCByZWFkcy5cbmZ1bmN0aW9uIG9wZXJhbmRTcGVjKFxuICBmb3JtdWxhOiBWYWx1ZUZvcm11bGFDb25maWcgfCBudWxsLFxuICBsYXllclZhbHVlczogUmVwb3J0Q29tcG9uZW50W10sXG4pOiBOdW1iZXJGb3JtYXRTcGVjIHwgdW5kZWZpbmVkIHtcbiAgaWYgKGZvcm11bGE/Lm9wICE9PSBSZXBvcnRWYWx1ZUZvcm11bGEuQ2hhbmdlICYmIGZvcm11bGE/Lm9wICE9PSBSZXBvcnRWYWx1ZUZvcm11bGEuU3VtKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGNvbnN0IGZpcnN0ID0gU3RyaW5nKGZvcm11bGEub2Y/LlswXSA/PyAnJykudG9Mb3dlckNhc2UoKTtcblxuICByZXR1cm4gYnlJZChsYXllclZhbHVlcykuZmlsdGVyKCh2YWx1ZSkgPT4gdmFsdWVLZXkodmFsdWUpID09PSBmaXJzdCkucG9wKCk/LmNvbmZpZz8ubWVhc3VyZTtcbn1cbiJdfQ==