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