ngx-dynamic-entity-builder 1.1.0 → 1.2.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.
@@ -13,6 +13,7 @@ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
13
13
  import { MatToolbarModule } from '@angular/material/toolbar';
14
14
  import { MatTooltipModule } from '@angular/material/tooltip';
15
15
  import { COMMON_MODULES, resolveLabel, } from '@dynamic-entity/core';
16
+ import { ConfigSourceService } from 'ngx-dynamic-entity';
16
17
  import { BuilderStore } from './builder-store.service';
17
18
  import { FieldInspectorComponent } from './components/field-inspector.component';
18
19
  import { FieldPaletteComponent } from './components/field-palette.component';
@@ -41,6 +42,11 @@ const EMPTY_ROLES = Object.freeze([]);
41
42
  */
42
43
  export class EntityBuilderComponent {
43
44
  store = inject(BuilderStore);
45
+ /**
46
+ * Optional: only apps that registered a CONFIG_SOURCE have one. Used to drop the cached
47
+ * copy of a config the moment it is edited — see `doSave`.
48
+ */
49
+ configSource = inject(ConfigSourceService, { optional: true });
44
50
  /** Existing config to edit. When omitted, the builder starts blank. */
45
51
  config;
46
52
  /** Languages available for label/placeholder editing. First entry is the default. */
@@ -95,7 +101,13 @@ export class EntityBuilderComponent {
95
101
  }
96
102
  // ─── Toolbar actions ──────────────────────────────────────────────────────
97
103
  doSave() {
98
- this.save.emit(this.store.exportConfig());
104
+ const config = this.store.exportConfig();
105
+ // Saving is the moment this entity's config changes, so anything holding a cached copy is
106
+ // now stale — most visibly a referenced field elsewhere resolving against the old schema.
107
+ // ConfigSourceService caches per entity and exposed clearCache from the start, but nothing
108
+ // ever called it, so a cache entry lived for the lifetime of the page.
109
+ this.configSource?.clearCache(config.entity);
110
+ this.save.emit(config);
99
111
  }
100
112
  get json() {
101
113
  return JSON.stringify(this.store.exportConfig(), null, 2);
@@ -123,7 +135,7 @@ export class EntityBuilderComponent {
123
135
  this.store.setPermission(action, roles);
124
136
  }
125
137
  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" }] });
138
+ 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: 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" }] });
127
139
  }
128
140
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityBuilderComponent, decorators: [{
129
141
  type: Component,
@@ -145,7 +157,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
145
157
  TabManagerComponent,
146
158
  FieldInspectorComponent,
147
159
  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"] }]
160
+ ], 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
161
  }], ctorParameters: () => [], propDecorators: { config: [{
150
162
  type: Input
151
163
  }], languages: [{
@@ -161,4 +173,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
161
173
  }], save: [{
162
174
  type: Output
163
175
  }] } });
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=
176
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9lbnRpdHktYnVpbGRlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi9zcmMvbGliL2VudGl0eS1idWlsZGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEVBRU4sTUFBTSxFQUNOLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFlLGNBQWMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDL0QsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDakUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDdEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUNMLGNBQWMsRUFJZCxZQUFZLEdBQ2IsTUFBTSxz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QixnQkFBZ0IsaUpBQ2hCLGdCQUFnQiw4VEFDaEIscUJBQXFCLGlGQUNyQixtQkFBbUIsNERBQ25CLHVCQUF1QixnRUFDdkIsNEJBQTRCOzs0RkFLbkIsc0JBQXNCO2tCQTFCbEMsU0FBUzsrQkFDRSxvQkFBb0IsY0FDbEIsSUFBSSxhQUNMLENBQUMsWUFBWSxDQUFDLFdBQ2hCO3dCQUNQLFdBQVc7d0JBQ1gsY0FBYzt3QkFDZCxlQUFlO3dCQUNmLGFBQWE7d0JBQ2IsaUJBQWlCO3dCQUNqQixrQkFBa0I7d0JBQ2xCLGtCQUFrQjt3QkFDbEIsYUFBYTt3QkFDYixjQUFjO3dCQUNkLGVBQWU7d0JBQ2Ysb0JBQW9CO3dCQUNwQixnQkFBZ0I7d0JBQ2hCLGdCQUFnQjt3QkFDaEIscUJBQXFCO3dCQUNyQixtQkFBbUI7d0JBQ25CLHVCQUF1Qjt3QkFDdkIsNEJBQTRCO3FCQUM3Qjt3REFhUSxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxjQUFjO3NCQUF0QixLQUFLO2dCQU1HLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRUcsYUFBYTtzQkFBckIsS0FBSztnQkFHSSxZQUFZO3NCQUFyQixNQUFNO2dCQUVHLElBQUk7c0JBQWIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIGVmZmVjdCxcbiAgaW5qZWN0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQ2RrRHJhZ0Ryb3AsIERyYWdEcm9wTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2RyYWctZHJvcCc7XG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgTWF0Q2FyZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NhcmQnO1xuaW1wb3J0IHsgTWF0Q2hlY2tib3hNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jaGVja2JveCc7XG5pbXBvcnQgeyBNYXRFeHBhbnNpb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9leHBhbnNpb24nO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0JztcbmltcG9ydCB7IE1hdFNlbGVjdE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NlbGVjdCc7XG5pbXBvcnQgeyBNYXRTbGlkZVRvZ2dsZU1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NsaWRlLXRvZ2dsZSc7XG5pbXBvcnQgeyBNYXRUb29sYmFyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbGJhcic7XG5pbXBvcnQgeyBNYXRUb29sdGlwTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdG9vbHRpcCc7XG5pbXBvcnQge1xuICBDT01NT05fTU9EVUxFUyxcbiAgdHlwZSBDb21tb25Nb2R1bGVFbnRyeSxcbiAgdHlwZSBFbnRpdHlGb3JtQ29uZmlnLFxuICB0eXBlIEVudGl0eVBlcm1pc3Npb25zLFxuICByZXNvbHZlTGFiZWwsXG59IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IENvbmZpZ1NvdXJjZVNlcnZpY2UgfSBmcm9tICduZ3gtZHluYW1pYy1lbnRpdHknO1xuaW1wb3J0IHsgQnVpbGRlclN0b3JlIH0gZnJvbSAnLi9idWlsZGVyLXN0b3JlLnNlcnZpY2UnO1xuaW1wb3J0IHsgRmllbGRJbnNwZWN0b3JDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvZmllbGQtaW5zcGVjdG9yLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBGaWVsZFBhbGV0dGVDb21wb25lbnQgfSBmcm9tICcuL2NvbXBvbmVudHMvZmllbGQtcGFsZXR0ZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgVGFiTWFuYWdlckNvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy90YWItbWFuYWdlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgRW50aXR5QnVpbGRlckNhbnZhc0NvbXBvbmVudCB9IGZyb20gJy4vY29tcG9uZW50cy9lbnRpdHktYnVpbGRlci1jYW52YXMuY29tcG9uZW50JztcbmltcG9ydCB7IGdldEZpZWxkVHlwZU1ldGEgfSBmcm9tICcuL2ZpZWxkLWNhdGFsb2cnO1xuXG4vKiogUkJBQyBhY3Rpb25zIHN1cmZhY2VkIGluIHRoZSBzZXR0aW5ncyBwYW5lbC4gKi9cbmNvbnN0IFJCQUNfQUNUSU9OUzogKGtleW9mIEVudGl0eVBlcm1pc3Npb25zKVtdID0gWyd2aWV3JywgJ2VkaXQnLCAnZGVsZXRlJ107XG5cbi8qKiBTaGFyZWQgc3RhYmxlIGVtcHR5IGFycmF5IOKAlCBuZXZlciBhbGxvY2F0ZSBhIGZyZXNoIFtdIHBlciBjaGFuZ2UtZGV0ZWN0aW9uIChtYXQtc2VsZWN0IGxvb3BzKS4gKi9cbmNvbnN0IEVNUFRZX1JPTEVTOiByZWFkb25seSBzdHJpbmdbXSA9IE9iamVjdC5mcmVlemUoW10pO1xuXG4vKipcbiAqIEVudGl0eUJ1aWxkZXJDb21wb25lbnQg4oCUIHRoZSB0b3AtbGV2ZWwgdmlzdWFsIGJ1aWxkZXIgZm9yIGFuIEVudGl0eUZvcm1Db25maWcuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1lbnRpdHktYnVpbGRlcicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHByb3ZpZGVyczogW0J1aWxkZXJTdG9yZV0sXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBEcmFnRHJvcE1vZHVsZSxcbiAgICBNYXRCdXR0b25Nb2R1bGUsXG4gICAgTWF0Q2FyZE1vZHVsZSxcbiAgICBNYXRDaGVja2JveE1vZHVsZSxcbiAgICBNYXRFeHBhbnNpb25Nb2R1bGUsXG4gICAgTWF0Rm9ybUZpZWxkTW9kdWxlLFxuICAgIE1hdEljb25Nb2R1bGUsXG4gICAgTWF0SW5wdXRNb2R1bGUsXG4gICAgTWF0U2VsZWN0TW9kdWxlLFxuICAgIE1hdFNsaWRlVG9nZ2xlTW9kdWxlLFxuICAgIE1hdFRvb2xiYXJNb2R1bGUsXG4gICAgTWF0VG9vbHRpcE1vZHVsZSxcbiAgICBGaWVsZFBhbGV0dGVDb21wb25lbnQsXG4gICAgVGFiTWFuYWdlckNvbXBvbmVudCxcbiAgICBGaWVsZEluc3BlY3RvckNvbXBvbmVudCxcbiAgICBFbnRpdHlCdWlsZGVyQ2FudmFzQ29tcG9uZW50LFxuICBdLFxuICB0ZW1wbGF0ZVVybDogJy4vZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZW50aXR5LWJ1aWxkZXIuY29tcG9uZW50LmNzcycsXG59KVxuZXhwb3J0IGNsYXNzIEVudGl0eUJ1aWxkZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgc3RvcmUgPSBpbmplY3QoQnVpbGRlclN0b3JlKTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsOiBvbmx5IGFwcHMgdGhhdCByZWdpc3RlcmVkIGEgQ09ORklHX1NPVVJDRSBoYXZlIG9uZS4gVXNlZCB0byBkcm9wIHRoZSBjYWNoZWRcbiAgICogY29weSBvZiBhIGNvbmZpZyB0aGUgbW9tZW50IGl0IGlzIGVkaXRlZCDigJQgc2VlIGBkb1NhdmVgLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBjb25maWdTb3VyY2UgPSBpbmplY3QoQ29uZmlnU291cmNlU2VydmljZSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICAvKiogRXhpc3RpbmcgY29uZmlnIHRvIGVkaXQuIFdoZW4gb21pdHRlZCwgdGhlIGJ1aWxkZXIgc3RhcnRzIGJsYW5rLiAqL1xuICBASW5wdXQoKSBjb25maWc/OiBFbnRpdHlGb3JtQ29uZmlnO1xuICAvKiogTGFuZ3VhZ2VzIGF2YWlsYWJsZSBmb3IgbGFiZWwvcGxhY2Vob2xkZXIgZWRpdGluZy4gRmlyc3QgZW50cnkgaXMgdGhlIGRlZmF1bHQuICovXG4gIEBJbnB1dCgpIGxhbmd1YWdlczogc3RyaW5nW10gPSBbJ2VuJ107XG4gIC8qKiBPcHRpb25hbCByb2xlIGxpc3Qg4oCUIGVuYWJsZXMgbXVsdGktc2VsZWN0IHJvbGUgcGlja2VycyBmb3IgUkJBQyBpbnN0ZWFkIG9mIGZyZWUgdGV4dC4gKi9cbiAgQElucHV0KCkgYXZhaWxhYmxlUm9sZXM6IHN0cmluZ1tdID0gW107XG4gIC8qKlxuICAgKiBSb2xlcyBvZiB0aGUgcGVyc29uIHVzaW5nIHRoZSBidWlsZGVyLiBEaXN0aW5jdCBmcm9tIGBhdmFpbGFibGVSb2xlc2AsIHdoaWNoIGlzIHRoZVxuICAgKiB2b2NhYnVsYXJ5IGEgc2NoZW1hIG1heSByZWZlcmVuY2UuIFBhc3NlZCB0byB0aGUgYFNZU1RFTV9ERUZBVUxUX0NBTl9FRElUYCBwcmVkaWNhdGUgc29cbiAgICogaXQgY2FuIGRlY2lkZSB3aGV0aGVyIHRoaXMgdXNlciBtYXkgZWRpdCBzeXN0ZW0tZGVmYXVsdCB0YWJzLlxuICAgKi9cbiAgQElucHV0KCkgdXNlclJvbGVzOiBzdHJpbmdbXSA9IFtdO1xuICAvKiogT3B0aW9uYWwgY29tbW9uLW1vZHVsZSBkZWZpbml0aW9ucyBmb3IgbW9kdWxlIHRhYnM7IGRlZmF1bHRzIHRvIHRoZSBidWlsdC1pbiBsaXN0IGZyb20gY29yZS4gKi9cbiAgQElucHV0KCkgY29tbW9uTW9kdWxlczogcmVhZG9ubHkgQ29tbW9uTW9kdWxlRW50cnlbXSA9IENPTU1PTl9NT0RVTEVTO1xuXG4gIC8qKiBFbWl0dGVkIG9uIGV2ZXJ5IGNoYW5nZSB0byB0aGUgd29ya2luZyBjb25maWcuICovXG4gIEBPdXRwdXQoKSBjb25maWdDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPEVudGl0eUZvcm1Db25maWc+KCk7XG4gIC8qKiBFbWl0dGVkIHdoZW4gdGhlIHVzZXIgY2xpY2tzIFNhdmUuIENhcnJpZXMgYSBjbGVhbiwgZGVlcC1jbG9uZWQgY29uZmlnLiAqL1xuICBAT3V0cHV0KCkgc2F2ZSA9IG5ldyBFdmVudEVtaXR0ZXI8RW50aXR5Rm9ybUNvbmZpZz4oKTtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmJhY0FjdGlvbnMgPSBSQkFDX0FDVElPTlM7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgZWZmZWN0KCgpID0+IHRoaXMuY29uZmlnQ2hhbmdlLmVtaXQodGhpcy5zdG9yZS5jb25maWcoKSksIHsgYWxsb3dTaWduYWxXcml0ZXM6IHRydWUgfSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXNbJ2NvbmZpZyddICYmIGNoYW5nZXNbJ2NvbmZpZyddLmN1cnJlbnRWYWx1ZSAhPT0gY2hhbmdlc1snY29uZmlnJ10ucHJldmlvdXNWYWx1ZSkge1xuICAgICAgaWYgKHRoaXMuY29uZmlnKSB0aGlzLnN0b3JlLmxvYWQodGhpcy5jb25maWcpO1xuICAgICAgZWxzZSBpZiAoY2hhbmdlc1snY29uZmlnJ10uaXNGaXJzdENoYW5nZSgpKSB0aGlzLnN0b3JlLnJlc2V0KCk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWydsYW5ndWFnZXMnXSAmJiB0aGlzLmxhbmd1YWdlcy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IGFjdGl2ZSA9IHRoaXMuc3RvcmUuYWN0aXZlTGFuZ3VhZ2UoKTtcbiAgICAgIGlmICghdGhpcy5sYW5ndWFnZXMuaW5jbHVkZXMoYWN0aXZlKSkgdGhpcy5zdG9yZS5zZXRBY3RpdmVMYW5ndWFnZSh0aGlzLmxhbmd1YWdlc1swXSk7XG4gICAgfVxuICAgIGlmIChjaGFuZ2VzWyd1c2VyUm9sZXMnXSkge1xuICAgICAgdGhpcy5zdG9yZS5zZXRVc2VyUm9sZXModGhpcy51c2VyUm9sZXMpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBGaWVsZCBjYW52YXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIG9uRHJvcChldmVudDogQ2RrRHJhZ0Ryb3A8dW5rbm93bj4pOiB2b2lkIHtcbiAgICB0aGlzLnN0b3JlLnJlb3JkZXJGaWVsZChldmVudC5wcmV2aW91c0luZGV4LCBldmVudC5jdXJyZW50SW5kZXgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZpZWxkVHlwZUxhYmVsKHR5cGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGdldEZpZWxkVHlwZU1ldGEodHlwZSk/LmxhYmVsID8/IHR5cGU7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmllbGRUeXBlSWNvbih0eXBlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBnZXRGaWVsZFR5cGVNZXRhKHR5cGUpPy5pY29uID8/ICdoZWxwX291dGxpbmUnO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZpZWxkTGFiZWwoZmllbGQ6IHsgaWQ6IHN0cmluZzsgbGFiZWw/OiBhbnkgfSk6IHN0cmluZyB7XG4gICAgY29uc3QgbGFuZyA9IHRoaXMuc3RvcmUuYWN0aXZlTGFuZ3VhZ2UoKTtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKGZpZWxkLmxhYmVsLCBsYW5nKSB8fCBmaWVsZC5pZDtcbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBUb29sYmFyIGFjdGlvbnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJvdGVjdGVkIGRvU2F2ZSgpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLnN0b3JlLmV4cG9ydENvbmZpZygpO1xuXG4gICAgLy8gU2F2aW5nIGlzIHRoZSBtb21lbnQgdGhpcyBlbnRpdHkncyBjb25maWcgY2hhbmdlcywgc28gYW55dGhpbmcgaG9sZGluZyBhIGNhY2hlZCBjb3B5IGlzXG4gICAgLy8gbm93IHN0YWxlIOKAlCBtb3N0IHZpc2libHkgYSByZWZlcmVuY2VkIGZpZWxkIGVsc2V3aGVyZSByZXNvbHZpbmcgYWdhaW5zdCB0aGUgb2xkIHNjaGVtYS5cbiAgICAvLyBDb25maWdTb3VyY2VTZXJ2aWNlIGNhY2hlcyBwZXIgZW50aXR5IGFuZCBleHBvc2VkIGNsZWFyQ2FjaGUgZnJvbSB0aGUgc3RhcnQsIGJ1dCBub3RoaW5nXG4gICAgLy8gZXZlciBjYWxsZWQgaXQsIHNvIGEgY2FjaGUgZW50cnkgbGl2ZWQgZm9yIHRoZSBsaWZldGltZSBvZiB0aGUgcGFnZS5cbiAgICB0aGlzLmNvbmZpZ1NvdXJjZT8uY2xlYXJDYWNoZShjb25maWcuZW50aXR5KTtcblxuICAgIHRoaXMuc2F2ZS5lbWl0KGNvbmZpZyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IGpzb24oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy5zdG9yZS5leHBvcnRDb25maWcoKSwgbnVsbCwgMik7XG4gIH1cblxuICBwcm90ZWN0ZWQgY29weUpzb24oKTogdm9pZCB7XG4gICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT09ICd1bmRlZmluZWQnICYmIG5hdmlnYXRvci5jbGlwYm9hcmQpIHtcbiAgICAgIHZvaWQgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQodGhpcy5qc29uKTtcbiAgICB9XG4gIH1cblxuICAvLyDilIDilIDilIAgUkJBQyBzZXR0aW5ncyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcm90ZWN0ZWQgcm9sZXNGb3IoYWN0aW9uOiBrZXlvZiBFbnRpdHlQZXJtaXNzaW9ucyk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICAvLyBSZXR1cm4gdGhlIHN0b3JlZCBhcnJheSAoc3RhYmxlIHJlZiBiZXR3ZWVuIG11dGF0aW9ucykgb3IgYSBzaGFyZWQgZW1wdHkg4oCUIE5PVCBhIGZyZXNoIFtdLFxuICAgIC8vIHdoaWNoIHdvdWxkIG1ha2UgdGhlIGJvdW5kIG1hdC1zZWxlY3QgcmUtZXZhbHVhdGUgZXZlcnkgQ0QgYW5kIGxvb3AgZm9yZXZlci5cbiAgICByZXR1cm4gdGhpcy5zdG9yZS5jb25maWcoKS5wZXJtaXNzaW9ucz8uW2FjdGlvbl0gPz8gRU1QVFlfUk9MRVM7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0Um9sZXMoYWN0aW9uOiBrZXlvZiBFbnRpdHlQZXJtaXNzaW9ucywgcm9sZXM6IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdGhpcy5zdG9yZS5zZXRQZXJtaXNzaW9uKGFjdGlvbiwgcm9sZXMpO1xuICB9XG5cbiAgLyoqIFBhcnNlIGEgY29tbWEtc2VwYXJhdGVkIHJvbGUgc3RyaW5nIGludG8gYSB0cmltbWVkLCBkZS1kdXBsaWNhdGVkIGFycmF5LiAqL1xuICBwcm90ZWN0ZWQgc2V0Um9sZXNGcm9tVGV4dChhY3Rpb246IGtleW9mIEVudGl0eVBlcm1pc3Npb25zLCB0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCByb2xlcyA9IEFycmF5LmZyb20oXG4gICAgICBuZXcgU2V0KFxuICAgICAgICB0ZXh0XG4gICAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgICAubWFwKHIgPT4gci50cmltKCkpXG4gICAgICAgICAgLmZpbHRlcihCb29sZWFuKSxcbiAgICAgICksXG4gICAgKTtcbiAgICB0aGlzLnN0b3JlLnNldFBlcm1pc3Npb24oYWN0aW9uLCByb2xlcyk7XG4gIH1cbn1cbiIsIjxtYXQtdG9vbGJhciBjbGFzcz1cImRlYi10b29sYmFyXCIgY29sb3I9XCJwcmltYXJ5XCI+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=