bways-report 0.1.6 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +293 -464
  2. package/esm2022/lib/core/config/bways-report-config.mjs +83 -0
  3. package/esm2022/lib/core/index.mjs +2 -1
  4. package/esm2022/lib/core/models/report-definition.model.mjs +1 -1
  5. package/esm2022/lib/core/services/report-data-discovery.service.mjs +6 -3
  6. package/esm2022/lib/core/services/report-session-context.service.mjs +11 -7
  7. package/esm2022/lib/core/tokens/reporting-config.token.mjs +1 -1
  8. package/esm2022/lib/core/utils/data-normalization.util.mjs +87 -1
  9. package/esm2022/lib/core/utils/report-parameter.util.mjs +119 -3
  10. package/esm2022/lib/data-access/adapters/endpoint-datasource.adapter.mjs +69 -0
  11. package/esm2022/lib/data-access/adapters/endpoint-lookup.adapter.mjs +98 -0
  12. package/esm2022/lib/data-access/adapters/endpoint-masterdata.adapter.mjs +57 -0
  13. package/esm2022/lib/data-access/adapters/endpoint-persistence.adapter.mjs +85 -0
  14. package/esm2022/lib/data-access/adapters/endpoint-schema-discovery.adapter.mjs +163 -0
  15. package/esm2022/lib/data-access/adapters/endpoint-tokens.mjs +12 -0
  16. package/esm2022/lib/data-access/adapters/http-lookup.adapter.mjs +4 -23
  17. package/esm2022/lib/data-access/adapters/index.mjs +8 -1
  18. package/esm2022/lib/data-access/contracts/lookup.contract.mjs +1 -1
  19. package/esm2022/lib/features/designer/components/component-palette/component-palette.component.mjs +12 -2
  20. package/esm2022/lib/features/designer/components/design-canvas/design-canvas.component.mjs +5 -5
  21. package/esm2022/lib/features/designer/components/dialogs/report-saved-dialog.component.mjs +407 -0
  22. package/esm2022/lib/features/designer/components/property-editor/parameter-binding-editor.component.mjs +109 -60
  23. package/esm2022/lib/features/designer/components/property-editor/property-editor-action.component.mjs +3 -3
  24. package/esm2022/lib/features/designer/components/property-editor/property-editor-datasource.component.mjs +110 -20
  25. package/esm2022/lib/features/designer/components/property-editor/property-editor-general.component.mjs +3 -3
  26. package/esm2022/lib/features/designer/components/property-editor/property-editor-grid.component.mjs +60 -3
  27. package/esm2022/lib/features/designer/components/property-editor/property-editor-layout.component.mjs +11 -5
  28. package/esm2022/lib/features/designer/components/property-editor/property-editor-report.component.mjs +3 -3
  29. package/esm2022/lib/features/designer/components/property-editor/property-editor-validation.component.mjs +15 -3
  30. package/esm2022/lib/features/designer/components/toolbar/designer-toolbar.component.mjs +204 -10
  31. package/esm2022/lib/features/designer/designer.component.mjs +43 -2
  32. package/esm2022/lib/features/designer/services/designer-state.service.mjs +9 -2
  33. package/esm2022/lib/features/embed/bways-report-builder.component.mjs +207 -0
  34. package/esm2022/lib/features/embed/bways-report-menu.component.mjs +433 -0
  35. package/esm2022/lib/features/embed/bways-report-page.component.mjs +204 -0
  36. package/esm2022/lib/features/embed/index.mjs +5 -0
  37. package/esm2022/lib/features/embed/inject-report-menu.mjs +99 -0
  38. package/esm2022/lib/features/index.mjs +2 -1
  39. package/esm2022/lib/features/persistence/services/report-store.service.mjs +43 -5
  40. package/esm2022/lib/features/routing/components/routed-report-runtime.component.mjs +4 -4
  41. package/esm2022/lib/features/routing/index.mjs +2 -2
  42. package/esm2022/lib/features/routing/models/report-route.models.mjs +1 -1
  43. package/esm2022/lib/features/routing/report-routes.mjs +42 -1
  44. package/esm2022/lib/features/routing/resolvers/report.resolver.mjs +6 -8
  45. package/esm2022/lib/features/routing/services/report-menu.service.mjs +14 -4
  46. package/esm2022/lib/features/runtime/dynamic-renderer.component.mjs +22 -3
  47. package/esm2022/lib/features/runtime/report-grid-bridge.component.mjs +16 -2
  48. package/esm2022/lib/primitives/components/button/rpt-button.component.mjs +28 -5
  49. package/esm2022/lib/primitives/components/dropdown/rpt-dropdown.component.mjs +86 -19
  50. package/esm2022/lib/primitives/components/icon/rpt-icon.component.mjs +8 -1
  51. package/esm2022/lib/primitives/components/index.mjs +2 -1
  52. package/esm2022/lib/primitives/components/number/rpt-number.component.mjs +9 -3
  53. package/esm2022/lib/primitives/components/searchable-select/rpt-searchable-select.component.mjs +386 -0
  54. package/esm2022/lib/provide-reporting.mjs +137 -7
  55. package/fesm2022/bways-report.mjs +4053 -840
  56. package/fesm2022/bways-report.mjs.map +1 -1
  57. package/lib/core/config/bways-report-config.d.ts +161 -0
  58. package/lib/core/index.d.ts +1 -0
  59. package/lib/core/models/report-definition.model.d.ts +16 -0
  60. package/lib/core/services/report-session-context.service.d.ts +1 -0
  61. package/lib/core/tokens/reporting-config.token.d.ts +16 -0
  62. package/lib/core/utils/data-normalization.util.d.ts +10 -0
  63. package/lib/core/utils/report-parameter.util.d.ts +18 -1
  64. package/lib/data-access/adapters/endpoint-datasource.adapter.d.ts +13 -0
  65. package/lib/data-access/adapters/endpoint-lookup.adapter.d.ts +14 -0
  66. package/lib/data-access/adapters/endpoint-masterdata.adapter.d.ts +11 -0
  67. package/lib/data-access/adapters/endpoint-persistence.adapter.d.ts +15 -0
  68. package/lib/data-access/adapters/endpoint-schema-discovery.adapter.d.ts +21 -0
  69. package/lib/data-access/adapters/endpoint-tokens.d.ts +21 -0
  70. package/lib/data-access/adapters/index.d.ts +7 -0
  71. package/lib/data-access/contracts/lookup.contract.d.ts +2 -2
  72. package/lib/features/designer/components/component-palette/component-palette.component.d.ts +1 -0
  73. package/lib/features/designer/components/design-canvas/design-canvas.component.d.ts +1 -1
  74. package/lib/features/designer/components/dialogs/report-saved-dialog.component.d.ts +34 -0
  75. package/lib/features/designer/components/property-editor/parameter-binding-editor.component.d.ts +1 -0
  76. package/lib/features/designer/components/property-editor/property-editor-datasource.component.d.ts +12 -2
  77. package/lib/features/designer/components/property-editor/property-editor-grid.component.d.ts +10 -0
  78. package/lib/features/designer/components/toolbar/designer-toolbar.component.d.ts +13 -1
  79. package/lib/features/designer/designer.component.d.ts +4 -0
  80. package/lib/features/embed/bways-report-builder.component.d.ts +48 -0
  81. package/lib/features/embed/bways-report-menu.component.d.ts +40 -0
  82. package/lib/features/embed/bways-report-page.component.d.ts +61 -0
  83. package/lib/features/embed/index.d.ts +4 -0
  84. package/lib/features/embed/inject-report-menu.d.ts +44 -0
  85. package/lib/features/index.d.ts +1 -0
  86. package/lib/features/persistence/services/report-store.service.d.ts +5 -0
  87. package/lib/features/routing/index.d.ts +1 -1
  88. package/lib/features/routing/models/report-route.models.d.ts +3 -0
  89. package/lib/features/routing/report-routes.d.ts +40 -0
  90. package/lib/features/routing/resolvers/report.resolver.d.ts +1 -1
  91. package/lib/features/runtime/dynamic-renderer.component.d.ts +1 -0
  92. package/lib/features/runtime/report-grid-bridge.component.d.ts +1 -1
  93. package/lib/primitives/components/button/rpt-button.component.d.ts +3 -0
  94. package/lib/primitives/components/dropdown/rpt-dropdown.component.d.ts +16 -3
  95. package/lib/primitives/components/index.d.ts +2 -0
  96. package/lib/primitives/components/searchable-select/rpt-searchable-select.component.d.ts +89 -0
  97. package/lib/provide-reporting.d.ts +22 -6
  98. package/package.json +1 -1
