ngx-dynamic-entity-builder 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +2 -1
  2. package/fesm2022/ngx-dynamic-entity-builder.mjs +521 -105
  3. package/fesm2022/ngx-dynamic-entity-builder.mjs.map +1 -1
  4. package/package.json +7 -7
  5. package/types/ngx-dynamic-entity-builder.d.ts +582 -0
  6. package/esm2022/lib/builder-store.service.mjs +0 -1057
  7. package/esm2022/lib/clone.mjs +0 -14
  8. package/esm2022/lib/components/entity-builder-canvas.component.mjs +0 -84
  9. package/esm2022/lib/components/entity-builder-tree-node.component.mjs +0 -192
  10. package/esm2022/lib/components/entity-reference-config.component.mjs +0 -405
  11. package/esm2022/lib/components/field-inspector.component.mjs +0 -139
  12. package/esm2022/lib/components/field-palette.component.mjs +0 -57
  13. package/esm2022/lib/components/field-rules-list.component.mjs +0 -224
  14. package/esm2022/lib/components/referenced-field-config.component.mjs +0 -235
  15. package/esm2022/lib/components/rule-form.component.mjs +0 -201
  16. package/esm2022/lib/components/tab-manager.component.mjs +0 -354
  17. package/esm2022/lib/entity-builder.component.mjs +0 -159
  18. package/esm2022/lib/field-catalog.mjs +0 -6
  19. package/esm2022/ngx-dynamic-entity-builder.mjs +0 -5
  20. package/esm2022/public-api.mjs +0 -16
  21. package/index.d.ts +0 -5
  22. package/lib/builder-store.service.d.ts +0 -206
  23. package/lib/clone.d.ts +0 -9
  24. package/lib/components/entity-builder-canvas.component.d.ts +0 -9
  25. package/lib/components/entity-builder-tree-node.component.d.ts +0 -17
  26. package/lib/components/entity-reference-config.component.d.ts +0 -29
  27. package/lib/components/field-inspector.component.d.ts +0 -33
  28. package/lib/components/field-palette.component.d.ts +0 -13
  29. package/lib/components/field-rules-list.component.d.ts +0 -19
  30. package/lib/components/referenced-field-config.component.d.ts +0 -24
  31. package/lib/components/rule-form.component.d.ts +0 -16
  32. package/lib/components/tab-manager.component.d.ts +0 -28
  33. package/lib/entity-builder.component.d.ts +0 -45
  34. package/lib/field-catalog.d.ts +0 -5
  35. package/public-api.d.ts +0 -12
