ngx-dynamic-entity-builder 1.1.0 → 1.3.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.
@@ -1,6 +1,5 @@
1
- import { Component, EventEmitter, Input, Output, effect, inject, } from '@angular/core';
1
+ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, effect, inject } from '@angular/core';
2
2
  import { FormsModule } from '@angular/forms';
3
- import { DragDropModule } from '@angular/cdk/drag-drop';
4
3
  import { MatButtonModule } from '@angular/material/button';
5
4
  import { MatCardModule } from '@angular/material/card';
6
5
  import { MatCheckboxModule } from '@angular/material/checkbox';
@@ -12,13 +11,13 @@ import { MatSelectModule } from '@angular/material/select';
12
11
  import { MatSlideToggleModule } from '@angular/material/slide-toggle';
13
12
  import { MatToolbarModule } from '@angular/material/toolbar';
14
13
  import { MatTooltipModule } from '@angular/material/tooltip';
15
- import { COMMON_MODULES, resolveLabel, } from '@dynamic-entity/core';
14
+ import { COMMON_MODULES, } from '@dynamic-entity/core';
15
+ import { ConfigSourceService } from 'ngx-dynamic-entity';
16
16
  import { BuilderStore } from './builder-store.service';
17
17
  import { FieldInspectorComponent } from './components/field-inspector.component';
18
18
  import { FieldPaletteComponent } from './components/field-palette.component';
19
19
  import { TabManagerComponent } from './components/tab-manager.component';
20
20
  import { EntityBuilderCanvasComponent } from './components/entity-builder-canvas.component';
21
- import { getFieldTypeMeta } from './field-catalog';
22
21
  import * as i0 from "@angular/core";
23
22
  import * as i1 from "@angular/forms";
24
23
  import * as i2 from "@angular/material/button";
@@ -41,6 +40,11 @@ const EMPTY_ROLES = Object.freeze([]);
41
40
  */
42
41
  export class EntityBuilderComponent {
43
42
  store = inject(BuilderStore);
43
+ /**
44
+ * Optional: only apps that registered a CONFIG_SOURCE have one. Used to drop the cached
45
+ * copy of a config the moment it is edited — see `doSave`.
46
+ */
47
+ configSource = inject(ConfigSourceService, { optional: true });
44
48
  /** Existing config to edit. When omitted, the builder starts blank. */
45
49
  config;
46
50
  /** Languages available for label/placeholder editing. First entry is the default. */
@@ -79,23 +83,15 @@ export class EntityBuilderComponent {
79
83
  this.store.setUserRoles(this.userRoles);
80
84
  }
81
85
  }
82
- // ─── Field canvas ─────────────────────────────────────────────────────────
83
- onDrop(event) {
84
- this.store.reorderField(event.previousIndex, event.currentIndex);
85
- }
86
- fieldTypeLabel(type) {
87
- return getFieldTypeMeta(type)?.label ?? type;
88
- }
89
- fieldTypeIcon(type) {
90
- return getFieldTypeMeta(type)?.icon ?? 'help_outline';
91
- }
92
- fieldLabel(field) {
93
- const lang = this.store.activeLanguage();
94
- return resolveLabel(field.label, lang) || field.id;
95
- }
96
86
  // ─── Toolbar actions ──────────────────────────────────────────────────────
97
87
  doSave() {
98
- this.save.emit(this.store.exportConfig());
88
+ const config = this.store.exportConfig();
89
+ // Saving is the moment this entity's config changes, so anything holding a cached copy is
90
+ // now stale — most visibly a referenced field elsewhere resolving against the old schema.
91
+ // ConfigSourceService caches per entity and exposed clearCache from the start, but nothing
92
+ // ever called it, so a cache entry lived for the lifetime of the page.
93
+ this.configSource?.clearCache(config.entity);
94
+ this.save.emit(config);
99
95
  }