@@ -0,0 +1,207 @@
1
+ import { ChangeDetectionStrategy, Component, DestroyRef, inject, input, output, signal, } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
+ import { ReportStoreService } from '../persistence/services/report-store.service';
6
+ import { DesignerComponent } from '../designer/designer.component';
7
+ import { RptIconComponent } from '../../primitives/components/icon/rpt-icon.component';
8
+ import * as i0 from "@angular/core";
9
+ import * as i1 from "@angular/forms";
10
+ /**
11
+ * `<bways-report-builder>`
12
+ *
13
+ * Drop-in, single-tag visual report designer component for host applications.
14
+ *
15
+ * Wraps the full visual builder with:
16
+ * - Direct width and height inputs (`width="100%" height="calc(100vh - 64px)"`)
17
+ * - Built-in report selector dropdown and "+ New Report" button
18
+ * - Automatic persistence and menu synchronization
19
+ *
20
+ * Usage:
21
+ * ```html
22
+ * <!-- Drop anywhere in your admin or report management page -->
23
+ * <bways-report-builder width="100%" height="calc(100vh - 64px)" />
24
+ * ```
25
+ */
26
+ export class BwaysReportBuilderComponent {
27
+ store = inject(ReportStoreService);
28
+ destroyRef = inject(DestroyRef);
29
+ /** Width of the builder container. Defaults to '100%'. */
30
+ width = input('100%');
31
+ /** Height of the builder container. Defaults to '100%'. */
32
+ height = input('100%');
33
+ /** Initial report ID to open in the designer. */
34
+ reportId = input(undefined);
35
+ /** Whether to show the top switcher bar with report selector and "+ New" button. */
36
+ showReportList = input(true);
37
+ /** Emitted when a report definition is saved. */
38
+ saved = output();
39
+ /** Emitted when the report definition changes. */
40
+ definitionChange = output();
41
+ /** Emitted when a report is selected from the list. */
42
+ reportSelect = output();
43
+ activeReportId = signal(null);
44
+ reportsList = signal([]);
45
+ saveStatus = signal(null);
46
+ designerKey = signal(1);
47
+ ngOnInit() {
48
+ if (this.reportId()) {
49
+ this.activeReportId.set(this.reportId());
50
+ }
51
+ this.refreshReports();
52
+ }
53
+ onSelectReport(id) {
54
+ const target = id ? id : null;
55
+ this.activeReportId.set(target);
56
+ this.designerKey.update((k) => k + 1);
57
+ if (target) {
58
+ this.reportSelect.emit(target);
59
+ }
60
+ }
61
+ createNewReport() {
62
+ this.activeReportId.set(null);
63
+ this.designerKey.update((k) => k + 1);
64
+ }
65
+ onReportSaved(def) {
66
+ this.activeReportId.set(def.id);
67
+ this.saveStatus.set(`Saved "${def.name}"`);
68
+ this.saved.emit(def);
69
+ // Refresh store summaries so navigation reflects changes immediately
70
+ this.refreshReports();
71
+ setTimeout(() => {
72
+ this.saveStatus.set(null);
73
+ }, 3500);
74
+ }
75
+ refreshReports() {
76
+ this.store
77
+ .loadSummaries()
78
+ .pipe(takeUntilDestroyed(this.destroyRef))
79
+ .subscribe({
80
+ next: (list) => this.reportsList.set(list),
81
+ error: (err) => console.warn('[bways-report] Failed to load reports list:', err),
82
+ });
83
+ }
84
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: BwaysReportBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
85
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: BwaysReportBuilderComponent, isStandalone: true, selector: "bways-report-builder", inputs: { width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, reportId: { classPropertyName: "reportId", publicName: "reportId", isSignal: true, isRequired: false, transformFunction: null }, showReportList: { classPropertyName: "showReportList", publicName: "showReportList", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { saved: "saved", definitionChange: "definitionChange", reportSelect: "reportSelect" }, ngImport: i0, template: `
86
+ <div
87
+ class="rpt-builder-container"
88
+ [style.width]="width()"
89
+ [style.height]="height()"
90
+ >
91
+ @if (showReportList()) {
92
+ <div class="rpt-builder-header">
93
+ <div class="rpt-header-left">
94
+ <span class="rpt-header-label">Report:</span>
95
+ <div class="rpt-select-wrapper">
96
+ <select
97
+ class="rpt-report-select"
98
+ [ngModel]="activeReportId() ?? ''"
99
+ (ngModelChange)="onSelectReport($event)"
100
+ >
101
+ <option value="">-- New Report (unsaved) --</option>
102
+ @for (item of reportsList(); track item.id) {
103
+ <option [value]="item.id">
104
+ {{ item.name }} {{ item.category ? '(' + item.category + ')' : '' }}
105
+ </option>
106
+ }
107
+ </select>
108
+ <rpt-icon name="chevron-down" [size]="12" class="rpt-select-arrow" />
109
+ </div>
110
+
111
+ <button
112
+ type="button"
113
+ class="rpt-btn-new-report"
114
+ (click)="createNewReport()"
115
+ title="Create a new blank report"
116
+ >
117
+ <rpt-icon name="plus" [size]="14" />
118
+ <span>New</span>
119
+ </button>
120
+ </div>
121
+
122
+ <div class="rpt-header-right">
123
+ @if (saveStatus()) {
124
+ <span class="rpt-save-status">
125
+ <rpt-icon name="check" [size]="13" />
126
+ {{ saveStatus() }}
127
+ </span>
128
+ }
129
+ </div>
130
+ </div>
131
+ }
132
+
133
+ <div class="rpt-builder-designer-area">
134
+ @if (designerKey()) {
135
+ <rpt-designer
136
+ [reportId]="activeReportId() ?? undefined"
137
+ (save)="onReportSaved($event)"
138
+ (definitionChange)="definitionChange.emit($event)"
139
+ />
140
+ }
141
+ </div>
142
+ </div>
143
+ `, isInline: true, styles: [":host{display:block;width:100%;height:100%;box-sizing:border-box;font-family:var(--rpt-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif)}.rpt-builder-container{display:flex;flex-direction:column;position:relative;overflow:hidden;background:#f8fafc;box-sizing:border-box}.rpt-builder-header{display:flex;align-items:center;justify-content:space-between;padding:8px 16px;background:#fff;border-bottom:1px solid #e2e8f0;z-index:10;flex-shrink:0}.rpt-header-left{display:flex;align-items:center;gap:10px}.rpt-header-label{font-size:.8125rem;font-weight:600;color:#475569}.rpt-select-wrapper{position:relative;display:inline-flex;align-items:center}.rpt-report-select{appearance:none;-webkit-appearance:none;padding:5px 28px 5px 12px;font-size:.8125rem;font-weight:500;color:#0f172a;background:#f8fafc;border:1px solid #cbd5e1;border-radius:6px;outline:none;cursor:pointer;min-width:220px;transition:all .15s ease}.rpt-report-select:focus{background:#fff;border-color:#2563eb;box-shadow:0 0 0 2px #2563eb26}.rpt-select-arrow{position:absolute;right:10px;pointer-events:none;color:#64748b}.rpt-btn-new-report{display:inline-flex;align-items:center;gap:5px;padding:5px 12px;background:#eff6ff;border:1px solid #bfdbfe;color:#2563eb;border-radius:6px;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .15s ease}.rpt-btn-new-report:hover{background:#dbeafe;border-color:#93c5fd}.rpt-header-right{display:flex;align-items:center;gap:12px}.rpt-save-status{display:inline-flex;align-items:center;gap:5px;font-size:.75rem;font-weight:600;color:#16a34a;background:#f0fdf4;padding:3px 8px;border-radius:9999px;border:1px solid #bbf7d0;animation:rpt-status-fade .2s ease}@keyframes rpt-status-fade{0%{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:translateY(0)}}.rpt-builder-designer-area{flex:1;width:100%;height:100%;overflow:hidden;position:relative}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: DesignerComponent, selector: "rpt-designer", inputs: ["reportId", "initialReport"], outputs: ["save", "definitionChange"] }, { kind: "component", type: RptIconComponent, selector: "rpt-icon", inputs: ["name", "size", "color", "strokeWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
144
+ }
145
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: BwaysReportBuilderComponent, decorators: [{
146
+ type: Component,
147
+ args: [{ selector: 'bways-report-builder', standalone: true, imports: [CommonModule, FormsModule, DesignerComponent, RptIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
148
+ <div
149
+ class="rpt-builder-container"
150
+ [style.width]="width()"
151
+ [style.height]="height()"
152
+ >
153
+ @if (showReportList()) {
154
+ <div class="rpt-builder-header">
155
+ <div class="rpt-header-left">
156
+ <span class="rpt-header-label">Report:</span>
157
+ <div class="rpt-select-wrapper">
158
+ <select
159
+ class="rpt-report-select"
160
+ [ngModel]="activeReportId() ?? ''"
161
+ (ngModelChange)="onSelectReport($event)"
162
+ >
163
+ <option value="">-- New Report (unsaved) --</option>
164
+ @for (item of reportsList(); track item.id) {
165
+ <option [value]="item.id">
166
+ {{ item.name }} {{ item.category ? '(' + item.category + ')' : '' }}
167
+ </option>
168
+ }
169
+ </select>
170
+ <rpt-icon name="chevron-down" [size]="12" class="rpt-select-arrow" />
171
+ </div>
172
+
173
+ <button
174
+ type="button"
175
+ class="rpt-btn-new-report"
176
+ (click)="createNewReport()"
177
+ title="Create a new blank report"
178
+ >
179
+ <rpt-icon name="plus" [size]="14" />
180
+ <span>New</span>
181
+ </button>
182
+ </div>
183
+
184
+ <div class="rpt-header-right">
185
+ @if (saveStatus()) {
186
+ <span class="rpt-save-status">
187
+ <rpt-icon name="check" [size]="13" />
188
+ {{ saveStatus() }}
189
+ </span>
190
+ }
191
+ </div>
192
+ </div>
193
+ }
194
+
195
+ <div class="rpt-builder-designer-area">
196
+ @if (designerKey()) {
197
+ <rpt-designer
198
+ [reportId]="activeReportId() ?? undefined"
199
+ (save)="onReportSaved($event)"
200
+ (definitionChange)="definitionChange.emit($event)"
201
+ />
202
+ }
203
+ </div>
204
+ </div>
205
+ `, styles: [":host{display:block;width:100%;height:100%;box-sizing:border-box;font-family:var(--rpt-font-family, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif)}.rpt-builder-container{display:flex;flex-direction:column;position:relative;overflow:hidden;background:#f8fafc;box-sizing:border-box}.rpt-builder-header{display:flex;align-items:center;justify-content:space-between;padding:8px 16px;background:#fff;border-bottom:1px solid #e2e8f0;z-index:10;flex-shrink:0}.rpt-header-left{display:flex;align-items:center;gap:10px}.rpt-header-label{font-size:.8125rem;font-weight:600;color:#475569}.rpt-select-wrapper{position:relative;display:inline-flex;align-items:center}.rpt-report-select{appearance:none;-webkit-appearance:none;padding:5px 28px 5px 12px;font-size:.8125rem;font-weight:500;color:#0f172a;background:#f8fafc;border:1px solid #cbd5e1;border-radius:6px;outline:none;cursor:pointer;min-width:220px;transition:all .15s ease}.rpt-report-select:focus{background:#fff;border-color:#2563eb;box-shadow:0 0 0 2px #2563eb26}.rpt-select-arrow{position:absolute;right:10px;pointer-events:none;color:#64748b}.rpt-btn-new-report{display:inline-flex;align-items:center;gap:5px;padding:5px 12px;background:#eff6ff;border:1px solid #bfdbfe;color:#2563eb;border-radius:6px;font-size:.8125rem;font-weight:600;cursor:pointer;transition:all .15s ease}.rpt-btn-new-report:hover{background:#dbeafe;border-color:#93c5fd}.rpt-header-right{display:flex;align-items:center;gap:12px}.rpt-save-status{display:inline-flex;align-items:center;gap:5px;font-size:.75rem;font-weight:600;color:#16a34a;background:#f0fdf4;padding:3px 8px;border-radius:9999px;border:1px solid #bbf7d0;animation:rpt-status-fade .2s ease}@keyframes rpt-status-fade{0%{opacity:0;transform:translateY(-2px)}to{opacity:1;transform:translateY(0)}}.rpt-builder-designer-area{flex:1;width:100%;height:100%;overflow:hidden;position:relative}\n"] }]
206
+ }] });
207
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYndheXMtcmVwb3J0LWJ1aWxkZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvYndheXMtcmVwb3J0L3NyYy9saWIvZmVhdHVyZXMvZW1iZWQvYndheXMtcmVwb3J0LWJ1aWxkZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULFVBQVUsRUFDVixNQUFNLEVBQ04sS0FBSyxFQUVMLE1BQU0sRUFDTixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw4Q0FBOEMsQ0FBQztBQUNsRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNuRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxREFBcUQsQ0FBQzs7O0FBRXZGOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQW1NSCxNQUFNLE9BQU8sMkJBQTJCO0lBQ3JCLEtBQUssR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztJQUNuQyxVQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBRWpELDBEQUEwRDtJQUNqRCxLQUFLLEdBQUcsS0FBSyxDQUFTLE1BQU0sQ0FBQyxDQUFDO0lBRXZDLDJEQUEyRDtJQUNsRCxNQUFNLEdBQUcsS0FBSyxDQUFTLE1BQU0sQ0FBQyxDQUFDO0lBRXhDLGlEQUFpRDtJQUN4QyxRQUFRLEdBQUcsS0FBSyxDQUFxQixTQUFTLENBQUMsQ0FBQztJQUV6RCxvRkFBb0Y7SUFDM0UsY0FBYyxHQUFH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NEZBK0w3RCwyQkFBMkI7a0JBbE12QyxTQUFTOytCQUNFLHNCQUFzQixjQUNwQixJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLGdCQUFnQixDQUFDLG1CQUN4RCx1QkFBdUIsQ0FBQyxNQUFNLFlBQ3JDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMERUIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRGVzdHJveVJlZixcbiAgaW5qZWN0LFxuICBpbnB1dCxcbiAgT25Jbml0LFxuICBvdXRwdXQsXG4gIHNpZ25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBSZXBvcnREZWZpbml0aW9uLCBSZXBvcnRTdW1tYXJ5IH0gZnJvbSAnLi4vLi4vY29yZS9tb2RlbHMvcmVwb3J0LWRlZmluaXRpb24ubW9kZWwnO1xuaW1wb3J0IHsgUmVwb3J0U3RvcmVTZXJ2aWNlIH0gZnJvbSAnLi4vcGVyc2lzdGVuY2Uvc2VydmljZXMvcmVwb3J0LXN0b3JlLnNlcnZpY2UnO1xuaW1wb3J0IHsgRGVzaWduZXJDb21wb25lbnQgfSBmcm9tICcuLi9kZXNpZ25lci9kZXNpZ25lci5jb21wb25lbnQnO1xuaW1wb3J0IHsgUnB0SWNvbkNvbXBvbmVudCB9IGZyb20gJy4uLy4uL3ByaW1pdGl2ZXMvY29tcG9uZW50cy9pY29uL3JwdC1pY29uLmNvbXBvbmVudCc7XG5cbi8qKlxuICogYDxid2F5cy1yZXBvcnQtYnVpbGRlcj5gXG4gKlxuICogRHJvcC1pbiwgc2luZ2xlLXRhZyB2aXN1YWwgcmVwb3J0IGRlc2lnbmVyIGNvbXBvbmVudCBmb3IgaG9zdCBhcHBsaWNhdGlvbnMuXG4gKlxuICogV3JhcHMgdGhlIGZ1bGwgdmlzdWFsIGJ1aWxkZXIgd2l0aDpcbiAqIC0gRGlyZWN0IHdpZHRoIGFuZCBoZWlnaHQgaW5wdXRzIChgd2lkdGg9XCIxMDAlXCIgaGVpZ2h0PVwiY2FsYygxMDB2aCAtIDY0cHgpXCJgKVxuICogLSBCdWlsdC1pbiByZXBvcnQgc2VsZWN0b3IgZHJvcGRvd24gYW5kIFwiKyBOZXcgUmVwb3J0XCIgYnV0dG9uXG4gKiAtIEF1dG9tYXRpYyBwZXJzaXN0ZW5jZSBhbmQgbWVudSBzeW5jaHJvbml6YXRpb25cbiAqXG4gKiBVc2FnZTpcbiAqIGBgYGh0bWxcbiAqIDwhLS0gRHJvcCBhbnl3aGVyZSBpbiB5b3VyIGFkbWluIG9yIHJlcG9ydCBtYW5hZ2VtZW50IHBhZ2UgLS0+XG4gKiA8YndheXMtcmVwb3J0LWJ1aWxkZXIgd2lkdGg9XCIxMDAlXCIgaGVpZ2h0PVwiY2FsYygxMDB2aCAtIDY0cHgpXCIgLz5cbiAqIGBgYFxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdid2F5cy1yZXBvcnQtYnVpbGRlcicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlLCBEZXNpZ25lckNvbXBvbmVudCwgUnB0SWNvbkNvbXBvbmVudF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwicnB0LWJ1aWxkZXItY29udGFpbmVyXCJcbiAgICAgIFtzdHlsZS53aWR0aF09XCJ3aWR0aCgpXCJcbiAgICAgIFtzdHlsZS5oZWlnaHRdPVwiaGVpZ2h0KClcIlxuICAgID5cbiAgICAgIEBpZiAoc2hvd1JlcG9ydExpc3QoKSkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwicnB0LWJ1aWxkZXItaGVhZGVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInJwdC1oZWFkZXItbGVmdFwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJycHQtaGVhZGVyLWxhYmVsXCI+UmVwb3J0Ojwvc3Bhbj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJycHQtc2VsZWN0LXdyYXBwZXJcIj5cbiAgICAgICAgICAgICAgPHNlbGVjdFxuICAgICAgICAgICAgICAgIGNsYXNzPVwicnB0LXJlcG9ydC1zZWxlY3RcIlxuICAgICAgICAgICAgICAgIFtuZ01vZGVsXT1cImFjdGl2ZVJlcG9ydElkKCkgPz8gJydcIlxuICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uU2VsZWN0UmVwb3J0KCRldmVudClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cIlwiPi0tIE5ldyBSZXBvcnQgKHVuc2F2ZWQpIC0tPC9vcHRpb24+XG4gICAgICAgICAgICAgICAgQGZvciAoaXRlbSBvZiByZXBvcnRzTGlzdCgpOyB0cmFjayBpdGVtLmlkKSB7XG4gICAgICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCJpdGVtLmlkXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0ubmFtZSB9fSB7eyBpdGVtLmNhdGVnb3J5ID8gJygnICsgaXRlbS5jYXRlZ29yeSArICcpJyA6ICcnIH19XG4gICAgICAgICAgICAgICAgICA8L29wdGlvbj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDwvc2VsZWN0PlxuICAgICAgICAgICAgICA8cnB0LWljb24gbmFtZT1cImNoZXZyb24tZG93blwiIFtzaXplXT1cIjEyXCIgY2xhc3M9XCJycHQtc2VsZWN0LWFycm93XCIgLz5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICBjbGFzcz1cInJwdC1idG4tbmV3LXJlcG9ydFwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJjcmVhdGVOZXdSZXBvcnQoKVwiXG4gICAgICAgICAgICAgIHRpdGxlPVwiQ3JlYXRlIGEgbmV3IGJsYW5rIHJlcG9ydFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxycHQtaWNvbiBuYW1lPVwicGx1c1wiIFtzaXplXT1cIjE0XCIgLz5cbiAgICAgICAgICAgICAgPHNwYW4+TmV3PC9zcGFuPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicnB0LWhlYWRlci1yaWdodFwiPlxuICAgICAgICAgICAgQGlmIChzYXZlU3RhdHVzKCkpIHtcbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJycHQtc2F2ZS1zdGF0dXNcIj5cbiAgICAgICAgICAgICAgICA8cnB0LWljb24gbmFtZT1cImNoZWNrXCIgW3NpemVdPVwiMTNcIiAvPlxuICAgICAgICAgICAgICAgIHt7IHNhdmVTdGF0dXMoKSB9fVxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgfVxuXG4gICAgICA8ZGl2IGNsYXNzPVwicnB0LWJ1aWxkZXItZGVzaWduZXItYXJlYVwiPlxuICAgICAgICBAaWYgKGRlc2lnbmVyS2V5KCkpIHtcbiAgICAgICAgICA8cnB0LWRlc2lnbmVyXG4gICAgICAgICAgICBbcmVwb3J0SWRdPVwiYWN0aXZlUmVwb3J0SWQoKSA/PyB1bmRlZmluZWRcIlxuICAgICAgICAgICAgKHNhdmUpPVwib25SZXBvcnRTYXZlZCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChkZWZpbml0aW9uQ2hhbmdlKT1cImRlZmluaXRpb25DaGFuZ2UuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgICAvPlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbYFxuICAgIDpob3N0IHtcbiAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICBoZWlnaHQ6IDEwMCU7XG4gICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAgICAgZm9udC1mYW1pbHk6IHZhcigtLXJwdC1mb250LWZhbWlseSwgLWFwcGxlLXN5c3RlbSwgQmxpbmtNYWNTeXN0ZW1Gb250LCBcIlNlZ29lIFVJXCIsIFJvYm90bywgc2Fucy1zZXJpZik7XG4gICAgfVxuXG4gICAgLnJwdC1idWlsZGVyLWNvbnRhaW5lciB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICBiYWNrZ3JvdW5kOiAjZjhmYWZjO1xuICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICB9XG5cbiAgICAucnB0LWJ1aWxkZXItaGVhZGVyIHtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgICAgcGFkZGluZzogOHB4IDE2cHg7XG4gICAgICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICNlMmU4ZjA7XG4gICAgICB6LWluZGV4OiAxMDtcbiAgICAgIGZsZXgtc2hyaW5rOiAwO1xuICAgIH1cblxuICAgIC5ycHQtaGVhZGVyLWxlZnQge1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICBnYXA6IDEwcHg7XG4gICAgfVxuXG4gICAgLnJwdC1oZWFkZXItbGFiZWwge1xuICAgICAgZm9udC1zaXplOiAwLjgxMjVyZW07XG4gICAgICBmb250LXdlaWdodDogNjAwO1xuICAgICAgY29sb3I6ICM0NzU1Njk7XG4gICAgfVxuXG4gICAgLnJwdC1zZWxlY3Qtd3JhcHBlciB7XG4gICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgICBkaXNwbGF5OiBpbmxpbmUtZmxleDtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgfVxuXG4gICAgLnJwdC1yZXBvcnQtc2VsZWN0IHtcbiAgICAgIGFwcGVhcmFuY2U6IG5vbmU7XG4gICAgICAtd2Via2l0LWFwcGVhcmFuY2U6IG5vbmU7XG4gICAgICBwYWRkaW5nOiA1cHggMjhweCA1cHggMTJweDtcbiAgICAgIGZvbnQtc2l6ZTogMC44MTI1cmVtO1xuICAgICAgZm9udC13ZWlnaHQ6IDUwMDtcbiAgICAgIGNvbG9yOiAjMGYxNzJhO1xuICAgICAgYmFja2dyb3VuZDogI2Y4ZmFmYztcbiAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNjYmQ1ZTE7XG4gICAgICBib3JkZXItcmFkaXVzOiA2cHg7XG4gICAgICBvdXRsaW5lOiBub25lO1xuICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgbWluLXdpZHRoOiAyMjBweDtcbiAgICAgIHRyYW5zaXRpb246IGFsbCAwLjE1cyBlYXNlO1xuICAgIH1cblxuICAgIC5ycHQtcmVwb3J0LXNlbGVjdDpmb2N1cyB7XG4gICAgICBiYWNrZ3JvdW5kOiAjZmZmZmZmO1xuICAgICAgYm9yZGVyLWNvbG9yOiAjMjU2M2ViO1xuICAgICAgYm94LXNoYWRvdzogMCAwIDAgMnB4IHJnYmEoMzcsIDk5LCAyMzUsIDAuMTUpO1xuICAgIH1cblxuICAgIC5ycHQtc2VsZWN0LWFycm93IHtcbiAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIHJpZ2h0OiAxMHB4O1xuICAgICAgcG9pbnRlci1ldmVudHM6IG5vbmU7XG4gICAgICBjb2xvcjogIzY0NzQ4YjtcbiAgICB9XG5cbiAgICAucnB0LWJ0bi1uZXctcmVwb3J0IHtcbiAgICAgIGRpc3BsYXk6IGlubGluZS1mbGV4O1xuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgIGdhcDogNXB4O1xuICAgICAgcGFkZGluZzogNXB4IDEycHg7XG4gICAgICBiYWNrZ3JvdW5kOiAjZWZmNmZmO1xuICAgICAgYm9yZGVyOiAxcHggc29saWQgI2JmZGJmZTtcbiAgICAgIGNvbG9yOiAjMjU2M2ViO1xuICAgICAgYm9yZGVyLXJhZGl1czogNnB4O1xuICAgICAgZm9udC1zaXplOiAwLjgxMjVyZW07XG4gICAgICBmb250LXdlaWdodDogNjAwO1xuICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgdHJhbnNpdGlvbjogYWxsIDAuMTVzIGVhc2U7XG4gICAgfVxuXG4gICAgLnJwdC1idG4tbmV3LXJlcG9ydDpob3ZlciB7XG4gICAgICBiYWNrZ3JvdW5kOiAjZGJlYWZlO1xuICAgICAgYm9yZGVyLWNvbG9yOiAjOTNjNWZkO1xuICAgIH1cblxuICAgIC5ycHQtaGVhZGVyLXJpZ2h0IHtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgZ2FwOiAxMnB4O1xuICAgIH1cblxuICAgIC5ycHQtc2F2ZS1zdGF0dXMge1xuICAgICAgZGlzcGxheTogaW5saW5lLWZsZXg7XG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgZ2FwOiA1cHg7XG4gICAgICBmb250LXNpemU6IDAuNzVyZW07XG4gICAgICBmb250LXdlaWdodDogNjAwO1xuICAgICAgY29sb3I6ICMxNmEzNGE7XG4gICAgICBiYWNrZ3JvdW5kOiAjZjBmZGY0O1xuICAgICAgcGFkZGluZzogM3B4IDhweDtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDk5OTlweDtcbiAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNiYmY3ZDA7XG4gICAgICBhbmltYXRpb246IHJwdC1zdGF0dXMtZmFkZSAyMDBtcyBlYXNlO1xuICAgIH1cblxuICAgIEBrZXlmcmFtZXMgcnB0LXN0YXR1cy1mYWRlIHtcbiAgICAgIGZyb20geyBvcGFjaXR5OiAwOyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoLTJweCk7IH1cbiAgICAgIHRvIHsgb3BhY2l0eTogMTsgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDApOyB9XG4gICAgfVxuXG4gICAgLnJwdC1idWlsZGVyLWRlc2lnbmVyLWFyZWEge1xuICAgICAgZmxleDogMTtcbiAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgaGVpZ2h0OiAxMDAlO1xuICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICB9XG4gIGBdLFxufSlcbmV4cG9ydCBjbGFzcyBCd2F5c1JlcG9ydEJ1aWxkZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBwcml2YXRlIHJlYWRvbmx5IHN0b3JlID0gaW5qZWN0KFJlcG9ydFN0b3JlU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcblxuICAvKiogV2lkdGggb2YgdGhlIGJ1aWxkZXIgY29udGFpbmVyLiBEZWZhdWx0cyB0byAnMTAwJScuICovXG4gIHJlYWRvbmx5IHdpZHRoID0gaW5wdXQ8c3RyaW5nPignMTAwJScpO1xuXG4gIC8qKiBIZWlnaHQgb2YgdGhlIGJ1aWxkZXIgY29udGFpbmVyLiBEZWZhdWx0cyB0byAnMTAwJScuICovXG4gIHJlYWRvbmx5IGhlaWdodCA9IGlucHV0PHN0cmluZz4oJzEwMCUnKTtcblxuICAvKiogSW5pdGlhbCByZXBvcnQgSUQgdG8gb3BlbiBpbiB0aGUgZGVzaWduZXIuICovXG4gIHJlYWRvbmx5IHJlcG9ydElkID0gaW5wdXQ8c3RyaW5nIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuXG4gIC8qKiBXaGV0aGVyIHRvIHNob3cgdGhlIHRvcCBzd2l0Y2hlciBiYXIgd2l0aCByZXBvcnQgc2VsZWN0b3IgYW5kIFwiKyBOZXdcIiBidXR0b24uICovXG4gIHJlYWRvbmx5IHNob3dSZXBvcnRMaXN0ID0gaW5wdXQ8Ym9vbGVhbj4odHJ1ZSk7XG5cbiAgLyoqIEVtaXR0ZWQgd2hlbiBhIHJlcG9ydCBkZWZpbml0aW9uIGlzIHNhdmVkLiAqL1xuICByZWFkb25seSBzYXZlZCA9IG91dHB1dDxSZXBvcnREZWZpbml0aW9uPigpO1xuXG4gIC8qKiBFbWl0dGVkIHdoZW4gdGhlIHJlcG9ydCBkZWZpbml0aW9uIGNoYW5nZXMuICovXG4gIHJlYWRvbmx5IGRlZmluaXRpb25DaGFuZ2UgPSBvdXRwdXQ8UmVwb3J0RGVmaW5pdGlvbj4oKTtcblxuICAvKiogRW1pdHRlZCB3aGVuIGEgcmVwb3J0IGlzIHNlbGVjdGVkIGZyb20gdGhlIGxpc3QuICovXG4gIHJlYWRvbmx5IHJlcG9ydFNlbGVjdCA9IG91dHB1dDxzdHJpbmc+KCk7XG5cbiAgcmVhZG9ubHkgYWN0aXZlUmVwb3J0SWQgPSBzaWduYWw8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG4gIHJlYWRvbmx5IHJlcG9ydHNMaXN0ID0gc2lnbmFsPFJlcG9ydFN1bW1hcnlbXT4oW10pO1xuICByZWFkb25seSBzYXZlU3RhdHVzID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuICByZWFkb25seSBkZXNpZ25lcktleSA9IHNpZ25hbDxudW1iZXI+KDEpO1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnJlcG9ydElkKCkpIHtcbiAgICAgIHRoaXMuYWN0aXZlUmVwb3J0SWQuc2V0KHRoaXMucmVwb3J0SWQoKSEpO1xuICAgIH1cblxuICAgIHRoaXMucmVmcmVzaFJlcG9ydHMoKTtcbiAgfVxuXG4gIG9uU2VsZWN0UmVwb3J0KGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB0YXJnZXQgPSBpZCA/IGlkIDogbnVsbDtcbiAgICB0aGlzLmFjdGl2ZVJlcG9ydElkLnNldCh0YXJnZXQpO1xuICAgIHRoaXMuZGVzaWduZXJLZXkudXBkYXRlKChrKSA9PiBrICsgMSk7XG4gICAgaWYgKHRhcmdldCkge1xuICAgICAgdGhpcy5yZXBvcnRTZWxlY3QuZW1pdCh0YXJnZXQpO1xuICAgIH1cbiAgfVxuXG4gIGNyZWF0ZU5ld1JlcG9ydCgpOiB2b2lkIHtcbiAgICB0aGlzLmFjdGl2ZVJlcG9ydElkLnNldChudWxsKTtcbiAgICB0aGlzLmRlc2lnbmVyS2V5LnVwZGF0ZSgoaykgPT4gayArIDEpO1xuICB9XG5cbiAgb25SZXBvcnRTYXZlZChkZWY6IFJlcG9ydERlZmluaXRpb24pOiB2b2lkIHtcbiAgICB0aGlzLmFjdGl2ZVJlcG9ydElkLnNldChkZWYuaWQpO1xuICAgIHRoaXMuc2F2ZVN0YXR1cy5zZXQoYFNhdmVkIFwiJHtkZWYubmFtZX1cImApO1xuICAgIHRoaXMuc2F2ZWQuZW1pdChkZWYpO1xuXG4gICAgLy8gUmVmcmVzaCBzdG9yZSBzdW1tYXJpZXMgc28gbmF2aWdhdGlvbiByZWZsZWN0cyBjaGFuZ2VzIGltbWVkaWF0ZWx5XG4gICAgdGhpcy5yZWZyZXNoUmVwb3J0cygpO1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnNhdmVTdGF0dXMuc2V0KG51bGwpO1xuICAgIH0sIDM1MDApO1xuICB9XG5cbiAgcHJpdmF0ZSByZWZyZXNoUmVwb3J0cygpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JlXG4gICAgICAubG9hZFN1bW1hcmllcygpXG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiAobGlzdCkgPT4gdGhpcy5yZXBvcnRzTGlzdC5zZXQobGlzdCksXG4gICAgICAgIGVycm9yOiAoZXJyKSA9PiBjb25zb2xlLndhcm4oJ1tid2F5cy1yZXBvcnRdIEZhaWxlZCB0byBsb2FkIHJlcG9ydHMgbGlzdDonLCBlcnIpLFxuICAgICAgfSk7XG4gIH1cbn1cbiJdfQ==