ngx-dynamic-entity-builder 1.0.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 +54 -0
- package/esm2022/lib/builder-store.service.mjs +923 -0
- package/esm2022/lib/clone.mjs +14 -0
- package/esm2022/lib/components/connection-source-config.component.mjs +121 -0
- package/esm2022/lib/components/entity-builder-canvas.component.mjs +83 -0
- package/esm2022/lib/components/entity-builder-tree-node.component.mjs +173 -0
- package/esm2022/lib/components/entity-reference-config.component.mjs +405 -0
- package/esm2022/lib/components/field-inspector.component.mjs +139 -0
- package/esm2022/lib/components/field-palette.component.mjs +57 -0
- package/esm2022/lib/components/field-rules-list.component.mjs +224 -0
- package/esm2022/lib/components/referenced-field-config.component.mjs +228 -0
- package/esm2022/lib/components/rule-form.component.mjs +201 -0
- package/esm2022/lib/components/tab-manager.component.mjs +341 -0
- package/esm2022/lib/entity-builder.component.mjs +153 -0
- package/esm2022/lib/field-catalog.mjs +6 -0
- package/esm2022/ngx-dynamic-entity-builder.mjs +5 -0
- package/esm2022/public-api.mjs +17 -0
- package/fesm2022/ngx-dynamic-entity-builder.mjs +2910 -0
- package/fesm2022/ngx-dynamic-entity-builder.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/builder-store.service.d.ts +165 -0
- package/lib/clone.d.ts +9 -0
- package/lib/components/connection-source-config.component.d.ts +16 -0
- package/lib/components/entity-builder-canvas.component.d.ts +9 -0
- package/lib/components/entity-builder-tree-node.component.d.ts +17 -0
- package/lib/components/entity-reference-config.component.d.ts +29 -0
- package/lib/components/field-inspector.component.d.ts +33 -0
- package/lib/components/field-palette.component.d.ts +13 -0
- package/lib/components/field-rules-list.component.d.ts +19 -0
- package/lib/components/referenced-field-config.component.d.ts +18 -0
- package/lib/components/rule-form.component.d.ts +16 -0
- package/lib/components/tab-manager.component.d.ts +19 -0
- package/lib/entity-builder.component.d.ts +42 -0
- package/lib/field-catalog.d.ts +5 -0
- package/package.json +42 -0
- package/public-api.d.ts +13 -0
|
@@ -0,0 +1,923 @@
|
|
|
1
|
+
import { Injectable, computed, signal } from '@angular/core';
|
|
2
|
+
import { findTab, labelToId, normalizeConfigOptions, computeFieldDrift, createFieldSnapshot } from '@dynamic-entity/core';
|
|
3
|
+
import { createFieldConfig, getFieldTypeMeta, humanizeId, } from './field-catalog';
|
|
4
|
+
import { deepClone } from './clone';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
const clone = deepClone;
|
|
7
|
+
const ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
8
|
+
export class BuilderStore {
|
|
9
|
+
_config = signal(this.emptyConfig());
|
|
10
|
+
_selectedFieldId = signal(null);
|
|
11
|
+
_activeLanguage = signal('en');
|
|
12
|
+
/** Rules live beside the config: they are persisted per form, not inside `EntityFormConfig`. */
|
|
13
|
+
_rules = signal([]);
|
|
14
|
+
/**
|
|
15
|
+
* Field ids the author owns — set by an explicit rename, or by loading a saved config
|
|
16
|
+
* whose ids are already live data keys. Ids outside this set are still derived from the
|
|
17
|
+
* field's label. Builder-session state, deliberately not part of the exported config.
|
|
18
|
+
*/
|
|
19
|
+
manualIds = new Set();
|
|
20
|
+
_isDirty = signal(false);
|
|
21
|
+
config = this._config.asReadonly();
|
|
22
|
+
selectedFieldId = this._selectedFieldId.asReadonly();
|
|
23
|
+
activeLanguage = this._activeLanguage.asReadonly();
|
|
24
|
+
rules = this._rules.asReadonly();
|
|
25
|
+
isDirty = this._isDirty.asReadonly();
|
|
26
|
+
tabs = computed(() => this._config().tabs ?? []);
|
|
27
|
+
fields = computed(() => {
|
|
28
|
+
return (this._config().tabs ?? []).flatMap(t => t.fields ?? []);
|
|
29
|
+
});
|
|
30
|
+
selectedField = computed(() => {
|
|
31
|
+
const id = this._selectedFieldId();
|
|
32
|
+
if (!id)
|
|
33
|
+
return null;
|
|
34
|
+
return this.findFieldInTabs(this._config().tabs, id);
|
|
35
|
+
});
|
|
36
|
+
problems = computed(() => this.validate(this._config()));
|
|
37
|
+
errors = computed(() => this.problems().filter(p => p.level === 'error'));
|
|
38
|
+
isValid = computed(() => this.errors().length === 0);
|
|
39
|
+
// ─── Initialisation ─────────────────────────────────────────────────────────
|
|
40
|
+
load(config) {
|
|
41
|
+
// Check if any fields carry both inline options and listName before normalizing options
|
|
42
|
+
const fieldsWithBoth = this.getAllFields(config.tabs ?? []).filter(f => Array.isArray(f.options) && f.options.length > 0 && typeof f.listName === 'string' && f.listName.trim() !== '');
|
|
43
|
+
for (const f of fieldsWithBoth) {
|
|
44
|
+
console.warn(`[BuilderStore] Field "${f.id}" carries both inline options and listName "${f.listName}". ` +
|
|
45
|
+
`Inline options win; listName was dropped.`);
|
|
46
|
+
}
|
|
47
|
+
// The other boundary where a config enters the library (the renderer's ngOnChanges is
|
|
48
|
+
// the first). Authoring must start from the canonical option shape, or the builder
|
|
49
|
+
// would round-trip a legacy config straight back out unchanged.
|
|
50
|
+
const next = clone(normalizeConfigOptions(config));
|
|
51
|
+
next.tabs = next.tabs ?? [];
|
|
52
|
+
if (next.tabs.length === 0) {
|
|
53
|
+
next.tabs = [{ id: 'default', label: { en: 'Default' }, fields: [] }];
|
|
54
|
+
}
|
|
55
|
+
this._config.set(next);
|
|
56
|
+
const firstField = this.getAllFields(next.tabs)[0];
|
|
57
|
+
this._selectedFieldId.set(firstField?.id ?? null);
|
|
58
|
+
this._activeLanguage.set(next.defaultLanguage ?? 'en');
|
|
59
|
+
// Ids in a saved config are live data keys — records are already stored under them.
|
|
60
|
+
// Editing a label must never rewrite one, so freeze every id the config arrived with.
|
|
61
|
+
this.manualIds.clear();
|
|
62
|
+
for (const field of this.getAllFields(next.tabs))
|
|
63
|
+
this.manualIds.add(field.id);
|
|
64
|
+
this._isDirty.set(false);
|
|
65
|
+
}
|
|
66
|
+
reset(entity = '') {
|
|
67
|
+
this._config.set(this.emptyConfig(entity));
|
|
68
|
+
this._selectedFieldId.set(null);
|
|
69
|
+
this._rules.set([]);
|
|
70
|
+
this.manualIds.clear();
|
|
71
|
+
this._isDirty.set(false);
|
|
72
|
+
}
|
|
73
|
+
resetDirty() {
|
|
74
|
+
this._isDirty.set(false);
|
|
75
|
+
}
|
|
76
|
+
emptyConfig(entity = '') {
|
|
77
|
+
return {
|
|
78
|
+
entity,
|
|
79
|
+
version: 1,
|
|
80
|
+
defaultLanguage: 'en',
|
|
81
|
+
tabs: [],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// ─── Entity-level settings ──────────────────────────────────────────────────
|
|
85
|
+
setEntityName(entity) {
|
|
86
|
+
this.mutate(draft => {
|
|
87
|
+
draft.entity = entity.trim();
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
setDefaultLanguage(language) {
|
|
91
|
+
this.mutate(draft => {
|
|
92
|
+
draft.defaultLanguage = language;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
setMaskData(mask) {
|
|
96
|
+
this.mutate(draft => {
|
|
97
|
+
draft.maskData = mask;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
setPermission(action, roles) {
|
|
101
|
+
this.mutate(draft => {
|
|
102
|
+
const permissions = { ...(draft.permissions ?? {}) };
|
|
103
|
+
permissions[action] = roles;
|
|
104
|
+
draft.permissions = permissions;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
setActiveLanguage(language) {
|
|
108
|
+
this._activeLanguage.set(language);
|
|
109
|
+
}
|
|
110
|
+
// ─── Helper Traversal ───────────────────────────────────────────────────────
|
|
111
|
+
getAllFields(tabs = []) {
|
|
112
|
+
const list = [];
|
|
113
|
+
for (const t of tabs) {
|
|
114
|
+
if (t.fields)
|
|
115
|
+
list.push(...t.fields);
|
|
116
|
+
if (t.children)
|
|
117
|
+
list.push(...this.getAllFields(t.children));
|
|
118
|
+
}
|
|
119
|
+
return list;
|
|
120
|
+
}
|
|
121
|
+
findFieldInTabs(tabs = [], id) {
|
|
122
|
+
for (const t of tabs) {
|
|
123
|
+
if (t.fields) {
|
|
124
|
+
const found = t.fields.find(f => f.id === id);
|
|
125
|
+
if (found)
|
|
126
|
+
return found;
|
|
127
|
+
}
|
|
128
|
+
if (t.children) {
|
|
129
|
+
const found = this.findFieldInTabs(t.children, id);
|
|
130
|
+
if (found)
|
|
131
|
+
return found;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
// ─── Field CRUD ─────────────────────────────────────────────────────────────
|
|
137
|
+
addField(type, targetTabId) {
|
|
138
|
+
const meta = getFieldTypeMeta(type);
|
|
139
|
+
const prefix = meta?.idPrefix ?? 'field';
|
|
140
|
+
const allFields = this.fields();
|
|
141
|
+
const id = this.uniqueId(prefix, allFields);
|
|
142
|
+
this.mutate(draft => {
|
|
143
|
+
const field = createFieldConfig(type, id, draft.defaultLanguage ?? 'en');
|
|
144
|
+
const targetTab = targetTabId
|
|
145
|
+
? draft.tabs.find(t => t.id === targetTabId)
|
|
146
|
+
: draft.tabs[0];
|
|
147
|
+
if (targetTab) {
|
|
148
|
+
targetTab.fields = targetTab.fields ?? [];
|
|
149
|
+
targetTab.fields.push(field);
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
draft.tabs.push({ id: 'main', label: { en: 'Main' }, fields: [field] });
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
this._selectedFieldId.set(id);
|
|
156
|
+
return id;
|
|
157
|
+
}
|
|
158
|
+
updateField(id, patch) {
|
|
159
|
+
this.mutate(draft => {
|
|
160
|
+
const field = this.findFieldInTabs(draft.tabs, id);
|
|
161
|
+
if (field)
|
|
162
|
+
Object.assign(field, patch);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Rename a field explicitly, pinning the id so it is no longer derived from the label.
|
|
167
|
+
*
|
|
168
|
+
* Not reachable from the inspector — the id input is read-only by design. This exists for
|
|
169
|
+
* programmatic callers that must match an id to an existing data key.
|
|
170
|
+
*/
|
|
171
|
+
renameField(oldId, newId) {
|
|
172
|
+
const trimmed = newId.trim();
|
|
173
|
+
if (!trimmed || trimmed === oldId)
|
|
174
|
+
return;
|
|
175
|
+
if (this.fields().some(f => f.id === trimmed))
|
|
176
|
+
return;
|
|
177
|
+
if (!this.findFieldInTabs(this._config().tabs, oldId))
|
|
178
|
+
return;
|
|
179
|
+
this.applyRename(oldId, trimmed);
|
|
180
|
+
this.manualIds.delete(oldId);
|
|
181
|
+
this.manualIds.add(trimmed);
|
|
182
|
+
}
|
|
183
|
+
/** Whether this field's id is pinned (loaded from storage or explicitly renamed). */
|
|
184
|
+
hasManualId(id) {
|
|
185
|
+
return this.manualIds.has(id);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Move a field to a new id and repoint every id-based reference in the config at it.
|
|
189
|
+
*
|
|
190
|
+
* Ids are the wiring between fields — rules, cascades, patches and `showWhen` all address
|
|
191
|
+
* fields by id — so a rename that only touches `field.id` silently breaks that wiring.
|
|
192
|
+
* That was survivable while renaming was a rare manual act; label-derived ids make it
|
|
193
|
+
* routine, so the references move with it.
|
|
194
|
+
*/
|
|
195
|
+
applyRename(oldId, newId) {
|
|
196
|
+
this.mutate(draft => {
|
|
197
|
+
const field = this.findFieldInTabs(draft.tabs, oldId);
|
|
198
|
+
if (!field)
|
|
199
|
+
return;
|
|
200
|
+
field.id = newId;
|
|
201
|
+
const walkFields = (fields) => {
|
|
202
|
+
for (const f of fields ?? []) {
|
|
203
|
+
if (f.showWhen && oldId in f.showWhen) {
|
|
204
|
+
const next = {};
|
|
205
|
+
// Rebuild in place so condition order survives the rename.
|
|
206
|
+
for (const [key, value] of Object.entries(f.showWhen)) {
|
|
207
|
+
next[key === oldId ? newId : key] = value;
|
|
208
|
+
}
|
|
209
|
+
f.showWhen = next;
|
|
210
|
+
}
|
|
211
|
+
if (f.entityReference?.parentField === oldId) {
|
|
212
|
+
f.entityReference = { ...f.entityReference, parentField: newId };
|
|
213
|
+
}
|
|
214
|
+
if (f.autoPatch) {
|
|
215
|
+
// `source` names a field on the *linked* record, not this config — leave it.
|
|
216
|
+
f.autoPatch = {
|
|
217
|
+
...f.autoPatch,
|
|
218
|
+
mappings: f.autoPatch.mappings.map(m => m.target === oldId ? { ...m, target: newId } : m),
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
if (f.patchOnTrue) {
|
|
222
|
+
f.patchOnTrue = f.patchOnTrue.map(m => ({
|
|
223
|
+
from: m.from === oldId ? newId : m.from,
|
|
224
|
+
to: m.to === oldId ? newId : m.to,
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
if (f.children?.length)
|
|
228
|
+
walkFields(f.children);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
const walkTabs = (tabs) => {
|
|
232
|
+
for (const tab of tabs ?? []) {
|
|
233
|
+
walkFields(tab.fields);
|
|
234
|
+
walkTabs(tab.children);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
walkTabs(draft.tabs);
|
|
238
|
+
});
|
|
239
|
+
this._rules.update(rules => rules.map(rule => ({
|
|
240
|
+
...rule,
|
|
241
|
+
fieldId: rule.fieldId === oldId ? newId : rule.fieldId,
|
|
242
|
+
targets: rule.targets.map(t => t.type === 'field' && t.id === oldId ? { ...t, id: newId } : t),
|
|
243
|
+
})));
|
|
244
|
+
if (this._selectedFieldId() === oldId)
|
|
245
|
+
this._selectedFieldId.set(newId);
|
|
246
|
+
}
|
|
247
|
+
removeField(id) {
|
|
248
|
+
this.mutate(draft => {
|
|
249
|
+
for (const tab of draft.tabs) {
|
|
250
|
+
if (tab.fields) {
|
|
251
|
+
tab.fields = tab.fields.filter(f => f.id !== id);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
this.manualIds.delete(id);
|
|
256
|
+
if (this._selectedFieldId() === id)
|
|
257
|
+
this._selectedFieldId.set(null);
|
|
258
|
+
}
|
|
259
|
+
duplicateField(id) {
|
|
260
|
+
// Look the source up by id — not by current selection. The insert below searches by id
|
|
261
|
+
// too, so falling back to the selected field could report a new id while inserting
|
|
262
|
+
// nothing, or duplicate a field the caller never named.
|
|
263
|
+
const source = this.findFieldInTabs(this._config().tabs, id);
|
|
264
|
+
if (!source)
|
|
265
|
+
return null;
|
|
266
|
+
const meta = getFieldTypeMeta(source.type);
|
|
267
|
+
const prefix = meta?.idPrefix ?? 'field';
|
|
268
|
+
const newId = this.uniqueId(prefix, this.fields());
|
|
269
|
+
this.mutate(draft => {
|
|
270
|
+
for (const tab of draft.tabs) {
|
|
271
|
+
const index = (tab.fields ?? []).findIndex(f => f.id === id);
|
|
272
|
+
if (index !== -1) {
|
|
273
|
+
const copy = clone(source);
|
|
274
|
+
copy.id = newId;
|
|
275
|
+
tab.fields.splice(index + 1, 0, copy);
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
this._selectedFieldId.set(newId);
|
|
281
|
+
return newId;
|
|
282
|
+
}
|
|
283
|
+
moveField(id, direction) {
|
|
284
|
+
this.mutate(draft => {
|
|
285
|
+
for (const tab of draft.tabs) {
|
|
286
|
+
const fields = tab.fields ?? [];
|
|
287
|
+
const from = fields.findIndex(f => f.id === id);
|
|
288
|
+
if (from !== -1) {
|
|
289
|
+
const to = from + direction;
|
|
290
|
+
if (to < 0 || to >= fields.length)
|
|
291
|
+
return;
|
|
292
|
+
const [item] = fields.splice(from, 1);
|
|
293
|
+
fields.splice(to, 0, item);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
/** Safe reorder for drag & drop within active tab or flat list */
|
|
300
|
+
reorderField(fromIndex, toIndex, tabId) {
|
|
301
|
+
this.mutate(draft => {
|
|
302
|
+
const targetTab = tabId
|
|
303
|
+
? draft.tabs.find(t => t.id === tabId)
|
|
304
|
+
: draft.tabs[0];
|
|
305
|
+
const fields = targetTab?.fields ?? [];
|
|
306
|
+
if (fromIndex < 0 ||
|
|
307
|
+
toIndex < 0 ||
|
|
308
|
+
fromIndex >= fields.length ||
|
|
309
|
+
toIndex >= fields.length) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
const [item] = fields.splice(fromIndex, 1);
|
|
313
|
+
fields.splice(toIndex, 0, item);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
selectField(id) {
|
|
317
|
+
this._selectedFieldId.set(id);
|
|
318
|
+
}
|
|
319
|
+
// ─── Localised text ─────────────────────────────────────────────────────────
|
|
320
|
+
/**
|
|
321
|
+
* Set a field's label, and derive the field's id from it: type "Employee Count", get
|
|
322
|
+
* `employeeCount`. The inspector renders the id read-only, so this is the only way a
|
|
323
|
+
* new field's id is set.
|
|
324
|
+
*
|
|
325
|
+
* Two things stop derivation: a config loaded from storage (its ids are live data keys
|
|
326
|
+
* that records are already stored under — see `load`), and an explicit `renameField`
|
|
327
|
+
* call, which remains available to programmatic callers.
|
|
328
|
+
*
|
|
329
|
+
* Only the config's default language drives the id; translating a label must not rename
|
|
330
|
+
* anything.
|
|
331
|
+
*/
|
|
332
|
+
setFieldLabel(id, language, value) {
|
|
333
|
+
this.mutate(draft => {
|
|
334
|
+
const field = this.findFieldInTabs(draft.tabs, id);
|
|
335
|
+
if (field)
|
|
336
|
+
field.label = { ...field.label, [language]: value };
|
|
337
|
+
});
|
|
338
|
+
if (language !== (this._config().defaultLanguage ?? 'en'))
|
|
339
|
+
return;
|
|
340
|
+
if (this.manualIds.has(id))
|
|
341
|
+
return;
|
|
342
|
+
const derived = labelToId(value);
|
|
343
|
+
if (!derived || derived === id)
|
|
344
|
+
return;
|
|
345
|
+
this.applyRename(id, this.availableId(derived, id));
|
|
346
|
+
}
|
|
347
|
+
/** `derived`, or `derived_2`, `derived_3`… if another field already holds it. */
|
|
348
|
+
availableId(derived, currentId) {
|
|
349
|
+
const taken = new Set(this.fields().map(f => f.id).filter(fid => fid !== currentId));
|
|
350
|
+
if (!taken.has(derived))
|
|
351
|
+
return derived;
|
|
352
|
+
let n = 2;
|
|
353
|
+
while (taken.has(`${derived}_${n}`))
|
|
354
|
+
n += 1;
|
|
355
|
+
return `${derived}_${n}`;
|
|
356
|
+
}
|
|
357
|
+
setFieldPlaceholder(id, language, value) {
|
|
358
|
+
this.mutate(draft => {
|
|
359
|
+
const field = this.findFieldInTabs(draft.tabs, id);
|
|
360
|
+
if (!field)
|
|
361
|
+
return;
|
|
362
|
+
field.placeholder = { ...(field.placeholder ?? {}), [language]: value };
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
// ─── Validators ─────────────────────────────────────────────────────────────
|
|
366
|
+
toggleFlagValidator(id, validator, on) {
|
|
367
|
+
this.mutate(draft => {
|
|
368
|
+
const field = this.findFieldInTabs(draft.tabs, id);
|
|
369
|
+
if (!field)
|
|
370
|
+
return;
|
|
371
|
+
field.validators = field.validators ?? {};
|
|
372
|
+
if (validator === 'required') {
|
|
373
|
+
if (on)
|
|
374
|
+
field.validators.required = true;
|
|
375
|
+
else
|
|
376
|
+
delete field.validators.required;
|
|
377
|
+
}
|
|
378
|
+
else if (validator === 'email') {
|
|
379
|
+
if (on)
|
|
380
|
+
field.validators.pattern = '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$';
|
|
381
|
+
else
|
|
382
|
+
delete field.validators.pattern;
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
setParamValidator(id, validator, value) {
|
|
387
|
+
this.mutate(draft => {
|
|
388
|
+
const field = this.findFieldInTabs(draft.tabs, id);
|
|
389
|
+
if (!field)
|
|
390
|
+
return;
|
|
391
|
+
field.validators = field.validators ?? {};
|
|
392
|
+
if (value === null || value === undefined || Number.isNaN(value)) {
|
|
393
|
+
delete field.validators[validator];
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
field.validators[validator] = value;
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
getParamValidator(field, validator) {
|
|
401
|
+
const val = field.validators?.[validator];
|
|
402
|
+
return typeof val === 'number' ? val : null;
|
|
403
|
+
}
|
|
404
|
+
hasFlagValidator(field, validator) {
|
|
405
|
+
if (validator === 'required')
|
|
406
|
+
return !!field.validators?.required;
|
|
407
|
+
if (validator === 'email')
|
|
408
|
+
return !!field.validators?.pattern;
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
// ─── Options (dropdown / multiSelect / radio) ────────────────────────────────
|
|
412
|
+
/**
|
|
413
|
+
* Where a choice field's options come from.
|
|
414
|
+
*
|
|
415
|
+
* `entity` is absent on purpose: in this model an entity reference is a field *type*
|
|
416
|
+
* (`entity-ref`), not a data source a dropdown can switch to, so offering it here would mean
|
|
417
|
+
* mutating the field's type — and rebuilding its control — from a source picker. The
|
|
418
|
+
* exclusion that matters within a choice field is inline `options` vs `listName`.
|
|
419
|
+
*/
|
|
420
|
+
fieldDataSource(field) {
|
|
421
|
+
if (!field)
|
|
422
|
+
return 'none';
|
|
423
|
+
// Presence, not emptiness: a source the author has picked but not filled in yet — no
|
|
424
|
+
// options authored, no list name typed — must still read as that source, or the editor
|
|
425
|
+
// for it disappears the moment they select it.
|
|
426
|
+
if (Array.isArray(field.options))
|
|
427
|
+
return 'manual';
|
|
428
|
+
if (typeof field.listName === 'string')
|
|
429
|
+
return 'lookup';
|
|
430
|
+
return 'none';
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Switch a choice field's data source, clearing the one it is leaving.
|
|
434
|
+
*
|
|
435
|
+
* The reference makes these mutually exclusive (doc §4.4) and it has to stay that way here:
|
|
436
|
+
* `optionsFor` resolves inline options first, so a field left holding both would silently
|
|
437
|
+
* ignore its list.
|
|
438
|
+
*/
|
|
439
|
+
setFieldDataSource(fieldId, source) {
|
|
440
|
+
this.mutate(draft => {
|
|
441
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
442
|
+
if (!field)
|
|
443
|
+
return;
|
|
444
|
+
if (source === 'manual') {
|
|
445
|
+
delete field.listName;
|
|
446
|
+
field.options = field.options?.length ? field.options : [];
|
|
447
|
+
}
|
|
448
|
+
else if (source === 'lookup') {
|
|
449
|
+
delete field.options;
|
|
450
|
+
field.listName = field.listName ?? '';
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
delete field.options;
|
|
454
|
+
delete field.listName;
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
/** Set the named list a choice field reads its options from. */
|
|
459
|
+
setListName(fieldId, listName) {
|
|
460
|
+
this.mutate(draft => {
|
|
461
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
462
|
+
if (!field)
|
|
463
|
+
return;
|
|
464
|
+
const trimmed = listName.trim();
|
|
465
|
+
if (trimmed) {
|
|
466
|
+
field.listName = trimmed;
|
|
467
|
+
// Belt and braces: inline options would win over the list at render time.
|
|
468
|
+
delete field.options;
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
field.listName = '';
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
/** Link a field to a field defined in another entity configuration (Phase 8). */
|
|
476
|
+
linkReferencedField(fieldId, sourceEntityKey, sourceField) {
|
|
477
|
+
this.mutate(draft => {
|
|
478
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
479
|
+
if (!field)
|
|
480
|
+
return;
|
|
481
|
+
field.isReferenced = true;
|
|
482
|
+
field.referencedEntityKey = sourceEntityKey;
|
|
483
|
+
field.referencedFieldId = sourceField.id;
|
|
484
|
+
field.referencedSnapshot = createFieldSnapshot(sourceField);
|
|
485
|
+
field.hasDrift = false;
|
|
486
|
+
// Copy label, type, validators, options from source
|
|
487
|
+
if (sourceField.label)
|
|
488
|
+
field.label = clone(sourceField.label);
|
|
489
|
+
if (sourceField.type)
|
|
490
|
+
field.type = sourceField.type;
|
|
491
|
+
if (sourceField.validators)
|
|
492
|
+
field.validators = clone(sourceField.validators);
|
|
493
|
+
if (sourceField.options)
|
|
494
|
+
field.options = clone(sourceField.options);
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
/** Unlink a referenced field back to an independent field. */
|
|
498
|
+
unlinkReferencedField(fieldId) {
|
|
499
|
+
this.mutate(draft => {
|
|
500
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
501
|
+
if (!field)
|
|
502
|
+
return;
|
|
503
|
+
delete field.isReferenced;
|
|
504
|
+
delete field.referencedEntityKey;
|
|
505
|
+
delete field.referencedFieldId;
|
|
506
|
+
delete field.referencedSnapshot;
|
|
507
|
+
delete field.hasDrift;
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
/** Sync a drifted referenced field with the updated source field definition. */
|
|
511
|
+
syncReferencedField(fieldId, currentSourceField) {
|
|
512
|
+
this.mutate(draft => {
|
|
513
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
514
|
+
if (!field || !field.isReferenced)
|
|
515
|
+
return;
|
|
516
|
+
field.referencedSnapshot = createFieldSnapshot(currentSourceField);
|
|
517
|
+
field.hasDrift = false;
|
|
518
|
+
if (currentSourceField.label)
|
|
519
|
+
field.label = clone(currentSourceField.label);
|
|
520
|
+
if (currentSourceField.type)
|
|
521
|
+
field.type = currentSourceField.type;
|
|
522
|
+
if (currentSourceField.validators)
|
|
523
|
+
field.validators = clone(currentSourceField.validators);
|
|
524
|
+
if (currentSourceField.options)
|
|
525
|
+
field.options = clone(currentSourceField.options);
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
/** Scan all referenced fields in the config and update their hasDrift state against current source configs. */
|
|
529
|
+
checkDrift(sourceConfigs) {
|
|
530
|
+
this.mutate(draft => {
|
|
531
|
+
const scanFields = (fields) => {
|
|
532
|
+
for (const f of fields) {
|
|
533
|
+
if (f.isReferenced && f.referencedEntityKey && f.referencedFieldId) {
|
|
534
|
+
const sourceConfig = sourceConfigs[f.referencedEntityKey];
|
|
535
|
+
const sourceField = sourceConfig
|
|
536
|
+
? this.findFieldInTabs(sourceConfig.tabs ?? [], f.referencedFieldId)
|
|
537
|
+
: undefined;
|
|
538
|
+
f.hasDrift = computeFieldDrift(f, sourceField ?? undefined);
|
|
539
|
+
}
|
|
540
|
+
if (f.children?.length)
|
|
541
|
+
scanFields(f.children);
|
|
542
|
+
}
|
|
543
|
+
};
|
|
544
|
+
for (const tab of draft.tabs ?? []) {
|
|
545
|
+
if (tab.fields?.length)
|
|
546
|
+
scanFields(tab.fields);
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
addOption(fieldId) {
|
|
551
|
+
this.mutate(draft => {
|
|
552
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
553
|
+
if (!field)
|
|
554
|
+
return;
|
|
555
|
+
const options = field.options ?? [];
|
|
556
|
+
const n = options.length + 1;
|
|
557
|
+
const lang = draft.defaultLanguage ?? 'en';
|
|
558
|
+
options.push({ [lang]: `Option ${n}` });
|
|
559
|
+
field.options = options;
|
|
560
|
+
// Authoring an inline option makes this a manual field — see `setFieldDataSource`.
|
|
561
|
+
delete field.listName;
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
/** Merge language keys into an option. `setOptionLabel` is the usual single-language path. */
|
|
565
|
+
updateOption(fieldId, index, patch) {
|
|
566
|
+
this.mutate(draft => {
|
|
567
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
568
|
+
const option = field?.options?.[index];
|
|
569
|
+
if (!option)
|
|
570
|
+
return;
|
|
571
|
+
field.options[index] = { ...option, ...patch };
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
/**
|
|
575
|
+
* Set an option's text for one language.
|
|
576
|
+
*
|
|
577
|
+
* An option is a language-keyed object and the displayed text **is** the stored value,
|
|
578
|
+
* so this is the only way to edit one — there is no separate value to set.
|
|
579
|
+
*/
|
|
580
|
+
setOptionLabel(fieldId, index, language, value) {
|
|
581
|
+
this.mutate(draft => {
|
|
582
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
583
|
+
const option = field?.options?.[index];
|
|
584
|
+
if (!option)
|
|
585
|
+
return;
|
|
586
|
+
field.options[index] = { ...option, [language]: value };
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
removeOption(fieldId, index) {
|
|
590
|
+
this.mutate(draft => {
|
|
591
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
592
|
+
if (!field?.options)
|
|
593
|
+
return;
|
|
594
|
+
field.options = field.options.filter((_, i) => i !== index);
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
// ─── Entity reference / cascade ─────────────────────────────────────────────
|
|
598
|
+
/** Merge a patch into a field's `entityReference` block, keeping it enabled. */
|
|
599
|
+
updateEntityReference(fieldId, patch) {
|
|
600
|
+
this.mutate(draft => {
|
|
601
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
602
|
+
if (!field)
|
|
603
|
+
return;
|
|
604
|
+
const next = {
|
|
605
|
+
...(field.entityReference ?? { enabled: true }),
|
|
606
|
+
...patch,
|
|
607
|
+
enabled: true,
|
|
608
|
+
};
|
|
609
|
+
// Drop keys explicitly cleared to `undefined` so exported configs stay clean.
|
|
610
|
+
for (const key of Object.keys(patch)) {
|
|
611
|
+
if (patch[key] === undefined)
|
|
612
|
+
delete next[key];
|
|
613
|
+
}
|
|
614
|
+
field.entityReference = next;
|
|
615
|
+
});
|
|
616
|
+
}
|
|
617
|
+
// ─── autoPatch ──────────────────────────────────────────────────────────────
|
|
618
|
+
addAutoPatchMapping(fieldId) {
|
|
619
|
+
this.mutate(draft => {
|
|
620
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
621
|
+
if (!field)
|
|
622
|
+
return;
|
|
623
|
+
const targetTab = field.autoPatch?.targetTab ?? draft.tabs[0]?.id ?? '';
|
|
624
|
+
const mappings = [...(field.autoPatch?.mappings ?? []), { source: '', target: '' }];
|
|
625
|
+
field.autoPatch = { targetTab, mappings };
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
setAutoPatchTargetTab(fieldId, targetTab) {
|
|
629
|
+
this.mutate(draft => {
|
|
630
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
631
|
+
if (!field?.autoPatch)
|
|
632
|
+
return;
|
|
633
|
+
field.autoPatch = { ...field.autoPatch, targetTab };
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
updateAutoPatchMapping(fieldId, index, patch) {
|
|
637
|
+
this.mutate(draft => {
|
|
638
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
639
|
+
if (!field?.autoPatch?.mappings?.[index])
|
|
640
|
+
return;
|
|
641
|
+
field.autoPatch = {
|
|
642
|
+
...field.autoPatch,
|
|
643
|
+
mappings: field.autoPatch.mappings.map((m, i) => (i === index ? { ...m, ...patch } : m)),
|
|
644
|
+
};
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
/** Removing the last mapping drops `autoPatch` entirely — no empty config in the export. */
|
|
648
|
+
removeAutoPatchMapping(fieldId, index) {
|
|
649
|
+
this.mutate(draft => {
|
|
650
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
651
|
+
if (!field?.autoPatch)
|
|
652
|
+
return;
|
|
653
|
+
const mappings = field.autoPatch.mappings.filter((_, i) => i !== index);
|
|
654
|
+
if (mappings.length === 0)
|
|
655
|
+
delete field.autoPatch;
|
|
656
|
+
else
|
|
657
|
+
field.autoPatch = { ...field.autoPatch, mappings };
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
// ─── patchOnTrue ────────────────────────────────────────────────────────────
|
|
661
|
+
addPatchOnTrueMapping(fieldId) {
|
|
662
|
+
this.mutate(draft => {
|
|
663
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
664
|
+
if (!field)
|
|
665
|
+
return;
|
|
666
|
+
field.patchOnTrue = [...(field.patchOnTrue ?? []), { from: '', to: '' }];
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
updatePatchOnTrueMapping(fieldId, index, patch) {
|
|
670
|
+
this.mutate(draft => {
|
|
671
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
672
|
+
if (!field?.patchOnTrue?.[index])
|
|
673
|
+
return;
|
|
674
|
+
field.patchOnTrue = field.patchOnTrue.map((m, i) => (i === index ? { ...m, ...patch } : m));
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
removePatchOnTrueMapping(fieldId, index) {
|
|
678
|
+
this.mutate(draft => {
|
|
679
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
680
|
+
if (!field?.patchOnTrue)
|
|
681
|
+
return;
|
|
682
|
+
const mappings = field.patchOnTrue.filter((_, i) => i !== index);
|
|
683
|
+
if (mappings.length === 0)
|
|
684
|
+
delete field.patchOnTrue;
|
|
685
|
+
else
|
|
686
|
+
field.patchOnTrue = mappings;
|
|
687
|
+
});
|
|
688
|
+
}
|
|
689
|
+
// ─── showWhen (static conditional visibility) ───────────────────────────────
|
|
690
|
+
/** Replace a field's `showWhen` map; an empty map removes the condition. */
|
|
691
|
+
setShowWhen(fieldId, showWhen) {
|
|
692
|
+
this.mutate(draft => {
|
|
693
|
+
const field = this.findFieldInTabs(draft.tabs, fieldId);
|
|
694
|
+
if (!field)
|
|
695
|
+
return;
|
|
696
|
+
if (!showWhen || Object.keys(showWhen).length === 0)
|
|
697
|
+
delete field.showWhen;
|
|
698
|
+
else
|
|
699
|
+
field.showWhen = showWhen;
|
|
700
|
+
});
|
|
701
|
+
}
|
|
702
|
+
// ─── Rules ──────────────────────────────────────────────────────────────────
|
|
703
|
+
/** Rules for the field currently selected in the inspector. */
|
|
704
|
+
rulesForSelectedField = computed(() => {
|
|
705
|
+
const id = this._selectedFieldId();
|
|
706
|
+
if (!id)
|
|
707
|
+
return [];
|
|
708
|
+
return this._rules().filter(r => r.fieldId === id || r.targets.some(t => t.id === id));
|
|
709
|
+
});
|
|
710
|
+
loadRules(rules) {
|
|
711
|
+
this._rules.set(clone(rules));
|
|
712
|
+
}
|
|
713
|
+
addRule(rule) {
|
|
714
|
+
const id = rule.id?.trim() || this.uniqueId('rule', this._rules().map(r => ({ id: r.id ?? '' })));
|
|
715
|
+
this._rules.update(rules => [...rules, { ...clone(rule), id }]);
|
|
716
|
+
return id;
|
|
717
|
+
}
|
|
718
|
+
updateRule(id, patch) {
|
|
719
|
+
this._rules.update(rules => rules.map(r => (r.id === id ? { ...r, ...clone(patch), id } : r)));
|
|
720
|
+
}
|
|
721
|
+
removeRule(id) {
|
|
722
|
+
this._rules.update(rules => rules.filter(r => r.id !== id));
|
|
723
|
+
}
|
|
724
|
+
toggleRule(id, enabled) {
|
|
725
|
+
this.updateRule(id, { enabled });
|
|
726
|
+
}
|
|
727
|
+
/** Move a rule in priority order. Priorities are renumbered 1..n so they stay contiguous. */
|
|
728
|
+
moveRule(id, direction) {
|
|
729
|
+
this._rules.update(rules => {
|
|
730
|
+
const next = [...rules];
|
|
731
|
+
const from = next.findIndex(r => r.id === id);
|
|
732
|
+
if (from === -1)
|
|
733
|
+
return rules;
|
|
734
|
+
const to = from + direction;
|
|
735
|
+
if (to < 0 || to >= next.length)
|
|
736
|
+
return rules;
|
|
737
|
+
const [item] = next.splice(from, 1);
|
|
738
|
+
next.splice(to, 0, item);
|
|
739
|
+
return next.map((r, i) => ({ ...r, priority: i + 1 }));
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
exportRules() {
|
|
743
|
+
return clone(this._rules());
|
|
744
|
+
}
|
|
745
|
+
// ─── Tabs ───────────────────────────────────────────────────────────────────
|
|
746
|
+
addTab() {
|
|
747
|
+
// Must be unique across the whole tree, not just the top level: a tab id is the record
|
|
748
|
+
// storage path, so a new top-level tab colliding with an existing sub-tab would make two
|
|
749
|
+
// tabs write to the same key and break findTab/getTabPath.
|
|
750
|
+
const id = this.uniqueId('tab', this.allTabIds().map(tid => ({ id: tid })));
|
|
751
|
+
this.mutate(draft => {
|
|
752
|
+
const tabs = draft.tabs ?? (draft.tabs = []);
|
|
753
|
+
const lang = draft.defaultLanguage ?? 'en';
|
|
754
|
+
tabs.push({ id, label: { [lang]: humanizeId(id) }, fields: [] });
|
|
755
|
+
});
|
|
756
|
+
return id;
|
|
757
|
+
}
|
|
758
|
+
/** Every tab id in the tree, at any depth. Tab ids must be globally unique — they are paths. */
|
|
759
|
+
allTabIds() {
|
|
760
|
+
const ids = [];
|
|
761
|
+
const collect = (tabs) => {
|
|
762
|
+
for (const t of tabs ?? []) {
|
|
763
|
+
ids.push(t.id);
|
|
764
|
+
collect(t.children);
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
collect(this._config().tabs);
|
|
768
|
+
return ids;
|
|
769
|
+
}
|
|
770
|
+
addSubTab(parentId) {
|
|
771
|
+
const id = this.uniqueId('tab', this.allTabIds().map(tid => ({ id: tid })));
|
|
772
|
+
this.mutate(draft => {
|
|
773
|
+
const parent = findTab(draft.tabs, parentId);
|
|
774
|
+
if (parent) {
|
|
775
|
+
parent.children = parent.children ?? [];
|
|
776
|
+
const lang = draft.defaultLanguage ?? 'en';
|
|
777
|
+
parent.children.push({ id, label: { [lang]: humanizeId(id) }, fields: [] });
|
|
778
|
+
}
|
|
779
|
+
});
|
|
780
|
+
return id;
|
|
781
|
+
}
|
|
782
|
+
setPrimaryTab(tabId) {
|
|
783
|
+
this.mutate(draft => {
|
|
784
|
+
const markPrimary = (tabs) => {
|
|
785
|
+
for (const t of tabs) {
|
|
786
|
+
t.isPrimaryTab = t.id === tabId;
|
|
787
|
+
if (t.children)
|
|
788
|
+
markPrimary(t.children);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
markPrimary(draft.tabs ?? []);
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
updateTab(id, patch) {
|
|
795
|
+
this.mutate(draft => {
|
|
796
|
+
const tab = findTab(draft.tabs, id);
|
|
797
|
+
if (tab)
|
|
798
|
+
Object.assign(tab, patch);
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
setTabLabel(id, language, value) {
|
|
802
|
+
this.mutate(draft => {
|
|
803
|
+
const tab = findTab(draft.tabs, id);
|
|
804
|
+
if (tab)
|
|
805
|
+
tab.label = { ...tab.label, [language]: value };
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
removeTab(id) {
|
|
809
|
+
this.mutate(draft => {
|
|
810
|
+
const removeRecursive = (tabs) => {
|
|
811
|
+
return tabs
|
|
812
|
+
.filter(t => t.id !== id)
|
|
813
|
+
.map(t => ({
|
|
814
|
+
...t,
|
|
815
|
+
children: t.children ? removeRecursive(t.children) : undefined,
|
|
816
|
+
}));
|
|
817
|
+
};
|
|
818
|
+
draft.tabs = removeRecursive(draft.tabs ?? []);
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
moveTab(id, direction) {
|
|
822
|
+
this.mutate(draft => {
|
|
823
|
+
const tabs = draft.tabs ?? [];
|
|
824
|
+
const from = tabs.findIndex(t => t.id === id);
|
|
825
|
+
if (from === -1)
|
|
826
|
+
return;
|
|
827
|
+
const to = from + direction;
|
|
828
|
+
if (to < 0 || to >= tabs.length)
|
|
829
|
+
return;
|
|
830
|
+
const [item] = tabs.splice(from, 1);
|
|
831
|
+
tabs.splice(to, 0, item);
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
// ─── Export ─────────────────────────────────────────────────────────────────
|
|
835
|
+
exportConfig() {
|
|
836
|
+
return clone(this._config());
|
|
837
|
+
}
|
|
838
|
+
// ─── Internals ──────────────────────────────────────────────────────────────
|
|
839
|
+
mutate(fn) {
|
|
840
|
+
const draft = clone(this._config());
|
|
841
|
+
draft.tabs = draft.tabs ?? [];
|
|
842
|
+
fn(draft);
|
|
843
|
+
this._config.set(draft);
|
|
844
|
+
this._isDirty.set(true);
|
|
845
|
+
}
|
|
846
|
+
uniqueId(prefix, existing) {
|
|
847
|
+
const taken = new Set(existing.map(e => e.id));
|
|
848
|
+
let n = 1;
|
|
849
|
+
let candidate = `${prefix}_${n}`;
|
|
850
|
+
while (taken.has(candidate)) {
|
|
851
|
+
n += 1;
|
|
852
|
+
candidate = `${prefix}_${n}`;
|
|
853
|
+
}
|
|
854
|
+
return candidate;
|
|
855
|
+
}
|
|
856
|
+
validate(config) {
|
|
857
|
+
const problems = [];
|
|
858
|
+
if (!config.entity || !config.entity.trim()) {
|
|
859
|
+
problems.push({ level: 'error', message: 'Entity name is required.' });
|
|
860
|
+
}
|
|
861
|
+
else if (!ID_PATTERN.test(config.entity)) {
|
|
862
|
+
problems.push({
|
|
863
|
+
level: 'error',
|
|
864
|
+
message: 'Entity name must start with a letter or underscore and contain only letters, digits, and underscores.',
|
|
865
|
+
});
|
|
866
|
+
}
|
|
867
|
+
const allFields = this.getAllFields(config.tabs);
|
|
868
|
+
if (allFields.length === 0) {
|
|
869
|
+
problems.push({ level: 'warning', message: 'This entity has no fields yet.' });
|
|
870
|
+
}
|
|
871
|
+
const seen = new Map();
|
|
872
|
+
for (const field of allFields) {
|
|
873
|
+
seen.set(field.id, (seen.get(field.id) ?? 0) + 1);
|
|
874
|
+
if (!field.id || !ID_PATTERN.test(field.id)) {
|
|
875
|
+
problems.push({
|
|
876
|
+
level: 'error',
|
|
877
|
+
message: `Field id "${field.id}" is not a valid identifier.`,
|
|
878
|
+
fieldId: field.id,
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
const labels = field.label ?? {};
|
|
882
|
+
const hasLabel = Object.values(labels).some(v => typeof v === 'string' && v.trim());
|
|
883
|
+
if (!hasLabel) {
|
|
884
|
+
problems.push({
|
|
885
|
+
level: 'warning',
|
|
886
|
+
message: `Field "${field.id}" has no label.`,
|
|
887
|
+
fieldId: field.id,
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
const meta = getFieldTypeMeta(field.type);
|
|
891
|
+
// A field on the lookup source has no inline options by design — its options arrive from
|
|
892
|
+
// the registry at runtime. Warn only about the missing list name.
|
|
893
|
+
if (meta?.hasOptions && typeof field.listName === 'string') {
|
|
894
|
+
if (!field.listName.trim()) {
|
|
895
|
+
problems.push({
|
|
896
|
+
level: 'warning',
|
|
897
|
+
message: `Field "${field.id}" reads options from a named list but has no list name.`,
|
|
898
|
+
fieldId: field.id,
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
else if (meta?.hasOptions && (!field.options || field.options.length === 0)) {
|
|
903
|
+
problems.push({
|
|
904
|
+
level: 'warning',
|
|
905
|
+
message: `Field "${field.id}" is a ${field.type} but has no options.`,
|
|
906
|
+
fieldId: field.id,
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
for (const [id, count] of seen) {
|
|
911
|
+
if (count > 1) {
|
|
912
|
+
problems.push({ level: 'error', message: `Duplicate field id "${id}" (${count}×).`, fieldId: id });
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
return problems;
|
|
916
|
+
}
|
|
917
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BuilderStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
918
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BuilderStore });
|
|
919
|
+
}
|
|
920
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: BuilderStore, decorators: [{
|
|
921
|
+
type: Injectable
|
|
922
|
+
}] });
|
|
923
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGRlci1zdG9yZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9idWlsZGVyLXN0b3JlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBYTdELE9BQU8sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLHNCQUFzQixFQUFFLGlCQUFpQixFQUFFLG1CQUFtQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDMUgsT0FBTyxFQUNMLGlCQUFpQixFQUNqQixnQkFBZ0IsRUFDaEIsVUFBVSxHQUdYLE1BQU0saUJBQWlCLENBQUM7QUFDekIsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLFNBQVMsQ0FBQzs7QUFRcEMsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDO0FBRXhCLE1BQU0sVUFBVSxHQUFHLDBCQUEwQixDQUFDO0FBRzlDLE1BQU0sT0FBTyxZQUFZO0lBQ04sT0FBTyxHQUFHLE1BQU0sQ0FBbUIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFDdkQsZ0JBQWdCLEdBQUcsTUFBTSxDQUFnQixJQUFJLENBQUMsQ0FBQztJQUMvQyxlQUFlLEdBQUcsTUFBTSxDQUFTLElBQUksQ0FBQyxDQUFDO0lBQ3hELGdHQUFnRztJQUMvRSxNQUFNLEdBQUcsTUFBTSxDQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQ2pEOzs7O09BSUc7SUFDYyxTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUU5QixRQUFRLEdBQUcsTUFBTSxDQUFVLEtBQUssQ0FBQyxDQUFDO0lBRTFDLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ25DLGVBQWUsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDckQsY0FBYyxHQUFHLElBQUksQ0FB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Q0FBQyxJQUFJLHNCQUFzQjtvQkFDckUsT0FBTyxFQUFFLEtBQUssQ0FBQyxFQUFFO2lCQUNsQixDQUFDLENBQUM7WUFDTCxDQUFDO1FBQ0gsQ0FBQztRQUVELEtBQUssTUFBTSxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUMvQixJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDZCxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxLQUFLLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNyRyxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7d0dBcDdCVSxZQUFZOzRHQUFaLFlBQVk7OzRGQUFaLFlBQVk7a0JBRHhCLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBjb21wdXRlZCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB0eXBlIHtcclxuICBBdXRvUGF0Y2hNYXBwaW5nLFxyXG4gIERyb3Bkb3duT3B0aW9uLFxyXG4gIEVudGl0eUZvcm1Db25maWcsXHJcbiAgRW50aXR5UGVybWlzc2lvbnMsXHJcbiAgRW50aXR5UmVmZXJlbmNlQ29uZmlnLFxyXG4gIEZvcm1SdWxlLFxyXG4gIE5lc3RlZEZpZWxkQ29uZmlnLFxyXG4gIE5lc3RlZFRhYkNvbmZpZyxcclxuICBQYXRjaE9uVHJ1ZU1hcHBpbmcsXHJcbiAgUmljaEZpZWxkVHlwZSxcclxufSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XHJcbmltcG9ydCB7IGZpbmRUYWIsIGxhYmVsVG9JZCwgbm9ybWFsaXplQ29uZmlnT3B0aW9ucywgY29tcHV0ZUZpZWxkRHJpZnQsIGNyZWF0ZUZpZWxkU25hcHNob3QgfSBmcm9tICdAZHluYW1pYy1lbnRpdHkvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgY3JlYXRlRmllbGRDb25maWcsXHJcbiAgZ2V0RmllbGRUeXBlTWV0YSxcclxuICBodW1hbml6ZUlkLFxyXG4gIHR5cGUgRmxhZ1ZhbGlkYXRvcixcclxuICB0eXBlIFBhcmFtVmFsaWRhdG9yLFxyXG59IGZyb20gJy4vZmllbGQtY2F0YWxvZyc7XHJcbmltcG9ydCB7IGRlZXBDbG9uZSB9IGZyb20gJy4vY2xvbmUnO1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBCdWlsZGVyUHJvYmxlbSB7XHJcbiAgbGV2ZWw6ICdlcnJvcicgfCAnd2FybmluZyc7XHJcbiAgbWVzc2FnZTogc3RyaW5nO1xyXG4gIGZpZWxkSWQ/OiBzdHJpbmc7XHJcbn1cclxuXHJcbmNvbnN0IGNsb25lID0gZGVlcENsb25lO1xyXG5cclxuY29uc3QgSURfUEFUVEVSTiA9IC9eW0EtWmEtel9dW0EtWmEtejAtOV9dKiQvO1xyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgQnVpbGRlclN0b3JlIHtcclxuICBwcml2YXRlIHJlYWRvbmx5IF9jb25maWcgPSBzaWduYWw8RW50aXR5Rm9ybUNvbmZpZz4odGhpcy5lbXB0eUNvbmZpZygpKTtcclxuICBwcml2YXRlIHJlYWRvbmx5IF9zZWxlY3RlZEZpZWxkSWQgPSBzaWduYWw8c3RyaW5nIHwgbnVsbD4obnVsbCk7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBfYWN0aXZlTGFuZ3VhZ2UgPSBzaWduYWw8c3RyaW5nPignZW4nKTtcclxuICAvKiogUnVsZXMgbGl2ZSBiZXNpZGUgdGhlIGNvbmZpZzogdGhleSBhcmUgcGVyc2lzdGVkIHBlciBmb3JtLCBub3QgaW5zaWRlIGBFbnRpdHlGb3JtQ29uZmlnYC4gKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IF9ydWxlcyA9IHNpZ25hbDxGb3JtUnVsZVtdPihbXSk7XHJcbiAgLyoqXHJcbiAgICogRmllbGQgaWRzIHRoZSBhdXRob3Igb3ducyDigJQgc2V0IGJ5IGFuIGV4cGxpY2l0IHJlbmFtZSwgb3IgYnkgbG9hZGluZyBhIHNhdmVkIGNvbmZpZ1xyXG4gICAqIHdob3NlIGlkcyBhcmUgYWxyZWFkeSBsaXZlIGRhdGEga2V5cy4gSWRzIG91dHNpZGUgdGhpcyBzZXQgYXJlIHN0aWxsIGRlcml2ZWQgZnJvbSB0aGVcclxuICAgKiBmaWVsZCdzIGxhYmVsLiBCdWlsZGVyLXNlc3Npb24gc3RhdGUsIGRlbGliZXJhdGVseSBub3QgcGFydCBvZiB0aGUgZXhwb3J0ZWQgY29uZmlnLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgbWFudWFsSWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgX2lzRGlydHkgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xyXG5cclxuICByZWFkb25seSBjb25maWcgPSB0aGlzLl9jb25maWcuYXNSZWFkb25seSgpO1xyXG4gIHJlYWRvbmx5IHNlbGVjdGVkRmllbGRJZCA9IHRoaXMuX3NlbGVjdGVkRmllbGRJZC5hc1JlYWRvbmx5KCk7XHJcbiAgcmVhZG9ubHkgYWN0aXZlTGFuZ3VhZ2UgPSB0aGlzLl9hY3RpdmVMYW5ndWFnZS5hc1JlYWRvbmx5KCk7XHJcbiAgcmVhZG9ubHkgcnVsZXMgPSB0aGlzLl9ydWxlcy5hc1JlYWRvbmx5KCk7XHJcbiAgcmVhZG9ubHkgaXNEaXJ0eSA9IHRoaXMuX2lzRGlydHkuYXNSZWFkb25seSgpO1xyXG5cclxuICByZWFkb25seSB0YWJzID0gY29tcHV0ZWQ8TmVzdGVkVGFiQ29uZmlnW10+KCgpID0+IHRoaXMuX2NvbmZpZygpLnRhYnMgPz8gW10pO1xyXG5cclxuICByZWFkb25seSBmaWVsZHMgPSBjb21wdXRlZDxOZXN0ZWRGaWVsZENvbmZpZ1tdPigoKSA9PiB7XHJcbiAgICByZXR1cm4gKHRoaXMuX2NvbmZpZygpLnRhYnMgPz8gW10pLmZsYXRNYXAodCA9PiB0LmZpZWxkcyA/PyBbXSk7XHJcbiAgfSk7XHJcblxyXG4gIHJlYWRvbmx5IHNlbGVjdGVkRmllbGQgPSBjb21wdXRlZDxOZXN0ZWRGaWVsZENvbmZpZyB8IG51bGw+KCgpID0+IHtcclxuICAgIGNvbnN0IGlkID0gdGhpcy5fc2VsZWN0ZWRGaWVsZElkKCk7XHJcbiAgICBpZiAoIWlkKSByZXR1cm4gbnVsbDtcclxuICAgIHJldHVybiB0aGlzLmZpbmRGaWVsZEluVGFicyh0aGlzLl9jb25maWcoKS50YWJzLCBpZCk7XHJcbiAgfSk7XHJcblxyXG4gIHJlYWRvbmx5IHByb2JsZW1zID0gY29tcHV0ZWQ8QnVpbGRlclByb2JsZW1bXT4oKCkgPT4gdGhpcy52YWxpZGF0ZSh0aGlzLl9jb25maWcoKSkpO1xyXG4gIHJlYWRvbmx5IGVycm9ycyA9IGNvbXB1dGVkPEJ1aWxkZXJQcm9ibGVtW10+KCgpID0+XHJcbiAgICB0aGlzLnByb2JsZW1zKCkuZmlsdGVyKHAgPT4gcC5sZXZlbCA9PT0gJ2Vycm9yJyksXHJcbiAgKTtcclxuICByZWFkb25seSBpc1ZhbGlkID0gY29tcHV0ZWQ8Ym9vbGVhbj4oKCkgPT4gdGhpcy5lcnJvcnMoKS5sZW5ndGggPT09IDApO1xyXG5cclxuICAvLyDilIDilIDilIAgSW5pdGlhbGlzYXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIGxvYWQoY29uZmlnOiBFbnRpdHlGb3JtQ29uZmlnKTogdm9pZCB7XHJcbiAgICAvLyBDaGVjayBpZiBhbnkgZmllbGRzIGNhcnJ5IGJvdGggaW5saW5lIG9wdGlvbnMgYW5kIGxpc3ROYW1lIGJlZm9yZSBub3JtYWxpemluZyBvcHRpb25zXHJcbiAgICBjb25zdCBmaWVsZHNXaXRoQm90aCA9IHRoaXMuZ2V0QWxsRmllbGRzKGNvbmZpZy50YWJzID8/IFtdKS5maWx0ZXIoXHJcbiAgICAgIGYgPT4gQXJyYXkuaXNBcnJheShmLm9wdGlvbnMpICYmIGYub3B0aW9ucy5sZW5ndGggPiAwICYmIHR5cGVvZiBmLmxpc3ROYW1lID09PSAnc3RyaW5nJyAmJiBmLmxpc3ROYW1lLnRyaW0oKSAhPT0gJycsXHJcbiAgICApO1xyXG4gICAgZm9yIChjb25zdCBmIG9mIGZpZWxkc1dpdGhCb3RoKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICBgW0J1aWxkZXJTdG9yZV0gRmllbGQgXCIke2YuaWR9XCIgY2FycmllcyBib3RoIGlubGluZSBvcHRpb25zIGFuZCBsaXN0TmFtZSBcIiR7Zi5saXN0TmFtZX1cIi4gYCArXHJcbiAgICAgICAgICBgSW5saW5lIG9wdGlvbnMgd2luOyBsaXN0TmFtZSB3YXMgZHJvcHBlZC5gLFxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFRoZSBvdGhlciBib3VuZGFyeSB3aGVyZSBhIGNvbmZpZyBlbnRlcnMgdGhlIGxpYnJhcnkgKHRoZSByZW5kZXJlcidzIG5nT25DaGFuZ2VzIGlzXHJcbiAgICAvLyB0aGUgZmlyc3QpLiBBdXRob3JpbmcgbXVzdCBzdGFydCBmcm9tIHRoZSBjYW5vbmljYWwgb3B0aW9uIHNoYXBlLCBvciB0aGUgYnVpbGRlclxyXG4gICAgLy8gd291bGQgcm91bmQtdHJpcCBhIGxlZ2FjeSBjb25maWcgc3RyYWlnaHQgYmFjayBvdXQgdW5jaGFuZ2VkLlxyXG4gICAgY29uc3QgbmV4dCA9IGNsb25lKG5vcm1hbGl6ZUNvbmZpZ09wdGlvbnMoY29uZmlnKSk7XHJcbiAgICBuZXh0LnRhYnMgPSBuZXh0LnRhYnMgPz8gW107XHJcbiAgICBpZiAobmV4dC50YWJzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICBuZXh0LnRhYnMgPSBbeyBpZDogJ2RlZmF1bHQnLCBsYWJlbDogeyBlbjogJ0RlZmF1bHQnIH0sIGZpZWxkczogW10gfV07XHJcbiAgICB9XHJcbiAgICB0aGlzLl9jb25maWcuc2V0KG5leHQpO1xyXG4gICAgY29uc3QgZmlyc3RGaWVsZCA9IHRoaXMuZ2V0QWxsRmllbGRzKG5leHQudGFicylbMF07XHJcbiAgICB0aGlzLl9zZWxlY3RlZEZpZWxkSWQuc2V0KGZpcnN0RmllbGQ/LmlkID8/IG51bGwpO1xyXG4gICAgdGhpcy5fYWN0aXZlTGFuZ3VhZ2Uuc2V0KG5leHQuZGVmYXVsdExhbmd1YWdlID8/ICdlbicpO1xyXG5cclxuICAgIC8vIElkcyBpbiBhIHNhdmVkIGNvbmZpZyBhcmUgbGl2ZSBkYXRhIGtleXMg4oCUIHJlY29yZHMgYXJlIGFscmVhZHkgc3RvcmVkIHVuZGVyIHRoZW0uXHJcbiAgICAvLyBFZGl0aW5nIGEgbGFiZWwgbXVzdCBuZXZlciByZXdyaXRlIG9uZSwgc28gZnJlZXplIGV2ZXJ5IGlkIHRoZSBjb25maWcgYXJyaXZlZCB3aXRoLlxyXG4gICAgdGhpcy5tYW51YWxJZHMuY2xlYXIoKTtcclxuICAgIGZvciAoY29uc3QgZmllbGQgb2YgdGhpcy5nZXRBbGxGaWVsZHMobmV4dC50YWJzKSkgdGhpcy5tYW51YWxJZHMuYWRkKGZpZWxkLmlkKTtcclxuICAgIHRoaXMuX2lzRGlydHkuc2V0KGZhbHNlKTtcclxuICB9XHJcblxyXG4gIHJlc2V0KGVudGl0eSA9ICcnKTogdm9pZCB7XHJcbiAgICB0aGlzLl9jb25maWcuc2V0KHRoaXMuZW1wdHlDb25maWcoZW50aXR5KSk7XHJcbiAgICB0aGlzLl9zZWxlY3RlZEZpZWxkSWQuc2V0KG51bGwpO1xyXG4gICAgdGhpcy5fcnVsZXMuc2V0KFtdKTtcclxuICAgIHRoaXMubWFudWFsSWRzLmNsZWFyKCk7XHJcbiAgICB0aGlzLl9pc0RpcnR5LnNldChmYWxzZSk7XHJcbiAgfVxyXG5cclxuICByZXNldERpcnR5KCk6IHZvaWQge1xyXG4gICAgdGhpcy5faXNEaXJ0eS5zZXQoZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBlbXB0eUNvbmZpZyhlbnRpdHkgPSAnJyk6IEVudGl0eUZvcm1Db25maWcge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgZW50aXR5LFxyXG4gICAgICB2ZXJzaW9uOiAxLFxyXG4gICAgICBkZWZhdWx0TGFuZ3VhZ2U6ICdlbicsXHJcbiAgICAgIHRhYnM6IFtdLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBFbnRpdHktbGV2ZWwgc2V0dGluZ3Mg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIHNldEVudGl0eU5hbWUoZW50aXR5OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgZHJhZnQuZW50aXR5ID0gZW50aXR5LnRyaW0oKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc2V0RGVmYXVsdExhbmd1YWdlKGxhbmd1YWdlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgZHJhZnQuZGVmYXVsdExhbmd1YWdlID0gbGFuZ3VhZ2U7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHNldE1hc2tEYXRhKG1hc2s6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgZHJhZnQubWFza0RhdGEgPSBtYXNrO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzZXRQZXJtaXNzaW9uKGFjdGlvbjoga2V5b2YgRW50aXR5UGVybWlzc2lvbnMsIHJvbGVzOiBzdHJpbmdbXSk6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBwZXJtaXNzaW9uczogRW50aXR5UGVybWlzc2lvbnMgPSB7IC4uLihkcmFmdC5wZXJtaXNzaW9ucyA/PyB7fSkgfTtcclxuICAgICAgcGVybWlzc2lvbnNbYWN0aW9uXSA9IHJvbGVzO1xyXG4gICAgICBkcmFmdC5wZXJtaXNzaW9ucyA9IHBlcm1pc3Npb25zO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzZXRBY3RpdmVMYW5ndWFnZShsYW5ndWFnZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLl9hY3RpdmVMYW5ndWFnZS5zZXQobGFuZ3VhZ2UpO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIEhlbHBlciBUcmF2ZXJzYWwg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIHByaXZhdGUgZ2V0QWxsRmllbGRzKHRhYnM6IE5lc3RlZFRhYkNvbmZpZ1tdID0gW10pOiBOZXN0ZWRGaWVsZENvbmZpZ1tdIHtcclxuICAgIGNvbnN0IGxpc3Q6IE5lc3RlZEZpZWxkQ29uZmlnW10gPSBbXTtcclxuICAgIGZvciAoY29uc3QgdCBvZiB0YWJzKSB7XHJcbiAgICAgIGlmICh0LmZpZWxkcykgbGlzdC5wdXNoKC4uLnQuZmllbGRzKTtcclxuICAgICAgaWYgKHQuY2hpbGRyZW4pIGxpc3QucHVzaCguLi50aGlzLmdldEFsbEZpZWxkcyh0LmNoaWxkcmVuKSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gbGlzdDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZmluZEZpZWxkSW5UYWJzKHRhYnM6IE5lc3RlZFRhYkNvbmZpZ1tdID0gW10sIGlkOiBzdHJpbmcpOiBOZXN0ZWRGaWVsZENvbmZpZyB8IG51bGwge1xyXG4gICAgZm9yIChjb25zdCB0IG9mIHRhYnMpIHtcclxuICAgICAgaWYgKHQuZmllbGRzKSB7XHJcbiAgICAgICAgY29uc3QgZm91bmQgPSB0LmZpZWxkcy5maW5kKGYgPT4gZi5pZCA9PT0gaWQpO1xyXG4gICAgICAgIGlmIChmb3VuZCkgcmV0dXJuIGZvdW5kO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0LmNoaWxkcmVuKSB7XHJcbiAgICAgICAgY29uc3QgZm91bmQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyh0LmNoaWxkcmVuLCBpZCk7XHJcbiAgICAgICAgaWYgKGZvdW5kKSByZXR1cm4gZm91bmQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIEZpZWxkIENSVUQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIGFkZEZpZWxkKHR5cGU6IFJpY2hGaWVsZFR5cGUsIHRhcmdldFRhYklkPzogc3RyaW5nKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IG1ldGEgPSBnZXRGaWVsZFR5cGVNZXRhKHR5cGUpO1xyXG4gICAgY29uc3QgcHJlZml4ID0gbWV0YT8uaWRQcmVmaXggPz8gJ2ZpZWxkJztcclxuICAgIGNvbnN0IGFsbEZpZWxkcyA9IHRoaXMuZmllbGRzKCk7XHJcbiAgICBjb25zdCBpZCA9IHRoaXMudW5pcXVlSWQocHJlZml4LCBhbGxGaWVsZHMpO1xyXG5cclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSBjcmVhdGVGaWVsZENvbmZpZyh0eXBlLCBpZCwgZHJhZnQuZGVmYXVsdExhbmd1YWdlID8/ICdlbicpO1xyXG4gICAgICBjb25zdCB0YXJnZXRUYWIgPSB0YXJnZXRUYWJJZFxyXG4gICAgICAgID8gZHJhZnQudGFicy5maW5kKHQgPT4gdC5pZCA9PT0gdGFyZ2V0VGFiSWQpXHJcbiAgICAgICAgOiBkcmFmdC50YWJzWzBdO1xyXG4gICAgICBpZiAodGFyZ2V0VGFiKSB7XHJcbiAgICAgICAgdGFyZ2V0VGFiLmZpZWxkcyA9IHRhcmdldFRhYi5maWVsZHMgPz8gW107XHJcbiAgICAgICAgdGFyZ2V0VGFiLmZpZWxkcy5wdXNoKGZpZWxkKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBkcmFmdC50YWJzLnB1c2goeyBpZDogJ21haW4nLCBsYWJlbDogeyBlbjogJ01haW4nIH0sIGZpZWxkczogW2ZpZWxkXSB9KTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICB0aGlzLl9zZWxlY3RlZEZpZWxkSWQuc2V0KGlkKTtcclxuICAgIHJldHVybiBpZDtcclxuICB9XHJcblxyXG4gIHVwZGF0ZUZpZWxkKGlkOiBzdHJpbmcsIHBhdGNoOiBQYXJ0aWFsPE5lc3RlZEZpZWxkQ29uZmlnPik6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKGRyYWZ0LnRhYnMsIGlkKTtcclxuICAgICAgaWYgKGZpZWxkKSBPYmplY3QuYXNzaWduKGZpZWxkLCBwYXRjaCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJlbmFtZSBhIGZpZWxkIGV4cGxpY2l0bHksIHBpbm5pbmcgdGhlIGlkIHNvIGl0IGlzIG5vIGxvbmdlciBkZXJpdmVkIGZyb20gdGhlIGxhYmVsLlxyXG4gICAqXHJcbiAgICogTm90IHJlYWNoYWJsZSBmcm9tIHRoZSBpbnNwZWN0b3Ig4oCUIHRoZSBpZCBpbnB1dCBpcyByZWFkLW9ubHkgYnkgZGVzaWduLiBUaGlzIGV4aXN0cyBmb3JcclxuICAgKiBwcm9ncmFtbWF0aWMgY2FsbGVycyB0aGF0IG11c3QgbWF0Y2ggYW4gaWQgdG8gYW4gZXhpc3RpbmcgZGF0YSBrZXkuXHJcbiAgICovXHJcbiAgcmVuYW1lRmllbGQob2xkSWQ6IHN0cmluZywgbmV3SWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgdHJpbW1lZCA9IG5ld0lkLnRyaW0oKTtcclxuICAgIGlmICghdHJpbW1lZCB8fCB0cmltbWVkID09PSBvbGRJZCkgcmV0dXJuO1xyXG4gICAgaWYgKHRoaXMuZmllbGRzKCkuc29tZShmID0+IGYuaWQgPT09IHRyaW1tZWQpKSByZXR1cm47XHJcbiAgICBpZiAoIXRoaXMuZmluZEZpZWxkSW5UYWJzKHRoaXMuX2NvbmZpZygpLnRhYnMsIG9sZElkKSkgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMuYXBwbHlSZW5hbWUob2xkSWQsIHRyaW1tZWQpO1xyXG4gICAgdGhpcy5tYW51YWxJZHMuZGVsZXRlKG9sZElkKTtcclxuICAgIHRoaXMubWFudWFsSWRzLmFkZCh0cmltbWVkKTtcclxuICB9XHJcblxyXG4gIC8qKiBXaGV0aGVyIHRoaXMgZmllbGQncyBpZCBpcyBwaW5uZWQgKGxvYWRlZCBmcm9tIHN0b3JhZ2Ugb3IgZXhwbGljaXRseSByZW5hbWVkKS4gKi9cclxuICBoYXNNYW51YWxJZChpZDogc3RyaW5nKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5tYW51YWxJZHMuaGFzKGlkKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1vdmUgYSBmaWVsZCB0byBhIG5ldyBpZCBhbmQgcmVwb2ludCBldmVyeSBpZC1iYXNlZCByZWZlcmVuY2UgaW4gdGhlIGNvbmZpZyBhdCBpdC5cclxuICAgKlxyXG4gICAqIElkcyBhcmUgdGhlIHdpcmluZyBiZXR3ZWVuIGZpZWxkcyDigJQgcnVsZXMsIGNhc2NhZGVzLCBwYXRjaGVzIGFuZCBgc2hvd1doZW5gIGFsbCBhZGRyZXNzXHJcbiAgICogZmllbGRzIGJ5IGlkIOKAlCBzbyBhIHJlbmFtZSB0aGF0IG9ubHkgdG91Y2hlcyBgZmllbGQuaWRgIHNpbGVudGx5IGJyZWFrcyB0aGF0IHdpcmluZy5cclxuICAgKiBUaGF0IHdhcyBzdXJ2aXZhYmxlIHdoaWxlIHJlbmFtaW5nIHdhcyBhIHJhcmUgbWFudWFsIGFjdDsgbGFiZWwtZGVyaXZlZCBpZHMgbWFrZSBpdFxyXG4gICAqIHJvdXRpbmUsIHNvIHRoZSByZWZlcmVuY2VzIG1vdmUgd2l0aCBpdC5cclxuICAgKi9cclxuICBwcml2YXRlIGFwcGx5UmVuYW1lKG9sZElkOiBzdHJpbmcsIG5ld0lkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBvbGRJZCk7XHJcbiAgICAgIGlmICghZmllbGQpIHJldHVybjtcclxuICAgICAgZmllbGQuaWQgPSBuZXdJZDtcclxuXHJcbiAgICAgIGNvbnN0IHdhbGtGaWVsZHMgPSAoZmllbGRzOiBOZXN0ZWRGaWVsZENvbmZpZ1tdIHwgdW5kZWZpbmVkKSA9PiB7XHJcbiAgICAgICAgZm9yIChjb25zdCBmIG9mIGZpZWxkcyA/PyBbXSkge1xyXG4gICAgICAgICAgaWYgKGYuc2hvd1doZW4gJiYgb2xkSWQgaW4gZi5zaG93V2hlbikge1xyXG4gICAgICAgICAgICBjb25zdCBuZXh0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xyXG4gICAgICAgICAgICAvLyBSZWJ1aWxkIGluIHBsYWNlIHNvIGNvbmRpdGlvbiBvcmRlciBzdXJ2aXZlcyB0aGUgcmVuYW1lLlxyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhmLnNob3dXaGVuKSkge1xyXG4gICAgICAgICAgICAgIG5leHRba2V5ID09PSBvbGRJZCA/IG5ld0lkIDoga2V5XSA9IHZhbHVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGYuc2hvd1doZW4gPSBuZXh0O1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKGYuZW50aXR5UmVmZXJlbmNlPy5wYXJlbnRGaWVsZCA9PT0gb2xkSWQpIHtcclxuICAgICAgICAgICAgZi5lbnRpdHlSZWZlcmVuY2UgPSB7IC4uLmYuZW50aXR5UmVmZXJlbmNlLCBwYXJlbnRGaWVsZDogbmV3SWQgfTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmIChmLmF1dG9QYXRjaCkge1xyXG4gICAgICAgICAgICAvLyBgc291cmNlYCBuYW1lcyBhIGZpZWxkIG9uIHRoZSAqbGlua2VkKiByZWNvcmQsIG5vdCB0aGlzIGNvbmZpZyDigJQgbGVhdmUgaXQuXHJcbiAgICAgICAgICAgIGYuYXV0b1BhdGNoID0ge1xyXG4gICAgICAgICAgICAgIC4uLmYuYXV0b1BhdGNoLFxyXG4gICAgICAgICAgICAgIG1hcHBpbmdzOiBmLmF1dG9QYXRjaC5tYXBwaW5ncy5tYXAobSA9PlxyXG4gICAgICAgICAgICAgICAgbS50YXJnZXQgPT09IG9sZElkID8geyAuLi5tLCB0YXJnZXQ6IG5ld0lkIH0gOiBtLFxyXG4gICAgICAgICAgICAgICksXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAoZi5wYXRjaE9uVHJ1ZSkge1xyXG4gICAgICAgICAgICBmLnBhdGNoT25UcnVlID0gZi5wYXRjaE9uVHJ1ZS5tYXAobSA9PiAoe1xyXG4gICAgICAgICAgICAgIGZyb206IG0uZnJvbSA9PT0gb2xkSWQgPyBuZXdJZCA6IG0uZnJvbSxcclxuICAgICAgICAgICAgICB0bzogbS50byA9PT0gb2xkSWQgPyBuZXdJZCA6IG0udG8sXHJcbiAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGlmIChmLmNoaWxkcmVuPy5sZW5ndGgpIHdhbGtGaWVsZHMoZi5jaGlsZHJlbik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG4gICAgICBjb25zdCB3YWxrVGFicyA9ICh0YWJzOiBOZXN0ZWRUYWJDb25maWdbXSB8IHVuZGVmaW5lZCkgPT4ge1xyXG4gICAgICAgIGZvciAoY29uc3QgdGFiIG9mIHRhYnMgPz8gW10pIHtcclxuICAgICAgICAgIHdhbGtGaWVsZHModGFiLmZpZWxkcyk7XHJcbiAgICAgICAgICB3YWxrVGFicyh0YWIuY2hpbGRyZW4pO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuICAgICAgd2Fsa1RhYnMoZHJhZnQudGFicyk7XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLl9ydWxlcy51cGRhdGUocnVsZXMgPT5cclxuICAgICAgcnVsZXMubWFwKHJ1bGUgPT4gKHtcclxuICAgICAgICAuLi5ydWxlLFxyXG4gICAgICAgIGZpZWxkSWQ6IHJ1bGUuZmllbGRJZCA9PT0gb2xkSWQgPyBuZXdJZCA6IHJ1bGUuZmllbGRJZCxcclxuICAgICAgICB0YXJnZXRzOiBydWxlLnRhcmdldHMubWFwKHQgPT5cclxuICAgICAgICAgIHQudHlwZSA9PT0gJ2ZpZWxkJyAmJiB0LmlkID09PSBvbGRJZCA/IHsgLi4udCwgaWQ6IG5ld0lkIH0gOiB0LFxyXG4gICAgICAgICksXHJcbiAgICAgIH0pKSxcclxuICAgICk7XHJcblxyXG4gICAgaWYgKHRoaXMuX3NlbGVjdGVkRmllbGRJZCgpID09PSBvbGRJZCkgdGhpcy5fc2VsZWN0ZWRGaWVsZElkLnNldChuZXdJZCk7XHJcbiAgfVxyXG5cclxuICByZW1vdmVGaWVsZChpZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLm11dGF0ZShkcmFmdCA9PiB7XHJcbiAgICAgIGZvciAoY29uc3QgdGFiIG9mIGRyYWZ0LnRhYnMpIHtcclxuICAgICAgICBpZiAodGFiLmZpZWxkcykge1xyXG4gICAgICAgICAgdGFiLmZpZWxkcyA9IHRhYi5maWVsZHMuZmlsdGVyKGYgPT4gZi5pZCAhPT0gaWQpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICB0aGlzLm1hbnVhbElkcy5kZWxldGUoaWQpO1xyXG4gICAgaWYgKHRoaXMuX3NlbGVjdGVkRmllbGRJZCgpID09PSBpZCkgdGhpcy5fc2VsZWN0ZWRGaWVsZElkLnNldChudWxsKTtcclxuICB9XHJcblxyXG4gIGR1cGxpY2F0ZUZpZWxkKGlkOiBzdHJpbmcpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIC8vIExvb2sgdGhlIHNvdXJjZSB1cCBieSBpZCDigJQgbm90IGJ5IGN1cnJlbnQgc2VsZWN0aW9uLiBUaGUgaW5zZXJ0IGJlbG93IHNlYXJjaGVzIGJ5IGlkXHJcbiAgICAvLyB0b28sIHNvIGZhbGxpbmcgYmFjayB0byB0aGUgc2VsZWN0ZWQgZmllbGQgY291bGQgcmVwb3J0IGEgbmV3IGlkIHdoaWxlIGluc2VydGluZ1xyXG4gICAgLy8gbm90aGluZywgb3IgZHVwbGljYXRlIGEgZmllbGQgdGhlIGNhbGxlciBuZXZlciBuYW1lZC5cclxuICAgIGNvbnN0IHNvdXJjZSA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKHRoaXMuX2NvbmZpZygpLnRhYnMsIGlkKTtcclxuICAgIGlmICghc291cmNlKSByZXR1cm4gbnVsbDtcclxuICAgIGNvbnN0IG1ldGEgPSBnZXRGaWVsZFR5cGVNZXRhKHNvdXJjZS50eXBlKTtcclxuICAgIGNvbnN0IHByZWZpeCA9IG1ldGE/LmlkUHJlZml4ID8/ICdmaWVsZCc7XHJcbiAgICBjb25zdCBuZXdJZCA9IHRoaXMudW5pcXVlSWQocHJlZml4LCB0aGlzLmZpZWxkcygpKTtcclxuXHJcbiAgICB0aGlzLm11dGF0ZShkcmFmdCA9PiB7XHJcbiAgICAgIGZvciAoY29uc3QgdGFiIG9mIGRyYWZ0LnRhYnMpIHtcclxuICAgICAgICBjb25zdCBpbmRleCA9ICh0YWIuZmllbGRzID8/IFtdKS5maW5kSW5kZXgoZiA9PiBmLmlkID09PSBpZCk7XHJcbiAgICAgICAgaWYgKGluZGV4ICE9PSAtMSkge1xyXG4gICAgICAgICAgY29uc3QgY29weSA9IGNsb25lKHNvdXJjZSk7XHJcbiAgICAgICAgICBjb3B5LmlkID0gbmV3SWQ7XHJcbiAgICAgICAgICB0YWIuZmllbGRzIS5zcGxpY2UoaW5kZXggKyAxLCAwLCBjb3B5KTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICB0aGlzLl9zZWxlY3RlZEZpZWxkSWQuc2V0KG5ld0lkKTtcclxuICAgIHJldHVybiBuZXdJZDtcclxuICB9XHJcblxyXG4gIG1vdmVGaWVsZChpZDogc3RyaW5nLCBkaXJlY3Rpb246IC0xIHwgMSk6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBmb3IgKGNvbnN0IHRhYiBvZiBkcmFmdC50YWJzKSB7XHJcbiAgICAgICAgY29uc3QgZmllbGRzID0gdGFiLmZpZWxkcyA/PyBbXTtcclxuICAgICAgICBjb25zdCBmcm9tID0gZmllbGRzLmZpbmRJbmRleChmID0+IGYuaWQgPT09IGlkKTtcclxuICAgICAgICBpZiAoZnJvbSAhPT0gLTEpIHtcclxuICAgICAgICAgIGNvbnN0IHRvID0gZnJvbSArIGRpcmVjdGlvbjtcclxuICAgICAgICAgIGlmICh0byA8IDAgfHwgdG8gPj0gZmllbGRzLmxlbmd0aCkgcmV0dXJuO1xyXG4gICAgICAgICAgY29uc3QgW2l0ZW1dID0gZmllbGRzLnNwbGljZShmcm9tLCAxKTtcclxuICAgICAgICAgIGZpZWxkcy5zcGxpY2UodG8sIDAsIGl0ZW0pO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvKiogU2FmZSByZW9yZGVyIGZvciBkcmFnICYgZHJvcCB3aXRoaW4gYWN0aXZlIHRhYiBvciBmbGF0IGxpc3QgKi9cclxuICByZW9yZGVyRmllbGQoZnJvbUluZGV4OiBudW1iZXIsIHRvSW5kZXg6IG51bWJlciwgdGFiSWQ/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgdGFyZ2V0VGFiID0gdGFiSWRcclxuICAgICAgICA/IGRyYWZ0LnRhYnMuZmluZCh0ID0+IHQuaWQgPT09IHRhYklkKVxyXG4gICAgICAgIDogZHJhZnQudGFic1swXTtcclxuICAgICAgY29uc3QgZmllbGRzID0gdGFyZ2V0VGFiPy5maWVsZHMgPz8gW107XHJcbiAgICAgIGlmIChcclxuICAgICAgICBmcm9tSW5kZXggPCAwIHx8XHJcbiAgICAgICAgdG9JbmRleCA8IDAgfHxcclxuICAgICAgICBmcm9tSW5kZXggPj0gZmllbGRzLmxlbmd0aCB8fFxyXG4gICAgICAgIHRvSW5kZXggPj0gZmllbGRzLmxlbmd0aFxyXG4gICAgICApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgW2l0ZW1dID0gZmllbGRzLnNwbGljZShmcm9tSW5kZXgsIDEpO1xyXG4gICAgICBmaWVsZHMuc3BsaWNlKHRvSW5kZXgsIDAsIGl0ZW0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzZWxlY3RGaWVsZChpZDogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xyXG4gICAgdGhpcy5fc2VsZWN0ZWRGaWVsZElkLnNldChpZCk7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgTG9jYWxpc2VkIHRleHQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIC8qKlxyXG4gICAqIFNldCBhIGZpZWxkJ3MgbGFiZWwsIGFuZCBkZXJpdmUgdGhlIGZpZWxkJ3MgaWQgZnJvbSBpdDogdHlwZSBcIkVtcGxveWVlIENvdW50XCIsIGdldFxyXG4gICAqIGBlbXBsb3llZUNvdW50YC4gVGhlIGluc3BlY3RvciByZW5kZXJzIHRoZSBpZCByZWFkLW9ubHksIHNvIHRoaXMgaXMgdGhlIG9ubHkgd2F5IGFcclxuICAgKiBuZXcgZmllbGQncyBpZCBpcyBzZXQuXHJcbiAgICpcclxuICAgKiBUd28gdGhpbmdzIHN0b3AgZGVyaXZhdGlvbjogYSBjb25maWcgbG9hZGVkIGZyb20gc3RvcmFnZSAoaXRzIGlkcyBhcmUgbGl2ZSBkYXRhIGtleXNcclxuICAgKiB0aGF0IHJlY29yZHMgYXJlIGFscmVhZHkgc3RvcmVkIHVuZGVyIOKAlCBzZWUgYGxvYWRgKSwgYW5kIGFuIGV4cGxpY2l0IGByZW5hbWVGaWVsZGBcclxuICAgKiBjYWxsLCB3aGljaCByZW1haW5zIGF2YWlsYWJsZSB0byBwcm9ncmFtbWF0aWMgY2FsbGVycy5cclxuICAgKlxyXG4gICAqIE9ubHkgdGhlIGNvbmZpZydzIGRlZmF1bHQgbGFuZ3VhZ2UgZHJpdmVzIHRoZSBpZDsgdHJhbnNsYXRpbmcgYSBsYWJlbCBtdXN0IG5vdCByZW5hbWVcclxuICAgKiBhbnl0aGluZy5cclxuICAgKi9cclxuICBzZXRGaWVsZExhYmVsKGlkOiBzdHJpbmcsIGxhbmd1YWdlOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBpZCk7XHJcbiAgICAgIGlmIChmaWVsZCkgZmllbGQubGFiZWwgPSB7IC4uLmZpZWxkLmxhYmVsLCBbbGFuZ3VhZ2VdOiB2YWx1ZSB9O1xyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKGxhbmd1YWdlICE9PSAodGhpcy5fY29uZmlnKCkuZGVmYXVsdExhbmd1YWdlID8/ICdlbicpKSByZXR1cm47XHJcbiAgICBpZiAodGhpcy5tYW51YWxJZHMuaGFzKGlkKSkgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IGRlcml2ZWQgPSBsYWJlbFRvSWQodmFsdWUpO1xyXG4gICAgaWYgKCFkZXJpdmVkIHx8IGRlcml2ZWQgPT09IGlkKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy5hcHBseVJlbmFtZShpZCwgdGhpcy5hdmFpbGFibGVJZChkZXJpdmVkLCBpZCkpO1xyXG4gIH1cclxuXHJcbiAgLyoqIGBkZXJpdmVkYCwgb3IgYGRlcml2ZWRfMmAsIGBkZXJpdmVkXzNg4oCmIGlmIGFub3RoZXIgZmllbGQgYWxyZWFkeSBob2xkcyBpdC4gKi9cclxuICBwcml2YXRlIGF2YWlsYWJsZUlkKGRlcml2ZWQ6IHN0cmluZywgY3VycmVudElkOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgdGFrZW4gPSBuZXcgU2V0KHRoaXMuZmllbGRzKCkubWFwKGYgPT4gZi5pZCkuZmlsdGVyKGZpZCA9PiBmaWQgIT09IGN1cnJlbnRJZCkpO1xyXG4gICAgaWYgKCF0YWtlbi5oYXMoZGVyaXZlZCkpIHJldHVybiBkZXJpdmVkO1xyXG5cclxuICAgIGxldCBuID0gMjtcclxuICAgIHdoaWxlICh0YWtlbi5oYXMoYCR7ZGVyaXZlZH1fJHtufWApKSBuICs9IDE7XHJcbiAgICByZXR1cm4gYCR7ZGVyaXZlZH1fJHtufWA7XHJcbiAgfVxyXG5cclxuICBzZXRGaWVsZFBsYWNlaG9sZGVyKGlkOiBzdHJpbmcsIGxhbmd1YWdlOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBpZCk7XHJcbiAgICAgIGlmICghZmllbGQpIHJldHVybjtcclxuICAgICAgZmllbGQucGxhY2Vob2xkZXIgPSB7IC4uLihmaWVsZC5wbGFjZWhvbGRlciA/PyB7fSksIFtsYW5ndWFnZV06IHZhbHVlIH07XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBWYWxpZGF0b3JzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICB0b2dnbGVGbGFnVmFsaWRhdG9yKGlkOiBzdHJpbmcsIHZhbGlkYXRvcjogRmxhZ1ZhbGlkYXRvciwgb246IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBpZCk7XHJcbiAgICAgIGlmICghZmllbGQpIHJldHVybjtcclxuICAgICAgZmllbGQudmFsaWRhdG9ycyA9IGZpZWxkLnZhbGlkYXRvcnMgPz8ge307XHJcbiAgICAgIGlmICh2YWxpZGF0b3IgPT09ICdyZXF1aXJlZCcpIHtcclxuICAgICAgICBpZiAob24pIGZpZWxkLnZhbGlkYXRvcnMucmVxdWlyZWQgPSB0cnVlO1xyXG4gICAgICAgIGVsc2UgZGVsZXRlIGZpZWxkLnZhbGlkYXRvcnMucmVxdWlyZWQ7XHJcbiAgICAgIH0gZWxzZSBpZiAodmFsaWRhdG9yID09PSAnZW1haWwnKSB7XHJcbiAgICAgICAgaWYgKG9uKSBmaWVsZC52YWxpZGF0b3JzLnBhdHRlcm4gPSAnXlthLXpBLVowLTkuXyUrLV0rQFthLXpBLVowLTkuLV0rXFxcXC5bYS16QS1aXXsyLH0kJztcclxuICAgICAgICBlbHNlIGRlbGV0ZSBmaWVsZC52YWxpZGF0b3JzLnBhdHRlcm47XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgc2V0UGFyYW1WYWxpZGF0b3IoaWQ6IHN0cmluZywgdmFsaWRhdG9yOiBQYXJhbVZhbGlkYXRvciwgdmFsdWU6IG51bWJlciB8IG51bGwpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBpZCk7XHJcbiAgICAgIGlmICghZmllbGQpIHJldHVybjtcclxuICAgICAgZmllbGQudmFsaWRhdG9ycyA9IGZpZWxkLnZhbGlkYXRvcnMgPz8ge307XHJcbiAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IE51bWJlci5pc05hTih2YWx1ZSkpIHtcclxuICAgICAgICBkZWxldGUgZmllbGQudmFsaWRhdG9yc1t2YWxpZGF0b3JdO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGZpZWxkLnZhbGlkYXRvcnNbdmFsaWRhdG9yXSA9IHZhbHVlO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGdldFBhcmFtVmFsaWRhdG9yKGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZywgdmFsaWRhdG9yOiBQYXJhbVZhbGlkYXRvcik6IG51bWJlciB8IG51bGwge1xyXG4gICAgY29uc3QgdmFsID0gZmllbGQudmFsaWRhdG9ycz8uW3ZhbGlkYXRvcl07XHJcbiAgICByZXR1cm4gdHlwZW9mIHZhbCA9PT0gJ251bWJlcicgPyB2YWwgOiBudWxsO1xyXG4gIH1cclxuXHJcbiAgaGFzRmxhZ1ZhbGlkYXRvcihmaWVsZDogTmVzdGVkRmllbGRDb25maWcsIHZhbGlkYXRvcjogRmxhZ1ZhbGlkYXRvcik6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHZhbGlkYXRvciA9PT0gJ3JlcXVpcmVkJykgcmV0dXJuICEhZmllbGQudmFsaWRhdG9ycz8ucmVxdWlyZWQ7XHJcbiAgICBpZiAodmFsaWRhdG9yID09PSAnZW1haWwnKSByZXR1cm4gISFmaWVsZC52YWxpZGF0b3JzPy5wYXR0ZXJuO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIE9wdGlvbnMgKGRyb3Bkb3duIC8gbXVsdGlTZWxlY3QgLyByYWRpbykg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIC8qKlxyXG4gICAqIFdoZXJlIGEgY2hvaWNlIGZpZWxkJ3Mgb3B0aW9ucyBjb21lIGZyb20uXHJcbiAgICpcclxuICAgKiBgZW50aXR5YCBpcyBhYnNlbnQgb24gcHVycG9zZTogaW4gdGhpcyBtb2RlbCBhbiBlbnRpdHkgcmVmZXJlbmNlIGlzIGEgZmllbGQgKnR5cGUqXHJcbiAgICogKGBlbnRpdHktcmVmYCksIG5vdCBhIGRhdGEgc291cmNlIGEgZHJvcGRvd24gY2FuIHN3aXRjaCB0bywgc28gb2ZmZXJpbmcgaXQgaGVyZSB3b3VsZCBtZWFuXHJcbiAgICogbXV0YXRpbmcgdGhlIGZpZWxkJ3MgdHlwZSDigJQgYW5kIHJlYnVpbGRpbmcgaXRzIGNvbnRyb2wg4oCUIGZyb20gYSBzb3VyY2UgcGlja2VyLiBUaGVcclxuICAgKiBleGNsdXNpb24gdGhhdCBtYXR0ZXJzIHdpdGhpbiBhIGNob2ljZSBmaWVsZCBpcyBpbmxpbmUgYG9wdGlvbnNgIHZzIGBsaXN0TmFtZWAuXHJcbiAgICovXHJcbiAgZmllbGREYXRhU291cmNlKGZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZyB8IHVuZGVmaW5lZCk6ICdub25lJyB8ICdtYW51YWwnIHwgJ2xvb2t1cCcge1xyXG4gICAgaWYgKCFmaWVsZCkgcmV0dXJuICdub25lJztcclxuICAgIC8vIFByZXNlbmNlLCBub3QgZW1wdGluZXNzOiBhIHNvdXJjZSB0aGUgYXV0aG9yIGhhcyBwaWNrZWQgYnV0IG5vdCBmaWxsZWQgaW4geWV0IOKAlCBub1xyXG4gICAgLy8gb3B0aW9ucyBhdXRob3JlZCwgbm8gbGlzdCBuYW1lIHR5cGVkIOKAlCBtdXN0IHN0aWxsIHJlYWQgYXMgdGhhdCBzb3VyY2UsIG9yIHRoZSBlZGl0b3JcclxuICAgIC8vIGZvciBpdCBkaXNhcHBlYXJzIHRoZSBtb21lbnQgdGhleSBzZWxlY3QgaXQuXHJcbiAgICBpZiAoQXJyYXkuaXNBcnJheShmaWVsZC5vcHRpb25zKSkgcmV0dXJuICdtYW51YWwnO1xyXG4gICAgaWYgKHR5cGVvZiBmaWVsZC5saXN0TmFtZSA9PT0gJ3N0cmluZycpIHJldHVybiAnbG9va3VwJztcclxuICAgIHJldHVybiAnbm9uZSc7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTd2l0Y2ggYSBjaG9pY2UgZmllbGQncyBkYXRhIHNvdXJjZSwgY2xlYXJpbmcgdGhlIG9uZSBpdCBpcyBsZWF2aW5nLlxyXG4gICAqXHJcbiAgICogVGhlIHJlZmVyZW5jZSBtYWtlcyB0aGVzZSBtdXR1YWxseSBleGNsdXNpdmUgKGRvYyDCpzQuNCkgYW5kIGl0IGhhcyB0byBzdGF5IHRoYXQgd2F5IGhlcmU6XHJcbiAgICogYG9wdGlvbnNGb3JgIHJlc29sdmVzIGlubGluZSBvcHRpb25zIGZpcnN0LCBzbyBhIGZpZWxkIGxlZnQgaG9sZGluZyBib3RoIHdvdWxkIHNpbGVudGx5XHJcbiAgICogaWdub3JlIGl0cyBsaXN0LlxyXG4gICAqL1xyXG4gIHNldEZpZWxkRGF0YVNvdXJjZShmaWVsZElkOiBzdHJpbmcsIHNvdXJjZTogJ25vbmUnIHwgJ21hbnVhbCcgfCAnbG9va3VwJyk6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKGRyYWZ0LnRhYnMsIGZpZWxkSWQpO1xyXG4gICAgICBpZiAoIWZpZWxkKSByZXR1cm47XHJcbiAgICAgIGlmIChzb3VyY2UgPT09ICdtYW51YWwnKSB7XHJcbiAgICAgICAgZGVsZXRlIGZpZWxkLmxpc3ROYW1lO1xyXG4gICAgICAgIGZpZWxkLm9wdGlvbnMgPSBmaWVsZC5vcHRpb25zPy5sZW5ndGggPyBmaWVsZC5vcHRpb25zIDogW107XHJcbiAgICAgIH0gZWxzZSBpZiAoc291cmNlID09PSAnbG9va3VwJykge1xyXG4gICAgICAgIGRlbGV0ZSBmaWVsZC5vcHRpb25zO1xyXG4gICAgICAgIGZpZWxkLmxpc3ROYW1lID0gZmllbGQubGlzdE5hbWUgPz8gJyc7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZGVsZXRlIGZpZWxkLm9wdGlvbnM7XHJcbiAgICAgICAgZGVsZXRlIGZpZWxkLmxpc3ROYW1lO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKiBTZXQgdGhlIG5hbWVkIGxpc3QgYSBjaG9pY2UgZmllbGQgcmVhZHMgaXRzIG9wdGlvbnMgZnJvbS4gKi9cclxuICBzZXRMaXN0TmFtZShmaWVsZElkOiBzdHJpbmcsIGxpc3ROYW1lOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBmaWVsZElkKTtcclxuICAgICAgaWYgKCFmaWVsZCkgcmV0dXJuO1xyXG4gICAgICBjb25zdCB0cmltbWVkID0gbGlzdE5hbWUudHJpbSgpO1xyXG4gICAgICBpZiAodHJpbW1lZCkge1xyXG4gICAgICAgIGZpZWxkLmxpc3ROYW1lID0gdHJpbW1lZDtcclxuICAgICAgICAvLyBCZWx0IGFuZCBicmFjZXM6IGlubGluZSBvcHRpb25zIHdvdWxkIHdpbiBvdmVyIHRoZSBsaXN0IGF0IHJlbmRlciB0aW1lLlxyXG4gICAgICAgIGRlbGV0ZSBmaWVsZC5vcHRpb25zO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGZpZWxkLmxpc3ROYW1lID0gJyc7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqIExpbmsgYSBmaWVsZCB0byBhIGZpZWxkIGRlZmluZWQgaW4gYW5vdGhlciBlbnRpdHkgY29uZmlndXJhdGlvbiAoUGhhc2UgOCkuICovXHJcbiAgbGlua1JlZmVyZW5jZWRGaWVsZChmaWVsZElkOiBzdHJpbmcsIHNvdXJjZUVudGl0eUtleTogc3RyaW5nLCBzb3VyY2VGaWVsZDogTmVzdGVkRmllbGRDb25maWcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBmaWVsZElkKTtcclxuICAgICAgaWYgKCFmaWVsZCkgcmV0dXJuO1xyXG4gICAgICBmaWVsZC5pc1JlZmVyZW5jZWQgPSB0cnVlO1xyXG4gICAgICBmaWVsZC5yZWZlcmVuY2VkRW50aXR5S2V5ID0gc291cmNlRW50aXR5S2V5O1xyXG4gICAgICBmaWVsZC5yZWZlcmVuY2VkRmllbGRJZCA9IHNvdXJjZUZpZWxkLmlkO1xyXG4gICAgICBmaWVsZC5yZWZlcmVuY2VkU25hcHNob3QgPSBjcmVhdGVGaWVsZFNuYXBzaG90KHNvdXJjZUZpZWxkKTtcclxuICAgICAgZmllbGQuaGFzRHJpZnQgPSBmYWxzZTtcclxuICAgICAgLy8gQ29weSBsYWJlbCwgdHlwZSwgdmFsaWRhdG9ycywgb3B0aW9ucyBmcm9tIHNvdXJjZVxyXG4gICAgICBpZiAoc291cmNlRmllbGQubGFiZWwpIGZpZWxkLmxhYmVsID0gY2xvbmUoc291cmNlRmllbGQubGFiZWwpO1xyXG4gICAgICBpZiAoc291cmNlRmllbGQudHlwZSkgZmllbGQudHlwZSA9IHNvdXJjZUZpZWxkLnR5cGU7XHJcbiAgICAgIGlmIChzb3VyY2VGaWVsZC52YWxpZGF0b3JzKSBmaWVsZC52YWxpZGF0b3JzID0gY2xvbmUoc291cmNlRmllbGQudmFsaWRhdG9ycyk7XHJcbiAgICAgIGlmIChzb3VyY2VGaWVsZC5vcHRpb25zKSBmaWVsZC5vcHRpb25zID0gY2xvbmUoc291cmNlRmllbGQub3B0aW9ucyk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKiBVbmxpbmsgYSByZWZlcmVuY2VkIGZpZWxkIGJhY2sgdG8gYW4gaW5kZXBlbmRlbnQgZmllbGQuICovXHJcbiAgdW5saW5rUmVmZXJlbmNlZEZpZWxkKGZpZWxkSWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKGRyYWZ0LnRhYnMsIGZpZWxkSWQpO1xyXG4gICAgICBpZiAoIWZpZWxkKSByZXR1cm47XHJcbiAgICAgIGRlbGV0ZSBmaWVsZC5pc1JlZmVyZW5jZWQ7XHJcbiAgICAgIGRlbGV0ZSBmaWVsZC5yZWZlcmVuY2VkRW50aXR5S2V5O1xyXG4gICAgICBkZWxldGUgZmllbGQucmVmZXJlbmNlZEZpZWxkSWQ7XHJcbiAgICAgIGRlbGV0ZSBmaWVsZC5yZWZlcmVuY2VkU25hcHNob3Q7XHJcbiAgICAgIGRlbGV0ZSBmaWVsZC5oYXNEcmlmdDtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqIFN5bmMgYSBkcmlmdGVkIHJlZmVyZW5jZWQgZmllbGQgd2l0aCB0aGUgdXBkYXRlZCBzb3VyY2UgZmllbGQgZGVmaW5pdGlvbi4gKi9cclxuICBzeW5jUmVmZXJlbmNlZEZpZWxkKGZpZWxkSWQ6IHN0cmluZywgY3VycmVudFNvdXJjZUZpZWxkOiBOZXN0ZWRGaWVsZENvbmZpZyk6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKGRyYWZ0LnRhYnMsIGZpZWxkSWQpO1xyXG4gICAgICBpZiAoIWZpZWxkIHx8ICFmaWVsZC5pc1JlZmVyZW5jZWQpIHJldHVybjtcclxuICAgICAgZmllbGQucmVmZXJlbmNlZFNuYXBzaG90ID0gY3JlYXRlRmllbGRTbmFwc2hvdChjdXJyZW50U291cmNlRmllbGQpO1xyXG4gICAgICBmaWVsZC5oYXNEcmlmdCA9IGZhbHNlO1xyXG4gICAgICBpZiAoY3VycmVudFNvdXJjZUZpZWxkLmxhYmVsKSBmaWVsZC5sYWJlbCA9IGNsb25lKGN1cnJlbnRTb3VyY2VGaWVsZC5sYWJlbCk7XHJcbiAgICAgIGlmIChjdXJyZW50U291cmNlRmllbGQudHlwZSkgZmllbGQudHlwZSA9IGN1cnJlbnRTb3VyY2VGaWVsZC50eXBlO1xyXG4gICAgICBpZiAoY3VycmVudFNvdXJjZUZpZWxkLnZhbGlkYXRvcnMpIGZpZWxkLnZhbGlkYXRvcnMgPSBjbG9uZShjdXJyZW50U291cmNlRmllbGQudmFsaWRhdG9ycyk7XHJcbiAgICAgIGlmIChjdXJyZW50U291cmNlRmllbGQub3B0aW9ucykgZmllbGQub3B0aW9ucyA9IGNsb25lKGN1cnJlbnRTb3VyY2VGaWVsZC5vcHRpb25zKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqIFNjYW4gYWxsIHJlZmVyZW5jZWQgZmllbGRzIGluIHRoZSBjb25maWcgYW5kIHVwZGF0ZSB0aGVpciBoYXNEcmlmdCBzdGF0ZSBhZ2FpbnN0IGN1cnJlbnQgc291cmNlIGNvbmZpZ3MuICovXHJcbiAgY2hlY2tEcmlmdChzb3VyY2VDb25maWdzOiBSZWNvcmQ8c3RyaW5nLCBFbnRpdHlGb3JtQ29uZmlnPik6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBzY2FuRmllbGRzID0gKGZpZWxkczogTmVzdGVkRmllbGRDb25maWdbXSkgPT4ge1xyXG4gICAgICAgIGZvciAoY29uc3QgZiBvZiBmaWVsZHMpIHtcclxuICAgICAgICAgIGlmIChmLmlzUmVmZXJlbmNlZCAmJiBmLnJlZmVyZW5jZWRFbnRpdHlLZXkgJiYgZi5yZWZlcmVuY2VkRmllbGRJZCkge1xyXG4gICAgICAgICAgICBjb25zdCBzb3VyY2VDb25maWcgPSBzb3VyY2VDb25maWdzW2YucmVmZXJlbmNlZEVudGl0eUtleV07XHJcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZUZpZWxkID0gc291cmNlQ29uZmlnXHJcbiAgICAgICAgICAgICAgPyB0aGlzLmZpbmRGaWVsZEluVGFicyhzb3VyY2VDb25maWcudGFicyA/PyBbXSwgZi5yZWZlcmVuY2VkRmllbGRJZClcclxuICAgICAgICAgICAgICA6IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgZi5oYXNEcmlmdCA9IGNvbXB1dGVGaWVsZERyaWZ0KGYsIHNvdXJjZUZpZWxkID8/IHVuZGVmaW5lZCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBpZiAoZi5jaGlsZHJlbj8ubGVuZ3RoKSBzY2FuRmllbGRzKGYuY2hpbGRyZW4pO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuXHJcbiAgICAgIGZvciAoY29uc3QgdGFiIG9mIGRyYWZ0LnRhYnMgPz8gW10pIHtcclxuICAgICAgICBpZiAodGFiLmZpZWxkcz8ubGVuZ3RoKSBzY2FuRmllbGRzKHRhYi5maWVsZHMpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGFkZE9wdGlvbihmaWVsZElkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBmaWVsZElkKTtcclxuICAgICAgaWYgKCFmaWVsZCkgcmV0dXJuO1xyXG4gICAgICBjb25zdCBvcHRpb25zID0gZmllbGQub3B0aW9ucyA/PyBbXTtcclxuICAgICAgY29uc3QgbiA9IG9wdGlvbnMubGVuZ3RoICsgMTtcclxuICAgICAgY29uc3QgbGFuZyA9IGRyYWZ0LmRlZmF1bHRMYW5ndWFnZSA/PyAnZW4nO1xyXG4gICAgICBvcHRpb25zLnB1c2goeyBbbGFuZ106IGBPcHRpb24gJHtufWAgfSk7XHJcbiAgICAgIGZpZWxkLm9wdGlvbnMgPSBvcHRpb25zO1xyXG4gICAgICAvLyBBdXRob3JpbmcgYW4gaW5saW5lIG9wdGlvbiBtYWtlcyB0aGlzIGEgbWFudWFsIGZpZWxkIOKAlCBzZWUgYHNldEZpZWxkRGF0YVNvdXJjZWAuXHJcbiAgICAgIGRlbGV0ZSBmaWVsZC5saXN0TmFtZTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqIE1lcmdlIGxhbmd1YWdlIGtleXMgaW50byBhbiBvcHRpb24uIGBzZXRPcHRpb25MYWJlbGAgaXMgdGhlIHVzdWFsIHNpbmdsZS1sYW5ndWFnZSBwYXRoLiAqL1xyXG4gIHVwZGF0ZU9wdGlvbihmaWVsZElkOiBzdHJpbmcsIGluZGV4OiBudW1iZXIsIHBhdGNoOiBEcm9wZG93bk9wdGlvbik6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKGRyYWZ0LnRhYnMsIGZpZWxkSWQpO1xyXG4gICAgICBjb25zdCBvcHRpb24gPSBmaWVsZD8ub3B0aW9ucz8uW2luZGV4XTtcclxuICAgICAgaWYgKCFvcHRpb24pIHJldHVybjtcclxuICAgICAgZmllbGQub3B0aW9ucyFbaW5kZXhdID0geyAuLi5vcHRpb24sIC4uLnBhdGNoIH07XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNldCBhbiBvcHRpb24ncyB0ZXh0IGZvciBvbmUgbGFuZ3VhZ2UuXHJcbiAgICpcclxuICAgKiBBbiBvcHRpb24gaXMgYSBsYW5ndWFnZS1rZXllZCBvYmplY3QgYW5kIHRoZSBkaXNwbGF5ZWQgdGV4dCAqKmlzKiogdGhlIHN0b3JlZCB2YWx1ZSxcclxuICAgKiBzbyB0aGlzIGlzIHRoZSBvbmx5IHdheSB0byBlZGl0IG9uZSDigJQgdGhlcmUgaXMgbm8gc2VwYXJhdGUgdmFsdWUgdG8gc2V0LlxyXG4gICAqL1xyXG4gIHNldE9wdGlvbkxhYmVsKGZpZWxkSWQ6IHN0cmluZywgaW5kZXg6IG51bWJlciwgbGFuZ3VhZ2U6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKGRyYWZ0LnRhYnMsIGZpZWxkSWQpO1xyXG4gICAgICBjb25zdCBvcHRpb24gPSBmaWVsZD8ub3B0aW9ucz8uW2luZGV4XTtcclxuICAgICAgaWYgKCFvcHRpb24pIHJldHVybjtcclxuICAgICAgZmllbGQub3B0aW9ucyFbaW5kZXhdID0geyAuLi5vcHRpb24sIFtsYW5ndWFnZV06IHZhbHVlIH07XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHJlbW92ZU9wdGlvbihmaWVsZElkOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBmaWVsZElkKTtcclxuICAgICAgaWYgKCFmaWVsZD8ub3B0aW9ucykgcmV0dXJuO1xyXG4gICAgICBmaWVsZC5vcHRpb25zID0gZmllbGQub3B0aW9ucy5maWx0ZXIoKF8sIGkpID0+IGkgIT09IGluZGV4KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIEVudGl0eSByZWZlcmVuY2UgLyBjYXNjYWRlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICAvKiogTWVyZ2UgYSBwYXRjaCBpbnRvIGEgZmllbGQncyBgZW50aXR5UmVmZXJlbmNlYCBibG9jaywga2VlcGluZyBpdCBlbmFibGVkLiAqL1xyXG4gIHVwZGF0ZUVudGl0eVJlZmVyZW5jZShmaWVsZElkOiBzdHJpbmcsIHBhdGNoOiBQYXJ0aWFsPEVudGl0eVJlZmVyZW5jZUNvbmZpZz4pOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBmaWVsZElkKTtcclxuICAgICAgaWYgKCFmaWVsZCkgcmV0dXJuO1xyXG4gICAgICBjb25zdCBuZXh0OiBFbnRpdHlSZWZlcmVuY2VDb25maWcgPSB7XHJcbiAgICAgICAgLi4uKGZpZWxkLmVudGl0eVJlZmVyZW5jZSA/PyB7IGVuYWJsZWQ6IHRydWUgfSksXHJcbiAgICAgICAgLi4ucGF0Y2gsXHJcbiAgICAgICAgZW5hYmxlZDogdHJ1ZSxcclxuICAgICAgfTtcclxuICAgICAgLy8gRHJvcCBrZXlzIGV4cGxpY2l0bHkgY2xlYXJlZCB0byBgdW5kZWZpbmVkYCBzbyBleHBvcnRlZCBjb25maWdzIHN0YXkgY2xlYW4uXHJcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHBhdGNoKSBhcyAoa2V5b2YgRW50aXR5UmVmZXJlbmNlQ29uZmlnKVtdKSB7XHJcbiAgICAgICAgaWYgKHBhdGNoW2tleV0gPT09IHVuZGVmaW5lZCkgZGVsZXRlIG5leHRba2V5XTtcclxuICAgICAgfVxyXG4gICAgICBmaWVsZC5lbnRpdHlSZWZlcmVuY2UgPSBuZXh0O1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgYXV0b1BhdGNoIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBhZGRBdXRvUGF0Y2hNYXBwaW5nKGZpZWxkSWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKGRyYWZ0LnRhYnMsIGZpZWxkSWQpO1xyXG4gICAgICBpZiAoIWZpZWxkKSByZXR1cm47XHJcbiAgICAgIGNvbnN0IHRhcmdldFRhYiA9IGZpZWxkLmF1dG9QYXRjaD8udGFyZ2V0VGFiID8/IGRyYWZ0LnRhYnNbMF0/LmlkID8/ICcnO1xyXG4gICAgICBjb25zdCBtYXBwaW5ncyA9IFsuLi4oZmllbGQuYXV0b1BhdGNoPy5tYXBwaW5ncyA/PyBbXSksIHsgc291cmNlOiAnJywgdGFyZ2V0OiAnJyB9XTtcclxuICAgICAgZmllbGQuYXV0b1BhdGNoID0geyB0YXJnZXRUYWIsIG1hcHBpbmdzIH07XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHNldEF1dG9QYXRjaFRhcmdldFRhYihmaWVsZElkOiBzdHJpbmcsIHRhcmdldFRhYjogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLm11dGF0ZShkcmFmdCA9PiB7XHJcbiAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maW5kRmllbGRJblRhYnMoZHJhZnQudGFicywgZmllbGRJZCk7XHJcbiAgICAgIGlmICghZmllbGQ/LmF1dG9QYXRjaCkgcmV0dXJuO1xyXG4gICAgICBmaWVsZC5hdXRvUGF0Y2ggPSB7IC4uLmZpZWxkLmF1dG9QYXRjaCwgdGFyZ2V0VGFiIH07XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHVwZGF0ZUF1dG9QYXRjaE1hcHBpbmcoZmllbGRJZDogc3RyaW5nLCBpbmRleDogbnVtYmVyLCBwYXRjaDogUGFydGlhbDxBdXRvUGF0Y2hNYXBwaW5nPik6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBmaWVsZCA9IHRoaXMuZmluZEZpZWxkSW5UYWJzKGRyYWZ0LnRhYnMsIGZpZWxkSWQpO1xyXG4gICAgICBpZiAoIWZpZWxkPy5hdXRvUGF0Y2g/Lm1hcHBpbmdzPy5baW5kZXhdKSByZXR1cm47XHJcbiAgICAgIGZpZWxkLmF1dG9QYXRjaCA9IHtcclxuICAgICAgICAuLi5maWVsZC5hdXRvUGF0Y2gsXHJcbiAgICAgICAgbWFwcGluZ3M6IGZpZWxkLmF1dG9QYXRjaC5tYXBwaW5ncy5tYXAoKG0sIGkpID0+IChpID09PSBpbmRleCA/IHsgLi4ubSwgLi4ucGF0Y2ggfSA6IG0pKSxcclxuICAgICAgfTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqIFJlbW92aW5nIHRoZSBsYXN0IG1hcHBpbmcgZHJvcHMgYGF1dG9QYXRjaGAgZW50aXJlbHkg4oCUIG5vIGVtcHR5IGNvbmZpZyBpbiB0aGUgZXhwb3J0LiAqL1xyXG4gIHJlbW92ZUF1dG9QYXRjaE1hcHBpbmcoZmllbGRJZDogc3RyaW5nLCBpbmRleDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICB0aGlzLm11dGF0ZShkcmFmdCA9PiB7XHJcbiAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maW5kRmllbGRJblRhYnMoZHJhZnQudGFicywgZmllbGRJZCk7XHJcbiAgICAgIGlmICghZmllbGQ/LmF1dG9QYXRjaCkgcmV0dXJuO1xyXG4gICAgICBjb25zdCBtYXBwaW5ncyA9IGZpZWxkLmF1dG9QYXRjaC5tYXBwaW5ncy5maWx0ZXIoKF8sIGkpID0+IGkgIT09IGluZGV4KTtcclxuICAgICAgaWYgKG1hcHBpbmdzLmxlbmd0aCA9PT0gMCkgZGVsZXRlIGZpZWxkLmF1dG9QYXRjaDtcclxuICAgICAgZWxzZSBmaWVsZC5hdXRvUGF0Y2ggPSB7IC4uLmZpZWxkLmF1dG9QYXRjaCwgbWFwcGluZ3MgfTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIHBhdGNoT25UcnVlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBhZGRQYXRjaE9uVHJ1ZU1hcHBpbmcoZmllbGRJZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLm11dGF0ZShkcmFmdCA9PiB7XHJcbiAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maW5kRmllbGRJblRhYnMoZHJhZnQudGFicywgZmllbGRJZCk7XHJcbiAgICAgIGlmICghZmllbGQpIHJldHVybjtcclxuICAgICAgZmllbGQucGF0Y2hPblRydWUgPSBbLi4uKGZpZWxkLnBhdGNoT25UcnVlID8/IFtdKSwgeyBmcm9tOiAnJywgdG86ICcnIH1dO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICB1cGRhdGVQYXRjaE9uVHJ1ZU1hcHBpbmcoZmllbGRJZDogc3RyaW5nLCBpbmRleDogbnVtYmVyLCBwYXRjaDogUGFydGlhbDxQYXRjaE9uVHJ1ZU1hcHBpbmc+KTogdm9pZCB7XHJcbiAgICB0aGlzLm11dGF0ZShkcmFmdCA9PiB7XHJcbiAgICAgIGNvbnN0IGZpZWxkID0gdGhpcy5maW5kRmllbGRJblRhYnMoZHJhZnQudGFicywgZmllbGRJZCk7XHJcbiAgICAgIGlmICghZmllbGQ/LnBhdGNoT25UcnVlPy5baW5kZXhdKSByZXR1cm47XHJcbiAgICAgIGZpZWxkLnBhdGNoT25UcnVlID0gZmllbGQucGF0Y2hPblRydWUubWFwKChtLCBpKSA9PiAoaSA9PT0gaW5kZXggPyB7IC4uLm0sIC4uLnBhdGNoIH0gOiBtKSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHJlbW92ZVBhdGNoT25UcnVlTWFwcGluZyhmaWVsZElkOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBmaWVsZElkKTtcclxuICAgICAgaWYgKCFmaWVsZD8ucGF0Y2hPblRydWUpIHJldHVybjtcclxuICAgICAgY29uc3QgbWFwcGluZ3MgPSBmaWVsZC5wYXRjaE9uVHJ1ZS5maWx0ZXIoKF8sIGkpID0+IGkgIT09IGluZGV4KTtcclxuICAgICAgaWYgKG1hcHBpbmdzLmxlbmd0aCA9PT0gMCkgZGVsZXRlIGZpZWxkLnBhdGNoT25UcnVlO1xyXG4gICAgICBlbHNlIGZpZWxkLnBhdGNoT25UcnVlID0gbWFwcGluZ3M7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBzaG93V2hlbiAoc3RhdGljIGNvbmRpdGlvbmFsIHZpc2liaWxpdHkpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICAvKiogUmVwbGFjZSBhIGZpZWxkJ3MgYHNob3dXaGVuYCBtYXA7IGFuIGVtcHR5IG1hcCByZW1vdmVzIHRoZSBjb25kaXRpb24uICovXHJcbiAgc2V0U2hvd1doZW4oZmllbGRJZDogc3RyaW5nLCBzaG93V2hlbjogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLmZpbmRGaWVsZEluVGFicyhkcmFmdC50YWJzLCBmaWVsZElkKTtcclxuICAgICAgaWYgKCFmaWVsZCkgcmV0dXJuO1xyXG4gICAgICBpZiAoIXNob3dXaGVuIHx8IE9iamVjdC5rZXlzKHNob3dXaGVuKS5sZW5ndGggPT09IDApIGRlbGV0ZSBmaWVsZC5zaG93V2hlbjtcclxuICAgICAgZWxzZSBmaWVsZC5zaG93V2hlbiA9IHNob3dXaGVuO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgUnVsZXMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIC8qKiBSdWxlcyBmb3IgdGhlIGZpZWxkIGN1cnJlbnRseSBzZWxlY3RlZCBpbiB0aGUgaW5zcGVjdG9yLiAqL1xyXG4gIHJlYWRvbmx5IHJ1bGVzRm9yU2VsZWN0ZWRGaWVsZCA9IGNvbXB1dGVkPEZvcm1SdWxlW10+KCgpID0+IHtcclxuICAgIGNvbnN0IGlkID0gdGhpcy5fc2VsZWN0ZWRGaWVsZElkKCk7XHJcbiAgICBpZiAoIWlkKSByZXR1cm4gW107XHJcbiAgICByZXR1cm4gdGhpcy5fcnVsZXMoKS5maWx0ZXIociA9PiByLmZpZWxkSWQgPT09IGlkIHx8IHIudGFyZ2V0cy5zb21lKHQgPT4gdC5pZCA9PT0gaWQpKTtcclxuICB9KTtcclxuXHJcbiAgbG9hZFJ1bGVzKHJ1bGVzOiBGb3JtUnVsZVtdKTogdm9pZCB7XHJcbiAgICB0aGlzLl9ydWxlcy5zZXQoY2xvbmUocnVsZXMpKTtcclxuICB9XHJcblxyXG4gIGFkZFJ1bGUocnVsZTogRm9ybVJ1bGUpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgaWQgPSBydWxlLmlkPy50cmltKCkgfHwgdGhpcy51bmlxdWVJZCgncnVsZScsIHRoaXMuX3J1bGVzKCkubWFwKHIgPT4gKHsgaWQ6IHIuaWQgPz8gJycgfSkpKTtcclxuICAgIHRoaXMuX3J1bGVzLnVwZGF0ZShydWxlcyA9PiBbLi4ucnVsZXMsIHsgLi4uY2xvbmUocnVsZSksIGlkIH1dKTtcclxuICAgIHJldHVybiBpZDtcclxuICB9XHJcblxyXG4gIHVwZGF0ZVJ1bGUoaWQ6IHN0cmluZywgcGF0Y2g6IFBhcnRpYWw8Rm9ybVJ1bGU+KTogdm9pZCB7XHJcbiAgICB0aGlzLl9ydWxlcy51cGRhdGUocnVsZXMgPT4gcnVsZXMubWFwKHIgPT4gKHIuaWQgPT09IGlkID8geyAuLi5yLCAuLi5jbG9uZShwYXRjaCksIGlkIH0gOiByKSkpO1xyXG4gIH1cclxuXHJcbiAgcmVtb3ZlUnVsZShpZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLl9ydWxlcy51cGRhdGUocnVsZXMgPT4gcnVsZXMuZmlsdGVyKHIgPT4gci5pZCAhPT0gaWQpKTtcclxuICB9XHJcblxyXG4gIHRvZ2dsZVJ1bGUoaWQ6IHN0cmluZywgZW5hYmxlZDogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgdGhpcy51cGRhdGVSdWxlKGlkLCB7IGVuYWJsZWQgfSk7XHJcbiAgfVxyXG5cclxuICAvKiogTW92ZSBhIHJ1bGUgaW4gcHJpb3JpdHkgb3JkZXIuIFByaW9yaXRpZXMgYXJlIHJlbnVtYmVyZWQgMS4ubiBzbyB0aGV5IHN0YXkgY29udGlndW91cy4gKi9cclxuICBtb3ZlUnVsZShpZDogc3RyaW5nLCBkaXJlY3Rpb246IC0xIHwgMSk6IHZvaWQge1xyXG4gICAgdGhpcy5fcnVsZXMudXBkYXRlKHJ1bGVzID0+IHtcclxuICAgICAgY29uc3QgbmV4dCA9IFsuLi5ydWxlc107XHJcbiAgICAgIGNvbnN0IGZyb20gPSBuZXh0LmZpbmRJbmRleChyID0+IHIuaWQgPT09IGlkKTtcclxuICAgICAgaWYgKGZyb20gPT09IC0xKSByZXR1cm4gcnVsZXM7XHJcbiAgICAgIGNvbnN0IHRvID0gZnJvbSArIGRpcmVjdGlvbjtcclxuICAgICAgaWYgKHRvIDwgMCB8fCB0byA+PSBuZXh0Lmxlbmd0aCkgcmV0dXJuIHJ1bGVzO1xyXG4gICAgICBjb25zdCBbaXRlbV0gPSBuZXh0LnNwbGljZShmcm9tLCAxKTtcclxuICAgICAgbmV4dC5zcGxpY2UodG8sIDAsIGl0ZW0pO1xyXG4gICAgICByZXR1cm4gbmV4dC5tYXAoKHIsIGkpID0+ICh7IC4uLnIsIHByaW9yaXR5OiBpICsgMSB9KSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGV4cG9ydFJ1bGVzKCk6IEZvcm1SdWxlW10ge1xyXG4gICAgcmV0dXJuIGNsb25lKHRoaXMuX3J1bGVzKCkpO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIFRhYnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIGFkZFRhYigpOiBzdHJpbmcge1xyXG4gICAgLy8gTXVzdCBiZSB1bmlxdWUgYWNyb3NzIHRoZSB3aG9sZSB0cmVlLCBub3QganVzdCB0aGUgdG9wIGxldmVsOiBhIHRhYiBpZCBpcyB0aGUgcmVjb3JkXHJcbiAgICAvLyBzdG9yYWdlIHBhdGgsIHNvIGEgbmV3IHRvcC1sZXZlbCB0YWIgY29sbGlkaW5nIHdpdGggYW4gZXhpc3Rpbmcgc3ViLXRhYiB3b3VsZCBtYWtlIHR3b1xyXG4gICAgLy8gdGFicyB3cml0ZSB0byB0aGUgc2FtZSBrZXkgYW5kIGJyZWFrIGZpbmRUYWIvZ2V0VGFiUGF0aC5cclxuICAgIGNvbnN0IGlkID0gdGhpcy51bmlxdWVJZCgndGFiJywgdGhpcy5hbGxUYWJJZHMoKS5tYXAodGlkID0+ICh7IGlkOiB0aWQgfSkpKTtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgdGFicyA9IGRyYWZ0LnRhYnMgPz8gKGRyYWZ0LnRhYnMgPSBbXSk7XHJcbiAgICAgIGNvbnN0IGxhbmcgPSBkcmFmdC5kZWZhdWx0TGFuZ3VhZ2UgPz8gJ2VuJztcclxuICAgICAgdGFicy5wdXNoKHsgaWQsIGxhYmVsOiB7IFtsYW5nXTogaHVtYW5pemVJZChpZCkgfSwgZmllbGRzOiBbXSB9KTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGlkO1xyXG4gIH1cclxuXHJcbiAgLyoqIEV2ZXJ5IHRhYiBpZCBpbiB0aGUgdHJlZSwgYXQgYW55IGRlcHRoLiBUYWIgaWRzIG11c3QgYmUgZ2xvYmFsbHkgdW5pcXVlIOKAlCB0aGV5IGFyZSBwYXRocy4gKi9cclxuICBwcml2YXRlIGFsbFRhYklkcygpOiBzdHJpbmdbXSB7XHJcbiAgICBjb25zdCBpZHM6IHN0cmluZ1tdID0gW107XHJcbiAgICBjb25zdCBjb2xsZWN0ID0gKHRhYnM6IE5lc3RlZFRhYkNvbmZpZ1tdIHwgdW5kZWZpbmVkKSA9PiB7XHJcbiAgICAgIGZvciAoY29uc3QgdCBvZiB0YWJzID8/IFtdKSB7XHJcbiAgICAgICAgaWRzLnB1c2godC5pZCk7XHJcbiAgICAgICAgY29sbGVjdCh0LmNoaWxkcmVuKTtcclxuICAgICAgfVxyXG4gICAgfTtcclxuICAgIGNvbGxlY3QodGhpcy5fY29uZmlnKCkudGFicyk7XHJcbiAgICByZXR1cm4gaWRzO1xyXG4gIH1cclxuXHJcbiAgYWRkU3ViVGFiKHBhcmVudElkOiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgaWQgPSB0aGlzLnVuaXF1ZUlkKCd0YWInLCB0aGlzLmFsbFRhYklkcygpLm1hcCh0aWQgPT4gKHsgaWQ6IHRpZCB9KSkpO1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBwYXJlbnQgPSBmaW5kVGFiKGRyYWZ0LnRhYnMsIHBhcmVudElkKTtcclxuICAgICAgaWYgKHBhcmVudCkge1xyXG4gICAgICAgIHBhcmVudC5jaGlsZHJlbiA9IHBhcmVudC5jaGlsZHJlbiA/PyBbXTtcclxuICAgICAgICBjb25zdCBsYW5nID0gZHJhZnQuZGVmYXVsdExhbmd1YWdlID8/ICdlbic7XHJcbiAgICAgICAgcGFyZW50LmNoaWxkcmVuLnB1c2goeyBpZCwgbGFiZWw6IHsgW2xhbmddOiBodW1hbml6ZUlkKGlkKSB9LCBmaWVsZHM6IFtdIH0pO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICAgIHJldHVybiBpZDtcclxuICB9XHJcblxyXG4gIHNldFByaW1hcnlUYWIodGFiSWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5tdXRhdGUoZHJhZnQgPT4ge1xyXG4gICAgICBjb25zdCBtYXJrUHJpbWFyeSA9ICh0YWJzOiBOZXN0ZWRUYWJDb25maWdbXSkgPT4ge1xyXG4gICAgICAgIGZvciAoY29uc3QgdCBvZiB0YWJzKSB7XHJcbiAgICAgICAgICB0LmlzUHJpbWFyeVRhYiA9IHQuaWQgPT09IHRhYklkO1xyXG4gICAgICAgICAgaWYgKHQuY2hpbGRyZW4pIG1hcmtQcmltYXJ5KHQuY2hpbGRyZW4pO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuICAgICAgbWFya1ByaW1hcnkoZHJhZnQudGFicyA/PyBbXSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHVwZGF0ZVRhYihpZDogc3RyaW5nLCBwYXRjaDogUGFydGlhbDxOZXN0ZWRUYWJDb25maWc+KTogdm9pZCB7XHJcbiAgICB0aGlzLm11dGF0ZShkcmFmdCA9PiB7XHJcbiAgICAgIGNvbnN0IHRhYiA9IGZpbmRUYWIoZHJhZnQudGFicywgaWQpO1xyXG4gICAgICBpZiAodGFiKSBPYmplY3QuYXNzaWduKHRhYiwgcGF0Y2gpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzZXRUYWJMYWJlbChpZDogc3RyaW5nLCBsYW5ndWFnZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLm11dGF0ZShkcmFmdCA9PiB7XHJcbiAgICAgIGNvbnN0IHRhYiA9IGZpbmRUYWIoZHJhZnQudGFicywgaWQpO1xyXG4gICAgICBpZiAodGFiKSB0YWIubGFiZWwgPSB7IC4uLnRhYi5sYWJlbCwgW2xhbmd1YWdlXTogdmFsdWUgfTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcmVtb3ZlVGFiKGlkOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgcmVtb3ZlUmVjdXJzaXZlID0gKHRhYnM6IE5lc3RlZFRhYkNvbmZpZ1tdKTogTmVzdGVkVGFiQ29uZmlnW10gPT4ge1xyXG4gICAgICAgIHJldHVybiB0YWJzXHJcbiAgICAgICAgICAuZmlsdGVyKHQgPT4gdC5pZCAhPT0gaWQpXHJcbiAgICAgICAgICAubWFwKHQgPT4gKHtcclxuICAgICAgICAgICAgLi4udCxcclxuICAgICAgICAgICAgY2hpbGRyZW46IHQuY2hpbGRyZW4gPyByZW1vdmVSZWN1cnNpdmUodC5jaGlsZHJlbikgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICB9KSk7XHJcbiAgICAgIH07XHJcbiAgICAgIGRyYWZ0LnRhYnMgPSByZW1vdmVSZWN1cnNpdmUoZHJhZnQudGFicyA/PyBbXSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG1vdmVUYWIoaWQ6IHN0cmluZywgZGlyZWN0aW9uOiAtMSB8IDEpOiB2b2lkIHtcclxuICAgIHRoaXMubXV0YXRlKGRyYWZ0ID0+IHtcclxuICAgICAgY29uc3QgdGFicyA9IGRyYWZ0LnRhYnMgPz8gW107XHJcbiAgICAgIGNvbnN0IGZyb20gPSB0YWJzLmZpbmRJbmRleCh0ID0+IHQuaWQgPT09IGlkKTtcclxuICAgICAgaWYgKGZyb20gPT09IC0xKSByZXR1cm47XHJcbiAgICAgIGNvbnN0IHRvID0gZnJvbSArIGRpcmVjdGlvbjtcclxuICAgICAgaWYgKHRvIDwgMCB8fCB0byA+PSB0YWJzLmxlbmd0aCkgcmV0dXJuO1xyXG4gICAgICBjb25zdCBbaXRlbV0gPSB0YWJzLnNwbGljZShmcm9tLCAxKTtcclxuICAgICAgdGFicy5zcGxpY2UodG8sIDAsIGl0ZW0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgRXhwb3J0IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBleHBvcnRDb25maWcoKTogRW50aXR5Rm9ybUNvbmZpZyB7XHJcbiAgICByZXR1cm4gY2xvbmUodGhpcy5fY29uZmlnKCkpO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIEludGVybmFscyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgcHJpdmF0ZSBtdXRhdGUoZm46IChkcmFmdDogRW50aXR5Rm9ybUNvbmZpZykgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgY29uc3QgZHJhZnQgPSBjbG9uZSh0aGlzLl9jb25maWcoKSk7XHJcbiAgICBkcmFmdC50YWJzID0gZHJhZnQudGFicyA/PyBbXTtcclxuICAgIGZuKGRyYWZ0KTtcclxuICAgIHRoaXMuX2NvbmZpZy5zZXQoZHJhZnQpO1xyXG4gICAgdGhpcy5faXNEaXJ0eS5zZXQodHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVuaXF1ZUlkKHByZWZpeDogc3RyaW5nLCBleGlzdGluZzogeyBpZDogc3RyaW5nIH1bXSk6IHN0cmluZyB7XHJcbiAgICBjb25zdCB0YWtlbiA9IG5ldyBTZXQoZXhpc3RpbmcubWFwKGUgPT4gZS5pZCkpO1xyXG4gICAgbGV0IG4gPSAxO1xyXG4gICAgbGV0IGNhbmRpZGF0ZSA9IGAke3ByZWZpeH1fJHtufWA7XHJcbiAgICB3aGlsZSAodGFrZW4uaGFzKGNhbmRpZGF0ZSkpIHtcclxuICAgICAgbiArPSAxO1xyXG4gICAgICBjYW5kaWRhdGUgPSBgJHtwcmVmaXh9XyR7bn1gO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGNhbmRpZGF0ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGUoY29uZmlnOiBFbnRpdHlGb3JtQ29uZmlnKTogQnVpbGRlclByb2JsZW1bXSB7XHJcbiAgICBjb25zdCBwcm9ibGVtczogQnVpbGRlclByb2JsZW1bXSA9IFtdO1xyXG5cclxuICAgIGlmICghY29uZmlnLmVudGl0eSB8fCAhY29uZmlnLmVudGl0eS50cmltKCkpIHtcclxuICAgICAgcHJvYmxlbXMucHVzaCh7IGxldmVsOiAnZXJyb3InLCBtZXNzYWdlOiAnRW50aXR5IG5hbWUgaXMgcmVxdWlyZWQuJyB9KTtcclxuICAgIH0gZWxzZSBpZiAoIUlEX1BBVFRFUk4udGVzdChjb25maWcuZW50aXR5KSkge1xyXG4gICAgICBwcm9ibGVtcy5wdXNoKHtcclxuICAgICAgICBsZXZlbDogJ2Vycm9yJyxcclxuICAgICAgICBtZXNzYWdlOlxyXG4gICAgICAgICAgJ0VudGl0eSBuYW1lIG11c3Qgc3RhcnQgd2l0aCBhIGxldHRlciBvciB1bmRlcnNjb3JlIGFuZCBjb250YWluIG9ubHkgbGV0dGVycywgZGlnaXRzLCBhbmQgdW5kZXJzY29yZXMuJyxcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgYWxsRmllbGRzID0gdGhpcy5nZXRBbGxGaWVsZHMoY29uZmlnLnRhYnMpO1xyXG4gICAgaWYgKGFsbEZpZWxkcy5sZW5ndGggPT09IDApIHtcclxuICAgICAgcHJvYmxlbXMucHVzaCh7IGxldmVsOiAnd2FybmluZycsIG1lc3NhZ2U6ICdUaGlzIGVudGl0eSBoYXMgbm8gZmllbGRzIHlldC4nIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHNlZW4gPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xyXG4gICAgZm9yIChjb25zdCBmaWVsZCBvZiBhbGxGaWVsZHMpIHtcclxuICAgICAgc2Vlbi5zZXQoZmllbGQuaWQsIChzZWVuLmdldChmaWVsZC5pZCkgPz8gMCkgKyAxKTtcclxuXHJcbiAgICAgIGlmICghZmllbGQuaWQgfHwgIUlEX1BBVFRFUk4udGVzdChmaWVsZC5pZCkpIHtcclxuICAgICAgICBwcm9ibGVtcy5wdXNoKHtcclxuICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxyXG4gICAgICAgICAgbWVzc2FnZTogYEZpZWxkIGlkIFwiJHtmaWVsZC5pZH1cIiBpcyBub3QgYSB2YWxpZCBpZGVudGlmaWVyLmAsXHJcbiAgICAgICAgICBmaWVsZElkOiBmaWVsZC5pZCxcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgbGFiZWxzID0gZmllbGQubGFiZWwgPz8ge307XHJcbiAgICAgIGNvbnN0IGhhc0xhYmVsID0gT2JqZWN0LnZhbHVlcyhsYWJlbHMpLnNvbWUodiA9PiB0eXBlb2YgdiA9PT0gJ3N0cmluZycgJiYgdi50cmltKCkpO1xyXG4gICAgICBpZiAoIWhhc0xhYmVsKSB7XHJcbiAgICAgICAgcHJvYmxlbXMucHVzaCh7XHJcbiAgICAgICAgICBsZXZlbDogJ3dhcm5pbmcnLFxyXG4gICAgICAgICAgbWVzc2FnZTogYEZpZWxkIFwiJHtmaWVsZC5pZH1cIiBoYXMgbm8gbGFiZWwuYCxcclxuICAgICAgICAgIGZpZWxkSWQ6IGZpZWxkLmlkLFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCBtZXRhID0gZ2V0RmllbGRUeXBlTWV0YShmaWVsZC50eXBlKTtcclxuICAgICAgLy8gQSBmaWVsZCBvbiB0aGUgbG9va3VwIHNvdXJjZSBoYXMgbm8gaW5saW5lIG9wdGlvbnMgYnkgZGVzaWduIOKAlCBpdHMgb3B0aW9ucyBhcnJpdmUgZnJvbVxyXG4gICAgICAvLyB0aGUgcmVnaXN0cnkgYXQgcnVudGltZS4gV2FybiBvbmx5IGFib3V0IHRoZSBtaXNzaW5nIGxpc3QgbmFtZS5cclxuICAgICAgaWYgKG1ldGE/Lmhhc09wdGlvbnMgJiYgdHlwZW9mIGZpZWxkLmxpc3ROYW1lID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgIGlmICghZmllbGQubGlzdE5hbWUudHJpbSgpKSB7XHJcbiAgICAgICAgICBwcm9ibGVtcy5wdXNoKHtcclxuICAgICAgICAgICAgbGV2ZWw6ICd3YXJuaW5nJyxcclxuICAgICAgICAgICAgbWVzc2FnZTogYEZpZWxkIFwiJHtmaWVsZC5pZH1cIiByZWFkcyBvcHRpb25zIGZyb20gYSBuYW1lZCBsaXN0IGJ1dCBoYXMgbm8gbGlzdCBuYW1lLmAsXHJcbiAgICAgICAgICAgIGZpZWxkSWQ6IGZpZWxkLmlkLFxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2UgaWYgKG1ldGE/Lmhhc09wdGlvbnMgJiYgKCFmaWVsZC5vcHRpb25zIHx8IGZpZWxkLm9wdGlvbnMubGVuZ3RoID09PSAwKSkge1xyXG4gICAgICAgIHByb2JsZW1zLnB1c2goe1xyXG4gICAgICAgICAgbGV2ZWw6ICd3YXJuaW5nJyxcclxuICAgICAgICAgIG1lc3NhZ2U6IGBGaWVsZCBcIiR7ZmllbGQuaWR9XCIgaXMgYSAke2ZpZWxkLnR5cGV9IGJ1dCBoYXMgbm8gb3B0aW9ucy5gLFxyXG4gICAgICAgICAgZmllbGRJZDogZmllbGQuaWQsXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGNvbnN0IFtpZCwgY291bnRdIG9mIHNlZW4pIHtcclxuICAgICAgaWYgKGNvdW50ID4gMSkge1xyXG4gICAgICAgIHByb2JsZW1zLnB1c2goeyBsZXZlbDogJ2Vycm9yJywgbWVzc2FnZTogYER1cGxpY2F0ZSBmaWVsZCBpZCBcIiR7aWR9XCIgKCR7Y291bnR9w5cpLmAsIGZpZWxkSWQ6IGlkIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHByb2JsZW1zO1xyXG4gIH1cclxufVxyXG4iXX0=
|