100
96
  get json() {
101
97
  return JSON.stringify(this.store.exportConfig(), null, 2);
@@ -123,13 +119,12 @@ export class EntityBuilderComponent {
123
119
  this.store.setPermission(action, roles);
124
120
  }
125
121
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityBuilderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
126
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EntityBuilderComponent, isStandalone: true, selector: "ngx-entity-builder", inputs: { config: "config", languages: "languages", availableRoles: "availableRoles", userRoles: "userRoles", commonModules: "commonModules" }, outputs: { configChange: "configChange", save: "save" }, providers: [BuilderStore], usesOnChanges: true, ngImport: i0, template: "<mat-toolbar class=\"deb-toolbar\" color=\"primary\">\n <mat-icon>dashboard_customize</mat-icon>\n <span class=\"deb-toolbar__title\">Entity Builder</span>\n <span class=\"deb-spacer\"></span>\n\n @if (store.problems().length) {\n <button\n mat-button\n type=\"button\"\n class=\"deb-problems\"\n [class.deb-problems--error]=\"!store.isValid()\"\n [matTooltip]=\"store.problems().length + ' issue(s) \u2014 hover items in the list'\"\n >\n <mat-icon>{{ store.isValid() ? 'warning' : 'error' }}</mat-icon>\n {{ store.errors().length }} / {{ store.problems().length }}\n </button>\n }\n\n <button mat-button type=\"button\" (click)=\"copyJson()\">\n <mat-icon>content_copy</mat-icon> Copy JSON\n </button>\n <button mat-flat-button color=\"accent\" type=\"button\" [disabled]=\"!store.isValid()\" (click)=\"doSave()\">\n <mat-icon>save</mat-icon> Save\n </button>\n</mat-toolbar>\n\n<div class=\"deb-body\">\n <!-- \u2500\u2500\u2500 Left: settings, palette, tabs \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--left\">\n <mat-card>\n <mat-card-content>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>Entity name</mat-label>\n <input\n matInput\n [ngModel]=\"store.config().entity\"\n (ngModelChange)=\"store.setEntityName($event)\"\n placeholder=\"e.g. clients\"\n />\n </mat-form-field>\n\n <div class=\"deb-row\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-grow\">\n <mat-label>Editing language</mat-label>\n <mat-select\n [ngModel]=\"store.activeLanguage()\"\n (ngModelChange)=\"store.setActiveLanguage($event)\"\n >\n @for (l of languages; track l) {\n <mat-option [value]=\"l\">{{ l }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n <mat-slide-toggle\n [ngModel]=\"store.config().maskData ?? false\"\n (ngModelChange)=\"store.setMaskData($event)\"\n >Mask this entity (RBAC)</mat-slide-toggle>\n\n <mat-expansion-panel class=\"deb-rbac\">\n <mat-expansion-panel-header>\n <mat-panel-title>Permissions</mat-panel-title>\n </mat-expansion-panel-header>\n @for (action of rbacActions; track action) {\n @if (availableRoles.length) {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>{{ action }} roles</mat-label>\n <mat-select multiple [ngModel]=\"rolesFor(action)\" (ngModelChange)=\"setRoles(action, $event)\">\n @for (role of availableRoles; track role) {\n <mat-option [value]=\"role\">{{ role }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>{{ action }} roles (comma-separated)</mat-label>\n <input\n matInput\n [ngModel]=\"rolesFor(action).join(', ')\"\n (ngModelChange)=\"setRolesFromText(action, $event)\"\n />\n </mat-form-field>\n }\n }\n <p class=\"deb-hint\">Empty = no restriction for that action.</p>\n </mat-expansion-panel>\n </mat-card-content>\n </mat-card>\n\n <mat-card>\n <mat-card-header><mat-card-title>Add field</mat-card-title></mat-card-header>\n <mat-card-content>\n <ngx-field-palette (pick)=\"store.addField($event)\"></ngx-field-palette>\n </mat-card-content>\n </mat-card>\n\n <mat-card>\n <mat-card-content>\n <ngx-tab-manager></ngx-tab-manager>\n </mat-card-content>\n </mat-card>\n </div>\n\n <!-- \u2500\u2500\u2500 Center: field canvas \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--center\">\n <ngx-entity-builder-canvas />\n </div>\n\n <!-- \u2500\u2500\u2500 Right: inspector \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--right\">\n <mat-card>\n <mat-card-header><mat-card-title>Field properties</mat-card-title></mat-card-header>\n <mat-card-content>\n <ngx-field-inspector></ngx-field-inspector>\n </mat-card-content>\n </mat-card>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Footer: JSON + optional live preview \u2500\u2500\u2500 -->\n<div class=\"deb-footer\">\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>data_object</mat-icon>&nbsp;Config JSON</mat-panel-title>\n </mat-expansion-panel-header>\n <pre class=\"deb-json\">{{ json }}</pre>\n </mat-expansion-panel>\n\n <div class=\"deb-preview-slot\">\n <ng-content select=\"[ngxBuilderPreview]\"></ng-content>\n </div>\n</div>\n", styles: [":host{--deb-accent: #6366f1;--deb-accent-hover: #4f46e5;--deb-accent-soft: #eeef2;--deb-border: #e2e8f0;--deb-muted: #64748b;--deb-surface: #ffffff;display:block}.deb-toolbar__title{margin-left:8px;font-family:var(--font-heading, sans-serif);font-size:16px;font-weight:700;color:#0f172a}.deb-spacer{flex:1 1 auto}.deb-problems--error{color:#ef4444;font-weight:600}.deb-full{width:100%}.deb-grow{flex:1}.deb-row{display:flex;gap:8px;align-items:center}.deb-section-title{font-family:var(--font-heading, sans-serif);font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--deb-muted)}.deb-hint{margin:4px 0 0;font-size:12px;color:var(--deb-muted)}.deb-chip{display:inline-block;padding:3px 10px;border-radius:9999px;background:var(--deb-accent-soft);color:var(--deb-accent-hover);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em}.deb-chip--muted{background:#f1f5f9;color:var(--deb-muted)}.deb-body{display:grid;grid-template-columns:320px minmax(0,1fr) 380px;gap:20px;padding:20px;align-items:start}.deb-col{display:flex;flex-direction:column;gap:16px;min-width:0}.deb-col--right{position:sticky;top:20px}@media (max-width: 1100px){.deb-body{grid-template-columns:1fr}.deb-col--right{position:static}}.deb-field-list{display:flex;flex-direction:column;gap:10px}.deb-field-row{display:flex;align-items:center;gap:10px;padding:10px 14px;border:1px solid var(--deb-border);border-radius:10px;background:var(--deb-surface);cursor:pointer;box-shadow:0 1px 3px #00000008;transition:all .18s cubic-bezier(.16,1,.3,1)}.deb-field-row:hover{border-color:#a5b4fc;background:#fcfaff;transform:translateY(-1px);box-shadow:0 4px 12px #6366f114}.deb-field-row--active{border-color:var(--deb-accent);border-left:4px solid var(--deb-accent);background:#f5f3ff;box-shadow:0 4px 16px #6366f12e}.deb-type-badge{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:2px 7px;border-radius:6px;background:#e0e7ff;color:#4338ca}.deb-drag-handle{cursor:grab;color:#94a3b8;transition:color .15s}.deb-drag-handle:hover,.deb-field-type{color:var(--deb-accent)}.deb-field-meta{display:flex;flex-direction:column;min-width:0;flex:1}.deb-field-label{font-family:var(--font-heading, sans-serif);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#0f172a;font-size:14px}.deb-field-id{font-size:11px;color:var(--deb-muted);font-family:ui-monospace,SFMono-Regular,monospace}.deb-req{color:#ef4444;font-weight:700}.deb-empty,.deb-inspector__empty{text-align:center;color:var(--deb-muted);padding:40px 16px}.deb-empty mat-icon{transform:scale(1.8);margin-bottom:16px;color:#cbd5e1}.cdk-drag-preview{box-shadow:0 12px 28px #4f46e538;border-radius:10px;border:1px solid var(--deb-accent);background:#fff}.cdk-drag-placeholder{opacity:.35}.cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.deb-field-list.cdk-drop-list-dragging .deb-field-row:not(.cdk-drag-placeholder){transition:transform .2s cubic-bezier(0,0,.2,1)}.deb-footer{padding:0 20px 20px;display:flex;flex-direction:column;gap:16px}.deb-json{margin:0;max-height:320px;overflow:auto;font-family:ui-monospace,SFMono-Regular,monospace;font-size:12px;line-height:1.5;padding:14px;background:#0f172a;color:#e2e8f0;border-radius:10px}\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: DragDropModule }, { 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: "ngmodule", type: MatCardModule }, { kind: "component", type: i3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i3.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i3.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatSelectModule }, { kind: "component", type: i8.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i10.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i11.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: FieldPaletteComponent, selector: "ngx-field-palette", outputs: ["pick"] }, { kind: "component", type: TabManagerComponent, selector: "ngx-tab-manager" }, { kind: "component", type: FieldInspectorComponent, selector: "ngx-field-inspector" }, { kind: "component", type: EntityBuilderCanvasComponent, selector: "ngx-entity-builder-canvas" }] });
122
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EntityBuilderComponent, isStandalone: true, selector: "ngx-entity-builder", inputs: { config: "config", languages: "languages", availableRoles: "availableRoles", userRoles: "userRoles", commonModules: "commonModules" }, outputs: { configChange: "configChange", save: "save" }, providers: [BuilderStore], usesOnChanges: true, ngImport: i0, template: "<mat-toolbar class=\"deb-toolbar\" color=\"primary\">\n <mat-icon>dashboard_customize</mat-icon>\n <span class=\"deb-toolbar__title\">Entity Builder</span>\n <span class=\"deb-spacer\"></span>\n\n @if (store.problems().length) {\n <button\n mat-button\n type=\"button\"\n class=\"deb-problems\"\n [class.deb-problems--error]=\"!store.isValid()\"\n [matTooltip]=\"store.problems().length + ' issue(s) \u2014 hover items in the list'\"\n >\n <mat-icon>{{ store.isValid() ? 'warning' : 'error' }}</mat-icon>\n {{ store.errors().length }} / {{ store.problems().length }}\n </button>\n }\n\n <button mat-button type=\"button\" (click)=\"copyJson()\">\n <mat-icon>content_copy</mat-icon> Copy JSON\n </button>\n <!-- primary, not accent: white on Material's default pink accent is 3.33:1, below AA. -->\n <button mat-flat-button color=\"primary\" type=\"button\" [disabled]=\"!store.isValid()\" (click)=\"doSave()\">\n <mat-icon>save</mat-icon> Save\n </button>\n</mat-toolbar>\n\n<div class=\"deb-body\">\n <!-- \u2500\u2500\u2500 Left: settings, palette, tabs \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--left\">\n <mat-card>\n <mat-card-content>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>Entity name</mat-label>\n <input\n matInput\n [ngModel]=\"store.config().entity\"\n (ngModelChange)=\"store.setEntityName($event)\"\n placeholder=\"e.g. clients\"\n />\n </mat-form-field>\n\n <div class=\"deb-row\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-grow\">\n <mat-label>Editing language</mat-label>\n <mat-select\n [ngModel]=\"store.activeLanguage()\"\n (ngModelChange)=\"store.setActiveLanguage($event)\"\n >\n @for (l of languages; track l) {\n <mat-option [value]=\"l\">{{ l }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n <mat-slide-toggle\n [ngModel]=\"store.config().maskData ?? false\"\n (ngModelChange)=\"store.setMaskData($event)\"\n >Mask this entity (RBAC)</mat-slide-toggle>\n\n <mat-expansion-panel class=\"deb-rbac\">\n <mat-expansion-panel-header>\n <mat-panel-title>Permissions</mat-panel-title>\n </mat-expansion-panel-header>\n @for (action of rbacActions; track action) {\n @if (availableRoles.length) {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>{{ action }} roles</mat-label>\n <mat-select multiple [ngModel]=\"rolesFor(action)\" (ngModelChange)=\"setRoles(action, $event)\">\n @for (role of availableRoles; track role) {\n <mat-option [value]=\"role\">{{ role }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>{{ action }} roles (comma-separated)</mat-label>\n <input\n matInput\n [ngModel]=\"rolesFor(action).join(', ')\"\n (ngModelChange)=\"setRolesFromText(action, $event)\"\n />\n </mat-form-field>\n }\n }\n <p class=\"deb-hint\">Empty = no restriction for that action.</p>\n </mat-expansion-panel>\n </mat-card-content>\n </mat-card>\n\n <mat-card>\n <mat-card-header><mat-card-title>Add field</mat-card-title></mat-card-header>\n <mat-card-content>\n <ngx-field-palette (pick)=\"store.addField($event)\"></ngx-field-palette>\n </mat-card-content>\n </mat-card>\n\n <mat-card>\n <mat-card-content>\n <ngx-tab-manager></ngx-tab-manager>\n </mat-card-content>\n </mat-card>\n </div>\n\n <!-- \u2500\u2500\u2500 Center: field canvas \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--center\">\n <ngx-entity-builder-canvas />\n </div>\n\n <!-- \u2500\u2500\u2500 Right: inspector \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--right\">\n <mat-card>\n <mat-card-header><mat-card-title>Field properties</mat-card-title></mat-card-header>\n <mat-card-content>\n <ngx-field-inspector></ngx-field-inspector>\n </mat-card-content>\n </mat-card>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Footer: JSON + optional live preview \u2500\u2500\u2500 -->\n<div class=\"deb-footer\">\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>data_object</mat-icon>&nbsp;Config JSON</mat-panel-title>\n </mat-expansion-panel-header>\n <pre class=\"deb-json\">{{ json }}</pre>\n </mat-expansion-panel>\n\n <div class=\"deb-preview-slot\">\n <ng-content select=\"[ngxBuilderPreview]\"></ng-content>\n </div>\n</div>\n", styles: [":host{--deb-accent: #6366f1;--deb-accent-hover: #4f46e5;--deb-accent-soft: #eeef2;--deb-border: #e2e8f0;--deb-muted: #64748b;--deb-surface: #ffffff;display:block}.deb-toolbar__title{margin-left:8px;font-family:var(--font-heading, sans-serif);font-size:16px;font-weight:700;color:#fff}.deb-spacer{flex:1 1 auto}.deb-problems--error{color:#ef4444;font-weight:600}.deb-full{width:100%}.deb-grow{flex:1}.deb-row{display:flex;gap:8px;align-items:center}.deb-section-title{font-family:var(--font-heading, sans-serif);font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--deb-muted)}.deb-hint{margin:4px 0 0;font-size:12px;color:var(--deb-muted)}.deb-chip{display:inline-block;padding:3px 10px;border-radius:9999px;background:var(--deb-accent-soft);color:var(--deb-accent-hover);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em}.deb-chip--muted{background:#f1f5f9;color:var(--deb-muted)}.deb-body{display:grid;grid-template-columns:320px minmax(0,1fr) 380px;gap:20px;padding:20px;align-items:start}.deb-col{display:flex;flex-direction:column;gap:16px;min-width:0}.deb-col--right{position:sticky;top:20px}@media (max-width: 1100px){.deb-body{grid-template-columns:1fr}.deb-col--right{position:static}}.deb-field-list{display:flex;flex-direction:column;gap:10px}.deb-field-row{display:flex;align-items:center;gap:10px;padding:10px 14px;border:1px solid var(--deb-border);border-radius:10px;background:var(--deb-surface);cursor:pointer;box-shadow:0 1px 3px #00000008;transition:all .18s cubic-bezier(.16,1,.3,1)}.deb-field-row:hover{border-color:#a5b4fc;background:#fcfaff;transform:translateY(-1px);box-shadow:0 4px 12px #6366f114}.deb-field-row--active{border-color:var(--deb-accent);border-left:4px solid var(--deb-accent);background:#f5f3ff;box-shadow:0 4px 16px #6366f12e}.deb-type-badge{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:2px 7px;border-radius:6px;background:#e0e7ff;color:#4338ca}.deb-drag-handle{cursor:grab;color:#94a3b8;transition:color .15s}.deb-drag-handle:hover,.deb-field-type{color:var(--deb-accent)}.deb-field-meta{display:flex;flex-direction:column;min-width:0;flex:1}.deb-field-label{font-family:var(--font-heading, sans-serif);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#0f172a;font-size:14px}.deb-field-id{font-size:11px;color:var(--deb-muted);font-family:ui-monospace,SFMono-Regular,monospace}.deb-req{color:#ef4444;font-weight:700}.deb-empty,.deb-inspector__empty{text-align:center;color:var(--deb-muted);padding:40px 16px}.deb-empty mat-icon{transform:scale(1.8);margin-bottom:16px;color:#cbd5e1}.cdk-drag-preview{box-shadow:0 12px 28px #4f46e538;border-radius:10px;border:1px solid var(--deb-accent);background:#fff}.cdk-drag-placeholder{opacity:.35}.cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.deb-field-list.cdk-drop-list-dragging .deb-field-row:not(.cdk-drag-placeholder){transition:transform .2s cubic-bezier(0,0,.2,1)}.deb-footer{padding:0 20px 20px;display:flex;flex-direction:column;gap:16px}.deb-json{margin:0;max-height:320px;overflow:auto;font-family:ui-monospace,SFMono-Regular,monospace;font-size:12px;line-height:1.5;padding:14px;background:#0f172a;color:#e2e8f0;border-radius:10px}\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: "ngmodule", type: MatCardModule }, { kind: "component", type: i3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i3.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i3.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "component", type: i4.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i4.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i4.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.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: MatSelectModule }, { kind: "component", type: i8.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i10.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i11.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: FieldPaletteComponent, selector: "ngx-field-palette", outputs: ["pick"] }, { kind: "component", type: TabManagerComponent, selector: "ngx-tab-manager" }, { kind: "component", type: FieldInspectorComponent, selector: "ngx-field-inspector" }, { kind: "component", type: EntityBuilderCanvasComponent, selector: "ngx-entity-builder-canvas" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
127
123
  }
128
124
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityBuilderComponent, decorators: [{
129
125
  type: Component,
130
- args: [{ selector: 'ngx-entity-builder', standalone: true, providers: [BuilderStore], imports: [
126
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngx-entity-builder', standalone: true, providers: [BuilderStore], imports: [
131
127
  FormsModule,
132
- DragDropModule,
133
128
  MatButtonModule,
134
129
  MatCardModule,
135
130
  MatCheckboxModule,
@@ -145,7 +140,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
145
140
  TabManagerComponent,
146
141
  FieldInspectorComponent,
147
142
  EntityBuilderCanvasComponent,
148
- ], template: "<mat-toolbar class=\"deb-toolbar\" color=\"primary\">\n <mat-icon>dashboard_customize</mat-icon>\n <span class=\"deb-toolbar__title\">Entity Builder</span>\n <span class=\"deb-spacer\"></span>\n\n @if (store.problems().length) {\n <button\n mat-button\n type=\"button\"\n class=\"deb-problems\"\n [class.deb-problems--error]=\"!store.isValid()\"\n [matTooltip]=\"store.problems().length + ' issue(s) \u2014 hover items in the list'\"\n >\n <mat-icon>{{ store.isValid() ? 'warning' : 'error' }}</mat-icon>\n {{ store.errors().length }} / {{ store.problems().length }}\n </button>\n }\n\n <button mat-button type=\"button\" (click)=\"copyJson()\">\n <mat-icon>content_copy</mat-icon> Copy JSON\n </button>\n <button mat-flat-button color=\"accent\" type=\"button\" [disabled]=\"!store.isValid()\" (click)=\"doSave()\">\n <mat-icon>save</mat-icon> Save\n </button>\n</mat-toolbar>\n\n<div class=\"deb-body\">\n <!-- \u2500\u2500\u2500 Left: settings, palette, tabs \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--left\">\n <mat-card>\n <mat-card-content>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>Entity name</mat-label>\n <input\n matInput\n [ngModel]=\"store.config().entity\"\n (ngModelChange)=\"store.setEntityName($event)\"\n placeholder=\"e.g. clients\"\n />\n </mat-form-field>\n\n <div class=\"deb-row\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-grow\">\n <mat-label>Editing language</mat-label>\n <mat-select\n [ngModel]=\"store.activeLanguage()\"\n (ngModelChange)=\"store.setActiveLanguage($event)\"\n >\n @for (l of languages; track l) {\n <mat-option [value]=\"l\">{{ l }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n <mat-slide-toggle\n [ngModel]=\"store.config().maskData ?? false\"\n (ngModelChange)=\"store.setMaskData($event)\"\n >Mask this entity (RBAC)</mat-slide-toggle>\n\n <mat-expansion-panel class=\"deb-rbac\">\n <mat-expansion-panel-header>\n <mat-panel-title>Permissions</mat-panel-title>\n </mat-expansion-panel-header>\n @for (action of rbacActions; track action) {\n @if (availableRoles.length) {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>{{ action }} roles</mat-label>\n <mat-select multiple [ngModel]=\"rolesFor(action)\" (ngModelChange)=\"setRoles(action, $event)\">\n @for (role of availableRoles; track role) {\n <mat-option [value]=\"role\">{{ role }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>{{ action }} roles (comma-separated)</mat-label>\n <input\n matInput\n [ngModel]=\"rolesFor(action).join(', ')\"\n (ngModelChange)=\"setRolesFromText(action, $event)\"\n />\n </mat-form-field>\n }\n }\n <p class=\"deb-hint\">Empty = no restriction for that action.</p>\n </mat-expansion-panel>\n </mat-card-content>\n </mat-card>\n\n <mat-card>\n <mat-card-header><mat-card-title>Add field</mat-card-title></mat-card-header>\n <mat-card-content>\n <ngx-field-palette (pick)=\"store.addField($event)\"></ngx-field-palette>\n </mat-card-content>\n </mat-card>\n\n <mat-card>\n <mat-card-content>\n <ngx-tab-manager></ngx-tab-manager>\n </mat-card-content>\n </mat-card>\n </div>\n\n <!-- \u2500\u2500\u2500 Center: field canvas \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--center\">\n <ngx-entity-builder-canvas />\n </div>\n\n <!-- \u2500\u2500\u2500 Right: inspector \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--right\">\n <mat-card>\n <mat-card-header><mat-card-title>Field properties</mat-card-title></mat-card-header>\n <mat-card-content>\n <ngx-field-inspector></ngx-field-inspector>\n </mat-card-content>\n </mat-card>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Footer: JSON + optional live preview \u2500\u2500\u2500 -->\n<div class=\"deb-footer\">\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>data_object</mat-icon>&nbsp;Config JSON</mat-panel-title>\n </mat-expansion-panel-header>\n <pre class=\"deb-json\">{{ json }}</pre>\n </mat-expansion-panel>\n\n <div class=\"deb-preview-slot\">\n <ng-content select=\"[ngxBuilderPreview]\"></ng-content>\n </div>\n</div>\n", styles: [":host{--deb-accent: #6366f1;--deb-accent-hover: #4f46e5;--deb-accent-soft: #eeef2;--deb-border: #e2e8f0;--deb-muted: #64748b;--deb-surface: #ffffff;display:block}.deb-toolbar__title{margin-left:8px;font-family:var(--font-heading, sans-serif);font-size:16px;font-weight:700;color:#0f172a}.deb-spacer{flex:1 1 auto}.deb-problems--error{color:#ef4444;font-weight:600}.deb-full{width:100%}.deb-grow{flex:1}.deb-row{display:flex;gap:8px;align-items:center}.deb-section-title{font-family:var(--font-heading, sans-serif);font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--deb-muted)}.deb-hint{margin:4px 0 0;font-size:12px;color:var(--deb-muted)}.deb-chip{display:inline-block;padding:3px 10px;border-radius:9999px;background:var(--deb-accent-soft);color:var(--deb-accent-hover);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em}.deb-chip--muted{background:#f1f5f9;color:var(--deb-muted)}.deb-body{display:grid;grid-template-columns:320px minmax(0,1fr) 380px;gap:20px;padding:20px;align-items:start}.deb-col{display:flex;flex-direction:column;gap:16px;min-width:0}.deb-col--right{position:sticky;top:20px}@media (max-width: 1100px){.deb-body{grid-template-columns:1fr}.deb-col--right{position:static}}.deb-field-list{display:flex;flex-direction:column;gap:10px}.deb-field-row{display:flex;align-items:center;gap:10px;padding:10px 14px;border:1px solid var(--deb-border);border-radius:10px;background:var(--deb-surface);cursor:pointer;box-shadow:0 1px 3px #00000008;transition:all .18s cubic-bezier(.16,1,.3,1)}.deb-field-row:hover{border-color:#a5b4fc;background:#fcfaff;transform:translateY(-1px);box-shadow:0 4px 12px #6366f114}.deb-field-row--active{border-color:var(--deb-accent);border-left:4px solid var(--deb-accent);background:#f5f3ff;box-shadow:0 4px 16px #6366f12e}.deb-type-badge{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:2px 7px;border-radius:6px;background:#e0e7ff;color:#4338ca}.deb-drag-handle{cursor:grab;color:#94a3b8;transition:color .15s}.deb-drag-handle:hover,.deb-field-type{color:var(--deb-accent)}.deb-field-meta{display:flex;flex-direction:column;min-width:0;flex:1}.deb-field-label{font-family:var(--font-heading, sans-serif);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#0f172a;font-size:14px}.deb-field-id{font-size:11px;color:var(--deb-muted);font-family:ui-monospace,SFMono-Regular,monospace}.deb-req{color:#ef4444;font-weight:700}.deb-empty,.deb-inspector__empty{text-align:center;color:var(--deb-muted);padding:40px 16px}.deb-empty mat-icon{transform:scale(1.8);margin-bottom:16px;color:#cbd5e1}.cdk-drag-preview{box-shadow:0 12px 28px #4f46e538;border-radius:10px;border:1px solid var(--deb-accent);background:#fff}.cdk-drag-placeholder{opacity:.35}.cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.deb-field-list.cdk-drop-list-dragging .deb-field-row:not(.cdk-drag-placeholder){transition:transform .2s cubic-bezier(0,0,.2,1)}.deb-footer{padding:0 20px 20px;display:flex;flex-direction:column;gap:16px}.deb-json{margin:0;max-height:320px;overflow:auto;font-family:ui-monospace,SFMono-Regular,monospace;font-size:12px;line-height:1.5;padding:14px;background:#0f172a;color:#e2e8f0;border-radius:10px}\n"] }]
143
+ ], template: "<mat-toolbar class=\"deb-toolbar\" color=\"primary\">\n <mat-icon>dashboard_customize</mat-icon>\n <span class=\"deb-toolbar__title\">Entity Builder</span>\n <span class=\"deb-spacer\"></span>\n\n @if (store.problems().length) {\n <button\n mat-button\n type=\"button\"\n class=\"deb-problems\"\n [class.deb-problems--error]=\"!store.isValid()\"\n [matTooltip]=\"store.problems().length + ' issue(s) \u2014 hover items in the list'\"\n >\n <mat-icon>{{ store.isValid() ? 'warning' : 'error' }}</mat-icon>\n {{ store.errors().length }} / {{ store.problems().length }}\n </button>\n }\n\n <button mat-button type=\"button\" (click)=\"copyJson()\">\n <mat-icon>content_copy</mat-icon> Copy JSON\n </button>\n <!-- primary, not accent: white on Material's default pink accent is 3.33:1, below AA. -->\n <button mat-flat-button color=\"primary\" type=\"button\" [disabled]=\"!store.isValid()\" (click)=\"doSave()\">\n <mat-icon>save</mat-icon> Save\n </button>\n</mat-toolbar>\n\n<div class=\"deb-body\">\n <!-- \u2500\u2500\u2500 Left: settings, palette, tabs \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--left\">\n <mat-card>\n <mat-card-content>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>Entity name</mat-label>\n <input\n matInput\n [ngModel]=\"store.config().entity\"\n (ngModelChange)=\"store.setEntityName($event)\"\n placeholder=\"e.g. clients\"\n />\n </mat-form-field>\n\n <div class=\"deb-row\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-grow\">\n <mat-label>Editing language</mat-label>\n <mat-select\n [ngModel]=\"store.activeLanguage()\"\n (ngModelChange)=\"store.setActiveLanguage($event)\"\n >\n @for (l of languages; track l) {\n <mat-option [value]=\"l\">{{ l }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n </div>\n\n <mat-slide-toggle\n [ngModel]=\"store.config().maskData ?? false\"\n (ngModelChange)=\"store.setMaskData($event)\"\n >Mask this entity (RBAC)</mat-slide-toggle>\n\n <mat-expansion-panel class=\"deb-rbac\">\n <mat-expansion-panel-header>\n <mat-panel-title>Permissions</mat-panel-title>\n </mat-expansion-panel-header>\n @for (action of rbacActions; track action) {\n @if (availableRoles.length) {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>{{ action }} roles</mat-label>\n <mat-select multiple [ngModel]=\"rolesFor(action)\" (ngModelChange)=\"setRoles(action, $event)\">\n @for (role of availableRoles; track role) {\n <mat-option [value]=\"role\">{{ role }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n } @else {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\" class=\"deb-full\">\n <mat-label>{{ action }} roles (comma-separated)</mat-label>\n <input\n matInput\n [ngModel]=\"rolesFor(action).join(', ')\"\n (ngModelChange)=\"setRolesFromText(action, $event)\"\n />\n </mat-form-field>\n }\n }\n <p class=\"deb-hint\">Empty = no restriction for that action.</p>\n </mat-expansion-panel>\n </mat-card-content>\n </mat-card>\n\n <mat-card>\n <mat-card-header><mat-card-title>Add field</mat-card-title></mat-card-header>\n <mat-card-content>\n <ngx-field-palette (pick)=\"store.addField($event)\"></ngx-field-palette>\n </mat-card-content>\n </mat-card>\n\n <mat-card>\n <mat-card-content>\n <ngx-tab-manager></ngx-tab-manager>\n </mat-card-content>\n </mat-card>\n </div>\n\n <!-- \u2500\u2500\u2500 Center: field canvas \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--center\">\n <ngx-entity-builder-canvas />\n </div>\n\n <!-- \u2500\u2500\u2500 Right: inspector \u2500\u2500\u2500 -->\n <div class=\"deb-col deb-col--right\">\n <mat-card>\n <mat-card-header><mat-card-title>Field properties</mat-card-title></mat-card-header>\n <mat-card-content>\n <ngx-field-inspector></ngx-field-inspector>\n </mat-card-content>\n </mat-card>\n </div>\n</div>\n\n<!-- \u2500\u2500\u2500 Footer: JSON + optional live preview \u2500\u2500\u2500 -->\n<div class=\"deb-footer\">\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title><mat-icon>data_object</mat-icon>&nbsp;Config JSON</mat-panel-title>\n </mat-expansion-panel-header>\n <pre class=\"deb-json\">{{ json }}</pre>\n </mat-expansion-panel>\n\n <div class=\"deb-preview-slot\">\n <ng-content select=\"[ngxBuilderPreview]\"></ng-content>\n </div>\n</div>\n", styles: [":host{--deb-accent: #6366f1;--deb-accent-hover: #4f46e5;--deb-accent-soft: #eeef2;--deb-border: #e2e8f0;--deb-muted: #64748b;--deb-surface: #ffffff;display:block}.deb-toolbar__title{margin-left:8px;font-family:var(--font-heading, sans-serif);font-size:16px;font-weight:700;color:#fff}.deb-spacer{flex:1 1 auto}.deb-problems--error{color:#ef4444;font-weight:600}.deb-full{width:100%}.deb-grow{flex:1}.deb-row{display:flex;gap:8px;align-items:center}.deb-section-title{font-family:var(--font-heading, sans-serif);font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--deb-muted)}.deb-hint{margin:4px 0 0;font-size:12px;color:var(--deb-muted)}.deb-chip{display:inline-block;padding:3px 10px;border-radius:9999px;background:var(--deb-accent-soft);color:var(--deb-accent-hover);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em}.deb-chip--muted{background:#f1f5f9;color:var(--deb-muted)}.deb-body{display:grid;grid-template-columns:320px minmax(0,1fr) 380px;gap:20px;padding:20px;align-items:start}.deb-col{display:flex;flex-direction:column;gap:16px;min-width:0}.deb-col--right{position:sticky;top:20px}@media (max-width: 1100px){.deb-body{grid-template-columns:1fr}.deb-col--right{position:static}}.deb-field-list{display:flex;flex-direction:column;gap:10px}.deb-field-row{display:flex;align-items:center;gap:10px;padding:10px 14px;border:1px solid var(--deb-border);border-radius:10px;background:var(--deb-surface);cursor:pointer;box-shadow:0 1px 3px #00000008;transition:all .18s cubic-bezier(.16,1,.3,1)}.deb-field-row:hover{border-color:#a5b4fc;background:#fcfaff;transform:translateY(-1px);box-shadow:0 4px 12px #6366f114}.deb-field-row--active{border-color:var(--deb-accent);border-left:4px solid var(--deb-accent);background:#f5f3ff;box-shadow:0 4px 16px #6366f12e}.deb-type-badge{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;padding:2px 7px;border-radius:6px;background:#e0e7ff;color:#4338ca}.deb-drag-handle{cursor:grab;color:#94a3b8;transition:color .15s}.deb-drag-handle:hover,.deb-field-type{color:var(--deb-accent)}.deb-field-meta{display:flex;flex-direction:column;min-width:0;flex:1}.deb-field-label{font-family:var(--font-heading, sans-serif);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#0f172a;font-size:14px}.deb-field-id{font-size:11px;color:var(--deb-muted);font-family:ui-monospace,SFMono-Regular,monospace}.deb-req{color:#ef4444;font-weight:700}.deb-empty,.deb-inspector__empty{text-align:center;color:var(--deb-muted);padding:40px 16px}.deb-empty mat-icon{transform:scale(1.8);margin-bottom:16px;color:#cbd5e1}.cdk-drag-preview{box-shadow:0 12px 28px #4f46e538;border-radius:10px;border:1px solid var(--deb-accent);background:#fff}.cdk-drag-placeholder{opacity:.35}.cdk-drag-animating{transition:transform .2s cubic-bezier(0,0,.2,1)}.deb-field-list.cdk-drop-list-dragging .deb-field-row:not(.cdk-drag-placeholder){transition:transform .2s cubic-bezier(0,0,.2,1)}.deb-footer{padding:0 20px 20px;display:flex;flex-direction:column;gap:16px}.deb-json{margin:0;max-height:320px;overflow:auto;font-family:ui-monospace,SFMono-Regular,monospace;font-size:12px;line-height:1.5;padding:14px;background:#0f172a;color:#e2e8f0;border-radius:10px}\n"] }]
149
144
  }], ctorParameters: () => [], propDecorators: { config: [{
150
145
  type: Input
151
146
  }], languages: [{
@@ -161,4 +156,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
161
156
  }], save: [{
162
157
  type: Output
163
158
  }] } });