@@ -1,354 +0,0 @@
1
- import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
2
- import { FormsModule } from '@angular/forms';
3
- import { MatButtonModule } from '@angular/material/button';
4
- import { MatCheckboxModule } from '@angular/material/checkbox';
5
- import { MatFormFieldModule } from '@angular/material/form-field';
6
- import { MatIconModule } from '@angular/material/icon';
7
- import { MatInputModule } from '@angular/material/input';
8
- import { MatSlideToggleModule } from '@angular/material/slide-toggle';
9
- import { MatTooltipModule } from '@angular/material/tooltip';
10
- import { resolveLabel } from '@dynamic-entity/core';
11
- import { SYSTEM_DEFAULT_CAN_EDIT } from 'ngx-dynamic-entity';
12
- import { BuilderStore } from '../builder-store.service';
13
- import * as i0 from "@angular/core";
14
- import * as i1 from "@angular/forms";
15
- import * as i2 from "@angular/material/button";
16
- import * as i3 from "@angular/material/checkbox";
17
- import * as i4 from "@angular/material/form-field";
18
- import * as i5 from "@angular/material/icon";
19
- import * as i6 from "@angular/material/input";
20
- import * as i7 from "@angular/material/tooltip";
21
- /**
22
- * Re-exported so existing imports from this package keep working.
23
- *
24
- * This file used to declare its own `new InjectionToken('SYSTEM_DEFAULT_CAN_EDIT')` while
25
- * `ngx-dynamic-entity` exported another under the same name. InjectionToken identity is by
26
- * object reference, so a consumer providing the renderer's — the documented one — was
27
- * providing a token nothing injected, and the predicate silently never ran. One token now,
28
- * defined in the lower-level package that both depend on.
29
- */
30
- export { SYSTEM_DEFAULT_CAN_EDIT };
31
- /**
32
- * TabManagerComponent — add / rename / reorder / remove tabs & sub-tabs with systemDefault protection.
33
- */
34
- export class TabManagerComponent {
35
- store = inject(BuilderStore);
36
- canEditSystemDefaultsFn = inject(SYSTEM_DEFAULT_CAN_EDIT, { optional: true });
37
- lang() {
38
- return this.store.activeLanguage();
39
- }
40
- tabLabel(tab) {
41
- return resolveLabel(tab.label, this.lang());
42
- }
43
- canEditTab(tab) {
44
- if (!tab.systemDefault)
45
- return true;
46
- if (this.canEditSystemDefaultsFn) {
47
- // The predicate's entire contract is (roles) => boolean. This passed a hardcoded []
48
- // regardless of who was using the builder, so any predicate that actually inspected
49
- // roles answered false for everyone and locked every system-default tab.
50
- return this.canEditSystemDefaultsFn(this.store.userRoles());
51
- }
52
- return true;
53
- }
54
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TabManagerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
55
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: TabManagerComponent, isStandalone: true, selector: "ngx-tab-manager", ngImport: i0, template: `
56
- <div class="deb-tabs">
57
- <div class="deb-tabs__head">
58
- <span class="deb-section-title">Tabs Manager</span>
59
- <button mat-stroked-button type="button" (click)="store.addTab()">
60
- <mat-icon>add</mat-icon> Add Tab
61
- </button>
62
- </div>
63
-
64
- @if (store.tabs().length === 0) {
65
- <p class="deb-hint">No tabs — all fields render in a single section.</p>
66
- }
67
-
68
- @for (tab of store.tabs(); track tab.id; let i = $index, count = $count) {
69
- <div class="deb-tab-card" [class.deb-tab-card--system]="tab.systemDefault">
70
- <div class="deb-tabs__row" [attr.data-testid]="'tab-row-' + tab.id">
71
- <mat-form-field appearance="outline" subscriptSizing="dynamic" class="deb-grow">
72
- <mat-label>{{ tab.id }} {{ tab.systemDefault ? '(System)' : '' }}</mat-label>
73
- <input
74
- matInput
75
- [disabled]="!canEditTab(tab)"
76
- [ngModel]="tabLabel(tab)"
77
- (ngModelChange)="store.setTabLabel(tab.id, lang(), $event)"
78
- />
79
- </mat-form-field>
80
- <button
81
- mat-icon-button
82
- type="button"
83
- [disabled]="i === 0 || !canEditTab(tab)"
84
- (click)="store.moveTab(tab.id, -1)"
85
- matTooltip="Move up" aria-label="Move tab up"
86
- >
87
- <mat-icon>arrow_upward</mat-icon>
88
- </button>
89
- <button
90
- mat-icon-button
91
- type="button"
92
- [disabled]="i === count - 1 || !canEditTab(tab)"
93
- (click)="store.moveTab(tab.id, 1)"
94
- matTooltip="Move down" aria-label="Move tab down"
95
- >
96
- <mat-icon>arrow_downward</mat-icon>
97
- </button>
98
- <button
99
- mat-icon-button
100
- type="button"
101
- color="warn"
102
- [disabled]="!canEditTab(tab)"
103
- (click)="store.removeTab(tab.id)"
104
- matTooltip="Remove tab" aria-label="Remove tab"
105
- >
106
- <mat-icon>delete</mat-icon>
107
- </button>
108
- </div>
109
-
110
- <!-- Tab settings row -->
111
- <div class="deb-tab-settings">
112
- <mat-checkbox
113
- [disabled]="!canEditTab(tab)"
114
- [ngModel]="tab.flatData"
115
- (ngModelChange)="store.updateTab(tab.id, { flatData: $event })"
116
- >
117
- Flat Data
118
- </mat-checkbox>
119
- <mat-checkbox
120
- [disabled]="!canEditTab(tab)"
121
- [ngModel]="tab.isPrimaryTab"
122
- (ngModelChange)="$event ? store.setPrimaryTab(tab.id) : store.updateTab(tab.id, { isPrimaryTab: false })"
123
- >
124
- Primary Tab
125
- </mat-checkbox>
126
- <mat-checkbox
127
- [disabled]="!canEditTab(tab)"
128
- [ngModel]="tab.maskData"
129
- (ngModelChange)="store.updateTab(tab.id, { maskData: $event })"
130
- >
131
- Mask Tab Data
132
- </mat-checkbox>
133
- <mat-checkbox
134
- [disabled]="!canEditTab(tab)"
135
- [ngModel]="tab.systemDefault"
136
- (ngModelChange)="store.updateTab(tab.id, { systemDefault: $event })"
137
- >
138
- System Default
139
- </mat-checkbox>
140
- <button
141
- mat-button
142
- type="button"
143
- color="primary"
144
- [disabled]="!canEditTab(tab)"
145
- (click)="store.addSubTab(tab.id)"
146
- >
147
- + Sub-tab
148
- </button>
149
- </div>
150
-
151
- <!-- Module tab configuration -->
152
- <div class="deb-tab-module">
153
- <mat-form-field appearance="outline" subscriptSizing="dynamic" class="deb-grow">
154
- <mat-label>Consumer Module Name (Optional)</mat-label>
155
- <input
156
- matInput
157
- placeholder="e.g. documents-view"
158
- [disabled]="!canEditTab(tab)"
159
- [ngModel]="tab.moduleName"
160
- (ngModelChange)="store.updateTab(tab.id, { moduleName: $event || undefined })"
161
- />
162
- </mat-form-field>
163
- </div>
164
-
165
- <!-- Sub-tabs recursive render (Level 2) -->
166
- @if (tab.children && tab.children.length > 0) {
167
- <div class="deb-subtabs">
168
- <span class="deb-subtabs__title">Sub-tabs:</span>
169
- @for (sub of tab.children; track sub.id) {
170
- <div class="deb-tabs__row deb-subtab-row" [attr.data-testid]="'subtab-row-' + sub.id">
171
- <mat-form-field appearance="outline" subscriptSizing="dynamic" class="deb-grow">
172
- <mat-label>{{ sub.id }}</mat-label>
173
- <input
174
- matInput
175
- [disabled]="!canEditTab(sub)"
176
- [ngModel]="tabLabel(sub)"
177
- (ngModelChange)="store.setTabLabel(sub.id, lang(), $event)"
178
- />
179
- </mat-form-field>
180
- <button
181
- mat-icon-button
182
- type="button"
183
- color="warn"
184
- [disabled]="!canEditTab(sub)"
185
- (click)="store.removeTab(sub.id)"
186
- matTooltip="Remove sub-tab" aria-label="Remove sub-tab"
187
- >
188
- <mat-icon>delete</mat-icon>
189
- </button>
190
- </div>
191
- }
192
- </div>
193
- }
194
- </div>
195
- }
196
- </div>
197
- `, isInline: true, styles: [".deb-tabs__head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.deb-tab-card{border:1px solid var(--deb-border, #e5e7eb);border-radius:8px;padding:10px;margin-bottom:10px;background:var(--deb-bg-surface, #ffffff)}.deb-tab-card--system{border-left:4px solid var(--deb-accent, #6366f1)}.deb-tabs__row{display:flex;align-items:center;gap:4px}.deb-tab-settings{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;margin-top:8px;font-size:13px}.deb-tab-module{margin-top:8px}.deb-subtabs{margin-top:8px;padding-left:16px;border-left:2px dashed var(--deb-border, #e5e7eb)}.deb-subtabs__title{font-size:12px;font-weight:600;color:var(--deb-muted, #6b7280)}.deb-subtab-row{margin-top:6px}.deb-grow{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { 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: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i6.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i7.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
198
- }
199
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TabManagerComponent, decorators: [{
200
- type: Component,
201
- args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngx-tab-manager', standalone: true, imports: [
202
- FormsModule,
203
- MatButtonModule,
204
- MatCheckboxModule,
205
- MatFormFieldModule,
206
- MatIconModule,
207
- MatInputModule,
208
- MatSlideToggleModule,
209
- MatTooltipModule,
210
- ], template: `
211
- <div class="deb-tabs">
212
- <div class="deb-tabs__head">
213
- <span class="deb-section-title">Tabs Manager</span>
214
- <button mat-stroked-button type="button" (click)="store.addTab()">
215
- <mat-icon>add</mat-icon> Add Tab
216
- </button>
217
- </div>
218
-
219
- @if (store.tabs().length === 0) {
220
- <p class="deb-hint">No tabs — all fields render in a single section.</p>
221
- }
222
-
223
- @for (tab of store.tabs(); track tab.id; let i = $index, count = $count) {
224
- <div class="deb-tab-card" [class.deb-tab-card--system]="tab.systemDefault">
225
- <div class="deb-tabs__row" [attr.data-testid]="'tab-row-' + tab.id">
226
- <mat-form-field appearance="outline" subscriptSizing="dynamic" class="deb-grow">
227
- <mat-label>{{ tab.id }} {{ tab.systemDefault ? '(System)' : '' }}</mat-label>
228
- <input
229
- matInput
230
- [disabled]="!canEditTab(tab)"
231
- [ngModel]="tabLabel(tab)"
232
- (ngModelChange)="store.setTabLabel(tab.id, lang(), $event)"
233
- />
234
- </mat-form-field>
235
- <button
236
- mat-icon-button
237
- type="button"
238
- [disabled]="i === 0 || !canEditTab(tab)"
239
- (click)="store.moveTab(tab.id, -1)"
240
- matTooltip="Move up" aria-label="Move tab up"
241
- >
242
- <mat-icon>arrow_upward</mat-icon>
243
- </button>
244
- <button
245
- mat-icon-button
246
- type="button"
247
- [disabled]="i === count - 1 || !canEditTab(tab)"
248
- (click)="store.moveTab(tab.id, 1)"
249
- matTooltip="Move down" aria-label="Move tab down"
250
- >
251
- <mat-icon>arrow_downward</mat-icon>
252
- </button>
253
- <button
254
- mat-icon-button
255
- type="button"
256
- color="warn"
257
- [disabled]="!canEditTab(tab)"
258
- (click)="store.removeTab(tab.id)"
259
- matTooltip="Remove tab" aria-label="Remove tab"
260
- >
261
- <mat-icon>delete</mat-icon>
262
- </button>
263
- </div>
264
-
265
- <!-- Tab settings row -->
266
- <div class="deb-tab-settings">
267
- <mat-checkbox
268
- [disabled]="!canEditTab(tab)"
269
- [ngModel]="tab.flatData"
270
- (ngModelChange)="store.updateTab(tab.id, { flatData: $event })"
271
- >
272
- Flat Data
273
- </mat-checkbox>
274
- <mat-checkbox
275
- [disabled]="!canEditTab(tab)"
276
- [ngModel]="tab.isPrimaryTab"
277
- (ngModelChange)="$event ? store.setPrimaryTab(tab.id) : store.updateTab(tab.id, { isPrimaryTab: false })"
278
- >
279
- Primary Tab
280
- </mat-checkbox>
281
- <mat-checkbox
282
- [disabled]="!canEditTab(tab)"
283
- [ngModel]="tab.maskData"
284
- (ngModelChange)="store.updateTab(tab.id, { maskData: $event })"
285
- >
286
- Mask Tab Data
287
- </mat-checkbox>
288
- <mat-checkbox
289
- [disabled]="!canEditTab(tab)"
290
- [ngModel]="tab.systemDefault"
291
- (ngModelChange)="store.updateTab(tab.id, { systemDefault: $event })"
292
- >
293
- System Default
294
- </mat-checkbox>
295
- <button
296
- mat-button
297
- type="button"
298
- color="primary"
299
- [disabled]="!canEditTab(tab)"
300
- (click)="store.addSubTab(tab.id)"
301
- >
302
- + Sub-tab
303
- </button>
304
- </div>
305
-
306
- <!-- Module tab configuration -->
307
- <div class="deb-tab-module">
308
- <mat-form-field appearance="outline" subscriptSizing="dynamic" class="deb-grow">
309
- <mat-label>Consumer Module Name (Optional)</mat-label>
310
- <input
311
- matInput
312
- placeholder="e.g. documents-view"
313
- [disabled]="!canEditTab(tab)"
314
- [ngModel]="tab.moduleName"
315
- (ngModelChange)="store.updateTab(tab.id, { moduleName: $event || undefined })"
316
- />
317
- </mat-form-field>
318
- </div>
319
-
320
- <!-- Sub-tabs recursive render (Level 2) -->
321
- @if (tab.children && tab.children.length > 0) {
322
- <div class="deb-subtabs">
323
- <span class="deb-subtabs__title">Sub-tabs:</span>
324
- @for (sub of tab.children; track sub.id) {
325
- <div class="deb-tabs__row deb-subtab-row" [attr.data-testid]="'subtab-row-' + sub.id">
326
- <mat-form-field appearance="outline" subscriptSizing="dynamic" class="deb-grow">
327
- <mat-label>{{ sub.id }}</mat-label>
328
- <input
329
- matInput
330
- [disabled]="!canEditTab(sub)"
331
- [ngModel]="tabLabel(sub)"
332
- (ngModelChange)="store.setTabLabel(sub.id, lang(), $event)"
333
- />
334
- </mat-form-field>
335
- <button
336
- mat-icon-button
337
- type="button"
338
- color="warn"
339
- [disabled]="!canEditTab(sub)"
340
- (click)="store.removeTab(sub.id)"
341
- matTooltip="Remove sub-tab" aria-label="Remove sub-tab"
342
- >
343
- <mat-icon>delete</mat-icon>
344
- </button>
345
- </div>
346
- }
347
- </div>
348
- }
349
- </div>
350
- }
351
- </div>
352
- `, styles: [".deb-tabs__head{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.deb-tab-card{border:1px solid var(--deb-border, #e5e7eb);border-radius:8px;padding:10px;margin-bottom:10px;background:var(--deb-bg-surface, #ffffff)}.deb-tab-card--system{border-left:4px solid var(--deb-accent, #6366f1)}.deb-tabs__row{display:flex;align-items:center;gap:4px}.deb-tab-settings{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;margin-top:8px;font-size:13px}.deb-tab-module{margin-top:8px}.deb-subtabs{margin-top:8px;padding-left:16px;border-left:2px dashed var(--deb-border, #e5e7eb)}.deb-subtabs__title{font-size:12px;font-weight:600;color:var(--deb-muted, #6b7280)}.deb-subtab-row{margin-top:6px}.deb-grow{flex:1}\n"] }]
353
- }] });
354
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFiLW1hbmFnZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9jb21wb25lbnRzL3RhYi1tYW5hZ2VyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDekQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFN0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3BELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzdELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7Ozs7O0FBRXhEOzs7Ozs7OztHQVFHO0FBQ0gsT0FBTyxFQUFFLHVCQUF1QixFQUFFLENBQUM7QUFFbkM7O0dBRUc7QUFtTkgsTUFBTSxPQUFPLG1CQUFtQjtJQUNYLEtBQUssR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDL0IsdUJBQXVCLEdBQUcsTUFBTSxDQUErQix1QkFBdUIsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBRW5ILElBQUk7UUFDWixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7SUFDckMsQ0FBQztJQUVTLFFBQVEsQ0FBQyxHQUFvQjtRQUNyQyxPQUFPLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzlDLENBQUM7SUFFUyxVQUFVLENBQUMsR0FBb0I7UUFDdkMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFDcEMsSUFBSSxJQUFJLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztZQUNqQyxvRkFBb0Y7WUFDcEYsb0ZBQW9GO1lBQ3BGLHlFQUF5RTtZQUN6RSxPQUFPLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDOUQsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQzt3R0FyQlUsbUJBQW1COzRGQUFuQixtQkFBbUIsMkVBcE1wQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThJVCw4eUJBdkpDLFdBQVcsOG1CQUNYLGVBQWUsd1VBQ2YsaUJBQWlCLDZXQUNqQixrQkFBa0IsMFNBQ2xCLGFBQWEsbUxBQ2IsY0FBYywwV0FDZCxvQkFBb0IsOEJBQ3BCLGdCQUFnQjs7NEZBc01QLG1CQUFtQjtrQkFsTi9CLFNBQVM7c0NBQ1MsdUJBQXVCLENBQUMsTUFBTSxZQUNyQyxpQkFBaUIsY0FDZixJQUFJLFdBQ1A7d0JBQ1AsV0FBVzt3QkFDWCxlQUFlO3dCQUNmLGlCQUFpQjt3QkFDakIsa0JBQWtCO3dCQUNsQixhQUFhO3dCQUNiLGNBQWM7d0JBQ2Qsb0JBQW9CO3dCQUNwQixnQkFBZ0I7cUJBQ2pCLFlBQ1M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4SVQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgTWF0QnV0dG9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYnV0dG9uJztcbmltcG9ydCB7IE1hdENoZWNrYm94TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvY2hlY2tib3gnO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0JztcbmltcG9ydCB7IE1hdFNsaWRlVG9nZ2xlTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc2xpZGUtdG9nZ2xlJztcbmltcG9ydCB7IE1hdFRvb2x0aXBNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90b29sdGlwJztcbmltcG9ydCB0eXBlIHsgTmVzdGVkVGFiQ29uZmlnIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHsgcmVzb2x2ZUxhYmVsIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHsgU1lTVEVNX0RFRkFVTFRfQ0FOX0VESVQgfSBmcm9tICduZ3gtZHluYW1pYy1lbnRpdHknO1xuaW1wb3J0IHsgQnVpbGRlclN0b3JlIH0gZnJvbSAnLi4vYnVpbGRlci1zdG9yZS5zZXJ2aWNlJztcblxuLyoqXG4gKiBSZS1leHBvcnRlZCBzbyBleGlzdGluZyBpbXBvcnRzIGZyb20gdGhpcyBwYWNrYWdlIGtlZXAgd29ya2luZy5cbiAqXG4gKiBUaGlzIGZpbGUgdXNlZCB0byBkZWNsYXJlIGl0cyBvd24gYG5ldyBJbmplY3Rpb25Ub2tlbignU1lTVEVNX0RFRkFVTFRfQ0FOX0VESVQnKWAgd2hpbGVcbiAqIGBuZ3gtZHluYW1pYy1lbnRpdHlgIGV4cG9ydGVkIGFub3RoZXIgdW5kZXIgdGhlIHNhbWUgbmFtZS4gSW5qZWN0aW9uVG9rZW4gaWRlbnRpdHkgaXMgYnlcbiAqIG9iamVjdCByZWZlcmVuY2UsIHNvIGEgY29uc3VtZXIgcHJvdmlkaW5nIHRoZSByZW5kZXJlcidzIOKAlCB0aGUgZG9jdW1lbnRlZCBvbmUg4oCUIHdhc1xuICogcHJvdmlkaW5nIGEgdG9rZW4gbm90aGluZyBpbmplY3RlZCwgYW5kIHRoZSBwcmVkaWNhdGUgc2lsZW50bHkgbmV2ZXIgcmFuLiBPbmUgdG9rZW4gbm93LFxuICogZGVmaW5lZCBpbiB0aGUgbG93ZXItbGV2ZWwgcGFja2FnZSB0aGF0IGJvdGggZGVwZW5kIG9uLlxuICovXG5leHBvcnQgeyBTWVNURU1fREVGQVVMVF9DQU5fRURJVCB9O1xuXG4vKipcbiAqIFRhYk1hbmFnZXJDb21wb25lbnQg4oCUIGFkZCAvIHJlbmFtZSAvIHJlb3JkZXIgLyByZW1vdmUgdGFicyAmIHN1Yi10YWJzIHdpdGggc3lzdGVtRGVmYXVsdCBwcm90ZWN0aW9uLlxuICovXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHNlbGVjdG9yOiAnbmd4LXRhYi1tYW5hZ2VyJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIEZvcm1zTW9kdWxlLFxuICAgIE1hdEJ1dHRvbk1vZHVsZSxcbiAgICBNYXRDaGVja2JveE1vZHVsZSxcbiAgICBNYXRGb3JtRmllbGRNb2R1bGUsXG4gICAgTWF0SWNvbk1vZHVsZSxcbiAgICBNYXRJbnB1dE1vZHVsZSxcbiAgICBNYXRTbGlkZVRvZ2dsZU1vZHVsZSxcbiAgICBNYXRUb29sdGlwTW9kdWxlLFxuICBdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJkZWItdGFic1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImRlYi10YWJzX19oZWFkXCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwiZGViLXNlY3Rpb24tdGl0bGVcIj5UYWJzIE1hbmFnZXI8L3NwYW4+XG4gICAgICAgIDxidXR0b24gbWF0LXN0cm9rZWQtYnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwic3RvcmUuYWRkVGFiKClcIj5cbiAgICAgICAgICA8bWF0LWljb24+YWRkPC9tYXQtaWNvbj4gQWRkIFRhYlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICBAaWYgKHN0b3JlLnRhYnMoKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgPHAgY2xhc3M9XCJkZWItaGludFwiPk5vIHRhYnMg4oCUIGFsbCBmaWVsZHMgcmVuZGVyIGluIGEgc2luZ2xlIHNlY3Rpb24uPC9wPlxuICAgICAgfVxuXG4gICAgICBAZm9yICh0YWIgb2Ygc3RvcmUudGFicygpOyB0cmFjayB0YWIuaWQ7IGxldCBpID0gJGluZGV4LCBjb3VudCA9ICRjb3VudCkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwiZGViLXRhYi1jYXJkXCIgW2NsYXNzLmRlYi10YWItY2FyZC0tc3lzdGVtXT1cInRhYi5zeXN0ZW1EZWZhdWx0XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImRlYi10YWJzX19yb3dcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCIndGFiLXJvdy0nICsgdGFiLmlkXCI+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBzdWJzY3JpcHRTaXppbmc9XCJkeW5hbWljXCIgY2xhc3M9XCJkZWItZ3Jvd1wiPlxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7IHRhYi5pZCB9fSB7eyB0YWIuc3lzdGVtRGVmYXVsdCA/ICcoU3lzdGVtKScgOiAnJyB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY2FuRWRpdFRhYih0YWIpXCJcbiAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ0YWJMYWJlbCh0YWIpXCJcbiAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdG9yZS5zZXRUYWJMYWJlbCh0YWIuaWQsIGxhbmcoKSwgJGV2ZW50KVwiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJpID09PSAwIHx8ICFjYW5FZGl0VGFiKHRhYilcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic3RvcmUubW92ZVRhYih0YWIuaWQsIC0xKVwiXG4gICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJNb3ZlIHVwXCIgYXJpYS1sYWJlbD1cIk1vdmUgdGFiIHVwXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG1hdC1pY29uPmFycm93X3Vwd2FyZDwvbWF0LWljb24+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaSA9PT0gY291bnQgLSAxIHx8ICFjYW5FZGl0VGFiKHRhYilcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic3RvcmUubW92ZVRhYih0YWIuaWQsIDEpXCJcbiAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIk1vdmUgZG93blwiIGFyaWEtbGFiZWw9XCJNb3ZlIHRhYiBkb3duXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG1hdC1pY29uPmFycm93X2Rvd253YXJkPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIGNvbG9yPVwid2FyblwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY2FuRWRpdFRhYih0YWIpXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInN0b3JlLnJlbW92ZVRhYih0YWIuaWQpXCJcbiAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlJlbW92ZSB0YWJcIiBhcmlhLWxhYmVsPVwiUmVtb3ZlIHRhYlwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8IS0tIFRhYiBzZXR0aW5ncyByb3cgLS0+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImRlYi10YWItc2V0dGluZ3NcIj5cbiAgICAgICAgICAgIDxtYXQtY2hlY2tib3hcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFjYW5FZGl0VGFiKHRhYilcIlxuICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ0YWIuZmxhdERhdGFcIlxuICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdG9yZS51cGRhdGVUYWIodGFiLmlkLCB7IGZsYXREYXRhOiAkZXZlbnQgfSlcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBGbGF0IERhdGFcbiAgICAgICAgICAgIDwvbWF0LWNoZWNrYm94PlxuICAgICAgICAgICAgPG1hdC1jaGVja2JveFxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWNhbkVkaXRUYWIodGFiKVwiXG4gICAgICAgICAgICAgIFtuZ01vZGVsXT1cInRhYi5pc1ByaW1hcnlUYWJcIlxuICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCIkZXZlbnQgPyBzdG9yZS5zZXRQcmltYXJ5VGFiKHRhYi5pZCkgOiBzdG9yZS51cGRhdGVUYWIodGFiLmlkLCB7IGlzUHJpbWFyeVRhYjogZmFsc2UgfSlcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBQcmltYXJ5IFRhYlxuICAgICAgICAgICAgPC9tYXQtY2hlY2tib3g+XG4gICAgICAgICAgICA8bWF0LWNoZWNrYm94XG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY2FuRWRpdFRhYih0YWIpXCJcbiAgICAgICAgICAgICAgW25nTW9kZWxdPVwidGFiLm1hc2tEYXRhXCJcbiAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3RvcmUudXBkYXRlVGFiKHRhYi5pZCwgeyBtYXNrRGF0YTogJGV2ZW50IH0pXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgTWFzayBUYWIgRGF0YVxuICAgICAgICAgICAgPC9tYXQtY2hlY2tib3g+XG4gICAgICAgICAgICA8bWF0LWNoZWNrYm94XG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY2FuRWRpdFRhYih0YWIpXCJcbiAgICAgICAgICAgICAgW25nTW9kZWxdPVwidGFiLnN5c3RlbURlZmF1bHRcIlxuICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdG9yZS51cGRhdGVUYWIodGFiLmlkLCB7IHN5c3RlbURlZmF1bHQ6ICRldmVudCB9KVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIFN5c3RlbSBEZWZhdWx0XG4gICAgICAgICAgICA8L21hdC1jaGVja2JveD5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFjYW5FZGl0VGFiKHRhYilcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic3RvcmUuYWRkU3ViVGFiKHRhYi5pZClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICArIFN1Yi10YWJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPCEtLSBNb2R1bGUgdGFiIGNvbmZpZ3VyYXRpb24gLS0+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImRlYi10YWItbW9kdWxlXCI+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBzdWJzY3JpcHRTaXppbmc9XCJkeW5hbWljXCIgY2xhc3M9XCJkZWItZ3Jvd1wiPlxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPkNvbnN1bWVyIE1vZHVsZSBOYW1lIChPcHRpb25hbCk8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cImUuZy4gZG9jdW1lbnRzLXZpZXdcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY2FuRWRpdFRhYih0YWIpXCJcbiAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ0YWIubW9kdWxlTmFtZVwiXG4gICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3RvcmUudXBkYXRlVGFiKHRhYi5pZCwgeyBtb2R1bGVOYW1lOiAkZXZlbnQgfHwgdW5kZWZpbmVkIH0pXCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8IS0tIFN1Yi10YWJzIHJlY3Vyc2l2ZSByZW5kZXIgKExldmVsIDIpIC0tPlxuICAgICAgICAgIEBpZiAodGFiLmNoaWxkcmVuICYmIHRhYi5jaGlsZHJlbi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGViLXN1YnRhYnNcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJkZWItc3VidGFic19fdGl0bGVcIj5TdWItdGFiczo8L3NwYW4+XG4gICAgICAgICAgICAgIEBmb3IgKHN1YiBvZiB0YWIuY2hpbGRyZW47IHRyYWNrIHN1Yi5pZCkge1xuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkZWItdGFic19fcm93IGRlYi1zdWJ0YWItcm93XCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ3N1YnRhYi1yb3ctJyArIHN1Yi5pZFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgc3Vic2NyaXB0U2l6aW5nPVwiZHluYW1pY1wiIGNsYXNzPVwiZGViLWdyb3dcIj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD57eyBzdWIuaWQgfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWNhbkVkaXRUYWIoc3ViKVwiXG4gICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwidGFiTGFiZWwoc3ViKVwiXG4gICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwic3RvcmUuc2V0VGFiTGFiZWwoc3ViLmlkLCBsYW5nKCksICRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICBjb2xvcj1cIndhcm5cIlxuICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWNhbkVkaXRUYWIoc3ViKVwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzdG9yZS5yZW1vdmVUYWIoc3ViLmlkKVwiXG4gICAgICAgICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJSZW1vdmUgc3ViLXRhYlwiIGFyaWEtbGFiZWw9XCJSZW1vdmUgc3ViLXRhYlwiXG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIC5kZWItdGFic19faGVhZCB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICAgICAgbWFyZ2luLWJvdHRvbTogMTJweDtcbiAgICAgIH1cbiAgICAgIC5kZWItdGFiLWNhcmQge1xuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1kZWItYm9yZGVyLCAjZTVlN2ViKTtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogOHB4O1xuICAgICAgICBwYWRkaW5nOiAxMHB4O1xuICAgICAgICBtYXJnaW4tYm90dG9tOiAxMHB4O1xuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1kZWItYmctc3VyZmFjZSwgI2ZmZmZmZik7XG4gICAgICB9XG4gICAgICAuZGViLXRhYi1jYXJkLS1zeXN0ZW0ge1xuICAgICAgICBib3JkZXItbGVmdDogNHB4IHNvbGlkIHZhcigtLWRlYi1hY2NlbnQsICM2MzY2ZjEpO1xuICAgICAgfVxuICAgICAgLmRlYi10YWJzX19yb3cge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBnYXA6IDRweDtcbiAgICAgIH1cbiAgICAgIC5kZWItdGFiLXNldHRpbmdzIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleC13cmFwOiB3cmFwO1xuICAgICAgICBnYXA6IDhweCAxNnB4O1xuICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAgICBtYXJnaW4tdG9wOiA4cHg7XG4gICAgICAgIGZvbnQtc2l6ZTogMTNweDtcbiAgICAgIH1cbiAgICAgIC5kZWItdGFiLW1vZHVsZSB7XG4gICAgICAgIG1hcmdpbi10b3A6IDhweDtcbiAgICAgIH1cbiAgICAgIC5kZWItc3VidGFicyB7XG4gICAgICAgIG1hcmdpbi10b3A6IDhweDtcbiAgICAgICAgcGFkZGluZy1sZWZ0OiAxNnB4O1xuICAgICAgICBib3JkZXItbGVmdDogMnB4IGRhc2hlZCB2YXIoLS1kZWItYm9yZGVyLCAjZTVlN2ViKTtcbiAgICAgIH1cbiAgICAgIC5kZWItc3VidGFic19fdGl0bGUge1xuICAgICAgICBmb250LXNpemU6IDEycHg7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7XG4gICAgICAgIGNvbG9yOiB2YXIoLS1kZWItbXV0ZWQsICM2YjcyODApO1xuICAgICAgfVxuICAgICAgLmRlYi1zdWJ0YWItcm93IHtcbiAgICAgICAgbWFyZ2luLXRvcDogNnB4O1xuICAgICAgfVxuICAgICAgLmRlYi1ncm93IHtcbiAgICAgICAgZmxleDogMTtcbiAgICAgIH1cbiAgICBgLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBUYWJNYW5hZ2VyQ29tcG9uZW50IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHN0b3JlID0gaW5qZWN0KEJ1aWxkZXJTdG9yZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FuRWRpdFN5c3RlbURlZmF1bHRzRm4gPSBpbmplY3Q8KHJvbGVzOiBzdHJpbmdbXSkgPT4gYm9vbGVhbj4oU1lTVEVNX0RFRkFVTFRfQ0FOX0VESVQsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cbiAgcHJvdGVjdGVkIGxhbmcoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zdG9yZS5hY3RpdmVMYW5ndWFnZSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHRhYkxhYmVsKHRhYjogeyBsYWJlbD86IGFueSB9KTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKHRhYi5sYWJlbCwgdGhpcy5sYW5nKCkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGNhbkVkaXRUYWIodGFiOiBOZXN0ZWRUYWJDb25maWcpOiBib29sZWFuIHtcbiAgICBpZiAoIXRhYi5zeXN0ZW1EZWZhdWx0KSByZXR1cm4gdHJ1ZTtcbiAgICBpZiAodGhpcy5jYW5FZGl0U3lzdGVtRGVmYXVsdHNGbikge1xuICAgICAgLy8gVGhlIHByZWRpY2F0ZSdzIGVudGlyZSBjb250cmFjdCBpcyAocm9sZXMpID0+IGJvb2xlYW4uIFRoaXMgcGFzc2VkIGEgaGFyZGNvZGVkIFtdXG4gICAgICAvLyByZWdhcmRsZXNzIG9mIHdobyB3YXMgdXNpbmcgdGhlIGJ1aWxkZXIsIHNvIGFueSBwcmVkaWNhdGUgdGhhdCBhY3R1YWxseSBpbnNwZWN0ZWRcbiAgICAgIC8vIHJvbGVzIGFuc3dlcmVkIGZhbHNlIGZvciBldmVyeW9uZSBhbmQgbG9ja2VkIGV2ZXJ5IHN5c3RlbS1kZWZhdWx0IHRhYi5cbiAgICAgIHJldHVybiB0aGlzLmNhbkVkaXRTeXN0ZW1EZWZhdWx0c0ZuKHRoaXMuc3RvcmUudXNlclJvbGVzKCkpO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufVxuIl19