obsidian-dev-utils 24.1.1 → 24.2.1-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/lib/cjs/Library.cjs +1 -1
  3. package/dist/lib/cjs/Object.cjs +1 -1
  4. package/dist/lib/cjs/Object.d.cts +6 -2
  5. package/dist/lib/cjs/ScriptUtils/esbuild/preprocessPlugin.cjs +1 -1
  6. package/dist/lib/cjs/Transformers/Transformer.cjs +1 -1
  7. package/dist/lib/cjs/Transformers/Transformer.d.cts +2 -1
  8. package/dist/lib/cjs/Type.cjs +1 -1
  9. package/dist/lib/cjs/Type.d.cts +6 -0
  10. package/dist/lib/cjs/obsidian/App.cjs +1 -1
  11. package/dist/lib/cjs/obsidian/FileChange.cjs +1 -1
  12. package/dist/lib/cjs/obsidian/Frontmatter.cjs +1 -1
  13. package/dist/lib/cjs/obsidian/Frontmatter.d.cts +2 -1
  14. package/dist/lib/cjs/obsidian/Link.cjs +1 -1
  15. package/dist/lib/cjs/obsidian/MonkeyAround.cjs +1 -1
  16. package/dist/lib/cjs/obsidian/Plugin/PluginBase.cjs +4 -4
  17. package/dist/lib/cjs/obsidian/Plugin/PluginBase.d.cts +4 -4
  18. package/dist/lib/cjs/obsidian/Plugin/PluginSettingsManagerBase.cjs +157 -258
  19. package/dist/lib/cjs/obsidian/Plugin/PluginSettingsManagerBase.d.cts +56 -93
  20. package/dist/lib/cjs/obsidian/Plugin/PluginSettingsTabBase.cjs +27 -19
  21. package/dist/lib/cjs/obsidian/Plugin/PluginSettingsWrapper.cjs +24 -0
  22. package/dist/lib/cjs/obsidian/Plugin/PluginSettingsWrapper.d.cts +25 -0
  23. package/dist/lib/cjs/obsidian/Plugin/PluginTypesBase.cjs +1 -1
  24. package/dist/lib/cjs/obsidian/Plugin/PluginTypesBase.d.cts +27 -0
  25. package/dist/lib/cjs/obsidian/Plugin/index.cjs +4 -1
  26. package/dist/lib/cjs/obsidian/Plugin/index.d.cts +1 -0
  27. package/dist/lib/esm/Library.mjs +1 -1
  28. package/dist/lib/esm/Object.d.mts +6 -2
  29. package/dist/lib/esm/Object.mjs +1 -1
  30. package/dist/lib/esm/ScriptUtils/esbuild/preprocessPlugin.mjs +1 -1
  31. package/dist/lib/esm/Transformers/Transformer.d.mts +2 -1
  32. package/dist/lib/esm/Transformers/Transformer.mjs +1 -1
  33. package/dist/lib/esm/Type.d.mts +6 -0
  34. package/dist/lib/esm/obsidian/App.mjs +1 -1
  35. package/dist/lib/esm/obsidian/FileChange.mjs +1 -1
  36. package/dist/lib/esm/obsidian/Frontmatter.d.mts +2 -1
  37. package/dist/lib/esm/obsidian/Frontmatter.mjs +1 -1
  38. package/dist/lib/esm/obsidian/Link.mjs +1 -1
  39. package/dist/lib/esm/obsidian/MonkeyAround.mjs +1 -1
  40. package/dist/lib/esm/obsidian/Plugin/PluginBase.d.mts +4 -4
  41. package/dist/lib/esm/obsidian/Plugin/PluginBase.mjs +4 -4
  42. package/dist/lib/esm/obsidian/Plugin/PluginSettingsManagerBase.d.mts +56 -93
  43. package/dist/lib/esm/obsidian/Plugin/PluginSettingsManagerBase.mjs +158 -255
  44. package/dist/lib/esm/obsidian/Plugin/PluginSettingsTabBase.mjs +27 -19
  45. package/dist/lib/esm/obsidian/Plugin/PluginSettingsWrapper.d.mts +25 -0
  46. package/dist/lib/esm/obsidian/Plugin/PluginSettingsWrapper.mjs +8 -0
  47. package/dist/lib/esm/obsidian/Plugin/PluginTypesBase.d.mts +27 -0
  48. package/dist/lib/esm/obsidian/Plugin/index.d.mts +1 -0
  49. package/dist/lib/esm/obsidian/Plugin/index.mjs +3 -1
  50. package/obsidian/Plugin/PluginSettingsWrapper/package.json +6 -0
  51. package/package.json +5 -5