164
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9lbnRpdHktYnVpbGRlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi9zcmMvbGliL2VudGl0eS1idWlsZGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEVBRU4sTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFlLGNBQWMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDL0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDakUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUNMLGNBQWMsRUFJZCxZQUFZLEdBQ2IsTUFBTSxz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ZTt3QkFDZixvQkFBb0I7d0JBQ3BCLGdCQUFnQjt3QkFDaEIsZ0JBQWdCO3dCQUNoQixxQkFBcUI7d0JBQ3JCLG1CQUFtQjt3QkFDbkIsdUJBQXVCO3dCQUN2Qiw0QkFBNEI7cUJBQzdCO3dEQVFRLE1BQU07c0JBQWQsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBTUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxhQUFhO3NCQUFyQixLQUFLO2dCQUdJLFlBQVk7c0JBQXJCLE1BQU07Z0JBRUcsSUFBSTtzQkFBYixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgZWZmZWN0LFxuICBpbmplY3QsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBDZGtEcmFnRHJvcCwgRHJhZ0Ryb3BNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jZGsvZHJhZy1kcm9wJztcbmltcG9ydCB7IE1hdEJ1dHRvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XG5pbXBvcnQgeyBNYXRDYXJkTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvY2FyZCc7XG5pbXBvcnQgeyBNYXRDaGVja2JveE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NoZWNrYm94JztcbmltcG9ydCB7IE1hdEV4cGFuc2lvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2V4cGFuc2lvbic7XG5pbXBvcnQgeyBNYXRGb3JtRmllbGRNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9mb3JtLWZpZWxkJztcbmltcG9ydCB7IE1hdEljb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcbmltcG9ydCB7IE1hdElucHV0TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaW5wdXQnO1xuaW1wb3J0IHsgTWF0U2VsZWN0TW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc2VsZWN0JztcbmltcG9ydCB7IE1hdFNsaWRlVG9nZ2xlTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc2xpZGUtdG9nZ2xlJztcbmltcG9ydCB7IE1hdFRvb2xiYXJNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90b29sYmFyJztcbmltcG9ydCB7IE1hdFRvb2x0aXBNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90b29sdGlwJztcbmltcG9ydCB7XG4gIENPTU1PTl9NT0RVTEVTLFxuICB0eXBlIENvbW1vbk1vZHVsZUVudHJ5LFxuICB0eXBlIEVudGl0eUZvcm1Db25maWcsXG4gIHR5cGUgRW50aXR5UGVybWlzc2lvbnMsXG4gIHJlc29sdmVMYWJlbCxcbn0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHsgQnVpbGRlclN0b3JlIH0gZnJvbSAnLi9idWlsZGVyLXN0b3JlLnNlcnZpY2UnO1xuaW1wb3J0IHsgRmllbGRJbnNwZWN0b3JDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvZmllbGQtaW5zcGVjdG9yLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBGaWVsZFBhbGV0dGVDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvZmllbGQtcGFsZXR0ZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgVGFiTWFuYWdlckNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy90YWItbWFuYWdlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgRW50aXR5QnVpbGRlckNhbnZhc0NvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy9lbnRpdHktYnVpbGRlci1jYW52YXMuY29tcG9uZW50JztcbmltcG9ydCB7IGdldEZpZWxkVHlwZU1ldGEgfSBmcm9tICcuL2ZpZWxkLWNhdGFsb2cnO1xuXG4vKiogUkJBQyBhY3Rpb25zIHN1cmZhY2VkIGluIHRoZSBzZXR0aW5ncyBwYW5lbC4gKi9cbmNvbnN0IFJCQUNfQUNUSU9OUzogKGtleW9mIEVudGl0eVBlcm1pc3Npb25zKVtdID0gWyd2aWV3JywgJ2VkaXQnLCAnZGVsZXRlJ107XG5cbi8qKiBTaGFyZWQgc3RhYmxlIGVtcHR5IGFycmF5IOKAlCBuZXZlciBhbGxvY2F0ZSBhIGZyZXNoIFtdIHBlciBjaGFuZ2UtZGV0ZWN0aW9uIChtYXQtc2VsZWN0IGxvb3BzKS4gKi9cbmNvbnN0IEVNUFRZX1JPTEVTOiByZWFkb25seSBzdHJpbmdbXSA9IE9iamVjdC5mcmVlemUoW10pO1xuXG4vKipcbiAqIEVudGl0eUJ1aWxkZXJDb21wb25lbnQg4oCUIHRoZSB0b3AtbGV2ZWwgdmlzdWFsIGJ1aWxkZXIgZm9yIGFuIEVudGl0eUZvcm1Db25maWcuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1lbnRpdHktYnVpbGRlcicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHByb3ZpZGVyczogW0J1aWxkZXJTdG9yZV0sXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBEcmFnRHJvcE1vZHVsZSxcbiAgICBNYXRCdXR0b25Nb2R1bGUsXG4gICAgTWF0Q2FyZE1vZHVsZSxcbiAgICBNYXRDaGVja2JveE1vZHVsZSxcbiAgICBNYXRFeHBhbnNpb25Nb2R1bGUsXG4gICAgTWF0Rm9ybUZpZWxkTW9kdWxlLFxuICAgIE1hdEljb25Nb2R1bGUsXG4gICAgTWF0SW5wdXRNb2R1bGUsXG4gICAgTWF0U2VsZWN0TW9kdWxlLFxuICAgIE1hdFNsaWRlVG9nZ2xlTW9kdWxlLFxuICAgIE1hdFRvb2xiYXJNb2R1bGUsXG4gICAgTWF0VG9vbHRpcE1vZHVsZSxcbiAgICBGaWVsZFBhbGV0dGVDb21wb25lbnQsXG4gICAgVGFiTWFuYWdlckNvbXBvbmVudCxcbiAgICBGaWVsZEluc3BlY3RvckNvbXBvbmVudCxcbiAgICBFbnRpdHlCdWlsZGVyQ2FudmFzQ29tcG9uZW50LFxuICBdLFxuICB0ZW1wbGF0ZVVybDogJy4vZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50LmNzcycsXG59KVxuZXhwb3J0IGNsYXNzIEVudGl0eUJ1aWxkZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc3RvcmUgPSBpbmplY3QoQnVpbGRlclN0b3JlKTtcblxuICAvKiogRXhpc3RpbmcgY29uZmlnIHRvIGVkaXQuIFdoZW4gb21pdHRlZCwgdGhlIGJ1aWxkZXIgc3RhcnRzIGJsYW5rLiAqL1xuICBASW5wdXQoKSBjb25maWc/OiBFbnRpdHlGb3JtQ29uZmlnO1xuICAvKiogTGFuZ3VhZ2VzIGF2YWlsYWJsZSBmb3IgbGFiZWwvcGxhY2Vob2xkZXIgZWRpdGluZy4gRmlyc3QgZW50cnkgaXMgdGhlIGRlZmF1bHQuICovXG4gIEBJbnB1dCgpIGxhbmd1YWdlczogc3RyaW5nW10gPSBbJ2VuJ107XG4gIC8qKiBPcHRpb25hbCByb2xlIGxpc3Qg4oCUIGVuYWJsZXMgbXVsdGktc2VsZWN0IHJvbGUgcGlja2VycyBmb3IgUkJBQyBpbnN0ZWFkIG9mIGZyZWUgdGV4dC4gKi9cbiAgQElucHV0KCkgYXZhaWxhYmxlUm9sZXM6IHN0cmluZ1tdID0gW107XG4gIC8qKlxuICAgKiBSb2xlcyBvZiB0aGUgcGVyc29uIHVzaW5nIHRoZSBidWlsZGVyLiBEaXN0aW5jdCBmcm9tIGBhdmFpbGFibGVSb2xlc2AsIHdoaWNoIGlzIHRoZVxuICAgKiB2b2NhYnVsYXJ5IGEgc2NoZW1hIG1heSByZWZlcmVuY2UuIFBhc3NlZCB0byB0aGUgYFNZU1RFTV9ERUZBVUxUX0NBTl9FRElUYCBwcmVkaWNhdGUgc29cbiAgICogaXQgY2FuIGRlY2lkZSB3aGV0aGVyIHRoaXMgdXNlciBtYXkgZWRpdCBzeXN0ZW0tZGVmYXVsdCB0YWJzLlxuICAgKi9cbiAgQElucHV0KCkgdXNlclJvbGVzOiBzdHJpbmdbXSA9IFtdO1xuICAvKiogT3B0aW9uYWwgY29tbW9uLW1vZHVsZSBkZWZpbml0aW9ucyBmb3IgbW9kdWxlIHRhYnM7IGRlZmF1bHRzIHRvIHRoZSBidWlsdC1pbiBsaXN0IGZyb20gY29yZS4gKi9cbiAgQElucHV0KCkgY29tbW9uTW9kdWxlczogcmVhZG9ubHkgQ29tbW9uTW9kdWxlRW50cnlbXSA9IENPTU1PTl9NT0RVTEVTO1xuXG4gIC8qKiBFbWl0dGVkIG9uIGV2ZXJ5IGNoYW5nZSB0byB0aGUgd29ya2luZyBjb25maWcuICovXG4gIEBPdXRwdXQoKSBjb25maWdDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEVudGl0eUZvcm1Db25maWc+KCk7XG4gIC8qKiBFbWl0dGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIFNhdmUuIENhcnJpZXMgYSBjbGVhbiwgZGVlcC1jbG9uZWQgY29uZmlnLiAqL1xuICBAT3V0cHV0KCkgc2F2ZSA9IG5ldyBFdmVudEVtaXR0ZXI8RW50aXR5Rm9ybUNvbmZpZz4oKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmJhY0FjdGlvbnMgPSBSQkFDX0FDVElPTlM7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgZWZmZWN0KCgpID0+IHRoaXMuY29uZmlnQ2hhbmdlLmVtaXQodGhpcy5zdG9yZS5jb25maWcoKSksIHsgYWxsb3dTaWduYWxXcml0ZXM6IHRydWUgfSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ2NvbmZpZyddICYmIGNoYW5nZXNbJ2NvbmZpZyddLmN1cnJlbnRWYWx1ZSAhPT0gY2hhbmdlc1snY29uZmlnJ10ucHJldmlvdXNWYWx1ZSkge1xuICAgICAgaWYgKHRoaXMuY29uZmlnKSB0aGlzLnN0b3JlLmxvYWQodGhpcy5jb25maWcpO1xuICAgICAgZWxzZSBpZiAoY2hhbmdlc1snY29uZmlnJ10uaXNGaXJzdENoYW5nZSgpKSB0aGlzLnN0b3JlLnJlc2V0KCk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWydsYW5ndWFnZXMnXSAmJiB0aGlzLmxhbmd1YWdlcy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuc3RvcmUuYWN0aXZlTGFuZ3VhZ2UoKTtcbiAgICAgIGlmICghdGhpcy5sYW5ndWFnZXMuaW5jbHVkZXMoYWN0aXZlKSkgdGhpcy5zdG9yZS5zZXRBY3RpdmVMYW5ndWFnZSh0aGlzLmxhbmd1YWdlc1swXSk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWyd1c2VyUm9sZXMnXSkge1xuICAgICAgdGhpcy5zdG9yZS5zZXRVc2VyUm9sZXModGhpcy51c2VyUm9sZXMpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBGaWVsZCBjYW52YXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIG9uRHJvcChldmVudDogQ2RrRHJhZ0Ryb3A8dW5rbm93bj4pOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JlLnJlb3JkZXJGaWVsZChldmVudC5wcmV2aW91c0luZGV4LCBldmVudC5jdXJyZW50SW5kZXgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZpZWxkVHlwZUxhYmVsKHR5cGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGdldEZpZWxkVHlwZU1ldGEodHlwZSk/LmxhYmVsID8/IHR5cGU7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmllbGRUeXBlSWNvbih0eXBlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBnZXRGaWVsZFR5cGVNZXRhKHR5cGUpPy5pY29uID8/ICdoZWxwX291dGxpbmUnO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZpZWxkTGFiZWwoZmllbGQ6IHsgaWQ6IHN0cmluZzsgbGFiZWw/OiBhbnkgfSk6IHN0cmluZyB7XG4gICAgY29uc3QgbGFuZyA9IHRoaXMuc3RvcmUuYWN0aXZlTGFuZ3VhZ2UoKTtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKGZpZWxkLmxhYmVsLCBsYW5nKSB8fCBmaWVsZC5pZDtcbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBUb29sYmFyIGFjdGlvbnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIGRvU2F2ZSgpOiB2b2lkIHtcbiAgICB0aGlzLnNhdmUuZW1pdCh0aGlzLnN0b3JlLmV4cG9ydENvbmZpZygpKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQganNvbigpOiBzdHJpbmcge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLnN0b3JlLmV4cG9ydENvbmZpZygpLCBudWxsLCAyKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjb3B5SnNvbigpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiYgbmF2aWdhdG9yLmNsaXBib2FyZCkge1xuICAgICAgdm9pZCBuYXZpZ2F0b3IuY2xpcGJvYXJkLndyaXRlVGV4dCh0aGlzLmpzb24pO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBSQkFDIHNldHRpbmdzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHByb3RlY3RlZCByb2xlc0ZvcihhY3Rpb246IGtleW9mIEVudGl0eVBlcm1pc3Npb25zKTogcmVhZG9ubHkgc3RyaW5nW10ge1xuICAgIC8vIFJldHVybiB0aGUgc3RvcmVkIGFycmF5IChzdGFibGUgcmVmIGJldHdlZW4gbXV0YXRpb25zKSBvciBhIHNoYXJlZCBlbXB0eSDigJQgTk9UIGEgZnJlc2ggW10sXG4gICAgLy8gd2hpY2ggd291bGQgbWFrZSB0aGUgYm91bmQgbWF0LXNlbGVjdCByZS1ldmFsdWF0ZSBldmVyeSBDRCBhbmQgbG9vcCBmb3JldmVyLlxuICAgIHJldHVybiB0aGlzLnN0b3JlLmNvbmZpZygpLnBlcm1pc3Npb25zPy5bYWN0aW9uXSA/PyBFTVBUWV9ST0xFUztcbiAgfVxuXG4gIHByb3RlY3RlZCBzZXRSb2xlcyhhY3Rpb246IGtleW9mIEVudGl0eVBlcm1pc3Npb25zLCByb2xlczogc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JlLnNldFBlcm1pc3Npb24oYWN0aW9uLCByb2xlcyk7XG4gIH1cblxuICAvKiogUGFyc2UgYSBjb21tYS1zZXBhcmF0ZWQgcm9sZSBzdHJpbmcgaW50byBhIHRyaW1tZWQsIGRlLWR1cGxpY2F0ZWQgYXJyYXkuICovXG4gIHByb3RlY3RlZCBzZXRSb2xlc0Zyb21UZXh0KGFjdGlvbjoga2V5b2YgRW50aXR5UGVybWlzc2lvbnMsIHRleHQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHJvbGVzID0gQXJyYXkuZnJvbShcbiAgICAgIG5ldyBTZXQoXG4gICAgICAgIHRleHRcbiAgICAgICAgICAuc3BsaXQoJywnKVxuICAgICAgICAgIC5tYXAociA9PiByLnRyaW0oKSlcbiAgICAgICAgICAuZmlsdGVyKEJvb2xlYW4pLFxuICAgICAgKSxcbiAgICApO1xuICAgIHRoaXMuc3RvcmUuc2V0UGVybWlzc2lvbihhY3Rpb24sIHJvbGVzKTtcbiAgfVxufVxuIiwiPG1hdC10b29sYmFyIGNsYXNzPVwiZGViLXRvb2xiYXJcIiBjb2xvcj1cInByaW1hcnlcIj5cbiAgPG1hdC1pY29uPmRhc2hib2FyZF9jdXN0b21pemU8L21hdC1pY29uPlxuICA8c3BhbiBjbGFzcz1cImRlYi10b29sYmFyX190aXRsZVwiPkVudGl0eSBCdWlsZGVyPC9zcGFuPlxuICA8c3BhbiBjbGFzcz1cImRlYi1zcGFjZXJcIj48L3NwYW4+XG5cbiAgQGlmIChzdG9yZS5wcm9ibGVtcygpLmxlbmd0aCkge1xuICAgIDxidXR0b25cbiAgICAgIG1hdC1idXR0b25cbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgY2xhc3M9XCJkZWItcHJvYmxlbXNcIlxuICAgICAgW2NsYXNzLmRlYi1wcm9ibGVtcy0tZXJyb3JdPVwiIXN0b3JlLmlzVmFsaWQoKVwiXG4gICAgICBbbWF0VG9vbHRpcF09XCJzdG9yZS5wcm9ibGVtcygpLmxlbmd0aCArICcgaXNzdWUocykg4oCUIGhvdmVyIGl0ZW1zIGluIHRoZSBsaXN0J1wiXG4gICAgPlxuICAgICAgPG1hdC1pY29uPnt7IHN0b3JlLmlzVmFsaWQoKSA/ICd3YXJuaW5nJyA6ICdlcnJvcicgfX08L21hdC1pY29uPlxuICAgICAge3sgc3RvcmUuZXJyb3JzKCkubGVuZ3RoIH19IC8ge3sgc3RvcmUucHJvYmxlbXMoKS5sZW5ndGggfX1cbiAgICA8L2J1dHRvbj5cbiAgfVxuXG4gIDxidXR0b24gbWF0LWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cImNvcHlKc29uKClcIj5cbiAgICA8bWF0LWljb24+Y29udGVudF9jb3B5PC9tYXQtaWNvbj4gQ29weSBKU09OXG4gIDwvYnV0dG9uPlxuICA8YnV0dG9uIG1hdC1mbGF0LWJ1dHRvbiBjb2xvcj1cImFjY2VudFwiIHR5cGU9XCJidXR0b25cIiBbZGlzYWJsZWRdPVwiIXN0b3JlLmlzVmFsaWQoKVwiIChjbGljayk9XCJkb1NhdmUoKVwiPlxuICAgIDxtYXQtaWNvbj5zYXZlPC9tYXQtaWNvbj4gU2F2ZVxuICA8L2J1dHRvbj5cbjwvbWF0LXRvb2xiYXI+XG5cbjxkaXYgY2xhc3M9XCJkZWItYm9keVwiPlxuICA8IS0tIOKUgOKUgOKUgCBMZWZ0OiBzZXR0aW5ncywgcGFsZXR0ZSwgdGFicyDilIDilIDilIAgLS0+XG4gIDxkaXYgY2xhc3M9XCJkZWItY29sIGRlYi1jb2wtLWxlZnRcIj5cbiAgICA8bWF0LWNhcmQ+XG4gICAgICA8bWF0LWNhcmQtY29udGVudD5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgc3Vic2NyaXB0U2l6aW5nPVwiZHluYW1pY1wiIGNsYXNzPVwiZGViLWZ1bGxcIj5cbiAgICAgICAgICA8bWF0LWxhYmVsPkVudGl0eSBuYW1lPC9tYXQtbGFiZWw+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgW25nTW9kZWxdPVwic3RvcmUuY29uZmlnKCkuZW50aXR5XCJcbiAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInN0b3JlLnNldEVudGl0eU5hbWUoJGV2ZW50KVwiXG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cImUuZy4gY2xpZW50c1wiXG4gICAgICAgICAgLz5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGViLXJvd1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwib3V0bGluZVwiIHN1YnNjcmlwdFNpemluZz1cImR5bmFtaWNcIiBjbGFzcz1cImRlYi1ncm93XCI+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPkVkaXRpbmcgbGFuZ3VhZ2U8L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgIFtuZ01vZGVsXT1cInN0b3JlLmFjdGl2ZUxhbmd1YWdlKClcIlxuICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdG9yZS5zZXRBY3RpdmVMYW5ndWFnZSgkZXZlbnQpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgQGZvciAobCBvZiBsYW5ndWFnZXM7IHRyYWNrIGwpIHtcbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwibFwiPnt7IGwgfX08L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8bWF0LXNsaWRlLXRvZ2dsZVxuICAgICAgICAgIFtuZ01vZGVsXT1cInN0b3JlLmNvbmZpZygpLm1hc2tEYXRhID8/IGZhbHNlXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdG9yZS5zZXRNYXNrRGF0YSgkZXZlbnQpXCJcbiAgICAgICAgPk1hc2sgdGhpcyBlbnRpdHkgKFJCQUMpPC9tYXQtc2xpZGUtdG9nZ2xlPlxuXG4gICAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsIGNsYXNzPVwiZGViLXJiYWNcIj5cbiAgICAgICAgICA8bWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XG4gICAgICAgICAgICA8bWF0LXBhbmVsLXRpdGxlPlBlcm1pc3Npb25zPC9tYXQtcGFuZWwtdGl0bGU+XG4gICAgICAgICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cbiAgICAgICAgICBAZm9yIChhY3Rpb24gb2YgcmJhY0FjdGlvbnM7IHRyYWNrIGFjdGlvbikge1xuICAgICAgICAgICAgQGlmIChhdmFpbGFibGVSb2xlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgc3Vic2NyaXB0U2l6aW5nPVwiZHluYW1pY1wiIGNsYXNzPVwiZGViLWZ1bGxcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7IGFjdGlvbiB9fSByb2xlczwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0IG11bHRpcGxlIFtuZ01vZGVsXT1cInJvbGVzRm9yKGFjdGlvbilcIiAobmdNb2RlbENoYW5nZSk9XCJzZXRSb2xlcyhhY3Rpb24sICRldmVudClcIj5cbiAgICAgICAgICAgICAgICAgIEBmb3IgKHJvbGUgb2YgYXZhaWxhYmxlUm9sZXM7IHRyYWNrIHJvbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cInJvbGVcIj57eyByb2xlIH19PC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBzdWJzY3JpcHRTaXppbmc9XCJkeW5hbWljXCIgY2xhc3M9XCJkZWItZnVsbFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgYWN0aW9uIH19IHJvbGVzIChjb21tYS1zZXBhcmF0ZWQpPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwicm9sZXNGb3IoYWN0aW9uKS5qb2luKCcsICcpXCJcbiAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNldFJvbGVzRnJvbVRleHQoYWN0aW9uLCAkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICA8cCBjbGFzcz1cImRlYi1oaW50XCI+RW1wdHkgPSBubyByZXN0cmljdGlvbiBmb3IgdGhhdCBhY3Rpb24uPC9wPlxuICAgICAgICA8L21hdC1leHBhbnNpb24tcGFuZWw+XG4gICAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XG4gICAgPC9tYXQtY2FyZD5cblxuICAgIDxtYXQtY2FyZD5cbiAgICAgIDxtYXQtY2FyZC1oZWFkZXI+PG1hdC1jYXJkLXRpdGxlPkFkZCBmaWVsZDwvbWF0LWNhcmQtdGl0bGU+PC9tYXQtY2FyZC1oZWFkZXI+XG4gICAgICA8bWF0LWNhcmQtY29udGVudD5cbiAgICAgICAgPG5neC1maWVsZC1wYWxldHRlIChwaWNrKT1cInN0b3JlLmFkZEZpZWxkKCRldmVudClcIj48L25neC1maWVsZC1wYWxldHRlPlxuICAgICAgPC9tYXQtY2FyZC1jb250ZW50PlxuICAgIDwvbWF0LWNhcmQ+XG5cbiAgICA8bWF0LWNhcmQ+XG4gICAgICA8bWF0LWNhcmQtY29udGVudD5cbiAgICAgICAgPG5neC10YWItbWFuYWdlcj48L25neC10YWItbWFuYWdlcj5cbiAgICAgIDwvbWF0LWNhcmQtY29udGVudD5cbiAgICA8L21hdC1jYXJkPlxuICA8L2Rpdj5cblxuICA8IS0tIOKUgOKUgOKUgCBDZW50ZXI6IGZpZWxkIGNhbnZhcyDilIDilIDilIAgLS0+XG4gIDxkaXYgY2xhc3M9XCJkZWItY29sIGRlYi1jb2wtLWNlbnRlclwiPlxuICAgIDxuZ3gtZW50aXR5LWJ1aWxkZXItY2FudmFzIC8+XG4gIDwvZGl2PlxuXG4gIDwhLS0g4pSA4pSA4pSAIFJpZ2h0OiBpbnNwZWN0b3Ig4pSA4pSA4pSAIC0tPlxuICA8ZGl2IGNsYXNzPVwiZGViLWNvbCBkZWItY29sLS1yaWdodFwiPlxuICAgIDxtYXQtY2FyZD5cbiAgICAgIDxtYXQtY2FyZC1oZWFkZXI+PG1hdC1jYXJkLXRpdGxlPkZpZWxkIHByb3BlcnRpZXM8L21hdC1jYXJkLXRpdGxlPjwvbWF0LWNhcmQtaGVhZGVyPlxuICAgICAgPG1hdC1jYXJkLWNvbnRlbnQ+XG4gICAgICAgIDxuZ3gtZmllbGQtaW5zcGVjdG9yPjwvbmd4LWZpZWxkLWluc3BlY3Rvcj5cbiAgICAgIDwvbWF0LWNhcmQtY29udGVudD5cbiAgICA8L21hdC1jYXJkPlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48IS0tIOKUgOKUgOKUgCBGb290ZXI6IEpTT04gKyBvcHRpb25hbCBsaXZlIHByZXZpZXcg4pSA4pSA4pSAIC0tPlxuPGRpdiBjbGFzcz1cImRlYi1mb290ZXJcIj5cbiAgPG1hdC1leHBhbnNpb24tcGFuZWw+XG4gICAgPG1hdC1leHBhbnNpb24tcGFuZWwtaGVhZGVyPlxuICAgICAgPG1hdC1wYW5lbC10aXRsZT48bWF0LWljb24+ZGF0YV9vYmplY3Q8L21hdC1pY29uPiZuYnNwO0NvbmZpZyBKU09OPC9tYXQtcGFuZWwtdGl0bGU+XG4gICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cbiAgICA8cHJlIGNsYXNzPVwiZGViLWpzb25cIj57eyBqc29uIH19PC9wcmU+XG4gIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cblxuICA8ZGl2IGNsYXNzPVwiZGViLXByZXZpZXctc2xvdFwiPlxuICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIltuZ3hCdWlsZGVyUHJldmlld11cIj48L25nLWNvbnRlbnQ+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=
159
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9lbnRpdHktYnVpbGRlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi9zcmMvbGliL2VudGl0eS1idWlsZGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQWlCLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUksT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDL0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDakUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUNMLGNBQWMsR0FJZixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxN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ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uQ2hhbmdlcywgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzLCBlZmZlY3QsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgTWF0Q2FyZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NhcmQnO1xuaW1wb3J0IHsgTWF0Q2hlY2tib3hNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jaGVja2JveCc7XG5pbXBvcnQgeyBNYXRFeHBhbnNpb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9leHBhbnNpb24nO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0JztcbmltcG9ydCB7IE1hdFNlbGVjdE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NlbGVjdCc7XG5pbXBvcnQgeyBNYXRTbGlkZVRvZ2dsZU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NsaWRlLXRvZ2dsZSc7XG5pbXBvcnQgeyBNYXRUb29sYmFyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbGJhcic7XG5pbXBvcnQgeyBNYXRUb29sdGlwTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XG5pbXBvcnQge1xuICBDT01NT05fTU9EVUxFUyxcbiAgdHlwZSBDb21tb25Nb2R1bGVFbnRyeSxcbiAgdHlwZSBFbnRpdHlGb3JtQ29uZmlnLFxuICB0eXBlIEVudGl0eVBlcm1pc3Npb25zLFxufSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XG5pbXBvcnQgeyBDb25maWdTb3VyY2VTZXJ2aWNlIH0gZnJvbSAnbmd4LWR5bmFtaWMtZW50aXR5JztcbmltcG9ydCB7IEJ1aWxkZXJTdG9yZSB9IGZyb20gJy4vYnVpbGRlci1zdG9yZS5zZXJ2aWNlJztcbmltcG9ydCB7IEZpZWxkSW5zcGVjdG9yQ29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnRzL2ZpZWxkLWluc3BlY3Rvci5jb21wb25lbnQnO1xuaW1wb3J0IHsgRmllbGRQYWxldHRlQ29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnRzL2ZpZWxkLXBhbGV0dGUuY29tcG9uZW50JztcbmltcG9ydCB7IFRhYk1hbmFnZXJDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvdGFiLW1hbmFnZXIuY29tcG9uZW50JztcbmltcG9ydCB7IEVudGl0eUJ1aWxkZXJDYW52YXNDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvZW50aXR5LWJ1aWxkZXItY2FudmFzLmNvbXBvbmVudCc7XG5cbi8qKiBSQkFDIGFjdGlvbnMgc3VyZmFjZWQgaW4gdGhlIHNldHRpbmdzIHBhbmVsLiAqL1xuY29uc3QgUkJBQ19BQ1RJT05TOiAoa2V5b2YgRW50aXR5UGVybWlzc2lvbnMpW10gPSBbJ3ZpZXcnLCAnZWRpdCcsICdkZWxldGUnXTtcblxuLyoqIFNoYXJlZCBzdGFibGUgZW1wdHkgYXJyYXkg4oCUIG5ldmVyIGFsbG9jYXRlIGEgZnJlc2ggW10gcGVyIGNoYW5nZS1kZXRlY3Rpb24gKG1hdC1zZWxlY3QgbG9vcHMpLiAqL1xuY29uc3QgRU1QVFlfUk9MRVM6IHJlYWRvbmx5IHN0cmluZ1tdID0gT2JqZWN0LmZyZWV6ZShbXSk7XG5cbi8qKlxuICogRW50aXR5QnVpbGRlckNvbXBvbmVudCDigJQgdGhlIHRvcC1sZXZlbCB2aXN1YWwgYnVpbGRlciBmb3IgYW4gRW50aXR5Rm9ybUNvbmZpZy5cbiAqL1xuQENvbXBvbmVudCh7XG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzZWxlY3RvcjogJ25neC1lbnRpdHktYnVpbGRlcicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHByb3ZpZGVyczogW0J1aWxkZXJTdG9yZV0sXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBNYXRCdXR0b25Nb2R1bGUsXG4gICAgTWF0Q2FyZE1vZHVsZSxcbiAgICBNYXRDaGVja2JveE1vZHVsZSxcbiAgICBNYXRFeHBhbnNpb25Nb2R1bGUsXG4gICAgTWF0Rm9ybUZpZWxkTW9kdWxlLFxuICAgIE1hdEljb25Nb2R1bGUsXG4gICAgTWF0SW5wdXRNb2R1bGUsXG4gICAgTWF0U2VsZWN0TW9kdWxlLFxuICAgIE1hdFNsaWRlVG9nZ2xlTW9kdWxlLFxuICAgIE1hdFRvb2xiYXJNb2R1bGUsXG4gICAgTWF0VG9vbHRpcE1vZHVsZSxcbiAgICBGaWVsZFBhbGV0dGVDb21wb25lbnQsXG4gICAgVGFiTWFuYWdlckNvbXBvbmVudCxcbiAgICBGaWVsZEluc3BlY3RvckNvbXBvbmVudCxcbiAgICBFbnRpdHlCdWlsZGVyQ2FudmFzQ29tcG9uZW50LFxuICBdLFxuICB0ZW1wbGF0ZVVybDogJy4vZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50LmNzcycsXG59KVxuZXhwb3J0IGNsYXNzIEVudGl0eUJ1aWxkZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc3RvcmUgPSBpbmplY3QoQnVpbGRlclN0b3JlKTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsOiBvbmx5IGFwcHMgdGhhdCByZWdpc3RlcmVkIGEgQ09ORklHX1NPVVJDRSBoYXZlIG9uZS4gVXNlZCB0byBkcm9wIHRoZSBjYWNoZWRcbiAgICogY29weSBvZiBhIGNvbmZpZyB0aGUgbW9tZW50IGl0IGlzIGVkaXRlZCDigJQgc2VlIGBkb1NhdmVgLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBjb25maWdTb3VyY2UgPSBpbmplY3QoQ29uZmlnU291cmNlU2VydmljZSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICAvKiogRXhpc3RpbmcgY29uZmlnIHRvIGVkaXQuIFdoZW4gb21pdHRlZCwgdGhlIGJ1aWxkZXIgc3RhcnRzIGJsYW5rLiAqL1xuICBASW5wdXQoKSBjb25maWc/OiBFbnRpdHlGb3JtQ29uZmlnO1xuICAvKiogTGFuZ3VhZ2VzIGF2YWlsYWJsZSBmb3IgbGFiZWwvcGxhY2Vob2xkZXIgZWRpdGluZy4gRmlyc3QgZW50cnkgaXMgdGhlIGRlZmF1bHQuICovXG4gIEBJbnB1dCgpIGxhbmd1YWdlczogc3RyaW5nW10gPSBbJ2VuJ107XG4gIC8qKiBPcHRpb25hbCByb2xlIGxpc3Qg4oCUIGVuYWJsZXMgbXVsdGktc2VsZWN0IHJvbGUgcGlja2VycyBmb3IgUkJBQyBpbnN0ZWFkIG9mIGZyZWUgdGV4dC4gKi9cbiAgQElucHV0KCkgYXZhaWxhYmxlUm9sZXM6IHN0cmluZ1tdID0gW107XG4gIC8qKlxuICAgKiBSb2xlcyBvZiB0aGUgcGVyc29uIHVzaW5nIHRoZSBidWlsZGVyLiBEaXN0aW5jdCBmcm9tIGBhdmFpbGFibGVSb2xlc2AsIHdoaWNoIGlzIHRoZVxuICAgKiB2b2NhYnVsYXJ5IGEgc2NoZW1hIG1heSByZWZlcmVuY2UuIFBhc3NlZCB0byB0aGUgYFNZU1RFTV9ERUZBVUxUX0NBTl9FRElUYCBwcmVkaWNhdGUgc29cbiAgICogaXQgY2FuIGRlY2lkZSB3aGV0aGVyIHRoaXMgdXNlciBtYXkgZWRpdCBzeXN0ZW0tZGVmYXVsdCB0YWJzLlxuICAgKi9cbiAgQElucHV0KCkgdXNlclJvbGVzOiBzdHJpbmdbXSA9IFtdO1xuICAvKiogT3B0aW9uYWwgY29tbW9uLW1vZHVsZSBkZWZpbml0aW9ucyBmb3IgbW9kdWxlIHRhYnM7IGRlZmF1bHRzIHRvIHRoZSBidWlsdC1pbiBsaXN0IGZyb20gY29yZS4gKi9cbiAgQElucHV0KCkgY29tbW9uTW9kdWxlczogcmVhZG9ubHkgQ29tbW9uTW9kdWxlRW50cnlbXSA9IENPTU1PTl9NT0RVTEVTO1xuXG4gIC8qKiBFbWl0dGVkIG9uIGV2ZXJ5IGNoYW5nZSB0byB0aGUgd29ya2luZyBjb25maWcuICovXG4gIEBPdXRwdXQoKSBjb25maWdDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEVudGl0eUZvcm1Db25maWc+KCk7XG4gIC8qKiBFbWl0dGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIFNhdmUuIENhcnJpZXMgYSBjbGVhbiwgZGVlcC1jbG9uZWQgY29uZmlnLiAqL1xuICBAT3V0cHV0KCkgc2F2ZSA9IG5ldyBFdmVudEVtaXR0ZXI8RW50aXR5Rm9ybUNvbmZpZz4oKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmJhY0FjdGlvbnMgPSBSQkFDX0FDVElPTlM7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgZWZmZWN0KCgpID0+IHRoaXMuY29uZmlnQ2hhbmdlLmVtaXQodGhpcy5zdG9yZS5jb25maWcoKSksIHsgYWxsb3dTaWduYWxXcml0ZXM6IHRydWUgfSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ2NvbmZpZyddICYmIGNoYW5nZXNbJ2NvbmZpZyddLmN1cnJlbnRWYWx1ZSAhPT0gY2hhbmdlc1snY29uZmlnJ10ucHJldmlvdXNWYWx1ZSkge1xuICAgICAgaWYgKHRoaXMuY29uZmlnKSB0aGlzLnN0b3JlLmxvYWQodGhpcy5jb25maWcpO1xuICAgICAgZWxzZSBpZiAoY2hhbmdlc1snY29uZmlnJ10uaXNGaXJzdENoYW5nZSgpKSB0aGlzLnN0b3JlLnJlc2V0KCk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWydsYW5ndWFnZXMnXSAmJiB0aGlzLmxhbmd1YWdlcy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuc3RvcmUuYWN0aXZlTGFuZ3VhZ2UoKTtcbiAgICAgIGlmICghdGhpcy5sYW5ndWFnZXMuaW5jbHVkZXMoYWN0aXZlKSkgdGhpcy5zdG9yZS5zZXRBY3RpdmVMYW5ndWFnZSh0aGlzLmxhbmd1YWdlc1swXSk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWyd1c2VyUm9sZXMnXSkge1xuICAgICAgdGhpcy5zdG9yZS5zZXRVc2VyUm9sZXModGhpcy51c2VyUm9sZXMpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBUb29sYmFyIGFjdGlvbnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIGRvU2F2ZSgpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLnN0b3JlLmV4cG9ydENvbmZpZygpO1xuXG4gICAgLy8gU2F2aW5nIGlzIHRoZSBtb21lbnQgdGhpcyBlbnRpdHkncyBjb25maWcgY2hhbmdlcywgc28gYW55dGhpbmcgaG9sZGluZyBhIGNhY2hlZCBjb3B5IGlzXG4gICAgLy8gbm93IHN0YWxlIOKAlCBtb3N0IHZpc2libHkgYSByZWZlcmVuY2VkIGZpZWxkIGVsc2V3aGVyZSByZXNvbHZpbmcgYWdhaW5zdCB0aGUgb2xkIHNjaGVtYS5cbiAgICAvLyBDb25maWdTb3VyY2VTZXJ2aWNlIGNhY2hlcyBwZXIgZW50aXR5IGFuZCBleHBvc2VkIGNsZWFyQ2FjaGUgZnJvbSB0aGUgc3RhcnQsIGJ1dCBub3RoaW5nXG4gICAgLy8gZXZlciBjYWxsZWQgaXQsIHNvIGEgY2FjaGUgZW50cnkgbGl2ZWQgZm9yIHRoZSBsaWZldGltZSBvZiB0aGUgcGFnZS5cbiAgICB0aGlzLmNvbmZpZ1NvdXJjZT8uY2xlYXJDYWNoZShjb25maWcuZW50aXR5KTtcblxuICAgIHRoaXMuc2F2ZS5lbWl0KGNvbmZpZyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IGpzb24oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy5zdG9yZS5leHBvcnRDb25maWcoKSwgbnVsbCwgMik7XG4gIH1cblxuICBwcm90ZWN0ZWQgY29weUpzb24oKTogdm9pZCB7XG4gICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmIG5hdmlnYXRvci5jbGlwYm9hcmQpIHtcbiAgICAgIHZvaWQgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQodGhpcy5qc29uKTtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIDilIAgUkJBQyBzZXR0aW5ncyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcm90ZWN0ZWQgcm9sZXNGb3IoYWN0aW9uOiBrZXlvZiBFbnRpdHlQZXJtaXNzaW9ucyk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCBhcnJheSAoc3RhYmxlIHJlZiBiZXR3ZWVuIG11dGF0aW9ucykgb3IgYSBzaGFyZWQgZW1wdHkg4oCUIE5PVCBhIGZyZXNoIFtdLFxuICAgIC8vIHdoaWNoIHdvdWxkIG1ha2UgdGhlIGJvdW5kIG1hdC1zZWxlY3QgcmUtZXZhbHVhdGUgZXZlcnkgQ0QgYW5kIGxvb3AgZm9yZXZlci5cbiAgICByZXR1cm4gdGhpcy5zdG9yZS5jb25maWcoKS5wZXJtaXNzaW9ucz8uW2FjdGlvbl0gPz8gRU1QVFlfUk9MRVM7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0Um9sZXMoYWN0aW9uOiBrZXlvZiBFbnRpdHlQZXJtaXNzaW9ucywgcm9sZXM6IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdGhpcy5zdG9yZS5zZXRQZXJtaXNzaW9uKGFjdGlvbiwgcm9sZXMpO1xuICB9XG5cbiAgLyoqIFBhcnNlIGEgY29tbWEtc2VwYXJhdGVkIHJvbGUgc3RyaW5nIGludG8gYSB0cmltbWVkLCBkZS1kdXBsaWNhdGVkIGFycmF5LiAqL1xuICBwcm90ZWN0ZWQgc2V0Um9sZXNGcm9tVGV4dChhY3Rpb246IGtleW9mIEVudGl0eVBlcm1pc3Npb25zLCB0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCByb2xlcyA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFxuICAgICAgICB0ZXh0XG4gICAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgICAubWFwKHIgPT4gci50cmltKCkpXG4gICAgICAgICAgLmZpbHRlcihCb29sZWFuKSxcbiAgICAgICksXG4gICAgKTtcbiAgICB0aGlzLnN0b3JlLnNldFBlcm1pc3Npb24oYWN0aW9uLCByb2xlcyk7XG4gIH1cbn1cbiIsIjxtYXQtdG9vbGJhciBjbGFzcz1cImRlYi10b29sYmFyXCIgY29sb3I9XCJwcmltYXJ5XCI+XG4gIDxtYXQtaWNvbj5kYXNoYm9hcmRfY3VzdG9taXplPC9tYXQtaWNvbj5cbiAgPHNwYW4gY2xhc3M9XCJkZWItdG9vbGJhcl9fdGl0bGVcIj5FbnRpdHkgQnVpbGRlcjwvc3Bhbj5cbiAgPHNwYW4gY2xhc3M9XCJkZWItc3BhY2VyXCI+PC9zcGFuPlxuXG4gIEBpZiAoc3RvcmUucHJvYmxlbXMoKS5sZW5ndGgpIHtcbiAgICA8YnV0dG9uXG4gICAgICBtYXQtYnV0dG9uXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIGNsYXNzPVwiZGViLXByb2JsZW1zXCJcbiAgICAgIFtjbGFzcy5kZWItcHJvYmxlbXMtLWVycm9yXT1cIiFzdG9yZS5pc1ZhbGlkKClcIlxuICAgICAgW21hdFRvb2x0aXBdPVwic3RvcmUucHJvYmxlbXMoKS5sZW5ndGggKyAnIGlzc3VlKHMpIOKAlCBob3ZlciBpdGVtcyBpbiB0aGUgbGlzdCdcIlxuICAgID5cbiAgICAgIDxtYXQtaWNvbj57eyBzdG9yZS5pc1ZhbGlkKCkgPyAnd2FybmluZycgOiAnZXJyb3InIH19PC9tYXQtaWNvbj5cbiAgICAgIHt7IHN0b3JlLmVycm9ycygpLmxlbmd0aCB9fSAvIHt7IHN0b3JlLnByb2JsZW1zKCkubGVuZ3RoIH19XG4gICAgPC9idXR0b24+XG4gIH1cblxuICA8YnV0dG9uIG1hdC1idXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJjb3B5SnNvbigpXCI+XG4gICAgPG1hdC1pY29uPmNvbnRlbnRfY29weTwvbWF0LWljb24+IENvcHkgSlNPTlxuICA8L2J1dHRvbj5cbiAgPCEtLSBwcmltYXJ5LCBub3QgYWNjZW50OiB3aGl0ZSBvbiBNYXRlcmlhbCdzIGRlZmF1bHQgcGluayBhY2NlbnQgaXMgMy4zMzoxLCBiZWxvdyBBQS4gLS0+XG4gIDxidXR0b24gbWF0LWZsYXQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIHR5cGU9XCJidXR0b25cIiBbZGlzYWJsZWRdPVwiIXN0b3JlLmlzVmFsaWQoKVwiIChjbGljayk9XCJkb1NhdmUoKVwiPlxuICAgIDxtYXQtaWNvbj5zYXZlPC9tYXQtaWNvbj4gU2F2ZVxuICA8L2J1dHRvbj5cbjwvbWF0LXRvb2xiYXI+XG5cbjxkaXYgY2xhc3M9XCJkZWItYm9keVwiPlxuICA8IS0tIOKUgOKUgOKUgCBMZWZ0OiBzZXR0aW5ncywgcGFsZXR0ZSwgdGFicyDilIDilIDilIAgLS0+XG4gIDxkaXYgY2xhc3M9XCJkZWItY29sIGRlYi1jb2wtLWxlZnRcIj5cbiAgICA8bWF0LWNhcmQ+XG4gICAgICA8bWF0LWNhcmQtY29udGVudD5cbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgc3Vic2NyaXB0U2l6aW5nPVwiZHluYW1pY1wiIGNsYXNzPVwiZGViLWZ1bGxcIj5cbiAgICAgICAgICA8bWF0LWxhYmVsPkVudGl0eSBuYW1lPC9tYXQtbGFiZWw+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgW25nTW9kZWxdPVwic3RvcmUuY29uZmlnKCkuZW50aXR5XCJcbiAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInN0b3JlLnNldEVudGl0eU5hbWUoJGV2ZW50KVwiXG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cImUuZy4gY2xpZW50c1wiXG4gICAgICAgICAgLz5cbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGViLXJvd1wiPlxuICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwib3V0bGluZVwiIHN1YnNjcmlwdFNpemluZz1cImR5bmFtaWNcIiBjbGFzcz1cImRlYi1ncm93XCI+XG4gICAgICAgICAgICA8bWF0LWxhYmVsPkVkaXRpbmcgbGFuZ3VhZ2U8L21hdC1sYWJlbD5cbiAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgIFtuZ01vZGVsXT1cInN0b3JlLmFjdGl2ZUxhbmd1YWdlKClcIlxuICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdG9yZS5zZXRBY3RpdmVMYW5ndWFnZSgkZXZlbnQpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgQGZvciAobCBvZiBsYW5ndWFnZXM7IHRyYWNrIGwpIHtcbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwibFwiPnt7IGwgfX08L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8bWF0LXNsaWRlLXRvZ2dsZVxuICAgICAgICAgIFtuZ01vZGVsXT1cInN0b3JlLmNvbmZpZygpLm1hc2tEYXRhID8/IGZhbHNlXCJcbiAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJzdG9yZS5zZXRNYXNrRGF0YSgkZXZlbnQpXCJcbiAgICAgICAgPk1hc2sgdGhpcyBlbnRpdHkgKFJCQUMpPC9tYXQtc2xpZGUtdG9nZ2xlPlxuXG4gICAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsIGNsYXNzPVwiZGViLXJiYWNcIj5cbiAgICAgICAgICA8bWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XG4gICAgICAgICAgICA8bWF0LXBhbmVsLXRpdGxlPlBlcm1pc3Npb25zPC9tYXQtcGFuZWwtdGl0bGU+XG4gICAgICAgICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cbiAgICAgICAgICBAZm9yIChhY3Rpb24gb2YgcmJhY0FjdGlvbnM7IHRyYWNrIGFjdGlvbikge1xuICAgICAgICAgICAgQGlmIChhdmFpbGFibGVSb2xlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgc3Vic2NyaXB0U2l6aW5nPVwiZHluYW1pY1wiIGNsYXNzPVwiZGViLWZ1bGxcIj5cbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7IGFjdGlvbiB9fSByb2xlczwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0IG11bHRpcGxlIFtuZ01vZGVsXT1cInJvbGVzRm9yKGFjdGlvbilcIiAobmdNb2RlbENoYW5nZSk9XCJzZXRSb2xlcyhhY3Rpb24sICRldmVudClcIj5cbiAgICAgICAgICAgICAgICAgIEBmb3IgKHJvbGUgb2YgYXZhaWxhYmxlUm9sZXM7IHRyYWNrIHJvbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cInJvbGVcIj57eyByb2xlIH19PC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBzdWJzY3JpcHRTaXppbmc9XCJkeW5hbWljXCIgY2xhc3M9XCJkZWItZnVsbFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgYWN0aW9uIH19IHJvbGVzIChjb21tYS1zZXBhcmF0ZWQpPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgICAgW25nTW9kZWxdPVwicm9sZXNGb3IoYWN0aW9uKS5qb2luKCcsICcpXCJcbiAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNldFJvbGVzRnJvbVRleHQoYWN0aW9uLCAkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICA8cCBjbGFzcz1cImRlYi1oaW50XCI+RW1wdHkgPSBubyByZXN0cmljdGlvbiBmb3IgdGhhdCBhY3Rpb24uPC9wPlxuICAgICAgICA8L21hdC1leHBhbnNpb24tcGFuZWw+XG4gICAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XG4gICAgPC9tYXQtY2FyZD5cblxuICAgIDxtYXQtY2FyZD5cbiAgICAgIDxtYXQtY2FyZC1oZWFkZXI+PG1hdC1jYXJkLXRpdGxlPkFkZCBmaWVsZDwvbWF0LWNhcmQtdGl0bGU+PC9tYXQtY2FyZC1oZWFkZXI+XG4gICAgICA8bWF0LWNhcmQtY29udGVudD5cbiAgICAgICAgPG5neC1maWVsZC1wYWxldHRlIChwaWNrKT1cInN0b3JlLmFkZEZpZWxkKCRldmVudClcIj48L25neC1maWVsZC1wYWxldHRlPlxuICAgICAgPC9tYXQtY2FyZC1jb250ZW50PlxuICAgIDwvbWF0LWNhcmQ+XG5cbiAgICA8bWF0LWNhcmQ+XG4gICAgICA8bWF0LWNhcmQtY29udGVudD5cbiAgICAgICAgPG5neC10YWItbWFuYWdlcj48L25neC10YWItbWFuYWdlcj5cbiAgICAgIDwvbWF0LWNhcmQtY29udGVudD5cbiAgICA8L21hdC1jYXJkPlxuICA8L2Rpdj5cblxuICA8IS0tIOKUgOKUgOKUgCBDZW50ZXI6IGZpZWxkIGNhbnZhcyDilIDilIDilIAgLS0+XG4gIDxkaXYgY2xhc3M9XCJkZWItY29sIGRlYi1jb2wtLWNlbnRlclwiPlxuICAgIDxuZ3gtZW50aXR5LWJ1aWxkZXItY2FudmFzIC8+XG4gIDwvZGl2PlxuXG4gIDwhLS0g4pSA4pSA4pSAIFJpZ2h0OiBpbnNwZWN0b3Ig4pSA4pSA4pSAIC0tPlxuICA8ZGl2IGNsYXNzPVwiZGViLWNvbCBkZWItY29sLS1yaWdodFwiPlxuICAgIDxtYXQtY2FyZD5cbiAgICAgIDxtYXQtY2FyZC1oZWFkZXI+PG1hdC1jYXJkLXRpdGxlPkZpZWxkIHByb3BlcnRpZXM8L21hdC1jYXJkLXRpdGxlPjwvbWF0LWNhcmQtaGVhZGVyPlxuICAgICAgPG1hdC1jYXJkLWNvbnRlbnQ+XG4gICAgICAgIDxuZ3gtZmllbGQtaW5zcGVjdG9yPjwvbmd4LWZpZWxkLWluc3BlY3Rvcj5cbiAgICAgIDwvbWF0LWNhcmQtY29udGVudD5cbiAgICA8L21hdC1jYXJkPlxuICA8L2Rpdj5cbjwvZGl2PlxuXG48IS0tIOKUgOKUgOKUgCBGb290ZXI6IEpTT04gKyBvcHRpb25hbCBsaXZlIHByZXZpZXcg4pSA4pSA4pSAIC0tPlxuPGRpdiBjbGFzcz1cImRlYi1mb290ZXJcIj5cbiAgPG1hdC1leHBhbnNpb24tcGFuZWw+XG4gICAgPG1hdC1leHBhbnNpb24tcGFuZWwtaGVhZGVyPlxuICAgICAgPG1hdC1wYW5lbC10aXRsZT48bWF0LWljb24+ZGF0YV9vYmplY3Q8L21hdC1pY29uPiZuYnNwO0NvbmZpZyBKU09OPC9tYXQtcGFuZWwtdGl0bGU+XG4gICAgPC9tYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5cbiAgICA8cHJlIGNsYXNzPVwiZGViLWpzb25cIj57eyBqc29uIH19PC9wcmU+XG4gIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cblxuICA8ZGl2IGNsYXNzPVwiZGViLXByZXZpZXctc2xvdFwiPlxuICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIltuZ3hCdWlsZGVyUHJldmlld11cIj48L25nLWNvbnRlbnQ+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=