ngx-dynamic-entity 0.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -0
- package/esm2022/lib/field-types/array-field.component.mjs +160 -0
- package/esm2022/lib/field-types/boolean-field.component.mjs +100 -0
- package/esm2022/lib/field-types/checkbox-field.component.mjs +25 -17
- package/esm2022/lib/field-types/currency-field.component.mjs +101 -0
- package/esm2022/lib/field-types/date-field.component.mjs +21 -13
- package/esm2022/lib/field-types/dropdown-field.component.mjs +120 -29
- package/esm2022/lib/field-types/email-field.component.mjs +101 -0
- package/esm2022/lib/field-types/entity-ref-field.component.mjs +96 -32
- package/esm2022/lib/field-types/file-field.component.mjs +156 -0
- package/esm2022/lib/field-types/group-field.component.mjs +89 -0
- package/esm2022/lib/field-types/image-field.component.mjs +168 -0
- package/esm2022/lib/field-types/month-year-field.component.mjs +151 -0
- package/esm2022/lib/field-types/multi-select-field.component.mjs +79 -25
- package/esm2022/lib/field-types/number-field.component.mjs +60 -17
- package/esm2022/lib/field-types/password-field.component.mjs +109 -0
- package/esm2022/lib/field-types/radio-field.component.mjs +152 -0
- package/esm2022/lib/field-types/text-field.component.mjs +58 -18
- package/esm2022/lib/field-types/textarea-field.component.mjs +26 -15
- package/esm2022/lib/form/dynamic-field/dynamic-field.component.mjs +44 -26
- package/esm2022/lib/form/dynamic-form.component.mjs +676 -69
- package/esm2022/lib/form/dynamic-record-form.component.mjs +494 -0
- package/esm2022/lib/providers/provide-field-types.mjs +72 -0
- package/esm2022/lib/providers/provide-ngx-dynamic-entity.mjs +4 -5
- package/esm2022/lib/services/cascade-data.service.mjs +129 -0
- package/esm2022/lib/services/config-source.service.mjs +67 -0
- package/esm2022/lib/services/entity-ref-cache.mjs +20 -0
- package/esm2022/lib/services/entity-ref-registry.service.mjs +3 -3
- package/esm2022/lib/services/entity-ref-selection.service.mjs +27 -0
- package/esm2022/lib/services/entity-reference.service.mjs +168 -0
- package/esm2022/lib/services/field-registry.service.mjs +35 -30
- package/esm2022/lib/services/file-upload.service.mjs +89 -0
- package/esm2022/lib/services/lookup-registry.service.mjs +246 -0
- package/esm2022/lib/services/rbac.service.mjs +5 -11
- package/esm2022/lib/services/rules-evaluation.service.mjs +27 -0
- package/esm2022/lib/services/validator-registry.service.mjs +35 -7
- package/esm2022/lib/tokens/injection-tokens.mjs +104 -7
- package/esm2022/public-api.mjs +31 -6
- package/fesm2022/ngx-dynamic-entity.mjs +4094 -759
- package/fesm2022/ngx-dynamic-entity.mjs.map +1 -1
- package/lib/field-types/array-field.component.d.ts +22 -0
- package/lib/field-types/boolean-field.component.d.ts +18 -0
- package/lib/field-types/checkbox-field.component.d.ts +3 -2
- package/lib/field-types/currency-field.component.d.ts +17 -0
- package/lib/field-types/date-field.component.d.ts +3 -2
- package/lib/field-types/dropdown-field.component.d.ts +24 -4
- package/lib/field-types/email-field.component.d.ts +15 -0
- package/lib/field-types/entity-ref-field.component.d.ts +24 -11
- package/lib/field-types/file-field.component.d.ts +25 -0
- package/lib/field-types/group-field.component.d.ts +17 -0
- package/lib/field-types/image-field.component.d.ts +30 -0
- package/lib/field-types/month-year-field.component.d.ts +28 -0
- package/lib/field-types/multi-select-field.component.d.ts +18 -4
- package/lib/field-types/number-field.component.d.ts +5 -2
- package/lib/field-types/password-field.component.d.ts +17 -0
- package/lib/field-types/radio-field.component.d.ts +33 -0
- package/lib/field-types/text-field.component.d.ts +5 -3
- package/lib/field-types/textarea-field.component.d.ts +4 -2
- package/lib/form/dynamic-field/dynamic-field.component.d.ts +20 -7
- package/lib/form/dynamic-form.component.d.ts +203 -24
- package/lib/form/dynamic-record-form.component.d.ts +180 -0
- package/lib/providers/provide-field-types.d.ts +24 -0
- package/lib/providers/provide-ngx-dynamic-entity.d.ts +19 -8
- package/lib/services/cascade-data.service.d.ts +45 -0
- package/lib/services/config-source.service.d.ts +14 -0
- package/lib/services/entity-ref-cache.d.ts +27 -0
- package/lib/services/entity-ref-registry.service.d.ts +4 -3
- package/lib/services/entity-ref-selection.service.d.ts +24 -0
- package/lib/services/entity-reference.service.d.ts +49 -0
- package/lib/services/field-registry.service.d.ts +17 -7
- package/lib/services/file-upload.service.d.ts +27 -0
- package/lib/services/lookup-registry.service.d.ts +94 -0
- package/lib/services/rbac.service.d.ts +4 -9
- package/lib/services/rules-evaluation.service.d.ts +17 -0
- package/lib/services/validator-registry.service.d.ts +5 -4
- package/lib/tokens/injection-tokens.d.ts +113 -8
- package/package.json +18 -8
- package/public-api.d.ts +21 -4
- package/esm2022/lib/services/config.service.mjs +0 -58
- package/esm2022/lib/services/version.service.mjs +0 -40
- package/esm2022/lib/table/dynamic-table.component.mjs +0 -160
- package/lib/services/config.service.d.ts +0 -25
- package/lib/services/version.service.d.ts +0 -26
- package/lib/table/dynamic-table.component.d.ts +0 -56
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter, signal, computed, inject } from '@angular/core';
|
|
2
|
-
import { RbacService } from '../services/rbac.service';
|
|
3
|
-
import { VersionService } from '../services/version.service';
|
|
4
|
-
import * as i0 from "@angular/core";
|
|
5
|
-
/**
|
|
6
|
-
* DynamicTableComponent — renders entity records as a searchable, sortable, paginated table.
|
|
7
|
-
* Columns determined by FieldConfig.tableColumn === true.
|
|
8
|
-
* Cell masking applied via RbacService (defense-in-depth).
|
|
9
|
-
* Pagination, sort, and search emit events — parent controls data fetching (smart/dumb pattern).
|
|
10
|
-
*/
|
|
11
|
-
export class DynamicTableComponent {
|
|
12
|
-
// ─── Inputs ───────────────────────────────────────────────────────────────
|
|
13
|
-
config;
|
|
14
|
-
data = [];
|
|
15
|
-
userRoles = [];
|
|
16
|
-
language = 'en';
|
|
17
|
-
loading = false;
|
|
18
|
-
error = null;
|
|
19
|
-
totalRecords = 0;
|
|
20
|
-
pageSize = 20;
|
|
21
|
-
currentPage = 1;
|
|
22
|
-
// ─── Outputs ──────────────────────────────────────────────────────────────
|
|
23
|
-
rowClick = new EventEmitter();
|
|
24
|
-
rowEdit = new EventEmitter();
|
|
25
|
-
rowDelete = new EventEmitter();
|
|
26
|
-
pageChange = new EventEmitter();
|
|
27
|
-
pageSizeChange = new EventEmitter();
|
|
28
|
-
sortChange = new EventEmitter();
|
|
29
|
-
searchChange = new EventEmitter();
|
|
30
|
-
// ─── Services ─────────────────────────────────────────────────────────────
|
|
31
|
-
rbacService = inject(RbacService);
|
|
32
|
-
versionService = inject(VersionService);
|
|
33
|
-
// ─── Signals ──────────────────────────────────────────────────────────────
|
|
34
|
-
sortField = signal('');
|
|
35
|
-
sortDir = signal('desc');
|
|
36
|
-
searchTerm = signal('');
|
|
37
|
-
// ─── Computed ─────────────────────────────────────────────────────────────
|
|
38
|
-
tableColumns = computed(() => (this.config?.fields || []).filter(f => f.tableColumn === true));
|
|
39
|
-
get permissions() {
|
|
40
|
-
return this.rbacService.getPermissions(this.config, this.userRoles);
|
|
41
|
-
}
|
|
42
|
-
get totalPages() {
|
|
43
|
-
return Math.ceil(this.totalRecords / this.pageSize) || 0;
|
|
44
|
-
}
|
|
45
|
-
ngOnChanges(_changes) {
|
|
46
|
-
// Pre-resolve masking per column once (ONEHERMES hardening: pre-resolved at extract time)
|
|
47
|
-
this._resolveColumnMasks();
|
|
48
|
-
}
|
|
49
|
-
columnMaskCache = new Map();
|
|
50
|
-
_resolveColumnMasks() {
|
|
51
|
-
if (!this.config)
|
|
52
|
-
return;
|
|
53
|
-
this.columnMaskCache.clear();
|
|
54
|
-
for (const field of this.tableColumns()) {
|
|
55
|
-
const tab = (this.config.tabs || []).find(t => t.id === field.tab);
|
|
56
|
-
const masked = this.rbacService.shouldMaskField(field, tab, this.config, this.userRoles);
|
|
57
|
-
this.columnMaskCache.set(field.id, masked);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
61
|
-
isCellMasked(fieldId) {
|
|
62
|
-
return this.columnMaskCache.get(fieldId) ?? false;
|
|
63
|
-
}
|
|
64
|
-
getCellValue(record, fieldId) {
|
|
65
|
-
if (this.isCellMasked(fieldId))
|
|
66
|
-
return 'XXXXXXXXX';
|
|
67
|
-
const value = record[fieldId];
|
|
68
|
-
if (value === null || value === undefined)
|
|
69
|
-
return '—';
|
|
70
|
-
if (typeof value === 'boolean')
|
|
71
|
-
return value ? 'Yes' : 'No';
|
|
72
|
-
if (value instanceof Date || (typeof value === 'string' && value.match(/^\d{4}-\d{2}-\d{2}/))) {
|
|
73
|
-
try {
|
|
74
|
-
return new Date(value).toLocaleDateString();
|
|
75
|
-
}
|
|
76
|
-
catch {
|
|
77
|
-
return String(value);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
if (Array.isArray(value))
|
|
81
|
-
return value.join(', ');
|
|
82
|
-
return String(value);
|
|
83
|
-
}
|
|
84
|
-
needsMigration(record) {
|
|
85
|
-
return this.versionService.needsMigration(record, this.config);
|
|
86
|
-
}
|
|
87
|
-
getColumnLabel(fieldId) {
|
|
88
|
-
const field = (this.config?.fields || []).find(f => f.id === fieldId);
|
|
89
|
-
return field?.label?.[this.language] || field?.label?.['en'] || fieldId;
|
|
90
|
-
}
|
|
91
|
-
// ─── Sort / Search / Pagination ───────────────────────────────────────────
|
|
92
|
-
onSort(fieldId) {
|
|
93
|
-
if (this.sortField() === fieldId) {
|
|
94
|
-
const next = this.sortDir() === 'asc' ? 'desc' : 'asc';
|
|
95
|
-
this.sortDir.set(next);
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
this.sortField.set(fieldId);
|
|
99
|
-
this.sortDir.set('asc');
|
|
100
|
-
}
|
|
101
|
-
this.sortChange.emit({ field: this.sortField(), dir: this.sortDir() });
|
|
102
|
-
}
|
|
103
|
-
onSearch(event) {
|
|
104
|
-
const value = event.target.value;
|
|
105
|
-
this.searchTerm.set(value);
|
|
106
|
-
this.searchChange.emit(value);
|
|
107
|
-
}
|
|
108
|
-
onPageChange(page) {
|
|
109
|
-
if (page < 1 || page > this.totalPages)
|
|
110
|
-
return;
|
|
111
|
-
this.pageChange.emit(page);
|
|
112
|
-
}
|
|
113
|
-
onEdit(event, record) {
|
|
114
|
-
event.stopPropagation();
|
|
115
|
-
this.rowEdit.emit(record);
|
|
116
|
-
}
|
|
117
|
-
onDelete(event, record) {
|
|
118
|
-
event.stopPropagation();
|
|
119
|
-
this.rowDelete.emit(record);
|
|
120
|
-
}
|
|
121
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DynamicTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
122
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: DynamicTableComponent, isStandalone: true, selector: "ngx-dynamic-table", inputs: { config: "config", data: "data", userRoles: "userRoles", language: "language", loading: "loading", error: "error", totalRecords: "totalRecords", pageSize: "pageSize", currentPage: "currentPage" }, outputs: { rowClick: "rowClick", rowEdit: "rowEdit", rowDelete: "rowDelete", pageChange: "pageChange", pageSizeChange: "pageSizeChange", sortChange: "sortChange", searchChange: "searchChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"ngx-table\">\n\n <!-- Search bar -->\n <div class=\"ngx-table__toolbar\">\n <input\n class=\"ngx-table__search\"\n type=\"search\"\n placeholder=\"Search...\"\n [value]=\"searchTerm()\"\n (input)=\"onSearch($event)\"\n aria-label=\"Search records\"\n />\n </div>\n\n <!-- Error -->\n @if (error) {\n <div class=\"ngx-table__error\" role=\"alert\">{{ error }}</div>\n }\n\n <!-- Table -->\n <table class=\"ngx-table__table\">\n <thead>\n <tr>\n @for (col of tableColumns(); track col.id) {\n <th\n class=\"ngx-table__th\"\n [style.width]=\"col.columnWidth || 'auto'\"\n (click)=\"onSort(col.id)\"\n [attr.aria-sort]=\"sortField() === col.id ? sortDir() : 'none'\"\n role=\"columnheader\"\n >\n {{ getColumnLabel(col.id) }}\n @if (sortField() === col.id) {\n <span class=\"ngx-table__sort-icon\">{{ sortDir() === 'asc' ? '\u2191' : '\u2193' }}</span>\n }\n </th>\n }\n <!-- Actions column -->\n @if (permissions.canEdit || permissions.canDelete) {\n <th class=\"ngx-table__th ngx-table__th--actions\">Actions</th>\n }\n </tr>\n </thead>\n <tbody>\n @if (loading) {\n <tr>\n <td [attr.colspan]=\"tableColumns().length + 1\" class=\"ngx-table__loading\">Loading\u2026</td>\n </tr>\n } @else if (!data || !data.length) {\n <tr>\n <td [attr.colspan]=\"tableColumns().length + 1\" class=\"ngx-table__empty\">No records found</td>\n </tr>\n } @else {\n @for (record of data; track record['_id']) {\n <tr class=\"ngx-table__row\" (click)=\"rowClick.emit(record)\">\n @for (col of tableColumns(); track col.id) {\n <td\n class=\"ngx-table__td\"\n [class.ngx-table__td--masked]=\"isCellMasked(col.id)\"\n >\n {{ getCellValue(record, col.id) }}\n <!-- Migration badge \u2014 shows when record is stale -->\n @if (tableColumns().length > 0 && col.id === tableColumns()[0].id && needsMigration(record)) {\n <span class=\"ngx-table__migration-badge\" title=\"Needs migration\">\u26A0</span>\n }\n </td>\n }\n <!-- Action buttons \u2014 gated by RBAC permissions -->\n @if (permissions.canEdit || permissions.canDelete) {\n <td class=\"ngx-table__td ngx-table__actions\">\n @if (permissions.canEdit) {\n <button\n type=\"button\"\n class=\"ngx-table__action ngx-table__action--edit\"\n (click)=\"onEdit($event, record)\"\n title=\"Edit\"\n >\u270F</button>\n }\n @if (permissions.canDelete) {\n <button\n type=\"button\"\n class=\"ngx-table__action ngx-table__action--delete\"\n (click)=\"onDelete($event, record)\"\n title=\"Delete\"\n >\uD83D\uDDD1</button>\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n\n <!-- Pagination -->\n @if (totalPages > 1) {\n <div class=\"ngx-table__pagination\">\n <button\n type=\"button\"\n class=\"ngx-table__page-btn\"\n [disabled]=\"currentPage <= 1\"\n (click)=\"onPageChange(currentPage - 1)\"\n aria-label=\"Previous page\"\n >\u2190</button>\n\n <span class=\"ngx-table__page-info\">\n Page {{ currentPage }} of {{ totalPages }} ({{ totalRecords }} records)\n </span>\n\n <button\n type=\"button\"\n class=\"ngx-table__page-btn\"\n [disabled]=\"currentPage >= totalPages\"\n (click)=\"onPageChange(currentPage + 1)\"\n aria-label=\"Next page\"\n >\u2192</button>\n </div>\n }\n\n</div>\n" });
|
|
123
|
-
}
|
|
124
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DynamicTableComponent, decorators: [{
|
|
125
|
-
type: Component,
|
|
126
|
-
args: [{ selector: 'ngx-dynamic-table', standalone: true, imports: [], template: "<div class=\"ngx-table\">\n\n <!-- Search bar -->\n <div class=\"ngx-table__toolbar\">\n <input\n class=\"ngx-table__search\"\n type=\"search\"\n placeholder=\"Search...\"\n [value]=\"searchTerm()\"\n (input)=\"onSearch($event)\"\n aria-label=\"Search records\"\n />\n </div>\n\n <!-- Error -->\n @if (error) {\n <div class=\"ngx-table__error\" role=\"alert\">{{ error }}</div>\n }\n\n <!-- Table -->\n <table class=\"ngx-table__table\">\n <thead>\n <tr>\n @for (col of tableColumns(); track col.id) {\n <th\n class=\"ngx-table__th\"\n [style.width]=\"col.columnWidth || 'auto'\"\n (click)=\"onSort(col.id)\"\n [attr.aria-sort]=\"sortField() === col.id ? sortDir() : 'none'\"\n role=\"columnheader\"\n >\n {{ getColumnLabel(col.id) }}\n @if (sortField() === col.id) {\n <span class=\"ngx-table__sort-icon\">{{ sortDir() === 'asc' ? '\u2191' : '\u2193' }}</span>\n }\n </th>\n }\n <!-- Actions column -->\n @if (permissions.canEdit || permissions.canDelete) {\n <th class=\"ngx-table__th ngx-table__th--actions\">Actions</th>\n }\n </tr>\n </thead>\n <tbody>\n @if (loading) {\n <tr>\n <td [attr.colspan]=\"tableColumns().length + 1\" class=\"ngx-table__loading\">Loading\u2026</td>\n </tr>\n } @else if (!data || !data.length) {\n <tr>\n <td [attr.colspan]=\"tableColumns().length + 1\" class=\"ngx-table__empty\">No records found</td>\n </tr>\n } @else {\n @for (record of data; track record['_id']) {\n <tr class=\"ngx-table__row\" (click)=\"rowClick.emit(record)\">\n @for (col of tableColumns(); track col.id) {\n <td\n class=\"ngx-table__td\"\n [class.ngx-table__td--masked]=\"isCellMasked(col.id)\"\n >\n {{ getCellValue(record, col.id) }}\n <!-- Migration badge \u2014 shows when record is stale -->\n @if (tableColumns().length > 0 && col.id === tableColumns()[0].id && needsMigration(record)) {\n <span class=\"ngx-table__migration-badge\" title=\"Needs migration\">\u26A0</span>\n }\n </td>\n }\n <!-- Action buttons \u2014 gated by RBAC permissions -->\n @if (permissions.canEdit || permissions.canDelete) {\n <td class=\"ngx-table__td ngx-table__actions\">\n @if (permissions.canEdit) {\n <button\n type=\"button\"\n class=\"ngx-table__action ngx-table__action--edit\"\n (click)=\"onEdit($event, record)\"\n title=\"Edit\"\n >\u270F</button>\n }\n @if (permissions.canDelete) {\n <button\n type=\"button\"\n class=\"ngx-table__action ngx-table__action--delete\"\n (click)=\"onDelete($event, record)\"\n title=\"Delete\"\n >\uD83D\uDDD1</button>\n }\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n\n <!-- Pagination -->\n @if (totalPages > 1) {\n <div class=\"ngx-table__pagination\">\n <button\n type=\"button\"\n class=\"ngx-table__page-btn\"\n [disabled]=\"currentPage <= 1\"\n (click)=\"onPageChange(currentPage - 1)\"\n aria-label=\"Previous page\"\n >\u2190</button>\n\n <span class=\"ngx-table__page-info\">\n Page {{ currentPage }} of {{ totalPages }} ({{ totalRecords }} records)\n </span>\n\n <button\n type=\"button\"\n class=\"ngx-table__page-btn\"\n [disabled]=\"currentPage >= totalPages\"\n (click)=\"onPageChange(currentPage + 1)\"\n aria-label=\"Next page\"\n >\u2192</button>\n </div>\n }\n\n</div>\n" }]
|
|
127
|
-
}], propDecorators: { config: [{
|
|
128
|
-
type: Input
|
|
129
|
-
}], data: [{
|
|
130
|
-
type: Input
|
|
131
|
-
}], userRoles: [{
|
|
132
|
-
type: Input
|
|
133
|
-
}], language: [{
|
|
134
|
-
type: Input
|
|
135
|
-
}], loading: [{
|
|
136
|
-
type: Input
|
|
137
|
-
}], error: [{
|
|
138
|
-
type: Input
|
|
139
|
-
}], totalRecords: [{
|
|
140
|
-
type: Input
|
|
141
|
-
}], pageSize: [{
|
|
142
|
-
type: Input
|
|
143
|
-
}], currentPage: [{
|
|
144
|
-
type: Input
|
|
145
|
-
}], rowClick: [{
|
|
146
|
-
type: Output
|
|
147
|
-
}], rowEdit: [{
|
|
148
|
-
type: Output
|
|
149
|
-
}], rowDelete: [{
|
|
150
|
-
type: Output
|
|
151
|
-
}], pageChange: [{
|
|
152
|
-
type: Output
|
|
153
|
-
}], pageSizeChange: [{
|
|
154
|
-
type: Output
|
|
155
|
-
}], sortChange: [{
|
|
156
|
-
type: Output
|
|
157
|
-
}], searchChange: [{
|
|
158
|
-
type: Output
|
|
159
|
-
}] } });
|
|
160
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy10YWJsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3RhYmxlL2R5bmFtaWMtdGFibGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vc3JjL2xpYi90YWJsZS9keW5hbWljLXRhYmxlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQTRCLE1BQU0sZUFBZSxDQUFDO0FBRTNILE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7O0FBRTdEOzs7OztHQUtHO0FBT0gsTUFBTSxPQUFPLHFCQUFxQjtJQUNoQyw2RUFBNkU7SUFDcEUsTUFBTSxDQUFnQjtJQUN0QixJQUFJLEdBQXNCLEVBQUUsQ0FBQztJQUM3QixTQUFTLEdBQWEsRUFBRSxDQUFDO0lBQ3pCLFFBQVEsR0FBVyxJQUFJLENBQUM7SUFDeEIsT0FBTyxHQUFZLEtBQUssQ0FBQztJQUN6QixLQUFLLEdBQWtCLElBQUksQ0FBQztJQUM1QixZQUFZLEdBQVcsQ0FBQyxDQUFDO0lBQ3pCLFFBQVEsR0FBVyxFQUFFLENBQUM7SUFDdEIsV0FBVyxHQUFXLENBQUMsQ0FBQztJQUVqQyw2RUFBNkU7SUFDbkUsUUFBUSxHQUFHLElBQUksWUFBWSxFQUFtQixDQUFDO0lBQy9DLE9BQU8sR0FBRyxJQUFJLFlBQVksRUFBbUIsQ0FBQztJQUM5QyxTQUFTLEdBQUcsSUFBSSxZQUFZLEVBQW1CLENBQUM7SUFDaEQsVUFBVSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7SUFDeEMsY0FBYyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7SUFDNUMsVUFBVSxHQUFHLElBQUksWUFBWSxF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SEE7OzRGRHZHYSxxQkFBcUI7a0JBTmpDLFNBQVM7K0JBQ0UsbUJBQW1CLGNBQ2pCLElBQUksV0FDUCxFQUFFOzhCQUtGLE1BQU07c0JBQWQsS0FBSztnQkFDRyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxLQUFLO3NCQUFiLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBR0ksUUFBUTtzQkFBakIsTUFBTTtnQkFDRyxPQUFPO3NCQUFoQixNQUFNO2dCQUNHLFNBQVM7c0JBQWxCLE1BQU07Z0JBQ0csVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyxjQUFjO3NCQUF2QixNQUFNO2dCQUNHLFVBQVU7c0JBQW5CLE1BQU07Z0JBQ0csWUFBWTtzQkFBckIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBzaWduYWwsIGNvbXB1dGVkLCBpbmplY3QsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHR5cGUgeyBFbnRpdHlDb25maWcsIFZlcnNpb25lZFJlY29yZCB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IFJiYWNTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvcmJhYy5zZXJ2aWNlJztcbmltcG9ydCB7IFZlcnNpb25TZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvdmVyc2lvbi5zZXJ2aWNlJztcblxuLyoqXG4gKiBEeW5hbWljVGFibGVDb21wb25lbnQg4oCUIHJlbmRlcnMgZW50aXR5IHJlY29yZHMgYXMgYSBzZWFyY2hhYmxlLCBzb3J0YWJsZSwgcGFnaW5hdGVkIHRhYmxlLlxuICogQ29sdW1ucyBkZXRlcm1pbmVkIGJ5IEZpZWxkQ29uZmlnLnRhYmxlQ29sdW1uID09PSB0cnVlLlxuICogQ2VsbCBtYXNraW5nIGFwcGxpZWQgdmlhIFJiYWNTZXJ2aWNlIChkZWZlbnNlLWluLWRlcHRoKS5cbiAqIFBhZ2luYXRpb24sIHNvcnQsIGFuZCBzZWFyY2ggZW1pdCBldmVudHMg4oCUIHBhcmVudCBjb250cm9scyBkYXRhIGZldGNoaW5nIChzbWFydC9kdW1iIHBhdHRlcm4pLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZHluYW1pYy10YWJsZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtdLFxuICB0ZW1wbGF0ZVVybDogJy4vZHluYW1pYy10YWJsZS5jb21wb25lbnQuaHRtbCcsXG59KVxuZXhwb3J0IGNsYXNzIER5bmFtaWNUYWJsZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIC8vIOKUgOKUgOKUgCBJbnB1dHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG4gIEBJbnB1dCgpIGNvbmZpZyE6IEVudGl0eUNvbmZpZztcbiAgQElucHV0KCkgZGF0YTogVmVyc2lvbmVkUmVjb3JkW10gPSBbXTtcbiAgQElucHV0KCkgdXNlclJvbGVzOiBzdHJpbmdbXSA9IFtdO1xuICBASW5wdXQoKSBsYW5ndWFnZTogc3RyaW5nID0gJ2VuJztcbiAgQElucHV0KCkgbG9hZGluZzogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBlcnJvcjogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIEBJbnB1dCgpIHRvdGFsUmVjb3JkczogbnVtYmVyID0gMDtcbiAgQElucHV0KCkgcGFnZVNpemU6IG51bWJlciA9IDIwO1xuICBASW5wdXQoKSBjdXJyZW50UGFnZTogbnVtYmVyID0gMTtcblxuICAvLyDilIDilIDilIAgT3V0cHV0cyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgQE91dHB1dCgpIHJvd0NsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxWZXJzaW9uZWRSZWNvcmQ+KCk7XG4gIEBPdXRwdXQoKSByb3dFZGl0ID0gbmV3IEV2ZW50RW1pdHRlcjxWZXJzaW9uZWRSZWNvcmQ+KCk7XG4gIEBPdXRwdXQoKSByb3dEZWxldGUgPSBuZXcgRXZlbnRFbWl0dGVyPFZlcnNpb25lZFJlY29yZD4oKTtcbiAgQE91dHB1dCgpIHBhZ2VDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPG51bWJlcj4oKTtcbiAgQE91dHB1dCgpIHBhZ2VTaXplQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG4gIEBPdXRwdXQoKSBzb3J0Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjx7IGZpZWxkOiBzdHJpbmc7IGRpcjogJ2FzYycgfCAnZGVzYycgfT4oKTtcbiAgQE91dHB1dCgpIHNlYXJjaENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIC8vIOKUgOKUgOKUgCBTZXJ2aWNlcyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcbiAgcHJpdmF0ZSByZWFkb25seSByYmFjU2VydmljZSA9IGluamVjdChSYmFjU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgdmVyc2lvblNlcnZpY2UgPSBpbmplY3QoVmVyc2lvblNlcnZpY2UpO1xuXG4gIC8vIOKUgOKUgOKUgCBTaWduYWxzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICByZWFkb25seSBzb3J0RmllbGQgPSBzaWduYWw8c3RyaW5nPignJyk7XG4gIHJlYWRvbmx5IHNvcnREaXIgPSBzaWduYWw8J2FzYycgfCAnZGVzYyc+KCdkZXNjJyk7XG4gIHJlYWRvbmx5IHNlYXJjaFRlcm0gPSBzaWduYWw8c3RyaW5nPignJyk7XG5cbiAgLy8g4pSA4pSA4pSAIENvbXB1dGVkIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICByZWFkb25seSB0YWJsZUNvbHVtbnMgPSBjb21wdXRlZCgoKSA9PiBcbiAgICAodGhpcy5jb25maWc/LmZpZWxkcyB8fCBbXSkuZmlsdGVyKGYgPT4gZi50YWJsZUNvbHVtbiA9PT0gdHJ1ZSlcbiAgKTtcblxuICBnZXQgcGVybWlzc2lvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMucmJhY1NlcnZpY2UuZ2V0UGVybWlzc2lvbnModGhpcy5jb25maWcsIHRoaXMudXNlclJvbGVzKTtcbiAgfVxuXG4gIGdldCB0b3RhbFBhZ2VzKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIE1hdGguY2VpbCh0aGlzLnRvdGFsUmVjb3JkcyAvIHRoaXMucGFnZVNpemUpIHx8IDA7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhfY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIC8vIFByZS1yZXNvbHZlIG1hc2tpbmcgcGVyIGNvbHVtbiBvbmNlIChPTkVIRVJNRVMgaGFyZGVuaW5nOiBwcmUtcmVzb2x2ZWQgYXQgZXh0cmFjdCB0aW1lKVxuICAgIHRoaXMuX3Jlc29sdmVDb2x1bW5NYXNrcygpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb2x1bW5NYXNrQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgYm9vbGVhbj4oKTtcblxuICBwcml2YXRlIF9yZXNvbHZlQ29sdW1uTWFza3MoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZykgcmV0dXJuO1xuICAgIHRoaXMuY29sdW1uTWFza0NhY2hlLmNsZWFyKCk7XG4gICAgZm9yIChjb25zdCBmaWVsZCBvZiB0aGlzLnRhYmxlQ29sdW1ucygpKSB7XG4gICAgICBjb25zdCB0YWIgPSAodGhpcy5jb25maWcudGFicyB8fCBbXSkuZmluZCh0ID0+IHQuaWQgPT09IGZpZWxkLnRhYik7XG4gICAgICBjb25zdCBtYXNrZWQgPSB0aGlzLnJiYWNTZXJ2aWNlLnNob3VsZE1hc2tGaWVsZChmaWVsZCwgdGFiLCB0aGlzLmNvbmZpZywgdGhpcy51c2VyUm9sZXMpO1xuICAgICAgdGhpcy5jb2x1bW5NYXNrQ2FjaGUuc2V0KGZpZWxkLmlkLCBtYXNrZWQpO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgOKUgCBIZWxwZXJzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIGlzQ2VsbE1hc2tlZChmaWVsZElkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5jb2x1bW5NYXNrQ2FjaGUuZ2V0KGZpZWxkSWQpID8/IGZhbHNlO1xuICB9XG5cbiAgZ2V0Q2VsbFZhbHVlKHJlY29yZDogVmVyc2lvbmVkUmVjb3JkLCBmaWVsZElkOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmlzQ2VsbE1hc2tlZChmaWVsZElkKSkgcmV0dXJuICdYWFhYWFhYWFgnO1xuICAgIGNvbnN0IHZhbHVlID0gcmVjb3JkW2ZpZWxkSWRdO1xuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gJ+KAlCc7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSByZXR1cm4gdmFsdWUgPyAnWWVzJyA6ICdObyc7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSB8fCAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS5tYXRjaCgvXlxcZHs0fS1cXGR7Mn0tXFxkezJ9LykpKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gbmV3IERhdGUodmFsdWUpLnRvTG9jYWxlRGF0ZVN0cmluZygpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHJldHVybiB2YWx1ZS5qb2luKCcsICcpO1xuICAgIHJldHVybiBTdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgbmVlZHNNaWdyYXRpb24ocmVjb3JkOiBWZXJzaW9uZWRSZWNvcmQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy52ZXJzaW9uU2VydmljZS5uZWVkc01pZ3JhdGlvbihyZWNvcmQsIHRoaXMuY29uZmlnKTtcbiAgfVxuXG4gIGdldENvbHVtbkxhYmVsKGZpZWxkSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgZmllbGQgPSAodGhpcy5jb25maWc/LmZpZWxkcyB8fCBbXSkuZmluZChmID0+IGYuaWQgPT09IGZpZWxkSWQpO1xuICAgIHJldHVybiBmaWVsZD8ubGFiZWw/Llt0aGlzLmxhbmd1YWdlXSB8fCBmaWVsZD8ubGFiZWw/LlsnZW4nXSB8fCBmaWVsZElkO1xuICB9XG5cbiAgLy8g4pSA4pSA4pSAIFNvcnQgLyBTZWFyY2ggLyBQYWdpbmF0aW9uIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIG9uU29ydChmaWVsZElkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zb3J0RmllbGQoKSA9PT0gZmllbGRJZCkge1xuICAgICAgY29uc3QgbmV4dCA9IHRoaXMuc29ydERpcigpID09PSAnYXNjJyA/ICdkZXNjJyA6ICdhc2MnO1xuICAgICAgdGhpcy5zb3J0RGlyLnNldChuZXh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zb3J0RmllbGQuc2V0KGZpZWxkSWQpO1xuICAgICAgdGhpcy5zb3J0RGlyLnNldCgnYXNjJyk7XG4gICAgfVxuICAgIHRoaXMuc29ydENoYW5nZS5lbWl0KHsgZmllbGQ6IHRoaXMuc29ydEZpZWxkKCksIGRpcjogdGhpcy5zb3J0RGlyKCkgfSk7XG4gIH1cblxuICBvblNlYXJjaChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCB2YWx1ZSA9IChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWU7XG4gICAgdGhpcy5zZWFyY2hUZXJtLnNldCh2YWx1ZSk7XG4gICAgdGhpcy5zZWFyY2hDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gIH1cblxuICBvblBhZ2VDaGFuZ2UocGFnZTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHBhZ2UgPCAxIHx8IHBhZ2UgPiB0aGlzLnRvdGFsUGFnZXMpIHJldHVybjtcbiAgICB0aGlzLnBhZ2VDaGFuZ2UuZW1pdChwYWdlKTtcbiAgfVxuXG4gIG9uRWRpdChldmVudDogRXZlbnQsIHJlY29yZDogVmVyc2lvbmVkUmVjb3JkKTogdm9pZCB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5yb3dFZGl0LmVtaXQocmVjb3JkKTtcbiAgfVxuXG4gIG9uRGVsZXRlKGV2ZW50OiBFdmVudCwgcmVjb3JkOiBWZXJzaW9uZWRSZWNvcmQpOiB2b2lkIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB0aGlzLnJvd0RlbGV0ZS5lbWl0KHJlY29yZCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJuZ3gtdGFibGVcIj5cblxuICA8IS0tIFNlYXJjaCBiYXIgLS0+XG4gIDxkaXYgY2xhc3M9XCJuZ3gtdGFibGVfX3Rvb2xiYXJcIj5cbiAgICA8aW5wdXRcbiAgICAgIGNsYXNzPVwibmd4LXRhYmxlX19zZWFyY2hcIlxuICAgICAgdHlwZT1cInNlYXJjaFwiXG4gICAgICBwbGFjZWhvbGRlcj1cIlNlYXJjaC4uLlwiXG4gICAgICBbdmFsdWVdPVwic2VhcmNoVGVybSgpXCJcbiAgICAgIChpbnB1dCk9XCJvblNlYXJjaCgkZXZlbnQpXCJcbiAgICAgIGFyaWEtbGFiZWw9XCJTZWFyY2ggcmVjb3Jkc1wiXG4gICAgLz5cbiAgPC9kaXY+XG5cbiAgPCEtLSBFcnJvciAtLT5cbiAgQGlmIChlcnJvcikge1xuICAgIDxkaXYgY2xhc3M9XCJuZ3gtdGFibGVfX2Vycm9yXCIgcm9sZT1cImFsZXJ0XCI+e3sgZXJyb3IgfX08L2Rpdj5cbiAgfVxuXG4gIDwhLS0gVGFibGUgLS0+XG4gIDx0YWJsZSBjbGFzcz1cIm5neC10YWJsZV9fdGFibGVcIj5cbiAgICA8dGhlYWQ+XG4gICAgICA8dHI+XG4gICAgICAgIEBmb3IgKGNvbCBvZiB0YWJsZUNvbHVtbnMoKTsgdHJhY2sgY29sLmlkKSB7XG4gICAgICAgICAgPHRoXG4gICAgICAgICAgICBjbGFzcz1cIm5neC10YWJsZV9fdGhcIlxuICAgICAgICAgICAgW3N0eWxlLndpZHRoXT1cImNvbC5jb2x1bW5XaWR0aCB8fCAnYXV0bydcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm9uU29ydChjb2wuaWQpXCJcbiAgICAgICAgICAgIFthdHRyLmFyaWEtc29ydF09XCJzb3J0RmllbGQoKSA9PT0gY29sLmlkID8gc29ydERpcigpIDogJ25vbmUnXCJcbiAgICAgICAgICAgIHJvbGU9XCJjb2x1bW5oZWFkZXJcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt7IGdldENvbHVtbkxhYmVsKGNvbC5pZCkgfX1cbiAgICAgICAgICAgIEBpZiAoc29ydEZpZWxkKCkgPT09IGNvbC5pZCkge1xuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC10YWJsZV9fc29ydC1pY29uXCI+e3sgc29ydERpcigpID09PSAnYXNjJyA/ICfihpEnIDogJ+KGkycgfX08L3NwYW4+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC90aD5cbiAgICAgICAgfVxuICAgICAgICA8IS0tIEFjdGlvbnMgY29sdW1uIC0tPlxuICAgICAgICBAaWYgKHBlcm1pc3Npb25zLmNhbkVkaXQgfHwgcGVybWlzc2lvbnMuY2FuRGVsZXRlKSB7XG4gICAgICAgICAgPHRoIGNsYXNzPVwibmd4LXRhYmxlX190aCBuZ3gtdGFibGVfX3RoLS1hY3Rpb25zXCI+QWN0aW9uczwvdGg+XG4gICAgICAgIH1cbiAgICAgIDwvdHI+XG4gICAgPC90aGVhZD5cbiAgICA8dGJvZHk+XG4gICAgICBAaWYgKGxvYWRpbmcpIHtcbiAgICAgICAgPHRyPlxuICAgICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cInRhYmxlQ29sdW1ucygpLmxlbmd0aCArIDFcIiBjbGFzcz1cIm5neC10YWJsZV9fbG9hZGluZ1wiPkxvYWRpbmfigKY8L3RkPlxuICAgICAgICA8L3RyPlxuICAgICAgfSBAZWxzZSBpZiAoIWRhdGEgfHwgIWRhdGEubGVuZ3RoKSB7XG4gICAgICAgIDx0cj5cbiAgICAgICAgICA8dGQgW2F0dHIuY29sc3Bhbl09XCJ0YWJsZUNvbHVtbnMoKS5sZW5ndGggKyAxXCIgY2xhc3M9XCJuZ3gtdGFibGVfX2VtcHR5XCI+Tm8gcmVjb3JkcyBmb3VuZDwvdGQ+XG4gICAgICAgIDwvdHI+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgQGZvciAocmVjb3JkIG9mIGRhdGE7IHRyYWNrIHJlY29yZFsnX2lkJ10pIHtcbiAgICAgICAgICA8dHIgY2xhc3M9XCJuZ3gtdGFibGVfX3Jvd1wiIChjbGljayk9XCJyb3dDbGljay5lbWl0KHJlY29yZClcIj5cbiAgICAgICAgICAgIEBmb3IgKGNvbCBvZiB0YWJsZUNvbHVtbnMoKTsgdHJhY2sgY29sLmlkKSB7XG4gICAgICAgICAgICAgIDx0ZFxuICAgICAgICAgICAgICAgIGNsYXNzPVwibmd4LXRhYmxlX190ZFwiXG4gICAgICAgICAgICAgICAgW2NsYXNzLm5neC10YWJsZV9fdGQtLW1hc2tlZF09XCJpc0NlbGxNYXNrZWQoY29sLmlkKVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7eyBnZXRDZWxsVmFsdWUocmVjb3JkLCBjb2wuaWQpIH19XG4gICAgICAgICAgICAgICAgPCEtLSBNaWdyYXRpb24gYmFkZ2Ug4oCUIHNob3dzIHdoZW4gcmVjb3JkIGlzIHN0YWxlIC0tPlxuICAgICAgICAgICAgICAgIEBpZiAodGFibGVDb2x1bW5zKCkubGVuZ3RoID4gMCAmJiBjb2wuaWQgPT09IHRhYmxlQ29sdW1ucygpWzBdLmlkICYmIG5lZWRzTWlncmF0aW9uKHJlY29yZCkpIHtcbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LXRhYmxlX19taWdyYXRpb24tYmFkZ2VcIiB0aXRsZT1cIk5lZWRzIG1pZ3JhdGlvblwiPuKaoDwvc3Bhbj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICA8IS0tIEFjdGlvbiBidXR0b25zIOKAlCBnYXRlZCBieSBSQkFDIHBlcm1pc3Npb25zIC0tPlxuICAgICAgICAgICAgQGlmIChwZXJtaXNzaW9ucy5jYW5FZGl0IHx8IHBlcm1pc3Npb25zLmNhbkRlbGV0ZSkge1xuICAgICAgICAgICAgICA8dGQgY2xhc3M9XCJuZ3gtdGFibGVfX3RkIG5neC10YWJsZV9fYWN0aW9uc1wiPlxuICAgICAgICAgICAgICAgIEBpZiAocGVybWlzc2lvbnMuY2FuRWRpdCkge1xuICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJuZ3gtdGFibGVfX2FjdGlvbiBuZ3gtdGFibGVfX2FjdGlvbi0tZWRpdFwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkVkaXQoJGV2ZW50LCByZWNvcmQpXCJcbiAgICAgICAgICAgICAgICAgICAgdGl0bGU9XCJFZGl0XCJcbiAgICAgICAgICAgICAgICAgID7inI88L2J1dHRvbj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgQGlmIChwZXJtaXNzaW9ucy5jYW5EZWxldGUpIHtcbiAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibmd4LXRhYmxlX19hY3Rpb24gbmd4LXRhYmxlX19hY3Rpb24tLWRlbGV0ZVwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkRlbGV0ZSgkZXZlbnQsIHJlY29yZClcIlxuICAgICAgICAgICAgICAgICAgICB0aXRsZT1cIkRlbGV0ZVwiXG4gICAgICAgICAgICAgICAgICA+8J+XkTwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC90ZD5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3RyPlxuICAgICAgICB9XG4gICAgICB9XG4gICAgPC90Ym9keT5cbiAgPC90YWJsZT5cblxuICA8IS0tIFBhZ2luYXRpb24gLS0+XG4gIEBpZiAodG90YWxQYWdlcyA+IDEpIHtcbiAgICA8ZGl2IGNsYXNzPVwibmd4LXRhYmxlX19wYWdpbmF0aW9uXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cIm5neC10YWJsZV9fcGFnZS1idG5cIlxuICAgICAgICBbZGlzYWJsZWRdPVwiY3VycmVudFBhZ2UgPD0gMVwiXG4gICAgICAgIChjbGljayk9XCJvblBhZ2VDaGFuZ2UoY3VycmVudFBhZ2UgLSAxKVwiXG4gICAgICAgIGFyaWEtbGFiZWw9XCJQcmV2aW91cyBwYWdlXCJcbiAgICAgID7ihpA8L2J1dHRvbj5cblxuICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtdGFibGVfX3BhZ2UtaW5mb1wiPlxuICAgICAgICBQYWdlIHt7IGN1cnJlbnRQYWdlIH19IG9mIHt7IHRvdGFsUGFnZXMgfX0gKHt7IHRvdGFsUmVjb3JkcyB9fSByZWNvcmRzKVxuICAgICAgPC9zcGFuPlxuXG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cIm5neC10YWJsZV9fcGFnZS1idG5cIlxuICAgICAgICBbZGlzYWJsZWRdPVwiY3VycmVudFBhZ2UgPj0gdG90YWxQYWdlc1wiXG4gICAgICAgIChjbGljayk9XCJvblBhZ2VDaGFuZ2UoY3VycmVudFBhZ2UgKyAxKVwiXG4gICAgICAgIGFyaWEtbGFiZWw9XCJOZXh0IHBhZ2VcIlxuICAgICAgPuKGkjwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICB9XG5cbjwvZGl2PlxuIl19
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'rxjs';
|
|
2
|
-
import type { EntityConfig } from '@dynamic-entity/core';
|
|
3
|
-
import * as i0 from "@angular/core";
|
|
4
|
-
/**
|
|
5
|
-
* ConfigService — fetches entity configs from the dynamic-entity-server API.
|
|
6
|
-
* Uses shareReplay(1) to cache per config key — avoids duplicate HTTP requests.
|
|
7
|
-
* Following ONEHERMES smart service pattern: Observable$ + shareReplay.
|
|
8
|
-
*/
|
|
9
|
-
export declare class ConfigService {
|
|
10
|
-
private readonly http;
|
|
11
|
-
private readonly apiUrl;
|
|
12
|
-
private readonly cache;
|
|
13
|
-
/** Get a config by entity key. Cached via shareReplay(1). */
|
|
14
|
-
getConfig(entity: string): Observable<EntityConfig>;
|
|
15
|
-
/** List all configs */
|
|
16
|
-
listConfigs(): Observable<EntityConfig[]>;
|
|
17
|
-
/** Create a new config */
|
|
18
|
-
saveConfig(config: EntityConfig): Observable<EntityConfig>;
|
|
19
|
-
/** Update an existing config */
|
|
20
|
-
updateConfig(entity: string, updates: Partial<EntityConfig>): Observable<EntityConfig>;
|
|
21
|
-
/** Invalidate cache for an entity (call after config update) */
|
|
22
|
-
invalidate(entity: string): void;
|
|
23
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<ConfigService, never>;
|
|
24
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<ConfigService>;
|
|
25
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type { VersionedRecord, EntityConfig } from '@dynamic-entity/core';
|
|
2
|
-
import * as i0 from "@angular/core";
|
|
3
|
-
/**
|
|
4
|
-
* VersionService — checks config version staleness and migration strategy.
|
|
5
|
-
* ADR-005: Frontend strategy is 'strict' | 'graceful' only. Never 'auto'.
|
|
6
|
-
*/
|
|
7
|
-
export declare class VersionService {
|
|
8
|
-
private readonly strategy;
|
|
9
|
-
/**
|
|
10
|
-
* Check if a record is stale compared to the current config version.
|
|
11
|
-
* Returns true if the record needs migration.
|
|
12
|
-
*/
|
|
13
|
-
needsMigration(record: Partial<VersionedRecord>, config: EntityConfig): boolean;
|
|
14
|
-
/**
|
|
15
|
-
* Get the effective migration strategy for frontend use.
|
|
16
|
-
* Only 'strict' or 'graceful' — never 'auto' (ADR-005).
|
|
17
|
-
*/
|
|
18
|
-
getStrategy(): 'strict' | 'graceful';
|
|
19
|
-
/**
|
|
20
|
-
* Determine if form submission should be blocked for a stale record.
|
|
21
|
-
* 'strict' → block; 'graceful' → allow with warning.
|
|
22
|
-
*/
|
|
23
|
-
shouldBlockSubmit(record: Partial<VersionedRecord>, config: EntityConfig): boolean;
|
|
24
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<VersionService, never>;
|
|
25
|
-
static ɵprov: i0.ɵɵInjectableDeclaration<VersionService>;
|
|
26
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
|
|
2
|
-
import type { EntityConfig, VersionedRecord } from '@dynamic-entity/core';
|
|
3
|
-
import * as i0 from "@angular/core";
|
|
4
|
-
/**
|
|
5
|
-
* DynamicTableComponent — renders entity records as a searchable, sortable, paginated table.
|
|
6
|
-
* Columns determined by FieldConfig.tableColumn === true.
|
|
7
|
-
* Cell masking applied via RbacService (defense-in-depth).
|
|
8
|
-
* Pagination, sort, and search emit events — parent controls data fetching (smart/dumb pattern).
|
|
9
|
-
*/
|
|
10
|
-
export declare class DynamicTableComponent implements OnChanges {
|
|
11
|
-
config: EntityConfig;
|
|
12
|
-
data: VersionedRecord[];
|
|
13
|
-
userRoles: string[];
|
|
14
|
-
language: string;
|
|
15
|
-
loading: boolean;
|
|
16
|
-
error: string | null;
|
|
17
|
-
totalRecords: number;
|
|
18
|
-
pageSize: number;
|
|
19
|
-
currentPage: number;
|
|
20
|
-
rowClick: EventEmitter<VersionedRecord>;
|
|
21
|
-
rowEdit: EventEmitter<VersionedRecord>;
|
|
22
|
-
rowDelete: EventEmitter<VersionedRecord>;
|
|
23
|
-
pageChange: EventEmitter<number>;
|
|
24
|
-
pageSizeChange: EventEmitter<number>;
|
|
25
|
-
sortChange: EventEmitter<{
|
|
26
|
-
field: string;
|
|
27
|
-
dir: 'asc' | 'desc';
|
|
28
|
-
}>;
|
|
29
|
-
searchChange: EventEmitter<string>;
|
|
30
|
-
private readonly rbacService;
|
|
31
|
-
private readonly versionService;
|
|
32
|
-
readonly sortField: import("@angular/core").WritableSignal<string>;
|
|
33
|
-
readonly sortDir: import("@angular/core").WritableSignal<"asc" | "desc">;
|
|
34
|
-
readonly searchTerm: import("@angular/core").WritableSignal<string>;
|
|
35
|
-
readonly tableColumns: import("@angular/core").Signal<import("@dynamic-entity/core").FieldConfig[]>;
|
|
36
|
-
get permissions(): {
|
|
37
|
-
canView: boolean;
|
|
38
|
-
canEdit: boolean;
|
|
39
|
-
canDelete: boolean;
|
|
40
|
-
};
|
|
41
|
-
get totalPages(): number;
|
|
42
|
-
ngOnChanges(_changes: SimpleChanges): void;
|
|
43
|
-
private columnMaskCache;
|
|
44
|
-
private _resolveColumnMasks;
|
|
45
|
-
isCellMasked(fieldId: string): boolean;
|
|
46
|
-
getCellValue(record: VersionedRecord, fieldId: string): string;
|
|
47
|
-
needsMigration(record: VersionedRecord): boolean;
|
|
48
|
-
getColumnLabel(fieldId: string): string;
|
|
49
|
-
onSort(fieldId: string): void;
|
|
50
|
-
onSearch(event: Event): void;
|
|
51
|
-
onPageChange(page: number): void;
|
|
52
|
-
onEdit(event: Event, record: VersionedRecord): void;
|
|
53
|
-
onDelete(event: Event, record: VersionedRecord): void;
|
|
54
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<DynamicTableComponent, never>;
|
|
55
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<DynamicTableComponent, "ngx-dynamic-table", never, { "config": { "alias": "config"; "required": false; }; "data": { "alias": "data"; "required": false; }; "userRoles": { "alias": "userRoles"; "required": false; }; "language": { "alias": "language"; "required": false; }; "loading": { "alias": "loading"; "required": false; }; "error": { "alias": "error"; "required": false; }; "totalRecords": { "alias": "totalRecords"; "required": false; }; "pageSize": { "alias": "pageSize"; "required": false; }; "currentPage": { "alias": "currentPage"; "required": false; }; }, { "rowClick": "rowClick"; "rowEdit": "rowEdit"; "rowDelete": "rowDelete"; "pageChange": "pageChange"; "pageSizeChange": "pageSizeChange"; "sortChange": "sortChange"; "searchChange": "searchChange"; }, never, never, true, never>;
|
|
56
|
-
}
|