@@ -25,8 +25,7 @@ var __copyProps = (to, from, except, desc) => {
25
25
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
26
26
  var PluginSettingsManagerBase_exports = {};
27
27
  __export(PluginSettingsManagerBase_exports, {
28
- PluginSettingsManagerBase: () => PluginSettingsManagerBase,
29
- PluginSettingsProperty: () => PluginSettingsProperty
28
+ PluginSettingsManagerBase: () => PluginSettingsManagerBase
30
29
  });
31
30
  module.exports = __toCommonJS(PluginSettingsManagerBase_exports);
32
31
  var import_Function = require('../../Function.cjs');
@@ -40,59 +39,6 @@ const defaultTransformer = new import_GroupTransformer.GroupTransformer([
40
39
  new import_DateTransformer.DateTransformer(),
41
40
  new import_DurationTransformer.DurationTransformer()
42
41
  ]);
43
- class ProxyHandlerBase {
44
- constructor(properties) {
45
- this.properties = properties;
46
- }
47
- get(target, prop) {
48
- const record = target;
49
- if (typeof prop !== "string") {
50
- return record[prop];
51
- }
52
- const property = this.properties.get(prop);
53
- if (!property) {
54
- return record[prop];
55
- }
56
- return this.getPropertyValue(property);
57
- }
58
- }
59
- class EditableSettingsProxyHandler extends ProxyHandlerBase {
60
- validationPromise = Promise.resolve();
61
- set(target, prop, value) {
62
- const record = target;
63
- record[prop] = value;
64
- if (typeof prop !== "string") {
65
- return true;
66
- }
67
- const property = this.properties.get(prop);
68
- if (!property) {
69
- return true;
70
- }
71
- property.setValue(value);
72
- this.validationPromise = this.validationPromise.then(() => property.validate());
73
- return true;
74
- }
75
- getPropertyValue(property) {
76
- return property.currentValue;
77
- }
78
- }
79
- class PropertiesMap extends Map {
80
- getTyped(propertyName) {
81
- const property = super.get(propertyName);
82
- if (!property) {
83
- throw new Error(`Property ${String(propertyName)} not found`);
84
- }
85
- return property;
86
- }
87
- setTyped(propertyName, value) {
88
- return super.set(propertyName, value);
89
- }
90
- }
91
- class SafeSettingsProxyHandler extends ProxyHandlerBase {
92
- getPropertyValue(property) {
93
- return property.safeValue;
94
- }
95
- }
96
42
  class PluginSettingsManagerBase {
97
43
  /**
98
44
  * Creates a new plugin settings manager.
@@ -102,50 +48,63 @@ class PluginSettingsManagerBase {
102
48
  constructor(plugin) {
103
49
  this.plugin = plugin;
104
50
  this.app = plugin.app;
105
- this.currentSettings = this.createDefaultSettings();
51
+ this.defaultSettings = this.createDefaultSettings();
52
+ this.currentSettingsWrapper = this.createDefaultSettingsWrapper();
53
+ this.lastSavedSettingsWrapper = this.createDefaultSettingsWrapper();
54
+ this.propertyNames = (0, import_Object.getAllKeys)(this.currentSettingsWrapper.settings);
106
55
  this.registerValidators();
107
- this.properties = new PropertiesMap();
108
- const record = this.currentSettings;
109
- for (const propertyName of (0, import_Object.getAllKeys)(this.currentSettings)) {
110
- let propertySetter2 = function(value) {
111
- record[propertyName] = value;
112
- };
113
- var propertySetter = propertySetter2;
114
- this.properties.set(
115
- propertyName,
116
- new PluginSettingsProperty(propertyName, this.currentSettings[propertyName], this.validators.get(propertyName) ?? import_Function.noop, propertySetter2)
117
- );
118
- }
119
- this.validators.clear();
120
- this.safeSettings = new Proxy(this.currentSettings, new SafeSettingsProxyHandler(this.properties));
121
56
  }
122
57
  app;
123
- safeSettings;
124
- currentSettings;
125
- properties;
126
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ defaultSettings;
59
+ /**
60
+ * Gets the current settings wrapper.
61
+ *
62
+ * @returns The current settings wrapper.
63
+ */
64
+ get settingsWrapper() {
65
+ return this.currentSettingsWrapper;
66
+ }
67
+ currentSettingsWrapper;
68
+ lastSavedSettingsWrapper;
69
+ propertyNames;
127
70
  validators = /* @__PURE__ */ new Map();
128
71
  /**
129
72
  * Edits the plugin settings and saves them.
130
73
  *
131
- * @param editor - The editor.
74
+ * @param settingsEditor - The editor.
132
75
  * @param context - The context.
133
76
  * @returns A {@link Promise} that resolves when the settings are saved.
134
77
  */
135
- async editAndSave(editor, context) {
136
- const editableSettings = new Proxy(this.currentSettings, new EditableSettingsProxyHandler(this.properties));
137
- await editor(editableSettings);
138
- await editableSettings.validationPromise;
78
+ async editAndSave(settingsEditor, context) {
79
+ await this.edit(settingsEditor);
139
80
  await this.saveToFile(context);
140
81
  }
141
82
  /**
142
- * Gets a property of the plugin settings.
83
+ * Ensures the settings are safe.
143
84
  *
144
- * @param propertyName - The name of the property.
145
- * @returns The property.
85
+ * It runs validation for each property and sets the default value if the validation fails.
86
+ *
87
+ * @param settings - The settings.
88
+ * @returns A {@link Promise} that resolves when the settings are safe.
146
89
  */
147
- getProperty(propertyName) {
148
- return this.properties.getTyped(propertyName);
90
+ async ensureSafe(settings) {
91
+ const validationResult = await this.validate(settings);
92
+ for (const propertyName of this.propertyNames) {
93
+ if (validationResult[propertyName]) {
94
+ settings[propertyName] = this.defaultSettings[propertyName];
95
+ }
96
+ }
97
+ }
98
+ /**
99
+ * Gets a safe copy of the settings.
100
+ *
101
+ * @param settings - The settings.
102
+ * @returns A {@link Promise} that resolves to the safe copy of the settings.
103
+ */
104
+ async getSafeCopy(settings) {
105
+ const safeSettings = this.cloneSettings(settings);
106
+ await this.ensureSafe(safeSettings);
107
+ return safeSettings;
149
108
  }
150
109
  /**
151
110
  * Loads the plugin settings from the file.
@@ -154,51 +113,28 @@ class PluginSettingsManagerBase {
154
113
  * @returns A {@link Promise} that resolves when the settings are loaded.
155
114
  */
156
115
  async loadFromFile(isInitialLoad) {
157
- for (const property of this.properties.values()) {
158
- property.reset();
159
- }
160
116
  const data = await this.plugin.loadData();
117
+ this.lastSavedSettingsWrapper = this.createDefaultSettingsWrapper();
118
+ this.currentSettingsWrapper = this.createDefaultSettingsWrapper();
161
119
  if (data === void 0 || data === null) {
162
120
  return;
163
121
  }
164
- if (typeof data !== "object" || Array.isArray(data)) {
165
- const type = Array.isArray(data) ? "Array" : typeof data;
166
- console.error(`Invalid data type. Expected Object, got: ${type}`);
122
+ if (typeof data !== "object") {
123
+ console.error(`Invalid settings from data.json. Expected Object, got: ${typeof data}`);
167
124
  return;
168
125
  }
169
- let record = data;
170
- const originalJson = JSON.stringify(record);
171
- record = this.getTransformer().transformObjectRecursively(record);
172
- await this.onLoadRecord(record);
173
- const propertiesToSave = [];
174
- for (const [propertyName, value] of Object.entries(record)) {
175
- const property = this.properties.get(propertyName);
176
- if (!property) {
177
- console.warn(`Unknown property: ${propertyName}`);
178
- continue;
179
- }
180
- if (typeof value !== typeof property.defaultValue) {
181
- console.warn(
182
- "Possible invalid value type read from config file. It might lead to an unexpected behavior of the plugin. There is also a chance it is a false-negative warning, as we are unable to determine the exact type of the value in runtime.",
183
- {
184
- defaultValue: property.defaultValue,
185
- propertyName,
186
- value
187
- }
188
- );
189
- }
190
- property.setValue(value);
191
- propertiesToSave.push(property);
126
+ const rawRecord = data;
127
+ const parsedSettings = await this.rawRecordToSettings(rawRecord);
128
+ const validationResult = await this.validate(parsedSettings);
129
+ for (const propertyName of this.propertyNames) {
130
+ this.setPropertyImpl(propertyName, parsedSettings[propertyName], validationResult[propertyName]);
192
131
  }
193
- for (const property of propertiesToSave) {
194
- await property.validate();
195
- property.save();
196
- }
197
- const newJson = JSON.stringify(await this.prepareRecordToSave());
198
- if (newJson !== originalJson) {
132
+ this.lastSavedSettingsWrapper = this.cloneSettingsWrapper(this.currentSettingsWrapper);
133
+ const newRecord = await this.settingsToRawRecord(this.currentSettingsWrapper.settings);
134
+ if (!(0, import_Object.deepEqual)(newRecord, data)) {
199
135
  await this.saveToFileImpl();
200
136
  }
201
- await this.plugin.onLoadSettings(this.getSavedSettings(), isInitialLoad);
137
+ await this.plugin.onLoadSettings(this.currentSettingsWrapper, isInitialLoad);
202
138
  }
203
139
  /**
204
140
  * Saves the new plugin settings.
@@ -207,16 +143,42 @@ class PluginSettingsManagerBase {
207
143
  * @returns A {@link Promise} that resolves when the settings are saved.
208
144
  */
209
145
  async saveToFile(context) {
210
- const oldSettings = this.getSavedSettings();
211
- let hasChanges = false;
212
- for (const property of this.properties.values()) {
213
- hasChanges ||= property.save();
214
- }
215
- if (!hasChanges) {
146
+ if ((0, import_Object.deepEqual)(this.lastSavedSettingsWrapper.settings, this.currentSettingsWrapper.settings)) {
216
147
  return;
217
148
  }
218
149
  await this.saveToFileImpl();
219
- await this.plugin.onSaveSettings(this.getSavedSettings(), oldSettings, context);
150
+ await this.plugin.onSaveSettings(this.currentSettingsWrapper, this.lastSavedSettingsWrapper, context);
151
+ this.lastSavedSettingsWrapper = this.cloneSettingsWrapper(this.currentSettingsWrapper);
152
+ }
153
+ /**
154
+ * Sets the value of a property.
155
+ *
156
+ * @typeParam PropertyName - The name of the property.
157
+ * @param propertyName - The name of the property.
158
+ * @param value - The value to set.
159
+ * @returns A {@link Promise} that resolves to the validation message.
160
+ */
161
+ async setProperty(propertyName, value) {
162
+ await this.edit((settings) => {
163
+ settings[propertyName] = value;
164
+ });
165
+ return this.currentSettingsWrapper.validationMessages[propertyName];
166
+ }
167
+ /**
168
+ * Validates the settings.
169
+ *
170
+ * @param settings - The settings.
171
+ * @returns A {@link Promise} that resolves to the validation result.
172
+ */
173
+ async validate(settings) {
174
+ const result = {};
175
+ for (const [propertyName, validator] of this.validators.entries()) {
176
+ const validationMessage = await validator(settings[propertyName], settings);
177
+ if (validationMessage) {
178
+ result[propertyName] = validationMessage;
179
+ }
180
+ }
181
+ return result;
220
182
  }
221
183
  /**
222
184
  * Gets the transformer.
@@ -259,148 +221,85 @@ class PluginSettingsManagerBase {
259
221
  registerValidators() {
260
222
  (0, import_Function.noop)();
261
223
  }
262
- getSavedSettings() {
263
- const savedSettings = {};
264
- for (const [propertyName, property] of this.properties.entries()) {
265
- savedSettings[propertyName] = property.lastSavedValue;
266
- }
267
- const proto = Object.getPrototypeOf(this.currentSettings);
268
- Object.setPrototypeOf(savedSettings, proto);
269
- return savedSettings;
270
- }
271
- async prepareRecordToSave() {
272
- const settings = {};
273
- for (const [propertyName, property] of this.properties.entries()) {
274
- settings[propertyName] = property.currentValue;
224
+ cloneSettings(settings) {
225
+ const record = this.settingsToRawRecord(settings);
226
+ const json = JSON.stringify(record);
227
+ const cloneRecord = JSON.parse(json);
228
+ return this.rawRecordToSettings(cloneRecord);
229
+ }
230
+ cloneSettingsWrapper(settingsWrapper) {
231
+ return {
232
+ safeSettings: this.cloneSettings(settingsWrapper.safeSettings),
233
+ settings: this.cloneSettings(settingsWrapper.settings),
234
+ validationMessages: { ...settingsWrapper.validationMessages }
235
+ };
236
+ }
237
+ createDefaultSettingsWrapper() {
238
+ return {
239
+ safeSettings: this.createDefaultSettings(),
240
+ settings: this.createDefaultSettings(),
241
+ validationMessages: {}
242
+ };
243
+ }
244
+ async edit(settingsEditor) {
245
+ try {
246
+ await settingsEditor(this.currentSettingsWrapper.settings);
247
+ } finally {
248
+ const validationResult = await this.validate(this.currentSettingsWrapper.settings);
249
+ for (const propertyName of this.propertyNames) {
250
+ const validationMessage = validationResult[propertyName] ?? "";
251
+ this.currentSettingsWrapper.validationMessages[propertyName] = validationMessage;
252
+ this.currentSettingsWrapper.safeSettings[propertyName] = validationMessage ? this.defaultSettings[propertyName] : this.currentSettingsWrapper.settings[propertyName];
253
+ }
275
254
  }
276
- await this.onSavingRecord(settings);
277
- return this.getTransformer().transformObjectRecursively(settings);
278
- }
279
- async saveToFileImpl() {
280
- await this.plugin.saveData(await this.prepareRecordToSave());
281
- }
282
- }
283
- class PluginSettingsProperty {
284
- /**
285
- * Creates a new plugin settings property.
286
- *
287
- * @param propertyName - The name of the property.
288
- * @param defaultValue - The default value of the property.
289
- * @param validator - The validator of the property.
290
- * @param propertySetter - The property setter of the property.
291
- */
292
- constructor(propertyName, defaultValue, validator, propertySetter) {
293
- this.propertyName = propertyName;
294
- this.defaultValue = defaultValue;
295
- this.validator = validator;
296
- this.propertySetter = propertySetter;
297
- this._lastSavedValue = defaultValue;
298
- this._currentValue = defaultValue;
299
- }
300
- /**
301
- * The current value of the property.
302
- *
303
- * @returns The current value.
304
- */
305
- get currentValue() {
306
- return this._currentValue;
307
- }
308
- /**
309
- * The last saved value of the property.
310
- *
311
- * @returns The last saved value.
312
- */
313
- get lastSavedValue() {
314
- return this._lastSavedValue;
315
- }
316
- /**
317
- * The safe value of the property.
318
- *
319
- * @returns The safe value.
320
- */
321
- get safeValue() {
322
- return this._validationMessage ? this.defaultValue : this._currentValue;
323
255
  }
324
- /**
325
- * The validation message of the property.
326
- *
327
- * @returns The validation message.
328
- */
329
- get validationMessage() {
330
- return this._validationMessage;
331
- }
332
- _currentValue;
333
- _lastSavedValue;
334
- _validationMessage = "";
335
- /**
336
- * Resets the current value of the property to the default value.
337
- */
338
- reset() {
339
- this._currentValue = this.defaultValue;
340
- this._validationMessage = "";
341
- }
342
- /**
343
- * Saves the current value of the property.
344
- *
345
- * @returns `true` if the value was changed, `false` otherwise.
346
- */
347
- save() {
348
- if (this._lastSavedValue === this._currentValue) {
256
+ isValidPropertyName(prop) {
257
+ if (typeof prop !== "string") {
349
258
  return false;
350
259
  }
351
- this._lastSavedValue = this._currentValue;
352
- return true;
260
+ return this.propertyNames.includes(prop);
353
261
  }
354
- /**
355
- * Sets the validation message of the property.
356
- *
357
- * @param validationMessage - The validation message.
358
- */
359
- setValidationMessage(validationMessage) {
360
- this._validationMessage = validationMessage;
361
- this.showWarning();
262
+ async rawRecordToSettings(rawRecord) {
263
+ await this.onLoadRecord(rawRecord);
264
+ const settings = this.createDefaultSettings();
265
+ for (const [propertyName, value] of Object.entries(rawRecord)) {
266
+ if (!this.isValidPropertyName(propertyName)) {
267
+ console.warn(`Unknown property: ${propertyName}`);
268
+ continue;
269
+ }
270
+ if (typeof value !== typeof this.defaultSettings[propertyName]) {
271
+ console.warn(
272
+ "Possible invalid value type. It might lead to an unexpected behavior of the plugin. There is also a chance it is a false-negative warning, as we are unable to determine the exact type of the value in runtime.",
273
+ {
274
+ defaultValue: this.defaultSettings[propertyName],
275
+ propertyName,
276
+ value
277
+ }
278
+ );
279
+ }
280
+ settings[propertyName] = value;
281
+ }
282
+ return settings;
362
283
  }
363
- /**
364
- * Sets the current value of the property.
365
- *
366
- * @param value - The value to set.
367
- */
368
- setValue(value) {
369
- this._currentValue = value;
370
- this.propertySetter(value);
284
+ async saveToFileImpl() {
285
+ await this.plugin.saveData(await this.settingsToRawRecord(this.currentSettingsWrapper));
371
286
  }
372
- /**
373
- * Validates the current value of the property.
374
- *
375
- * @returns A {@link Promise} that resolves when the validation is complete.
376
- */
377
- async validate() {
378
- try {
379
- this._validationMessage = await this.validator(this._currentValue) ?? "";
380
- } catch (error) {
381
- console.error("Validation failed", {
382
- propertyName: this.propertyName,
383
- value: this._currentValue
384
- }, error);
385
- this._validationMessage = "Validation failed";
386
- }
387
- this.showWarning(this._currentValue);
287
+ setPropertyImpl(propertyName, value, validationMessage) {
288
+ this.currentSettingsWrapper.settings[propertyName] = value;
289
+ this.currentSettingsWrapper.validationMessages[propertyName] = validationMessage ?? "";
290
+ this.currentSettingsWrapper.safeSettings[propertyName] = validationMessage ? this.defaultSettings[propertyName] : value;
388
291
  }
389
- showWarning(value) {
390
- if (!this._validationMessage) {
391
- return;
292
+ async settingsToRawRecord(settings) {
293
+ const rawRecord = {};
294
+ for (const propertyName of this.propertyNames) {
295
+ rawRecord[propertyName] = settings[propertyName];
392
296
  }
393
- console.warn(`Could not set plugin setting: ${this.propertyName}. Using default value instead.`, {
394
- defaultValue: this.defaultValue,
395
- propertyName: this.propertyName,
396
- validationMessage: this._validationMessage,
397
- value
398
- });
297
+ await this.onSavingRecord(rawRecord);
298
+ return this.getTransformer().transformObjectRecursively(rawRecord);
399
299
  }
400
300
  }
401
301
  // Annotate the CommonJS export names for ESM import in node:
402
302
  0 && (module.exports = {
403
- PluginSettingsManagerBase,
404
- PluginSettingsProperty
303
+ PluginSettingsManagerBase
405
304
  });
406
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL1BsdWdpbi9QbHVnaW5TZXR0aW5nc01hbmFnZXJCYXNlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICpcbiAqIFBsdWdpbiBzZXR0aW5ncyBtYW5hZ2VyIGJhc2UgY2xhc3MuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBBcHAgfSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQgdHlwZSB7XG4gIFByb21pc2FibGUsXG4gIFJlYWRvbmx5RGVlcFxufSBmcm9tICd0eXBlLWZlc3QnO1xuXG5pbXBvcnQgdHlwZSB7IFRyYW5zZm9ybWVyIH0gZnJvbSAnLi4vLi4vVHJhbnNmb3JtZXJzL1RyYW5zZm9ybWVyLnRzJztcbmltcG9ydCB0eXBlIHtcbiAgTWF5YmVSZXR1cm4sXG4gIFN0cmluZ0tleXNcbn0gZnJvbSAnLi4vLi4vVHlwZS50cyc7XG5pbXBvcnQgdHlwZSB7XG4gIEV4dHJhY3RQbHVnaW4sXG4gIEV4dHJhY3RQbHVnaW5TZXR0aW5ncyxcbiAgUGx1Z2luVHlwZXNCYXNlXG59IGZyb20gJy4vUGx1Z2luVHlwZXNCYXNlLnRzJztcblxuaW1wb3J0IHtcbiAgbm9vcCxcbiAgbm9vcEFzeW5jXG59IGZyb20gJy4uLy4uL0Z1bmN0aW9uLnRzJztcbmltcG9ydCB7IGdldEFsbEtleXMgfSBmcm9tICcuLi8uLi9PYmplY3QudHMnO1xuaW1wb3J0IHsgRGF0ZVRyYW5zZm9ybWVyIH0gZnJvbSAnLi4vLi4vVHJhbnNmb3JtZXJzL0RhdGVUcmFuc2Zvcm1lci50cyc7XG5pbXBvcnQgeyBEdXJhdGlvblRyYW5zZm9ybWVyIH0gZnJvbSAnLi4vLi4vVHJhbnNmb3JtZXJzL0R1cmF0aW9uVHJhbnNmb3JtZXIudHMnO1xuaW1wb3J0IHsgR3JvdXBUcmFuc2Zvcm1lciB9IGZyb20gJy4uLy4uL1RyYW5zZm9ybWVycy9Hcm91cFRyYW5zZm9ybWVyLnRzJztcbmltcG9ydCB7IFNraXBQcml2YXRlUHJvcGVydHlUcmFuc2Zvcm1lciB9IGZyb20gJy4uLy4uL1RyYW5zZm9ybWVycy9Ta2lwUHJpdmF0ZVByb3BlcnR5VHJhbnNmb3JtZXIudHMnO1xuXG5jb25zdCBkZWZhdWx0VHJhbnNmb3JtZXIgPSBuZXcgR3JvdXBUcmFuc2Zvcm1lcihbXG4gIG5ldyBTa2lwUHJpdmF0ZVByb3BlcnR5VHJhbnNmb3JtZXIoKSxcbiAgbmV3IERhdGVUcmFuc2Zvcm1lcigpLFxuICBuZXcgRHVyYXRpb25UcmFuc2Zvcm1lcigpXG5dKTtcblxudHlwZSBQcm9wZXJ0eVNldHRlciA9ICh2YWx1ZTogdW5rbm93bikgPT4gdm9pZDtcblxudHlwZSBWYWxpZGF0b3I8VD4gPSAodmFsdWU6IFQpID0+IFByb21pc2FibGU8TWF5YmVSZXR1cm48c3RyaW5nPj47XG5cbmFic3RyYWN0IGNsYXNzIFByb3h5SGFuZGxlckJhc2U8UGx1Z2luU2V0dGluZ3MgZXh0ZW5kcyBvYmplY3Q+IGltcGxlbWVudHMgUHJveHlIYW5kbGVyPFBsdWdpblNldHRpbmdzPiB7XG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgcmVhZG9ubHkgcHJvcGVydGllczogUHJvcGVydGllc01hcDxQbHVnaW5TZXR0aW5ncz4pIHt9XG5cbiAgcHVibGljIGdldCh0YXJnZXQ6IFBsdWdpblNldHRpbmdzLCBwcm9wOiBzdHJpbmcgfCBzeW1ib2wpOiB1bmtub3duIHtcbiAgICBjb25zdCByZWNvcmQgPSB0YXJnZXQgYXMgUmVjb3JkPHN0cmluZyB8IHN5bWJvbCwgdW5rbm93bj47XG4gICAgaWYgKHR5cGVvZiBwcm9wICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHJlY29yZFtwcm9wXTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9wZXJ0eSA9IHRoaXMucHJvcGVydGllcy5nZXQocHJvcCk7XG4gICAgaWYgKCFwcm9wZXJ0eSkge1xuICAgICAgcmV0dXJuIHJlY29yZFtwcm9wXTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5nZXRQcm9wZXJ0eVZhbHVlKHByb3BlcnR5KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBnZXRQcm9wZXJ0eVZhbHVlKHByb3BlcnR5OiBQbHVnaW5TZXR0aW5nc1Byb3BlcnR5PHVua25vd24+KTogdW5rbm93bjtcbn1cblxuY2xhc3MgRWRpdGFibGVTZXR0aW5nc1Byb3h5SGFuZGxlcjxQbHVnaW5TZXR0aW5ncyBleHRlbmRzIG9iamVjdD4gZXh0ZW5kcyBQcm94eUhhbmRsZXJCYXNlPFBsdWdpblNldHRpbmdzPiB7XG4gIHByaXZhdGUgdmFsaWRhdGlvblByb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTtcbiAgcHVibGljIHNldCh0YXJnZXQ6IFBsdWdpblNldHRpbmdzLCBwcm9wOiBzdHJpbmcgfCBzeW1ib2wsIHZhbHVlOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgY29uc3QgcmVjb3JkID0gdGFyZ2V0IGFzIFJlY29yZDxzdHJpbmcgfCBzeW1ib2wsIHVua25vd24+O1xuICAgIHJlY29yZFtwcm9wXSA9IHZhbHVlO1xuXG4gICAgaWYgKHR5cGVvZiBwcm9wICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgcHJvcGVydHkgPSB0aGlzLnByb3BlcnRpZXMuZ2V0KHByb3ApO1xuICAgIGlmICghcHJvcGVydHkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHByb3BlcnR5LnNldFZhbHVlKHZhbHVlKTtcbiAgICB0aGlzLnZhbGlkYXRpb25Qcm9taXNlID0gdGhpcy52YWxpZGF0aW9uUHJvbWlzZS50aGVuKCgpID0+IHByb3BlcnR5LnZhbGlkYXRlKCkpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJvdGVjdGVkIG92ZXJyaWRlIGdldFByb3BlcnR5VmFsdWUocHJvcGVydHk6IFBsdWdpblNldHRpbmdzUHJvcGVydHk8dW5rbm93bj4pOiB1bmtub3duIHtcbiAgICByZXR1cm4gcHJvcGVydHkuY3VycmVudFZhbHVlO1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG5jbGFzcyBQcm9wZXJ0aWVzTWFwPFBsdWdpblNldHRpbmdzIGV4dGVuZHMgb2JqZWN0PiBleHRlbmRzIE1hcDxzdHJpbmcsIFBsdWdpblNldHRpbmdzUHJvcGVydHk8YW55Pj4ge1xuICBwdWJsaWMgZ2V0VHlwZWQ8UHJvcGVydHlOYW1lIGV4dGVuZHMgU3RyaW5nS2V5czxQbHVnaW5TZXR0aW5ncz4+KHByb3BlcnR5TmFtZTogUHJvcGVydHlOYW1lKTogUGx1Z2luU2V0dGluZ3NQcm9wZXJ0eTxQbHVnaW5TZXR0aW5nc1tQcm9wZXJ0eU5hbWVdPiB7XG4gICAgY29uc3QgcHJvcGVydHkgPSBzdXBlci5nZXQocHJvcGVydHlOYW1lKTtcbiAgICBpZiAoIXByb3BlcnR5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7U3RyaW5nKHByb3BlcnR5TmFtZSl9IG5vdCBmb3VuZGApO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9wZXJ0eSBhcyBQbHVnaW5TZXR0aW5nc1Byb3BlcnR5PFBsdWdpblNldHRpbmdzW1Byb3BlcnR5TmFtZV0+O1xuICB9XG5cbiAgcHVibGljIHNldFR5cGVkPFByb3BlcnR5TmFtZSBleHRlbmRzIFN0cmluZ0tleXM8UGx1Z2luU2V0dGluZ3M+PihcbiAgICBwcm9wZXJ0eU5hbWU6IFByb3BlcnR5TmFtZSxcbiAgICB2YWx1ZTogUGx1Z2luU2V0dGluZ3NQcm9wZXJ0eTxQbHVnaW5TZXR0aW5nc1tQcm9wZXJ0eU5hbWVdPlxuICApOiB0aGlzIHtcbiAgICByZXR1cm4gc3VwZXIuc2V0KHByb3BlcnR5TmFtZSwgdmFsdWUpO1xuICB9XG59XG5cbmNsYXNzIFNhZmVTZXR0aW5nc1Byb3h5SGFuZGxlcjxQbHVnaW5TZXR0aW5ncyBleHRlbmRzIG9iamVjdD4gZXh0ZW5kcyBQcm94eUhhbmRsZXJCYXNlPFBsdWdpblNldHRpbmdzPiB7XG4gIHByb3RlY3RlZCBvdmVycmlkZSBnZXRQcm9wZXJ0eVZhbHVlKHByb3BlcnR5OiBQbHVnaW5TZXR0aW5nc1Byb3BlcnR5PHVua25vd24+KTogdW5rbm93biB7XG4gICAgcmV0dXJuIHByb3BlcnR5LnNhZmVWYWx1ZTtcbiAgfVxufVxuXG4vKipcbiAqIEJhc2UgY2xhc3MgZm9yIG1hbmFnaW5nIHBsdWdpbiBzZXR0aW5ncy5cbiAqXG4gKiBAdHlwZVBhcmFtIFBsdWdpblR5cGVzIC0gUGx1Z2luLXNwZWNpZmljIHR5cGVzLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUGx1Z2luU2V0dGluZ3NNYW5hZ2VyQmFzZTxQbHVnaW5UeXBlcyBleHRlbmRzIFBsdWdpblR5cGVzQmFzZT4ge1xuICBwdWJsaWMgcmVhZG9ubHkgYXBwOiBBcHA7XG4gIHB1YmxpYyByZWFkb25seSBzYWZlU2V0dGluZ3M6IFJlYWRvbmx5RGVlcDxFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+PjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGN1cnJlbnRTZXR0aW5nczogRXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPjtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9wZXJ0aWVzOiBQcm9wZXJ0aWVzTWFwPEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4+O1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICBwcml2YXRlIHJlYWRvbmx5IHZhbGlkYXRvcnM6IE1hcDxzdHJpbmcsIFZhbGlkYXRvcjxhbnk+PiA9IG5ldyBNYXA8c3RyaW5nLCBWYWxpZGF0b3I8YW55Pj4oKTtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBwbHVnaW4gc2V0dGluZ3MgbWFuYWdlci5cbiAgICpcbiAgICogQHBhcmFtIHBsdWdpbiAtIFRoZSBwbHVnaW4uXG4gICAqL1xuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHBsdWdpbjogRXh0cmFjdFBsdWdpbjxQbHVnaW5UeXBlcz4pIHtcbiAgICB0aGlzLmFwcCA9IHBsdWdpbi5hcHA7XG4gICAgdGhpcy5jdXJyZW50U2V0dGluZ3MgPSB0aGlzLmNyZWF0ZURlZmF1bHRTZXR0aW5ncygpO1xuXG4gICAgdGhpcy5yZWdpc3RlclZhbGlkYXRvcnMoKTtcblxuICAgIHRoaXMucHJvcGVydGllcyA9IG5ldyBQcm9wZXJ0aWVzTWFwPEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4+KCk7XG5cbiAgICBjb25zdCByZWNvcmQgPSB0aGlzLmN1cnJlbnRTZXR0aW5ncyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcblxuICAgIGZvciAoY29uc3QgcHJvcGVydHlOYW1lIG9mIGdldEFsbEtleXModGhpcy5jdXJyZW50U2V0dGluZ3MpKSB7XG4gICAgICBmdW5jdGlvbiBwcm9wZXJ0eVNldHRlcih2YWx1ZTogdW5rbm93bik6IHZvaWQge1xuICAgICAgICByZWNvcmRbcHJvcGVydHlOYW1lXSA9IHZhbHVlO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnByb3BlcnRpZXMuc2V0KFxuICAgICAgICBwcm9wZXJ0eU5hbWUsXG4gICAgICAgIG5ldyBQbHVnaW5TZXR0aW5nc1Byb3BlcnR5KHByb3BlcnR5TmFtZSwgdGhpcy5jdXJyZW50U2V0dGluZ3NbcHJvcGVydHlOYW1lXSwgdGhpcy52YWxpZGF0b3JzLmdldChwcm9wZXJ0eU5hbWUpID8/IG5vb3AsIHByb3BlcnR5U2V0dGVyKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRvcnMuY2xlYXIoKTtcblxuICAgIHRoaXMuc2FmZVNldHRpbmdzID0gbmV3IFByb3h5KHRoaXMuY3VycmVudFNldHRpbmdzLCBuZXcgU2FmZVNldHRpbmdzUHJveHlIYW5kbGVyPEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4+KHRoaXMucHJvcGVydGllcykpIGFzIFJlYWRvbmx5RGVlcDxcbiAgICAgIEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz5cbiAgICA+O1xuICB9XG5cbiAgLyoqXG4gICAqIEVkaXRzIHRoZSBwbHVnaW4gc2V0dGluZ3MgYW5kIHNhdmVzIHRoZW0uXG4gICAqXG4gICAqIEBwYXJhbSBlZGl0b3IgLSBUaGUgZWRpdG9yLlxuICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0LlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHNldHRpbmdzIGFyZSBzYXZlZC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBlZGl0QW5kU2F2ZShlZGl0b3I6IChzZXR0aW5nczogRXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPikgPT4gUHJvbWlzYWJsZTx2b2lkPiwgY29udGV4dD86IHVua25vd24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBlZGl0YWJsZVNldHRpbmdzID0gbmV3IFByb3h5KHRoaXMuY3VycmVudFNldHRpbmdzLCBuZXcgRWRpdGFibGVTZXR0aW5nc1Byb3h5SGFuZGxlcjxFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+Pih0aGlzLnByb3BlcnRpZXMpKSBhcyB7XG4gICAgICB2YWxpZGF0aW9uUHJvbWlzZTogUHJvbWlzZTx2b2lkPjtcbiAgICB9ICYgRXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPjtcbiAgICBhd2FpdCBlZGl0b3IoZWRpdGFibGVTZXR0aW5ncyk7XG4gICAgYXdhaXQgZWRpdGFibGVTZXR0aW5ncy52YWxpZGF0aW9uUHJvbWlzZTtcbiAgICBhd2FpdCB0aGlzLnNhdmVUb0ZpbGUoY29udGV4dCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBhIHByb3BlcnR5IG9mIHRoZSBwbHVnaW4gc2V0dGluZ3MuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wZXJ0eU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEByZXR1cm5zIFRoZSBwcm9wZXJ0eS5cbiAgICovXG4gIHB1YmxpYyBnZXRQcm9wZXJ0eTxQcm9wZXJ0eU5hbWUgZXh0ZW5kcyBTdHJpbmdLZXlzPEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4+PihcbiAgICBwcm9wZXJ0eU5hbWU6IFByb3BlcnR5TmFtZVxuICApOiBQbHVnaW5TZXR0aW5nc1Byb3BlcnR5PEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz5bUHJvcGVydHlOYW1lXT4ge1xuICAgIHJldHVybiB0aGlzLnByb3BlcnRpZXMuZ2V0VHlwZWQocHJvcGVydHlOYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0aGUgcGx1Z2luIHNldHRpbmdzIGZyb20gdGhlIGZpbGUuXG4gICAqXG4gICAqIEBwYXJhbSBpc0luaXRpYWxMb2FkIC0gV2hldGhlciB0aGUgc2V0dGluZ3MgYXJlIGJlaW5nIGxvYWRlZCBmb3IgdGhlIGZpcnN0IHRpbWUuXG4gICAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgc2V0dGluZ3MgYXJlIGxvYWRlZC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBsb2FkRnJvbUZpbGUoaXNJbml0aWFsTG9hZDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvciAoY29uc3QgcHJvcGVydHkgb2YgdGhpcy5wcm9wZXJ0aWVzLnZhbHVlcygpKSB7XG4gICAgICBwcm9wZXJ0eS5yZXNldCgpO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLnBsdWdpbi5sb2FkRGF0YSgpIGFzIHVua25vd247XG5cbiAgICBpZiAoZGF0YSA9PT0gdW5kZWZpbmVkIHx8IGRhdGEgPT09IG51bGwpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRhdGEgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgIGNvbnN0IHR5cGUgPSBBcnJheS5pc0FycmF5KGRhdGEpID8gJ0FycmF5JyA6IHR5cGVvZiBkYXRhO1xuICAgICAgY29uc29sZS5lcnJvcihgSW52YWxpZCBkYXRhIHR5cGUuIEV4cGVjdGVkIE9iamVjdCwgZ290OiAke3R5cGV9YCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IHJlY29yZCA9IGRhdGEgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgY29uc3Qgb3JpZ2luYWxKc29uID0gSlNPTi5zdHJpbmdpZnkocmVjb3JkKTtcbiAgICByZWNvcmQgPSB0aGlzLmdldFRyYW5zZm9ybWVyKCkudHJhbnNmb3JtT2JqZWN0UmVjdXJzaXZlbHkocmVjb3JkKTtcbiAgICBhd2FpdCB0aGlzLm9uTG9hZFJlY29yZChyZWNvcmQpO1xuXG4gICAgY29uc3QgcHJvcGVydGllc1RvU2F2ZTogUGx1Z2luU2V0dGluZ3NQcm9wZXJ0eTx1bmtub3duPltdID0gW107XG5cbiAgICBmb3IgKGNvbnN0IFtwcm9wZXJ0eU5hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhyZWNvcmQpKSB7XG4gICAgICBjb25zdCBwcm9wZXJ0eSA9IHRoaXMucHJvcGVydGllcy5nZXQocHJvcGVydHlOYW1lKTtcbiAgICAgIGlmICghcHJvcGVydHkpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBVbmtub3duIHByb3BlcnR5OiAke3Byb3BlcnR5TmFtZX1gKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IHR5cGVvZiBwcm9wZXJ0eS5kZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICdQb3NzaWJsZSBpbnZhbGlkIHZhbHVlIHR5cGUgcmVhZCBmcm9tIGNvbmZpZyBmaWxlLiBJdCBtaWdodCBsZWFkIHRvIGFuIHVuZXhwZWN0ZWQgYmVoYXZpb3Igb2YgdGhlIHBsdWdpbi4gVGhlcmUgaXMgYWxzbyBhIGNoYW5jZSBpdCBpcyBhIGZhbHNlLW5lZ2F0aXZlIHdhcm5pbmcsIGFzIHdlIGFyZSB1bmFibGUgdG8gZGV0ZXJtaW5lIHRoZSBleGFjdCB0eXBlIG9mIHRoZSB2YWx1ZSBpbiBydW50aW1lLicsXG4gICAgICAgICAge1xuICAgICAgICAgICAgZGVmYXVsdFZhbHVlOiBwcm9wZXJ0eS5kZWZhdWx0VmFsdWUgYXMgdW5rbm93bixcbiAgICAgICAgICAgIHByb3BlcnR5TmFtZSxcbiAgICAgICAgICAgIHZhbHVlXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBwcm9wZXJ0eS5zZXRWYWx1ZSh2YWx1ZSk7XG4gICAgICBwcm9wZXJ0aWVzVG9TYXZlLnB1c2gocHJvcGVydHkpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgcHJvcGVydHkgb2YgcHJvcGVydGllc1RvU2F2ZSkge1xuICAgICAgYXdhaXQgcHJvcGVydHkudmFsaWRhdGUoKTtcbiAgICAgIHByb3BlcnR5LnNhdmUoKTtcbiAgICB9XG5cbiAgICBjb25zdCBuZXdKc29uID0gSlNPTi5zdHJpbmdpZnkoYXdhaXQgdGhpcy5wcmVwYXJlUmVjb3JkVG9TYXZlKCkpO1xuXG4gICAgaWYgKG5ld0pzb24gIT09IG9yaWdpbmFsSnNvbikge1xuICAgICAgYXdhaXQgdGhpcy5zYXZlVG9GaWxlSW1wbCgpO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMucGx1Z2luLm9uTG9hZFNldHRpbmdzKHRoaXMuZ2V0U2F2ZWRTZXR0aW5ncygpLCBpc0luaXRpYWxMb2FkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXZlcyB0aGUgbmV3IHBsdWdpbiBzZXR0aW5ncy5cbiAgICpcbiAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCBvZiB0aGUgc2F2ZSB0byBmaWxlIG9wZXJhdGlvbi5cbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBzZXR0aW5ncyBhcmUgc2F2ZWQuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgc2F2ZVRvRmlsZShjb250ZXh0PzogdW5rbm93bik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IG9sZFNldHRpbmdzID0gdGhpcy5nZXRTYXZlZFNldHRpbmdzKCk7XG5cbiAgICBsZXQgaGFzQ2hhbmdlcyA9IGZhbHNlO1xuXG4gICAgZm9yIChjb25zdCBwcm9wZXJ0eSBvZiB0aGlzLnByb3BlcnRpZXMudmFsdWVzKCkpIHtcbiAgICAgIGhhc0NoYW5nZXMgfHw9IHByb3BlcnR5LnNhdmUoKTtcbiAgICB9XG5cbiAgICBpZiAoIWhhc0NoYW5nZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnNhdmVUb0ZpbGVJbXBsKCk7XG4gICAgYXdhaXQgdGhpcy5wbHVnaW4ub25TYXZlU2V0dGluZ3ModGhpcy5nZXRTYXZlZFNldHRpbmdzKCksIG9sZFNldHRpbmdzLCBjb250ZXh0KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBjcmVhdGVEZWZhdWx0U2V0dGluZ3MoKTogRXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPjtcblxuICAvKipcbiAgICogR2V0cyB0aGUgdHJhbnNmb3JtZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSB0cmFuc2Zvcm1lci5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRUcmFuc2Zvcm1lcigpOiBUcmFuc2Zvcm1lciB7XG4gICAgcmV0dXJuIGRlZmF1bHRUcmFuc2Zvcm1lcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiB0aGUgcGx1Z2luIHNldHRpbmdzIGFyZSBsb2FkZWQuXG4gICAqXG4gICAqIEBwYXJhbSBfcmVjb3JkIC0gVGhlIHJlY29yZC5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBvbkxvYWRSZWNvcmQoX3JlY29yZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBub29wQXN5bmMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiB0aGUgcGx1Z2luIHNldHRpbmdzIGFyZSBzYXZpbmcuXG4gICAqXG4gICAqIEBwYXJhbSBfcmVjb3JkIC0gVGhlIHJlY29yZC5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBvblNhdmluZ1JlY29yZChfcmVjb3JkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IG5vb3BBc3luYygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVycyBhIHZhbGlkYXRvciBmb3IgYSBwcm9wZXJ0eS5cbiAgICpcbiAgICogQHBhcmFtIHByb3BlcnR5TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICogQHBhcmFtIHZhbGlkYXRvciAtIFRoZSB2YWxpZGF0b3IuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVnaXN0ZXJWYWxpZGF0b3I8UHJvcGVydHlOYW1lIGV4dGVuZHMgU3RyaW5nS2V5czxFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+Pj4oXG4gICAgcHJvcGVydHlOYW1lOiBQcm9wZXJ0eU5hbWUsXG4gICAgdmFsaWRhdG9yOiBWYWxpZGF0b3I8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPltQcm9wZXJ0eU5hbWVdPlxuICApOiB2b2lkIHtcbiAgICB0aGlzLnZhbGlkYXRvcnMuc2V0KHByb3BlcnR5TmFtZSwgdmFsaWRhdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgdGhlIHZhbGlkYXRvcnMuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHN1YmNsYXNzZXMgdG8gcmVnaXN0ZXIgdmFsaWRhdG9ycyBmb3IgcHJvcGVydGllcy5cbiAgICovXG4gIHByb3RlY3RlZCByZWdpc3RlclZhbGlkYXRvcnMoKTogdm9pZCB7XG4gICAgbm9vcCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTYXZlZFNldHRpbmdzKCk6IEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4ge1xuICAgIGNvbnN0IHNhdmVkU2V0dGluZ3M6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgZm9yIChjb25zdCBbcHJvcGVydHlOYW1lLCBwcm9wZXJ0eV0gb2YgdGhpcy5wcm9wZXJ0aWVzLmVudHJpZXMoKSkge1xuICAgICAgc2F2ZWRTZXR0aW5nc1twcm9wZXJ0eU5hbWVdID0gcHJvcGVydHkubGFzdFNhdmVkVmFsdWUgYXNcbiAgICAgICAgfCBFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+W1N0cmluZ0tleXM8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj5dXG4gICAgICAgIHwgdW5kZWZpbmVkO1xuICAgIH1cbiAgICBjb25zdCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzLmN1cnJlbnRTZXR0aW5ncykgYXMgb2JqZWN0O1xuICAgIE9iamVjdC5zZXRQcm90b3R5cGVPZihzYXZlZFNldHRpbmdzLCBwcm90byk7XG5cbiAgICByZXR1cm4gc2F2ZWRTZXR0aW5ncyBhcyBFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+O1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBwcmVwYXJlUmVjb3JkVG9TYXZlKCk6IFByb21pc2U8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+IHtcbiAgICBjb25zdCBzZXR0aW5nczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtwcm9wZXJ0eU5hbWUsIHByb3BlcnR5XSBvZiB0aGlzLnByb3BlcnRpZXMuZW50cmllcygpKSB7XG4gICAgICBzZXR0aW5nc1twcm9wZXJ0eU5hbWVdID0gcHJvcGVydHkuY3VycmVudFZhbHVlIGFzIHVua25vd247XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5vblNhdmluZ1JlY29yZChzZXR0aW5ncyk7XG5cbiAgICByZXR1cm4gdGhpcy5nZXRUcmFuc2Zvcm1lcigpLnRyYW5zZm9ybU9iamVjdFJlY3Vyc2l2ZWx5KHNldHRpbmdzKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2F2ZVRvRmlsZUltcGwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZURhdGEoYXdhaXQgdGhpcy5wcmVwYXJlUmVjb3JkVG9TYXZlKCkpO1xuICB9XG59XG5cbi8qKlxuICogQSBwcm9wZXJ0eSBvZiBhIHBsdWdpbiBzZXR0aW5ncy5cbiAqXG4gKiBAdHlwZVBhcmFtIFQgLSBUaGUgdHlwZSBvZiB0aGUgcHJvcGVydHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBQbHVnaW5TZXR0aW5nc1Byb3BlcnR5PFQ+IHtcbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgdmFsdWUuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGN1cnJlbnRWYWx1ZSgpOiBUIHtcbiAgICByZXR1cm4gdGhpcy5fY3VycmVudFZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBsYXN0IHNhdmVkIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIGxhc3Qgc2F2ZWQgdmFsdWUuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGxhc3RTYXZlZFZhbHVlKCk6IFQge1xuICAgIHJldHVybiB0aGlzLl9sYXN0U2F2ZWRWYWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgc2FmZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSBzYWZlIHZhbHVlLlxuICAgKi9cbiAgcHVibGljIGdldCBzYWZlVmFsdWUoKTogVCB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbGlkYXRpb25NZXNzYWdlID8gdGhpcy5kZWZhdWx0VmFsdWUgOiB0aGlzLl9jdXJyZW50VmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHZhbGlkYXRpb24gbWVzc2FnZSBvZiB0aGUgcHJvcGVydHkuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSB2YWxpZGF0aW9uIG1lc3NhZ2UuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHZhbGlkYXRpb25NZXNzYWdlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbGlkYXRpb25NZXNzYWdlO1xuICB9XG5cbiAgcHJpdmF0ZSBfY3VycmVudFZhbHVlOiBUO1xuXG4gIHByaXZhdGUgX2xhc3RTYXZlZFZhbHVlOiBUO1xuXG4gIHByaXZhdGUgX3ZhbGlkYXRpb25NZXNzYWdlID0gJyc7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgcGx1Z2luIHNldHRpbmdzIHByb3BlcnR5LlxuICAgKlxuICAgKiBAcGFyYW0gcHJvcGVydHlOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHByb3BlcnR5LlxuICAgKiBAcGFyYW0gZGVmYXVsdFZhbHVlIC0gVGhlIGRlZmF1bHQgdmFsdWUgb2YgdGhlIHByb3BlcnR5LlxuICAgKiBAcGFyYW0gdmFsaWRhdG9yIC0gVGhlIHZhbGlkYXRvciBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSBwcm9wZXJ0eVNldHRlciAtIFRoZSBwcm9wZXJ0eSBzZXR0ZXIgb2YgdGhlIHByb3BlcnR5LlxuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcHJvcGVydHlOYW1lOiBzdHJpbmcsXG4gICAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRWYWx1ZTogVCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHZhbGlkYXRvcjogVmFsaWRhdG9yPFQ+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcHJvcGVydHlTZXR0ZXI6IFByb3BlcnR5U2V0dGVyXG4gICkge1xuICAgIHRoaXMuX2xhc3RTYXZlZFZhbHVlID0gZGVmYXVsdFZhbHVlO1xuICAgIHRoaXMuX2N1cnJlbnRWYWx1ZSA9IGRlZmF1bHRWYWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldHMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIHByb3BlcnR5IHRvIHRoZSBkZWZhdWx0IHZhbHVlLlxuICAgKi9cbiAgcHVibGljIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMuX2N1cnJlbnRWYWx1ZSA9IHRoaXMuZGVmYXVsdFZhbHVlO1xuICAgIHRoaXMuX3ZhbGlkYXRpb25NZXNzYWdlID0gJyc7XG4gIH1cblxuICAvKipcbiAgICogU2F2ZXMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIHByb3BlcnR5LlxuICAgKlxuICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHZhbHVlIHdhcyBjaGFuZ2VkLCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICovXG4gIHB1YmxpYyBzYXZlKCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLl9sYXN0U2F2ZWRWYWx1ZSA9PT0gdGhpcy5fY3VycmVudFZhbHVlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdGhpcy5fbGFzdFNhdmVkVmFsdWUgPSB0aGlzLl9jdXJyZW50VmFsdWU7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgdmFsaWRhdGlvbiBtZXNzYWdlIG9mIHRoZSBwcm9wZXJ0eS5cbiAgICpcbiAgICogQHBhcmFtIHZhbGlkYXRpb25NZXNzYWdlIC0gVGhlIHZhbGlkYXRpb24gbWVzc2FnZS5cbiAgICovXG4gIHB1YmxpYyBzZXRWYWxpZGF0aW9uTWVzc2FnZSh2YWxpZGF0aW9uTWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5fdmFsaWRhdGlvbk1lc3NhZ2UgPSB2YWxpZGF0aW9uTWVzc2FnZTtcbiAgICB0aGlzLnNob3dXYXJuaW5nKCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgcHJvcGVydHkuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAqL1xuICBwdWJsaWMgc2V0VmFsdWUodmFsdWU6IFQpOiB2b2lkIHtcbiAgICB0aGlzLl9jdXJyZW50VmFsdWUgPSB2YWx1ZTtcbiAgICB0aGlzLnByb3BlcnR5U2V0dGVyKHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZXMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIHByb3BlcnR5LlxuICAgKlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHZhbGlkYXRpb24gaXMgY29tcGxldGUuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmFsaWRhdGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMuX3ZhbGlkYXRpb25NZXNzYWdlID0gKGF3YWl0IHRoaXMudmFsaWRhdG9yKHRoaXMuX2N1cnJlbnRWYWx1ZSkgYXMgc3RyaW5nIHwgdW5kZWZpbmVkKSA/PyAnJztcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcignVmFsaWRhdGlvbiBmYWlsZWQnLCB7XG4gICAgICAgIHByb3BlcnR5TmFtZTogdGhpcy5wcm9wZXJ0eU5hbWUsXG4gICAgICAgIHZhbHVlOiB0aGlzLl9jdXJyZW50VmFsdWVcbiAgICAgIH0sIGVycm9yKTtcbiAgICAgIHRoaXMuX3ZhbGlkYXRpb25NZXNzYWdlID0gJ1ZhbGlkYXRpb24gZmFpbGVkJztcbiAgICB9XG4gICAgdGhpcy5zaG93V2FybmluZyh0aGlzLl9jdXJyZW50VmFsdWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBzaG93V2FybmluZyh2YWx1ZT86IFQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuX3ZhbGlkYXRpb25NZXNzYWdlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc29sZS53YXJuKGBDb3VsZCBub3Qgc2V0IHBsdWdpbiBzZXR0aW5nOiAke3RoaXMucHJvcGVydHlOYW1lfS4gVXNpbmcgZGVmYXVsdCB2YWx1ZSBpbnN0ZWFkLmAsIHtcbiAgICAgIGRlZmF1bHRWYWx1ZTogdGhpcy5kZWZhdWx0VmFsdWUsXG4gICAgICBwcm9wZXJ0eU5hbWU6IHRoaXMucHJvcGVydHlOYW1lLFxuICAgICAgdmFsaWRhdGlvbk1lc3NhZ2U6IHRoaXMuX3ZhbGlkYXRpb25NZXNzYWdlLFxuICAgICAgdmFsdWVcbiAgICB9KTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQXVCQSxzQkFHTztBQUNQLG9CQUEyQjtBQUMzQiw2QkFBZ0M7QUFDaEMsaUNBQW9DO0FBQ3BDLDhCQUFpQztBQUNqQyw0Q0FBK0M7QUFFL0MsTUFBTSxxQkFBcUIsSUFBSSx5Q0FBaUI7QUFBQSxFQUM5QyxJQUFJLHFFQUErQjtBQUFBLEVBQ25DLElBQUksdUNBQWdCO0FBQUEsRUFDcEIsSUFBSSwrQ0FBb0I7QUFDMUIsQ0FBQztBQU1ELE1BQWUsaUJBQXdGO0FBQUEsRUFDOUYsWUFBK0IsWUFBMkM7QUFBM0M7QUFBQSxFQUE0QztBQUFBLEVBRTNFLElBQUksUUFBd0IsTUFBZ0M7QUFDakUsVUFBTSxTQUFTO0FBQ2YsUUFBSSxPQUFPLFNBQVMsVUFBVTtBQUM1QixhQUFPLE9BQU8sSUFBSTtBQUFBLElBQ3BCO0FBRUEsVUFBTSxXQUFXLEtBQUssV0FBVyxJQUFJLElBQUk7QUFDekMsUUFBSSxDQUFDLFVBQVU7QUFDYixhQUFPLE9BQU8sSUFBSTtBQUFBLElBQ3BCO0FBRUEsV0FBTyxLQUFLLGlCQUFpQixRQUFRO0FBQUEsRUFDdkM7QUFHRjtBQUVBLE1BQU0scUNBQW9FLGlCQUFpQztBQUFBLEVBQ2pHLG9CQUFvQixRQUFRLFFBQVE7QUFBQSxFQUNyQyxJQUFJLFFBQXdCLE1BQXVCLE9BQXlCO0FBQ2pGLFVBQU0sU0FBUztBQUNmLFdBQU8sSUFBSSxJQUFJO0FBRWYsUUFBSSxPQUFPLFNBQVMsVUFBVTtBQUM1QixhQUFPO0FBQUEsSUFDVDtBQUVBLFVBQU0sV0FBVyxLQUFLLFdBQVcsSUFBSSxJQUFJO0FBQ3pDLFFBQUksQ0FBQyxVQUFVO0FBQ2IsYUFB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
305
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL1BsdWdpbi9QbHVnaW5TZXR0aW5nc01hbmFnZXJCYXNlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICpcbiAqIFBsdWdpbiBzZXR0aW5ncyBtYW5hZ2VyIGJhc2UgY2xhc3MuXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBBcHAgfSBmcm9tICdvYnNpZGlhbic7XG5pbXBvcnQgdHlwZSB7XG4gIFByb21pc2FibGUsXG4gIFJlYWRvbmx5RGVlcFxufSBmcm9tICd0eXBlLWZlc3QnO1xuXG5pbXBvcnQgdHlwZSB7IEdlbmVyaWNPYmplY3QgfSBmcm9tICcuLi8uLi9PYmplY3QudHMnO1xuaW1wb3J0IHR5cGUgeyBUcmFuc2Zvcm1lciB9IGZyb20gJy4uLy4uL1RyYW5zZm9ybWVycy9UcmFuc2Zvcm1lci50cyc7XG5pbXBvcnQgdHlwZSB7XG4gIE1heWJlUmV0dXJuLFxuICBTdHJpbmdLZXlzXG59IGZyb20gJy4uLy4uL1R5cGUudHMnO1xuaW1wb3J0IHR5cGUgeyBQbHVnaW5TZXR0aW5nc1dyYXBwZXIgfSBmcm9tICcuL1BsdWdpblNldHRpbmdzV3JhcHBlci50cyc7XG5pbXBvcnQgdHlwZSB7XG4gIEV4dHJhY3RQbHVnaW4sXG4gIEV4dHJhY3RQbHVnaW5TZXR0aW5ncyxcbiAgRXh0cmFjdFBsdWdpblNldHRpbmdzUHJvcGVydHlOYW1lcyxcbiAgRXh0cmFjdFBsdWdpblNldHRpbmdzUHJvcGVydHlWYWx1ZXMsXG4gIEV4dHJhY3RQbHVnaW5TZXR0aW5nc1dyYXBwZXIsXG4gIEV4dHJhY3RSZWFkb25seVBsdWdpblNldHRpbmdzV3JhcHBlcixcbiAgUGx1Z2luVHlwZXNCYXNlXG59IGZyb20gJy4vUGx1Z2luVHlwZXNCYXNlLnRzJztcblxuaW1wb3J0IHtcbiAgbm9vcCxcbiAgbm9vcEFzeW5jXG59IGZyb20gJy4uLy4uL0Z1bmN0aW9uLnRzJztcbmltcG9ydCB7XG4gIGRlZXBFcXVhbCxcbiAgZ2V0QWxsS2V5c1xufSBmcm9tICcuLi8uLi9PYmplY3QudHMnO1xuaW1wb3J0IHsgRGF0ZVRyYW5zZm9ybWVyIH0gZnJvbSAnLi4vLi4vVHJhbnNmb3JtZXJzL0RhdGVUcmFuc2Zvcm1lci50cyc7XG5pbXBvcnQgeyBEdXJhdGlvblRyYW5zZm9ybWVyIH0gZnJvbSAnLi4vLi4vVHJhbnNmb3JtZXJzL0R1cmF0aW9uVHJhbnNmb3JtZXIudHMnO1xuaW1wb3J0IHsgR3JvdXBUcmFuc2Zvcm1lciB9IGZyb20gJy4uLy4uL1RyYW5zZm9ybWVycy9Hcm91cFRyYW5zZm9ybWVyLnRzJztcbmltcG9ydCB7IFNraXBQcml2YXRlUHJvcGVydHlUcmFuc2Zvcm1lciB9IGZyb20gJy4uLy4uL1RyYW5zZm9ybWVycy9Ta2lwUHJpdmF0ZVByb3BlcnR5VHJhbnNmb3JtZXIudHMnO1xuXG5jb25zdCBkZWZhdWx0VHJhbnNmb3JtZXIgPSBuZXcgR3JvdXBUcmFuc2Zvcm1lcihbXG4gIG5ldyBTa2lwUHJpdmF0ZVByb3BlcnR5VHJhbnNmb3JtZXIoKSxcbiAgbmV3IERhdGVUcmFuc2Zvcm1lcigpLFxuICBuZXcgRHVyYXRpb25UcmFuc2Zvcm1lcigpXG5dKTtcblxudHlwZSBWYWxpZGF0aW9uUmVzdWx0PFBsdWdpblNldHRpbmdzIGV4dGVuZHMgb2JqZWN0PiA9IFBhcnRpYWw8UmVjb3JkPFN0cmluZ0tleXM8UGx1Z2luU2V0dGluZ3M+LCBzdHJpbmc+PjtcblxudHlwZSBWYWxpZGF0b3I8UGx1Z2luU2V0dGluZ3MgZXh0ZW5kcyBvYmplY3QsIFByb3BlcnR5TmFtZSBleHRlbmRzIFN0cmluZ0tleXM8UGx1Z2luU2V0dGluZ3M+ID0gU3RyaW5nS2V5czxQbHVnaW5TZXR0aW5ncz4+ID0gKFxuICB2YWx1ZTogUGx1Z2luU2V0dGluZ3NbUHJvcGVydHlOYW1lXSxcbiAgc2V0dGluZ3M6IFBsdWdpblNldHRpbmdzXG4pID0+IFByb21pc2FibGU8TWF5YmVSZXR1cm48c3RyaW5nPj47XG5cbi8qKlxuICogQmFzZSBjbGFzcyBmb3IgbWFuYWdpbmcgcGx1Z2luIHNldHRpbmdzLlxuICpcbiAqIEB0eXBlUGFyYW0gUGx1Z2luVHlwZXMgLSBQbHVnaW4tc3BlY2lmaWMgdHlwZXMuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBQbHVnaW5TZXR0aW5nc01hbmFnZXJCYXNlPFBsdWdpblR5cGVzIGV4dGVuZHMgUGx1Z2luVHlwZXNCYXNlPiB7XG4gIHB1YmxpYyByZWFkb25seSBhcHA6IEFwcDtcblxuICBwdWJsaWMgcmVhZG9ubHkgZGVmYXVsdFNldHRpbmdzOiBSZWFkb25seURlZXA8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj47XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGN1cnJlbnQgc2V0dGluZ3Mgd3JhcHBlci5cbiAgICpcbiAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgc2V0dGluZ3Mgd3JhcHBlci5cbiAgICovXG4gIHB1YmxpYyBnZXQgc2V0dGluZ3NXcmFwcGVyKCk6IEV4dHJhY3RSZWFkb25seVBsdWdpblNldHRpbmdzV3JhcHBlcjxQbHVnaW5UeXBlcz4ge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRTZXR0aW5nc1dyYXBwZXIgYXMgRXh0cmFjdFJlYWRvbmx5UGx1Z2luU2V0dGluZ3NXcmFwcGVyPFBsdWdpblR5cGVzPjtcbiAgfVxuXG4gIHByaXZhdGUgY3VycmVudFNldHRpbmdzV3JhcHBlcjogRXh0cmFjdFBsdWdpblNldHRpbmdzV3JhcHBlcjxQbHVnaW5UeXBlcz47XG5cbiAgcHJpdmF0ZSBsYXN0U2F2ZWRTZXR0aW5nc1dyYXBwZXI6IEV4dHJhY3RQbHVnaW5TZXR0aW5nc1dyYXBwZXI8UGx1Z2luVHlwZXM+O1xuICBwcml2YXRlIHJlYWRvbmx5IHByb3BlcnR5TmFtZXM6IEV4dHJhY3RQbHVnaW5TZXR0aW5nc1Byb3BlcnR5TmFtZXM8UGx1Z2luVHlwZXM+W107XG4gIHByaXZhdGUgcmVhZG9ubHkgdmFsaWRhdG9ycyA9IG5ldyBNYXA8RXh0cmFjdFBsdWdpblNldHRpbmdzUHJvcGVydHlOYW1lczxQbHVnaW5UeXBlcz4sIFZhbGlkYXRvcjxFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+Pj4oKTtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgcGx1Z2luIHNldHRpbmdzIG1hbmFnZXIuXG4gICAqXG4gICAqIEBwYXJhbSBwbHVnaW4gLSBUaGUgcGx1Z2luLlxuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSBwbHVnaW46IEV4dHJhY3RQbHVnaW48UGx1Z2luVHlwZXM+KSB7XG4gICAgdGhpcy5hcHAgPSBwbHVnaW4uYXBwO1xuICAgIHRoaXMuZGVmYXVsdFNldHRpbmdzID0gdGhpcy5jcmVhdGVEZWZhdWx0U2V0dGluZ3MoKSBhcyBSZWFkb25seURlZXA8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj47XG4gICAgdGhpcy5jdXJyZW50U2V0dGluZ3NXcmFwcGVyID0gdGhpcy5jcmVhdGVEZWZhdWx0U2V0dGluZ3NXcmFwcGVyKCk7XG4gICAgdGhpcy5sYXN0U2F2ZWRTZXR0aW5nc1dyYXBwZXIgPSB0aGlzLmNyZWF0ZURlZmF1bHRTZXR0aW5nc1dyYXBwZXIoKTtcbiAgICB0aGlzLnByb3BlcnR5TmFtZXMgPSBnZXRBbGxLZXlzKHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlci5zZXR0aW5ncyk7XG4gICAgdGhpcy5yZWdpc3RlclZhbGlkYXRvcnMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFZGl0cyB0aGUgcGx1Z2luIHNldHRpbmdzIGFuZCBzYXZlcyB0aGVtLlxuICAgKlxuICAgKiBAcGFyYW0gc2V0dGluZ3NFZGl0b3IgLSBUaGUgZWRpdG9yLlxuICAgKiBAcGFyYW0gY29udGV4dCAtIFRoZSBjb250ZXh0LlxuICAgKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIHNldHRpbmdzIGFyZSBzYXZlZC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBlZGl0QW5kU2F2ZShzZXR0aW5nc0VkaXRvcjogKHNldHRpbmdzOiBFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+KSA9PiBQcm9taXNhYmxlPHZvaWQ+LCBjb250ZXh0PzogdW5rbm93bik6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZWRpdChzZXR0aW5nc0VkaXRvcik7XG4gICAgYXdhaXQgdGhpcy5zYXZlVG9GaWxlKGNvbnRleHQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuc3VyZXMgdGhlIHNldHRpbmdzIGFyZSBzYWZlLlxuICAgKlxuICAgKiBJdCBydW5zIHZhbGlkYXRpb24gZm9yIGVhY2ggcHJvcGVydHkgYW5kIHNldHMgdGhlIGRlZmF1bHQgdmFsdWUgaWYgdGhlIHZhbGlkYXRpb24gZmFpbHMuXG4gICAqXG4gICAqIEBwYXJhbSBzZXR0aW5ncyAtIFRoZSBzZXR0aW5ncy5cbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBzZXR0aW5ncyBhcmUgc2FmZS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBlbnN1cmVTYWZlKHNldHRpbmdzOiBFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdmFsaWRhdGlvblJlc3VsdCA9IGF3YWl0IHRoaXMudmFsaWRhdGUoc2V0dGluZ3MpO1xuICAgIGZvciAoY29uc3QgcHJvcGVydHlOYW1lIG9mIHRoaXMucHJvcGVydHlOYW1lcykge1xuICAgICAgaWYgKHZhbGlkYXRpb25SZXN1bHRbcHJvcGVydHlOYW1lXSkge1xuICAgICAgICBzZXR0aW5nc1twcm9wZXJ0eU5hbWVdID0gdGhpcy5kZWZhdWx0U2V0dGluZ3NbcHJvcGVydHlOYW1lXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBhIHNhZmUgY29weSBvZiB0aGUgc2V0dGluZ3MuXG4gICAqXG4gICAqIEBwYXJhbSBzZXR0aW5ncyAtIFRoZSBzZXR0aW5ncy5cbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB0byB0aGUgc2FmZSBjb3B5IG9mIHRoZSBzZXR0aW5ncy5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBnZXRTYWZlQ29weShzZXR0aW5nczogRXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPik6IFByb21pc2U8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj4ge1xuICAgIGNvbnN0IHNhZmVTZXR0aW5ncyA9IHRoaXMuY2xvbmVTZXR0aW5ncyhzZXR0aW5ncyk7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVTYWZlKHNhZmVTZXR0aW5ncyk7XG4gICAgcmV0dXJuIHNhZmVTZXR0aW5ncztcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0aGUgcGx1Z2luIHNldHRpbmdzIGZyb20gdGhlIGZpbGUuXG4gICAqXG4gICAqIEBwYXJhbSBpc0luaXRpYWxMb2FkIC0gV2hldGhlciB0aGUgc2V0dGluZ3MgYXJlIGJlaW5nIGxvYWRlZCBmb3IgdGhlIGZpcnN0IHRpbWUuXG4gICAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgc2V0dGluZ3MgYXJlIGxvYWRlZC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBsb2FkRnJvbUZpbGUoaXNJbml0aWFsTG9hZDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLnBsdWdpbi5sb2FkRGF0YSgpIGFzIHVua25vd247XG4gICAgdGhpcy5sYXN0U2F2ZWRTZXR0aW5nc1dyYXBwZXIgPSB0aGlzLmNyZWF0ZURlZmF1bHRTZXR0aW5nc1dyYXBwZXIoKTtcbiAgICB0aGlzLmN1cnJlbnRTZXR0aW5nc1dyYXBwZXIgPSB0aGlzLmNyZWF0ZURlZmF1bHRTZXR0aW5nc1dyYXBwZXIoKTtcblxuICAgIGlmIChkYXRhID09PSB1bmRlZmluZWQgfHwgZGF0YSA9PT0gbnVsbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgZGF0YSAhPT0gJ29iamVjdCcpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYEludmFsaWQgc2V0dGluZ3MgZnJvbSBkYXRhLmpzb24uIEV4cGVjdGVkIE9iamVjdCwgZ290OiAke3R5cGVvZiBkYXRhfWApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHJhd1JlY29yZCA9IGRhdGEgYXMgR2VuZXJpY09iamVjdDtcbiAgICBjb25zdCBwYXJzZWRTZXR0aW5ncyA9IGF3YWl0IHRoaXMucmF3UmVjb3JkVG9TZXR0aW5ncyhyYXdSZWNvcmQpO1xuICAgIGNvbnN0IHZhbGlkYXRpb25SZXN1bHQgPSBhd2FpdCB0aGlzLnZhbGlkYXRlKHBhcnNlZFNldHRpbmdzKTtcblxuICAgIGZvciAoY29uc3QgcHJvcGVydHlOYW1lIG9mIHRoaXMucHJvcGVydHlOYW1lcykge1xuICAgICAgdGhpcy5zZXRQcm9wZXJ0eUltcGwocHJvcGVydHlOYW1lLCBwYXJzZWRTZXR0aW5nc1twcm9wZXJ0eU5hbWVdLCB2YWxpZGF0aW9uUmVzdWx0W3Byb3BlcnR5TmFtZV0pO1xuICAgIH1cblxuICAgIHRoaXMubGFzdFNhdmVkU2V0dGluZ3NXcmFwcGVyID0gdGhpcy5jbG9uZVNldHRpbmdzV3JhcHBlcih0aGlzLmN1cnJlbnRTZXR0aW5nc1dyYXBwZXIpO1xuXG4gICAgY29uc3QgbmV3UmVjb3JkID0gYXdhaXQgdGhpcy5zZXR0aW5nc1RvUmF3UmVjb3JkKHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlci5zZXR0aW5ncyk7XG5cbiAgICBpZiAoIWRlZXBFcXVhbChuZXdSZWNvcmQsIGRhdGEpKSB7XG4gICAgICBhd2FpdCB0aGlzLnNhdmVUb0ZpbGVJbXBsKCk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy5wbHVnaW4ub25Mb2FkU2V0dGluZ3ModGhpcy5jdXJyZW50U2V0dGluZ3NXcmFwcGVyLCBpc0luaXRpYWxMb2FkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTYXZlcyB0aGUgbmV3IHBsdWdpbiBzZXR0aW5ncy5cbiAgICpcbiAgICogQHBhcmFtIGNvbnRleHQgLSBUaGUgY29udGV4dCBvZiB0aGUgc2F2ZSB0byBmaWxlIG9wZXJhdGlvbi5cbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBzZXR0aW5ncyBhcmUgc2F2ZWQuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgc2F2ZVRvRmlsZShjb250ZXh0PzogdW5rbm93bik6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChkZWVwRXF1YWwodGhpcy5sYXN0U2F2ZWRTZXR0aW5nc1dyYXBwZXIuc2V0dGluZ3MsIHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlci5zZXR0aW5ncykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLnNhdmVUb0ZpbGVJbXBsKCk7XG4gICAgYXdhaXQgdGhpcy5wbHVnaW4ub25TYXZlU2V0dGluZ3ModGhpcy5jdXJyZW50U2V0dGluZ3NXcmFwcGVyLCB0aGlzLmxhc3RTYXZlZFNldHRpbmdzV3JhcHBlciwgY29udGV4dCk7XG4gICAgdGhpcy5sYXN0U2F2ZWRTZXR0aW5nc1dyYXBwZXIgPSB0aGlzLmNsb25lU2V0dGluZ3NXcmFwcGVyKHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlcik7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eS5cbiAgICpcbiAgICogQHR5cGVQYXJhbSBQcm9wZXJ0eU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSBwcm9wZXJ0eU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBzZXQuXG4gICAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHZhbGlkYXRpb24gbWVzc2FnZS5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBzZXRQcm9wZXJ0eTxQcm9wZXJ0eU5hbWUgZXh0ZW5kcyBFeHRyYWN0UGx1Z2luU2V0dGluZ3NQcm9wZXJ0eU5hbWVzPFBsdWdpblR5cGVzPj4oXG4gICAgcHJvcGVydHlOYW1lOiBQcm9wZXJ0eU5hbWUsXG4gICAgdmFsdWU6IEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz5bUHJvcGVydHlOYW1lXVxuICApOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGF3YWl0IHRoaXMuZWRpdCgoc2V0dGluZ3MpID0+IHtcbiAgICAgIHNldHRpbmdzW3Byb3BlcnR5TmFtZV0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50U2V0dGluZ3NXcmFwcGVyLnZhbGlkYXRpb25NZXNzYWdlc1twcm9wZXJ0eU5hbWVdO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB0aGUgc2V0dGluZ3MuXG4gICAqXG4gICAqIEBwYXJhbSBzZXR0aW5ncyAtIFRoZSBzZXR0aW5ncy5cbiAgICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gdGhhdCByZXNvbHZlcyB0byB0aGUgdmFsaWRhdGlvbiByZXN1bHQuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdmFsaWRhdGUoc2V0dGluZ3M6IEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4pOiBQcm9taXNlPFZhbGlkYXRpb25SZXN1bHQ8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj4+IHtcbiAgICBjb25zdCByZXN1bHQ6IFZhbGlkYXRpb25SZXN1bHQ8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtwcm9wZXJ0eU5hbWUsIHZhbGlkYXRvcl0gb2YgdGhpcy52YWxpZGF0b3JzLmVudHJpZXMoKSkge1xuICAgICAgY29uc3QgdmFsaWRhdGlvbk1lc3NhZ2UgPSBhd2FpdCB2YWxpZGF0b3Ioc2V0dGluZ3NbcHJvcGVydHlOYW1lXSwgc2V0dGluZ3MpO1xuICAgICAgaWYgKHZhbGlkYXRpb25NZXNzYWdlKSB7XG4gICAgICAgIHJlc3VsdFtwcm9wZXJ0eU5hbWVdID0gdmFsaWRhdGlvbk1lc3NhZ2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBjcmVhdGVEZWZhdWx0U2V0dGluZ3MoKTogRXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPjtcblxuICAvKipcbiAgICogR2V0cyB0aGUgdHJhbnNmb3JtZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSB0cmFuc2Zvcm1lci5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRUcmFuc2Zvcm1lcigpOiBUcmFuc2Zvcm1lciB7XG4gICAgcmV0dXJuIGRlZmF1bHRUcmFuc2Zvcm1lcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiB0aGUgcGx1Z2luIHNldHRpbmdzIGFyZSBsb2FkZWQuXG4gICAqXG4gICAqIEBwYXJhbSBfcmVjb3JkIC0gVGhlIHJlY29yZC5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBvbkxvYWRSZWNvcmQoX3JlY29yZDogR2VuZXJpY09iamVjdCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IG5vb3BBc3luYygpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBwbHVnaW4gc2V0dGluZ3MgYXJlIHNhdmluZy5cbiAgICpcbiAgICogQHBhcmFtIF9yZWNvcmQgLSBUaGUgcmVjb3JkLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIG9uU2F2aW5nUmVjb3JkKF9yZWNvcmQ6IEdlbmVyaWNPYmplY3QpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBub29wQXN5bmMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgYSB2YWxpZGF0b3IgZm9yIGEgcHJvcGVydHkuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wZXJ0eU5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkuXG4gICAqIEBwYXJhbSB2YWxpZGF0b3IgLSBUaGUgdmFsaWRhdG9yLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlZ2lzdGVyVmFsaWRhdG9yPFByb3BlcnR5TmFtZSBleHRlbmRzIEV4dHJhY3RQbHVnaW5TZXR0aW5nc1Byb3BlcnR5TmFtZXM8UGx1Z2luVHlwZXM+PihcbiAgICBwcm9wZXJ0eU5hbWU6IFByb3BlcnR5TmFtZSxcbiAgICB2YWxpZGF0b3I6IFZhbGlkYXRvcjxFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+LCBQcm9wZXJ0eU5hbWU+XG4gICk6IHZvaWQge1xuICAgIHRoaXMudmFsaWRhdG9ycy5zZXQocHJvcGVydHlOYW1lLCB2YWxpZGF0b3IgYXMgVmFsaWRhdG9yPEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4+KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlcnMgdGhlIHZhbGlkYXRvcnMuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHN1YmNsYXNzZXMgdG8gcmVnaXN0ZXIgdmFsaWRhdG9ycyBmb3IgcHJvcGVydGllcy5cbiAgICovXG4gIHByb3RlY3RlZCByZWdpc3RlclZhbGlkYXRvcnMoKTogdm9pZCB7XG4gICAgbm9vcCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbG9uZVNldHRpbmdzKHNldHRpbmdzOiBFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+KTogRXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPiB7XG4gICAgY29uc3QgcmVjb3JkID0gdGhpcy5zZXR0aW5nc1RvUmF3UmVjb3JkKHNldHRpbmdzKTtcbiAgICBjb25zdCBqc29uID0gSlNPTi5zdHJpbmdpZnkocmVjb3JkKTtcbiAgICBjb25zdCBjbG9uZVJlY29yZCA9IEpTT04ucGFyc2UoanNvbikgYXMgR2VuZXJpY09iamVjdDtcbiAgICByZXR1cm4gdGhpcy5yYXdSZWNvcmRUb1NldHRpbmdzKGNsb25lUmVjb3JkKTtcbiAgfVxuXG4gIHByaXZhdGUgY2xvbmVTZXR0aW5nc1dyYXBwZXIoXG4gICAgc2V0dGluZ3NXcmFwcGVyOiBQbHVnaW5TZXR0aW5nc1dyYXBwZXI8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj5cbiAgKTogUGx1Z2luU2V0dGluZ3NXcmFwcGVyPEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4+IHtcbiAgICByZXR1cm4ge1xuICAgICAgc2FmZVNldHRpbmdzOiB0aGlzLmNsb25lU2V0dGluZ3Moc2V0dGluZ3NXcmFwcGVyLnNhZmVTZXR0aW5ncyksXG4gICAgICBzZXR0aW5nczogdGhpcy5jbG9uZVNldHRpbmdzKHNldHRpbmdzV3JhcHBlci5zZXR0aW5ncyksXG4gICAgICB2YWxpZGF0aW9uTWVzc2FnZXM6IHsgLi4uc2V0dGluZ3NXcmFwcGVyLnZhbGlkYXRpb25NZXNzYWdlcyB9XG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlRGVmYXVsdFNldHRpbmdzV3JhcHBlcigpOiBQbHVnaW5TZXR0aW5nc1dyYXBwZXI8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj4ge1xuICAgIHJldHVybiB7XG4gICAgICBzYWZlU2V0dGluZ3M6IHRoaXMuY3JlYXRlRGVmYXVsdFNldHRpbmdzKCksXG4gICAgICBzZXR0aW5nczogdGhpcy5jcmVhdGVEZWZhdWx0U2V0dGluZ3MoKSxcbiAgICAgIHZhbGlkYXRpb25NZXNzYWdlczoge30gYXMgUmVjb3JkPEV4dHJhY3RQbHVnaW5TZXR0aW5nc1Byb3BlcnR5TmFtZXM8UGx1Z2luVHlwZXM+LCBzdHJpbmc+XG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZWRpdChzZXR0aW5nc0VkaXRvcjogKHNldHRpbmdzOiBFeHRyYWN0UGx1Z2luU2V0dGluZ3M8UGx1Z2luVHlwZXM+KSA9PiBQcm9taXNhYmxlPHZvaWQ+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHNldHRpbmdzRWRpdG9yKHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlci5zZXR0aW5ncyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGNvbnN0IHZhbGlkYXRpb25SZXN1bHQgPSBhd2FpdCB0aGlzLnZhbGlkYXRlKHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlci5zZXR0aW5ncyk7XG4gICAgICBmb3IgKGNvbnN0IHByb3BlcnR5TmFtZSBvZiB0aGlzLnByb3BlcnR5TmFtZXMpIHtcbiAgICAgICAgY29uc3QgdmFsaWRhdGlvbk1lc3NhZ2UgPSB2YWxpZGF0aW9uUmVzdWx0W3Byb3BlcnR5TmFtZV0gPz8gJyc7XG4gICAgICAgIHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlci52YWxpZGF0aW9uTWVzc2FnZXNbcHJvcGVydHlOYW1lXSA9IHZhbGlkYXRpb25NZXNzYWdlO1xuICAgICAgICB0aGlzLmN1cnJlbnRTZXR0aW5nc1dyYXBwZXIuc2FmZVNldHRpbmdzW3Byb3BlcnR5TmFtZV0gPSB2YWxpZGF0aW9uTWVzc2FnZVxuICAgICAgICAgID8gdGhpcy5kZWZhdWx0U2V0dGluZ3NbcHJvcGVydHlOYW1lXVxuICAgICAgICAgIDogdGhpcy5jdXJyZW50U2V0dGluZ3NXcmFwcGVyLnNldHRpbmdzW3Byb3BlcnR5TmFtZV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpc1ZhbGlkUHJvcGVydHlOYW1lKHByb3A6IHVua25vd24pOiBwcm9wIGlzIEV4dHJhY3RQbHVnaW5TZXR0aW5nc1Byb3BlcnR5TmFtZXM8UGx1Z2luVHlwZXM+IHtcbiAgICBpZiAodHlwZW9mIHByb3AgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuICh0aGlzLnByb3BlcnR5TmFtZXMgYXMgc3RyaW5nW10pLmluY2x1ZGVzKHByb3ApO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByYXdSZWNvcmRUb1NldHRpbmdzKHJhd1JlY29yZDogR2VuZXJpY09iamVjdCk6IFByb21pc2U8RXh0cmFjdFBsdWdpblNldHRpbmdzPFBsdWdpblR5cGVzPj4ge1xuICAgIGF3YWl0IHRoaXMub25Mb2FkUmVjb3JkKHJhd1JlY29yZCk7XG5cbiAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuY3JlYXRlRGVmYXVsdFNldHRpbmdzKCk7XG5cbiAgICBmb3IgKGNvbnN0IFtwcm9wZXJ0eU5hbWUsIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhyYXdSZWNvcmQpKSB7XG4gICAgICBpZiAoIXRoaXMuaXNWYWxpZFByb3BlcnR5TmFtZShwcm9wZXJ0eU5hbWUpKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgVW5rbm93biBwcm9wZXJ0eTogJHtwcm9wZXJ0eU5hbWV9YCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSB0eXBlb2YgdGhpcy5kZWZhdWx0U2V0dGluZ3NbcHJvcGVydHlOYW1lXSkge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ1Bvc3NpYmxlIGludmFsaWQgdmFsdWUgdHlwZS4gSXQgbWlnaHQgbGVhZCB0byBhbiB1bmV4cGVjdGVkIGJlaGF2aW9yIG9mIHRoZSBwbHVnaW4uIFRoZXJlIGlzIGFsc28gYSBjaGFuY2UgaXQgaXMgYSBmYWxzZS1uZWdhdGl2ZSB3YXJuaW5nLCBhcyB3ZSBhcmUgdW5hYmxlIHRvIGRldGVybWluZSB0aGUgZXhhY3QgdHlwZSBvZiB0aGUgdmFsdWUgaW4gcnVudGltZS4nLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGRlZmF1bHRWYWx1ZTogdGhpcy5kZWZhdWx0U2V0dGluZ3NbcHJvcGVydHlOYW1lXSxcbiAgICAgICAgICAgIHByb3BlcnR5TmFtZSxcbiAgICAgICAgICAgIHZhbHVlXG4gICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBzZXR0aW5nc1twcm9wZXJ0eU5hbWVdID0gdmFsdWUgYXMgRXh0cmFjdFBsdWdpblNldHRpbmdzUHJvcGVydHlWYWx1ZXM8UGx1Z2luVHlwZXM+O1xuICAgIH1cblxuICAgIHJldHVybiBzZXR0aW5ncztcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2F2ZVRvRmlsZUltcGwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5wbHVnaW4uc2F2ZURhdGEoYXdhaXQgdGhpcy5zZXR0aW5nc1RvUmF3UmVjb3JkKHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlcikpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRQcm9wZXJ0eUltcGwoXG4gICAgcHJvcGVydHlOYW1lOiBFeHRyYWN0UGx1Z2luU2V0dGluZ3NQcm9wZXJ0eU5hbWVzPFBsdWdpblR5cGVzPixcbiAgICB2YWx1ZTogRXh0cmFjdFBsdWdpblNldHRpbmdzUHJvcGVydHlWYWx1ZXM8UGx1Z2luVHlwZXM+LFxuICAgIHZhbGlkYXRpb25NZXNzYWdlPzogc3RyaW5nXG4gICk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudFNldHRpbmdzV3JhcHBlci5zZXR0aW5nc1twcm9wZXJ0eU5hbWVdID0gdmFsdWU7XG4gICAgdGhpcy5jdXJyZW50U2V0dGluZ3NXcmFwcGVyLnZhbGlkYXRpb25NZXNzYWdlc1twcm9wZXJ0eU5hbWVdID0gdmFsaWRhdGlvbk1lc3NhZ2UgPz8gJyc7XG4gICAgdGhpcy5jdXJyZW50U2V0dGluZ3NXcmFwcGVyLnNhZmVTZXR0aW5nc1twcm9wZXJ0eU5hbWVdID0gdmFsaWRhdGlvbk1lc3NhZ2UgPyB0aGlzLmRlZmF1bHRTZXR0aW5nc1twcm9wZXJ0eU5hbWVdIDogdmFsdWU7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHNldHRpbmdzVG9SYXdSZWNvcmQoc2V0dGluZ3M6IEV4dHJhY3RQbHVnaW5TZXR0aW5nczxQbHVnaW5UeXBlcz4pOiBQcm9taXNlPEdlbmVyaWNPYmplY3Q+IHtcbiAgICBjb25zdCByYXdSZWNvcmQ6IEdlbmVyaWNPYmplY3QgPSB7fTtcblxuICAgIGZvciAoY29uc3QgcHJvcGVydHlOYW1lIG9mIHRoaXMucHJvcGVydHlOYW1lcykge1xuICAgICAgcmF3UmVjb3JkW3Byb3BlcnR5TmFtZV0gPSBzZXR0aW5nc1twcm9wZXJ0eU5hbWVdO1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMub25TYXZpbmdSZWNvcmQocmF3UmVjb3JkKTtcblxuICAgIHJldHVybiB0aGlzLmdldFRyYW5zZm9ybWVyKCkudHJhbnNmb3JtT2JqZWN0UmVjdXJzaXZlbHkocmF3UmVjb3JkKTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUE2QkEsc0JBR087QUFDUCxvQkFHTztBQUNQLDZCQUFnQztBQUNoQyxpQ0FBb0M7QUFDcEMsOEJBQWlDO0FBQ2pDLDRDQUErQztBQUUvQyxNQUFNLHFCQUFxQixJQUFJLHlDQUFpQjtBQUFBLEVBQzlDLElBQUkscUVBQStCO0FBQUEsRUFDbkMsSUFBSSx1Q0FBZ0I7QUFBQSxFQUNwQixJQUFJLCtDQUFvQjtBQUMxQixDQUFDO0FBY00sTUFBZSwwQkFBK0Q7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUF3QjVFLFlBQTRCLFFBQW9DO0FBQXBDO0FBQ2pDLFNBQUssTUFBTSxPQUFPO0FBQ2xCLFNBQUssa0JBQWtCLEtBQUssc0JBQXNCO0FBQ2xELFNBQUsseUJBQXlCLEtBQUssNkJBQTZCO0FBQ2hFLFNBQUssMkJBQTJCLEtBQUssNkJBQTZCO0FBQ2xFLFNBQUssb0JBQWdCLDBCQUFXLEtBQUssdUJBQXVCLFFBQVE7QUFDcEUsU0FBSyxtQkFBbUI7QUFBQSxFQUMxQjtBQUFBLEVBOUJnQjtBQUFBLEVBRUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPaEIsSUFBVyxrQkFBcUU7QUFDOUUsV0FBTyxLQUFLO0FBQUEsRUFDZDtBQUFBLEVBRVE7QUFBQSxFQUVBO0FBQUEs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