obsidian-dev-utils 69.2.0 → 69.2.2

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.
@@ -0,0 +1,864 @@
1
+ /*
2
+ THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
3
+ if you want to view the source, please visit the github repository of this plugin
4
+ */
5
+
6
+ (function initCjs() {
7
+ // eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
8
+ const globalThisRecord = globalThis;
9
+ globalThisRecord['__name'] ??= name;
10
+ const originalRequire = require;
11
+ if (originalRequire && !originalRequire.__isPatched) {
12
+ // eslint-disable-next-line no-global-assign, no-implicit-globals -- We need to patch the `require()` function.
13
+ require = Object.assign(
14
+ (id) => requirePatched(id),
15
+ originalRequire,
16
+ {
17
+ __isPatched: true
18
+ }
19
+ );
20
+ }
21
+
22
+ const newFuncs = {
23
+ __extractDefault() {
24
+ return extractDefault;
25
+ },
26
+ process() {
27
+ const browserProcess = {
28
+ browser: true,
29
+ cwd() {
30
+ return '/';
31
+ },
32
+ env: {},
33
+ platform: 'android'
34
+ };
35
+ return browserProcess;
36
+ }
37
+ };
38
+
39
+ for (const key of Object.keys(newFuncs)) {
40
+ globalThisRecord[key] ??= newFuncs[key]?.();
41
+ }
42
+
43
+ function name(obj) {
44
+ return obj;
45
+ }
46
+
47
+ function extractDefault(module) {
48
+ return module && module.__esModule && 'default' in module ? module.default : module;
49
+ }
50
+
51
+ const OBSIDIAN_BUILT_IN_MODULE_NAMES = [
52
+ 'obsidian',
53
+ '@codemirror/autocomplete',
54
+ '@codemirror/collab',
55
+ '@codemirror/commands',
56
+ '@codemirror/language',
57
+ '@codemirror/lint',
58
+ '@codemirror/search',
59
+ '@codemirror/state',
60
+ '@codemirror/text',
61
+ '@codemirror/view',
62
+ '@lezer/common',
63
+ '@lezer/lr',
64
+ '@lezer/highlight'];
65
+
66
+
67
+ const DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES = [
68
+ '@codemirror/closebrackets',
69
+ '@codemirror/comment',
70
+ '@codemirror/fold',
71
+ '@codemirror/gutter',
72
+ '@codemirror/highlight',
73
+ '@codemirror/history',
74
+ '@codemirror/matchbrackets',
75
+ '@codemirror/panel',
76
+ '@codemirror/rangeset',
77
+ '@codemirror/rectangular-selection',
78
+ '@codemirror/stream-parser',
79
+ '@codemirror/tooltip'];
80
+
81
+
82
+ function requirePatched(id) {
83
+ if (OBSIDIAN_BUILT_IN_MODULE_NAMES.includes(id) || DEPRECATED_OBSIDIAN_BUILT_IN_MODULE_NAMES.includes(id)) {
84
+ return originalRequire?.(id);
85
+ }
86
+
87
+ // eslint-disable-next-line @typescript-eslint/no-deprecated, obsidianmd/no-global-this -- Need access to app. Actively use globalThis.
88
+ if (globalThis.app.isMobile) {
89
+ if (id === 'process' || id === 'node:process') {
90
+ // eslint-disable-next-line no-console -- Valid usage.
91
+ console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Fake process object is returned instead.`);
92
+ // eslint-disable-next-line obsidianmd/no-global-this -- Actively use globalThis.
93
+ return globalThis.process;
94
+ }
95
+ } else {
96
+ const module = originalRequire?.(id);
97
+ if (module) {
98
+ return extractDefault(module);
99
+ }
100
+ }
101
+
102
+ // eslint-disable-next-line no-console -- Valid usage.
103
+ console.debug(`The most likely you can safely ignore this error. Module not found: ${id}. Empty object is returned instead.`);
104
+ return {};
105
+ }
106
+ })();
107
+
108
+ "use strict";
109
+ var __defProp = Object.defineProperty;
110
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
111
+ var __getOwnPropNames = Object.getOwnPropertyNames;
112
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
113
+ var __export = (target, all) => {
114
+ for (var name in all)
115
+ __defProp(target, name, { get: all[name], enumerable: true });
116
+ };
117
+ var __copyProps = (to, from, except, desc) => {
118
+ if (from && typeof from === "object" || typeof from === "function") {
119
+ for (let key of __getOwnPropNames(from))
120
+ if (!__hasOwnProp.call(to, key) && key !== except)
121
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
122
+ }
123
+ return to;
124
+ };
125
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
126
+ var rename_delete_handler_component_exports = {};
127
+ __export(rename_delete_handler_component_exports, {
128
+ EmptyFolderBehavior: () => EmptyFolderBehavior,
129
+ RenameDeleteHandlerComponent: () => RenameDeleteHandlerComponent
130
+ });
131
+ module.exports = __toCommonJS(rename_delete_handler_component_exports);
132
+ var import_implementations = require('@obsidian-typings/obsidian-public-latest/implementations');
133
+ var import_i18next = require('i18next');
134
+ var import_obsidian = require('obsidian');
135
+ var import_array = require('../../array.cjs');
136
+ var import_debug = require('../../debug.cjs');
137
+ var import_object_utils = require('../../object-utils.cjs');
138
+ var import_path = require('../../path.cjs');
139
+ var import_app = require('../app.cjs');
140
+ var import_attachment_path = require('../attachment-path.cjs');
141
+ var import_file_system = require('../file-system.cjs');
142
+ var import_link = require('../link.cjs');
143
+ var import_metadata_cache = require('../metadata-cache.cjs');
144
+ var import_queue = require('../queue.cjs');
145
+ var import_vault_delete = require('../vault-delete.cjs');
146
+ var import_vault = require('../vault.cjs');
147
+ var import_component_ex = require('./component-ex.cjs');
148
+ var import_monkey_around_component = require('./monkey-around-component.cjs');
149
+ var EmptyFolderBehavior = /* @__PURE__ */ ((EmptyFolderBehavior2) => {
150
+ EmptyFolderBehavior2["Delete"] = "Delete";
151
+ EmptyFolderBehavior2["DeleteWithEmptyParents"] = "DeleteWithEmptyParents";
152
+ EmptyFolderBehavior2["Keep"] = "Keep";
153
+ return EmptyFolderBehavior2;
154
+ })(EmptyFolderBehavior || {});
155
+ const PATCH_TOKEN = /* @__PURE__ */ Symbol.for("renameDeleteHandler");
156
+ class DeleteHandler {
157
+ constructor(app, file, abortSignal, settingsManager, deletedMetadataCacheMap) {
158
+ this.app = app;
159
+ this.file = file;
160
+ this.abortSignal = abortSignal;
161
+ this.settingsManager = settingsManager;
162
+ this.deletedMetadataCacheMap = deletedMetadataCacheMap;
163
+ }
164
+ app;
165
+ file;
166
+ abortSignal;
167
+ settingsManager;
168
+ deletedMetadataCacheMap;
169
+ async handle() {
170
+ this.abortSignal.throwIfAborted();
171
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:handleDelete")(`Handle Delete ${this.file.path}`);
172
+ if (!(0, import_file_system.isNote)(this.app, this.file)) {
173
+ return;
174
+ }
175
+ const settings = this.settingsManager.getSettings();
176
+ if (settings.isPathIgnored?.(this.file.path)) {
177
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:handleDelete")(`Skipping delete handler of ${this.file.path} as the path is ignored.`);
178
+ return;
179
+ }
180
+ const parentFolderPaths = /* @__PURE__ */ new Set([(0, import_path.dirname)(this.file.path)]);
181
+ if (settings.shouldHandleDeletions) {
182
+ const cache = this.deletedMetadataCacheMap.get(this.file.path);
183
+ this.deletedMetadataCacheMap.delete(this.file.path);
184
+ if (cache) {
185
+ const links = (0, import_metadata_cache.getAllLinks)(cache);
186
+ for (const link of links) {
187
+ const attachmentFile = (0, import_link.extractLinkFile)(this.app, link, this.file.path);
188
+ if (!attachmentFile) {
189
+ continue;
190
+ }
191
+ if (this.settingsManager.isNoteEx(attachmentFile.path)) {
192
+ continue;
193
+ }
194
+ parentFolderPaths.add(attachmentFile.parent?.path ?? "");
195
+ await (0, import_vault_delete.deleteIfNotUsed)(this.app, attachmentFile, this.file.path, false, settings.emptyFolderBehavior !== "Keep" /* Keep */);
196
+ this.abortSignal.throwIfAborted();
197
+ }
198
+ }
199
+ }
200
+ parentFolderPaths.delete("");
201
+ await cleanupParentFolders(this.app, this.settingsManager.getSettings(), Array.from(parentFolderPaths));
202
+ this.abortSignal.throwIfAborted();
203
+ if (!settings.shouldHandleDeletions) {
204
+ return;
205
+ }
206
+ const attachmentFolderPath = await (0, import_attachment_path.getAttachmentFolderPath)(this.app, this.file.path, import_attachment_path.AttachmentPathContext.DeleteNote);
207
+ const attachmentFolder = (0, import_file_system.getFolderOrNull)(this.app, attachmentFolderPath);
208
+ if (!attachmentFolder) {
209
+ return;
210
+ }
211
+ if (!await (0, import_attachment_path.hasOwnAttachmentFolder)(this.app, this.file.path, import_attachment_path.AttachmentPathContext.DeleteNote)) {
212
+ return;
213
+ }
214
+ this.abortSignal.throwIfAborted();
215
+ await (0, import_vault_delete.deleteIfNotUsed)(this.app, attachmentFolder, this.file.path, false, settings.emptyFolderBehavior !== "Keep" /* Keep */);
216
+ this.abortSignal.throwIfAborted();
217
+ }
218
+ }
219
+ class HandledRenames {
220
+ map = /* @__PURE__ */ new Map();
221
+ add(oldPath, newPath) {
222
+ this.map.set(this.keyToString(oldPath, newPath), { newPath, oldPath });
223
+ }
224
+ delete(oldPath, newPath) {
225
+ this.map.delete(this.keyToString(oldPath, newPath));
226
+ }
227
+ has(oldPath, newPath) {
228
+ return this.map.has(this.keyToString(oldPath, newPath));
229
+ }
230
+ keys() {
231
+ return this.map.values();
232
+ }
233
+ keyToString(oldPath, newPath) {
234
+ return `${oldPath} -> ${newPath}`;
235
+ }
236
+ }
237
+ class MetadataDeletedHandler {
238
+ constructor(app, file, prevCache, settingsManager, deletedMetadataCacheMap) {
239
+ this.app = app;
240
+ this.file = file;
241
+ this.prevCache = prevCache;
242
+ this.settingsManager = settingsManager;
243
+ this.deletedMetadataCacheMap = deletedMetadataCacheMap;
244
+ }
245
+ app;
246
+ file;
247
+ prevCache;
248
+ settingsManager;
249
+ deletedMetadataCacheMap;
250
+ handle() {
251
+ const settings = this.settingsManager.getSettings();
252
+ if (!settings.shouldHandleDeletions) {
253
+ return;
254
+ }
255
+ if (settings.isPathIgnored?.(this.file.path)) {
256
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:handleMetadataDeleted")(`Skipping metadata delete handler of ${this.file.path} as the path is ignored.`);
257
+ return;
258
+ }
259
+ if ((0, import_file_system.isMarkdownFile)(this.app, this.file) && this.prevCache) {
260
+ this.deletedMetadataCacheMap.set(this.file.path, this.prevCache);
261
+ }
262
+ }
263
+ }
264
+ class SettingsManager {
265
+ constructor(app) {
266
+ this.app = app;
267
+ this.renameDeleteHandlersMap = (0, import_app.getObsidianDevUtilsState)(app, "renameDeleteHandlersMap", /* @__PURE__ */ new Map()).value;
268
+ }
269
+ app;
270
+ renameDeleteHandlersMap;
271
+ getSettings() {
272
+ const settingsBuilders = Array.from(this.renameDeleteHandlersMap.values()).reverse();
273
+ const settings = {};
274
+ settings.isNote = (path) => (0, import_file_system.isNote)(this.app, path);
275
+ settings.isPathIgnored = () => false;
276
+ for (const settingsBuilder of settingsBuilders) {
277
+ const newSettings = settingsBuilder();
278
+ settings.shouldDeleteConflictingAttachments ||= newSettings.shouldDeleteConflictingAttachments ?? false;
279
+ if (newSettings.emptyFolderBehavior) {
280
+ settings.emptyFolderBehavior ??= newSettings.emptyFolderBehavior;
281
+ }
282
+ settings.shouldHandleDeletions ||= newSettings.shouldHandleDeletions ?? false;
283
+ settings.shouldHandleRenames ||= newSettings.shouldHandleRenames ?? false;
284
+ settings.shouldRenameAttachmentFiles ||= newSettings.shouldRenameAttachmentFiles ?? false;
285
+ settings.shouldRenameAttachmentFolder ||= newSettings.shouldRenameAttachmentFolder ?? false;
286
+ settings.shouldUpdateFileNameAliases ||= newSettings.shouldUpdateFileNameAliases ?? false;
287
+ const isPathIgnored = settings.isPathIgnored;
288
+ settings.isPathIgnored = (path) => isPathIgnored(path) || (newSettings.isPathIgnored?.(path) ?? false);
289
+ const currentIsNote = settings.isNote;
290
+ settings.isNote = (path) => currentIsNote(path) && (newSettings.isNote?.(path) ?? true);
291
+ }
292
+ settings.emptyFolderBehavior ??= "Keep" /* Keep */;
293
+ return settings;
294
+ }
295
+ isNoteEx(path) {
296
+ const settings = this.getSettings();
297
+ return settings.isNote?.(path) ?? false;
298
+ }
299
+ }
300
+ class RenameHandler {
301
+ abortSignal;
302
+ app;
303
+ handledRenames;
304
+ interruptedCombinedBacklinksMap;
305
+ interruptedRenamesMap;
306
+ newPath;
307
+ oldCache;
308
+ oldPath;
309
+ oldPathBacklinksMap;
310
+ oldPathLinks;
311
+ settingsManager;
312
+ constructor(params) {
313
+ this.app = params.app;
314
+ this.oldPath = params.oldPath;
315
+ this.newPath = params.newPath;
316
+ this.oldPathBacklinksMap = params.oldPathBacklinksMap;
317
+ this.oldCache = params.oldCache;
318
+ this.abortSignal = params.abortSignal;
319
+ this.settingsManager = params.settingsManager;
320
+ this.interruptedRenamesMap = params.interruptedRenamesMap;
321
+ this.oldPathLinks = this.oldCache ? (0, import_metadata_cache.getAllLinks)(this.oldCache) : [];
322
+ this.handledRenames = params.handledRenames;
323
+ this.interruptedCombinedBacklinksMap = params.interruptedCombinedBacklinksMap ?? /* @__PURE__ */ new Map();
324
+ }
325
+ async handle() {
326
+ if (this.oldPath === this.newPath) {
327
+ return;
328
+ }
329
+ this.abortSignal.throwIfAborted();
330
+ await this.continueInterruptedRenames();
331
+ this.abortSignal.throwIfAborted();
332
+ await this.refreshLinks();
333
+ this.abortSignal.throwIfAborted();
334
+ if (await this.handleCaseCollision()) {
335
+ return;
336
+ }
337
+ this.abortSignal.throwIfAborted();
338
+ const renamedFilePaths = (0, import_app.getObsidianDevUtilsState)(this.app, "renamedFilePaths", /* @__PURE__ */ new Set()).value;
339
+ const renamedLinks = (0, import_app.getObsidianDevUtilsState)(this.app, "renamedLinkPaths", /* @__PURE__ */ new Set()).value;
340
+ try {
341
+ const renameMap = new RenameMap({
342
+ abortSignal: this.abortSignal,
343
+ app: this.app,
344
+ newPath: this.newPath,
345
+ oldCache: this.oldCache,
346
+ oldPath: this.oldPath,
347
+ settingsManager: this.settingsManager
348
+ });
349
+ await renameMap.fill();
350
+ this.abortSignal.throwIfAborted();
351
+ const combinedBacklinksMap = /* @__PURE__ */ new Map();
352
+ renameMap.initOriginalLinksMap(combinedBacklinksMap);
353
+ renameMap.initBacklinksMap(this.oldPathBacklinksMap, combinedBacklinksMap, this.oldPath);
354
+ for (const attachmentOldPath of renameMap.keys()) {
355
+ if (attachmentOldPath === this.oldPath) {
356
+ continue;
357
+ }
358
+ const attachmentOldPathBacklinksMap = (await (0, import_metadata_cache.getBacklinksForFileSafe)(this.app, attachmentOldPath)).data;
359
+ this.abortSignal.throwIfAborted();
360
+ renameMap.initBacklinksMap(attachmentOldPathBacklinksMap, combinedBacklinksMap, attachmentOldPath);
361
+ }
362
+ const parentFolderPaths = /* @__PURE__ */ new Set();
363
+ for (const [oldAttachmentPath, newAttachmentPath] of renameMap.entries()) {
364
+ if (oldAttachmentPath !== this.oldPath) {
365
+ const fixedNewAttachmentPath = await this.renameHandled(oldAttachmentPath, newAttachmentPath);
366
+ this.abortSignal.throwIfAborted();
367
+ renameMap.set(oldAttachmentPath, fixedNewAttachmentPath);
368
+ }
369
+ if (!this.settingsManager.isNoteEx(oldAttachmentPath)) {
370
+ parentFolderPaths.add((0, import_path.dirname)(oldAttachmentPath));
371
+ }
372
+ }
373
+ await cleanupParentFolders(this.app, this.settingsManager.getSettings(), Array.from(parentFolderPaths));
374
+ this.abortSignal.throwIfAborted();
375
+ const settings = this.settingsManager.getSettings();
376
+ for (const [newBacklinkPath, linkJsonToPathMap] of Array.from(combinedBacklinksMap.entries()).concat(
377
+ Array.from(this.interruptedCombinedBacklinksMap.entries())
378
+ )) {
379
+ let linkIndex = 0;
380
+ await (0, import_link.editLinks)(this.app, newBacklinkPath, (link) => {
381
+ linkIndex++;
382
+ const oldAttachmentPath = linkJsonToPathMap.get((0, import_object_utils.toJson)(link));
383
+ if (!oldAttachmentPath) {
384
+ return;
385
+ }
386
+ const newAttachmentPath = renameMap.get(oldAttachmentPath) ?? oldAttachmentPath;
387
+ renamedFilePaths.add(newBacklinkPath);
388
+ renamedLinks.add(`${newBacklinkPath}//${String(linkIndex)}`);
389
+ return (0, import_link.updateLink)((0, import_object_utils.normalizeOptionalProperties)({
390
+ app: this.app,
391
+ link,
392
+ newSourcePathOrFile: newBacklinkPath,
393
+ newTargetPathOrFile: newAttachmentPath,
394
+ oldTargetPathOrFile: oldAttachmentPath,
395
+ shouldUpdateFileNameAlias: settings.shouldUpdateFileNameAliases
396
+ }));
397
+ }, {
398
+ shouldFailOnMissingFile: false
399
+ });
400
+ this.abortSignal.throwIfAborted();
401
+ }
402
+ if ((0, import_file_system.isNote)(this.app, this.newPath)) {
403
+ await (0, import_link.updateLinksInFile)((0, import_object_utils.normalizeOptionalProperties)({
404
+ app: this.app,
405
+ newSourcePathOrFile: this.newPath,
406
+ oldSourcePathOrFile: this.oldPath,
407
+ shouldFailOnMissingFile: false,
408
+ shouldUpdateFileNameAlias: settings.shouldUpdateFileNameAliases
409
+ }));
410
+ this.abortSignal.throwIfAborted();
411
+ }
412
+ if (!(0, import_file_system.getFileOrNull)(this.app, this.newPath)) {
413
+ let interruptedRenames = this.interruptedRenamesMap.get(this.newPath);
414
+ if (!interruptedRenames) {
415
+ interruptedRenames = [];
416
+ this.interruptedRenamesMap.set(this.newPath, interruptedRenames);
417
+ }
418
+ interruptedRenames.push({
419
+ combinedBacklinksMap,
420
+ oldPath: this.oldPath
421
+ });
422
+ }
423
+ } finally {
424
+ const orphanKeys = Array.from(this.handledRenames.keys());
425
+ (0, import_queue.addToQueue)({
426
+ abortSignal: this.abortSignal,
427
+ app: this.app,
428
+ operationFn: () => {
429
+ for (const orphanKey of orphanKeys) {
430
+ this.handledRenames.delete(orphanKey.oldPath, orphanKey.newPath);
431
+ }
432
+ if (renamedLinks.size === 0) {
433
+ return;
434
+ }
435
+ new import_obsidian.Notice((0, import_i18next.t)(($) => $.obsidianDevUtils.renameDeleteHandler.updatedLinks, { filesCount: renamedFilePaths.size, linksCount: renamedLinks.size }));
436
+ renamedFilePaths.clear();
437
+ renamedLinks.clear();
438
+ },
439
+ operationName: (0, import_i18next.t)(($) => $.obsidianDevUtils.renameDeleteHandler.handleOrphanedRenames)
440
+ });
441
+ }
442
+ }
443
+ async continueInterruptedRenames() {
444
+ const interruptedRenames = this.interruptedRenamesMap.get(this.oldPath);
445
+ if (interruptedRenames) {
446
+ this.interruptedRenamesMap.delete(this.oldPath);
447
+ for (const interruptedRename of interruptedRenames) {
448
+ await new RenameHandler({
449
+ abortSignal: this.abortSignal,
450
+ app: this.app,
451
+ handledRenames: this.handledRenames,
452
+ interruptedCombinedBacklinksMap: interruptedRename.combinedBacklinksMap,
453
+ interruptedRenamesMap: this.interruptedRenamesMap,
454
+ newPath: this.newPath,
455
+ oldCache: this.oldCache,
456
+ oldPath: interruptedRename.oldPath,
457
+ oldPathBacklinksMap: this.oldPathBacklinksMap,
458
+ settingsManager: this.settingsManager
459
+ }).handle();
460
+ }
461
+ }
462
+ }
463
+ async handleCaseCollision() {
464
+ if (!(0, import_implementations.getDataAdapterEx)(this.app).insensitive || this.oldPath.toLowerCase() !== this.newPath.toLowerCase()) {
465
+ return false;
466
+ }
467
+ const tempPath = (0, import_path.join)((0, import_path.dirname)(this.newPath), `__temp__${(0, import_path.basename)(this.newPath)}`);
468
+ await this.renameHandled(this.newPath, tempPath);
469
+ await new RenameHandler({
470
+ abortSignal: this.abortSignal,
471
+ app: this.app,
472
+ handledRenames: this.handledRenames,
473
+ interruptedRenamesMap: this.interruptedRenamesMap,
474
+ newPath: tempPath,
475
+ oldCache: this.oldCache,
476
+ oldPath: this.oldPath,
477
+ oldPathBacklinksMap: this.oldPathBacklinksMap,
478
+ settingsManager: this.settingsManager
479
+ }).handle();
480
+ await this.app.fileManager.renameFile((0, import_file_system.getFile)(this.app, tempPath), this.newPath);
481
+ return true;
482
+ }
483
+ async refreshLinks() {
484
+ const cache = this.app.metadataCache.getCache(this.oldPath) ?? this.app.metadataCache.getCache(this.newPath);
485
+ const oldPathLinksRefreshed = cache ? (0, import_metadata_cache.getAllLinks)(cache) : [];
486
+ const fakeOldFile = (0, import_file_system.getFile)(this.app, this.oldPath, true);
487
+ let oldPathBacklinksMapRefreshed = /* @__PURE__ */ new Map();
488
+ await (0, import_metadata_cache.tempRegisterFilesAndRun)(this.app, [fakeOldFile], async () => {
489
+ oldPathBacklinksMapRefreshed = (await (0, import_metadata_cache.getBacklinksForFileSafe)(this.app, fakeOldFile)).data;
490
+ });
491
+ for (const link of oldPathLinksRefreshed) {
492
+ if (this.oldPathLinks.includes(link)) {
493
+ continue;
494
+ }
495
+ this.oldPathLinks.push(link);
496
+ }
497
+ for (const [backlinkPath, refreshedLinks] of oldPathBacklinksMapRefreshed.entries()) {
498
+ let oldLinks = this.oldPathBacklinksMap.get(backlinkPath);
499
+ if (!oldLinks) {
500
+ oldLinks = [];
501
+ this.oldPathBacklinksMap.set(backlinkPath, oldLinks);
502
+ }
503
+ for (const link of refreshedLinks) {
504
+ if (oldLinks.includes(link)) {
505
+ continue;
506
+ }
507
+ oldLinks.push(link);
508
+ }
509
+ }
510
+ }
511
+ async renameHandled(oldPath, newPath) {
512
+ newPath = (0, import_vault.getSafeRenamePath)(this.app, oldPath, newPath);
513
+ if (oldPath === newPath) {
514
+ return newPath;
515
+ }
516
+ this.handledRenames.add(oldPath, newPath);
517
+ newPath = await (0, import_vault.renameSafe)(this.app, oldPath, newPath);
518
+ return newPath;
519
+ }
520
+ }
521
+ class RenameMap {
522
+ abortSignal;
523
+ app;
524
+ map = /* @__PURE__ */ new Map();
525
+ newPath;
526
+ oldCache;
527
+ oldPath;
528
+ oldPathLinks;
529
+ settingsManager;
530
+ constructor(params) {
531
+ this.abortSignal = params.abortSignal;
532
+ this.app = params.app;
533
+ this.settingsManager = params.settingsManager;
534
+ this.oldCache = params.oldCache;
535
+ this.oldPath = params.oldPath;
536
+ this.newPath = params.newPath;
537
+ this.oldPathLinks = this.oldCache ? (0, import_metadata_cache.getAllLinks)(this.oldCache) : [];
538
+ }
539
+ entries() {
540
+ return this.map.entries();
541
+ }
542
+ async fill() {
543
+ this.abortSignal.throwIfAborted();
544
+ this.map.set(this.oldPath, this.newPath);
545
+ if (!(0, import_file_system.isNote)(this.app, this.oldPath)) {
546
+ return;
547
+ }
548
+ const settings = this.settingsManager.getSettings();
549
+ const oldFile = (0, import_file_system.getFile)(this.app, this.oldPath, true);
550
+ let oldAttachmentFolderPath = "";
551
+ await (0, import_metadata_cache.tempRegisterFilesAndRunAsync)(this.app, [oldFile], async () => {
552
+ const shouldFakeOldPathCache = this.oldCache && oldFile.deleted;
553
+ if (shouldFakeOldPathCache) {
554
+ (0, import_metadata_cache.registerFileCacheForNonExistingFile)(this.app, oldFile, this.oldCache);
555
+ }
556
+ try {
557
+ oldAttachmentFolderPath = await (0, import_attachment_path.getAttachmentFolderPath)(this.app, this.oldPath, import_attachment_path.AttachmentPathContext.RenameNote);
558
+ } finally {
559
+ if (shouldFakeOldPathCache) {
560
+ (0, import_metadata_cache.unregisterFileCacheForNonExistingFile)(this.app, oldFile);
561
+ }
562
+ }
563
+ });
564
+ const newAttachmentFolderPath = settings.shouldRenameAttachmentFolder ? await (0, import_attachment_path.getAttachmentFolderPath)(this.app, this.newPath, import_attachment_path.AttachmentPathContext.RenameNote) : oldAttachmentFolderPath;
565
+ const isOldAttachmentFolderAtRoot = oldAttachmentFolderPath === "/";
566
+ const oldAttachmentFolder = (0, import_file_system.getFolderOrNull)(this.app, oldAttachmentFolderPath);
567
+ if (!oldAttachmentFolder) {
568
+ return;
569
+ }
570
+ if (oldAttachmentFolderPath === newAttachmentFolderPath && !settings.shouldRenameAttachmentFiles) {
571
+ return;
572
+ }
573
+ const oldAttachmentFiles = [];
574
+ if (await (0, import_attachment_path.hasOwnAttachmentFolder)(this.app, this.oldPath, import_attachment_path.AttachmentPathContext.RenameNote)) {
575
+ import_obsidian.Vault.recurseChildren(oldAttachmentFolder, (oldAttachmentFile) => {
576
+ this.abortSignal.throwIfAborted();
577
+ if ((0, import_file_system.isFile)(oldAttachmentFile)) {
578
+ oldAttachmentFiles.push(oldAttachmentFile);
579
+ }
580
+ });
581
+ } else {
582
+ for (const oldPathLink of this.oldPathLinks) {
583
+ this.abortSignal.throwIfAborted();
584
+ const oldAttachmentFile = (0, import_link.extractLinkFile)(this.app, oldPathLink, this.oldPath);
585
+ if (!oldAttachmentFile) {
586
+ continue;
587
+ }
588
+ if (isOldAttachmentFolderAtRoot || oldAttachmentFile.path.startsWith(oldAttachmentFolderPath)) {
589
+ const oldAttachmentBacklinks = await (0, import_metadata_cache.getBacklinksForFileSafe)(this.app, oldAttachmentFile);
590
+ this.abortSignal.throwIfAborted();
591
+ const keys = new Set(oldAttachmentBacklinks.keys());
592
+ keys.delete(this.oldPath);
593
+ keys.delete(this.newPath);
594
+ if (keys.size === 0) {
595
+ oldAttachmentFiles.push(oldAttachmentFile);
596
+ }
597
+ }
598
+ }
599
+ }
600
+ for (const oldAttachmentFile of oldAttachmentFiles) {
601
+ this.abortSignal.throwIfAborted();
602
+ if (this.settingsManager.isNoteEx(oldAttachmentFile.path)) {
603
+ continue;
604
+ }
605
+ let newAttachmentFilePath;
606
+ if (settings.shouldRenameAttachmentFiles) {
607
+ newAttachmentFilePath = await (0, import_attachment_path.getAttachmentFilePath)({
608
+ app: this.app,
609
+ context: import_attachment_path.AttachmentPathContext.RenameNote,
610
+ notePathOrFile: this.newPath,
611
+ oldAttachmentPathOrFile: oldAttachmentFile,
612
+ oldNotePathOrFile: this.oldPath,
613
+ shouldSkipDuplicateCheck: true
614
+ });
615
+ this.abortSignal.throwIfAborted();
616
+ } else {
617
+ const relativePath = isOldAttachmentFolderAtRoot ? oldAttachmentFile.path : (0, import_path.relative)(oldAttachmentFolderPath, oldAttachmentFile.path);
618
+ const newFolder = (0, import_path.join)(newAttachmentFolderPath, (0, import_path.dirname)(relativePath));
619
+ newAttachmentFilePath = (0, import_path.join)(newFolder, oldAttachmentFile.name);
620
+ }
621
+ if (oldAttachmentFile.path === newAttachmentFilePath) {
622
+ continue;
623
+ }
624
+ if (settings.shouldDeleteConflictingAttachments) {
625
+ const newAttachmentFile = (0, import_file_system.getFileOrNull)(this.app, newAttachmentFilePath);
626
+ if (newAttachmentFile) {
627
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:fillRenameMap")(`Removing conflicting attachment ${newAttachmentFile.path}.`);
628
+ await (0, import_vault.trashSafe)(this.app, newAttachmentFile);
629
+ this.abortSignal.throwIfAborted();
630
+ }
631
+ } else {
632
+ const dir = (0, import_path.dirname)(newAttachmentFilePath);
633
+ const ext = (0, import_path.extname)(newAttachmentFilePath);
634
+ const baseName = (0, import_path.basename)(newAttachmentFilePath, ext);
635
+ newAttachmentFilePath = this.app.vault.getAvailablePath((0, import_path.join)(dir, baseName), ext.slice(1));
636
+ }
637
+ this.map.set(oldAttachmentFile.path, newAttachmentFilePath);
638
+ }
639
+ }
640
+ get(oldPath) {
641
+ return this.map.get(oldPath);
642
+ }
643
+ initBacklinksMap(singleBacklinksMap, combinedBacklinksMap, path) {
644
+ for (const [backlinkPath, links] of singleBacklinksMap.entries()) {
645
+ const newBacklinkPath = this.map.get(backlinkPath) ?? backlinkPath;
646
+ const linkJsonToPathMap = combinedBacklinksMap.get(newBacklinkPath) ?? /* @__PURE__ */ new Map();
647
+ combinedBacklinksMap.set(newBacklinkPath, linkJsonToPathMap);
648
+ for (const link of links) {
649
+ linkJsonToPathMap.set((0, import_object_utils.toJson)(link), path);
650
+ }
651
+ }
652
+ }
653
+ initOriginalLinksMap(combinedBacklinksMap) {
654
+ for (const oldPathLink of this.oldPathLinks) {
655
+ const oldAttachmentFile = (0, import_link.extractLinkFile)(this.app, oldPathLink, this.oldPath);
656
+ if (!oldAttachmentFile) {
657
+ continue;
658
+ }
659
+ const backlinksMap = /* @__PURE__ */ new Map();
660
+ backlinksMap.set(this.newPath, [oldPathLink]);
661
+ this.initBacklinksMap(backlinksMap, combinedBacklinksMap, oldAttachmentFile.path);
662
+ }
663
+ }
664
+ keys() {
665
+ return this.map.keys();
666
+ }
667
+ set(oldPath, newPath) {
668
+ this.map.set(oldPath, newPath);
669
+ }
670
+ }
671
+ class RenameDeleteHandlerComponent extends import_component_ex.ComponentEx {
672
+ abortSignalComponent;
673
+ app;
674
+ deletedMetadataCacheMap = /* @__PURE__ */ new Map();
675
+ handledRenames = new HandledRenames();
676
+ interruptedRenamesMap = /* @__PURE__ */ new Map();
677
+ pluginId;
678
+ settingsBuilder;
679
+ settingsManager;
680
+ /**
681
+ * Creates an instance of RenameDeleteHandlerComponent.
682
+ *
683
+ * @param params - The parameters for the RenameDeleteHandlerComponent.
684
+ */
685
+ constructor(params) {
686
+ super();
687
+ this.abortSignalComponent = params.abortSignalComponent;
688
+ this.app = params.app;
689
+ this.pluginId = params.pluginId;
690
+ this.settingsBuilder = params.settingsBuilder;
691
+ this.settingsManager = new SettingsManager(this.app);
692
+ }
693
+ /**
694
+ * Loads the component
695
+ */
696
+ onload() {
697
+ const renameDeleteHandlersMap = this.settingsManager.renameDeleteHandlersMap;
698
+ renameDeleteHandlersMap.set(this.pluginId, this.settingsBuilder);
699
+ this.logRegisteredHandlers();
700
+ this.register(() => {
701
+ renameDeleteHandlersMap.delete(this.pluginId);
702
+ this.logRegisteredHandlers();
703
+ });
704
+ this.registerEvent(this.app.vault.on("delete", this.handleDelete.bind(this)));
705
+ this.registerEvent(this.app.vault.on("rename", this.handleRename.bind(this)));
706
+ this.registerEvent(this.app.metadataCache.on("deleted", this.handleMetadataDeleted.bind(this)));
707
+ const patch = this.addChild(new import_monkey_around_component.MonkeyAroundComponent());
708
+ patch.registerMethodPatch({
709
+ methodName: "runAsyncLinkUpdate",
710
+ obj: this.app.fileManager,
711
+ patchHandler: ({
712
+ fallback,
713
+ originalArgs: [linkUpdatesHandler],
714
+ originalMethod,
715
+ originalMethodBound
716
+ }) => {
717
+ if ((0, import_monkey_around_component.hasPatchToken)(originalMethod, PATCH_TOKEN)) {
718
+ return fallback();
719
+ }
720
+ const newHandler = (linkUpdates) => this.wrapLinkUpdatesHandler(linkUpdates, linkUpdatesHandler);
721
+ return originalMethodBound(newHandler);
722
+ }
723
+ });
724
+ }
725
+ handleDelete(file) {
726
+ if (!this.shouldInvokeHandler()) {
727
+ return;
728
+ }
729
+ (0, import_queue.addToQueue)({
730
+ app: this.app,
731
+ operationFn: (abortSignal) => new DeleteHandler(this.app, file, abortSignal, this.settingsManager, this.deletedMetadataCacheMap).handle(),
732
+ operationName: (0, import_i18next.t)(($) => $.obsidianDevUtils.renameDeleteHandler.handleDelete, { filePath: file.path })
733
+ });
734
+ }
735
+ handleMetadataDeleted(file, prevCache) {
736
+ if (!this.shouldInvokeHandler()) {
737
+ return;
738
+ }
739
+ new MetadataDeletedHandler(this.app, file, prevCache, this.settingsManager, this.deletedMetadataCacheMap).handle();
740
+ }
741
+ handleRename(file, oldPath) {
742
+ if (!this.shouldInvokeHandler()) {
743
+ return;
744
+ }
745
+ if (!(0, import_file_system.isFile)(file)) {
746
+ return;
747
+ }
748
+ const newPath = file.path;
749
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Handle Rename ${oldPath} -> ${newPath}`);
750
+ if (this.handledRenames.has(oldPath, newPath)) {
751
+ this.handledRenames.delete(oldPath, newPath);
752
+ return;
753
+ }
754
+ const settings = this.settingsManager.getSettings();
755
+ if (!settings.shouldHandleRenames) {
756
+ return;
757
+ }
758
+ if (settings.isPathIgnored?.(oldPath)) {
759
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Skipping rename handler of old path ${oldPath} as the path is ignored.`);
760
+ return;
761
+ }
762
+ if (settings.isPathIgnored?.(newPath)) {
763
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Skipping rename handler of new path ${newPath} as the path is ignored.`);
764
+ return;
765
+ }
766
+ const oldCache = this.app.metadataCache.getCache(oldPath) ?? this.app.metadataCache.getCache(newPath);
767
+ const oldPathBacklinksMap = (0, import_metadata_cache.getBacklinksForFileOrPath)(this.app, oldPath).data;
768
+ (0, import_queue.addToQueue)({
769
+ abortSignal: this.abortSignalComponent.abortSignal,
770
+ app: this.app,
771
+ operationFn: (abortSignal) => new RenameHandler({
772
+ abortSignal,
773
+ app: this.app,
774
+ handledRenames: this.handledRenames,
775
+ interruptedRenamesMap: this.interruptedRenamesMap,
776
+ newPath,
777
+ oldCache,
778
+ oldPath,
779
+ oldPathBacklinksMap,
780
+ settingsManager: this.settingsManager
781
+ }).handle(),
782
+ operationName: (0, import_i18next.t)(($) => $.obsidianDevUtils.renameDeleteHandler.handleRename, { newPath, oldPath })
783
+ });
784
+ }
785
+ logRegisteredHandlers() {
786
+ const renameDeleteHandlersMap = this.settingsManager.renameDeleteHandlersMap;
787
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:logRegisteredHandlers")(
788
+ `Plugins with registered rename/delete handlers: ${JSON.stringify(Array.from(renameDeleteHandlersMap.keys()))}`
789
+ );
790
+ }
791
+ shouldInvokeHandler() {
792
+ const renameDeleteHandlersMap = this.settingsManager.renameDeleteHandlersMap;
793
+ const mainPluginId = Array.from(renameDeleteHandlersMap.keys())[0];
794
+ return mainPluginId === this.pluginId;
795
+ }
796
+ async wrapLinkUpdatesHandler(linkUpdates, linkUpdatesHandler) {
797
+ let isRenameCalled = false;
798
+ const eventRef = this.app.vault.on("rename", () => {
799
+ isRenameCalled = true;
800
+ });
801
+ try {
802
+ await linkUpdatesHandler(linkUpdates);
803
+ } finally {
804
+ this.app.vault.offref(eventRef);
805
+ }
806
+ const settings = this.settingsManager.getSettings();
807
+ if (!isRenameCalled || !settings.shouldHandleRenames) {
808
+ return;
809
+ }
810
+ (0, import_array.filterInPlace)(
811
+ linkUpdates,
812
+ (linkUpdate) => {
813
+ if (settings.isPathIgnored?.(linkUpdate.sourceFile.path)) {
814
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:runAsyncLinkUpdate")(
815
+ `Roll back to default link update of source file ${linkUpdate.sourceFile.path} as the path is ignored.`
816
+ );
817
+ return true;
818
+ }
819
+ if (settings.isPathIgnored?.(linkUpdate.resolvedFile.path)) {
820
+ (0, import_debug.getLibDebugger)("RenameDeleteHandler:runAsyncLinkUpdate")(
821
+ `Roll back to default link update of resolved file ${linkUpdate.resolvedFile.path} as the path is ignored.`
822
+ );
823
+ return true;
824
+ }
825
+ if (!this.app.internalPlugins.getEnabledPluginById(import_implementations.InternalPluginName.Canvas)) {
826
+ return false;
827
+ }
828
+ if (this.app.plugins.getPlugin("backlink-cache")) {
829
+ return false;
830
+ }
831
+ if (linkUpdate.sourceFile.extension === import_file_system.CANVAS_FILE_EXTENSION) {
832
+ return true;
833
+ }
834
+ if (linkUpdate.resolvedFile.extension === import_file_system.CANVAS_FILE_EXTENSION) {
835
+ return true;
836
+ }
837
+ return false;
838
+ }
839
+ );
840
+ }
841
+ }
842
+ async function cleanupParentFolders(app, settings, parentFolderPaths) {
843
+ if (settings.emptyFolderBehavior === "Keep" /* Keep */) {
844
+ return;
845
+ }
846
+ for (const parentFolderPath of parentFolderPaths) {
847
+ switch (settings.emptyFolderBehavior) {
848
+ case "Delete" /* Delete */:
849
+ await (0, import_vault.deleteEmptyFolder)(app, parentFolderPath);
850
+ break;
851
+ case "DeleteWithEmptyParents" /* DeleteWithEmptyParents */:
852
+ await (0, import_vault.deleteEmptyFolderHierarchy)(app, parentFolderPath);
853
+ break;
854
+ default:
855
+ break;
856
+ }
857
+ }
858
+ }
859
+ // Annotate the CommonJS export names for ESM import in node:
860
+ 0 && (module.exports = {
861
+ EmptyFolderBehavior,
862
+ RenameDeleteHandlerComponent
863
+ });
864
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL2NvbXBvbmVudHMvcmVuYW1lLWRlbGV0ZS1oYW5kbGVyLWNvbXBvbmVudC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIENvbnRhaW5zIHV0aWxpdHkgZnVuY3Rpb25zIGZvciBoYW5kbGluZyByZW5hbWUgYW5kIGRlbGV0ZSBldmVudHMgaW4gT2JzaWRpYW4uXG4gKi9cblxuaW1wb3J0IHR5cGUge1xuICBMaW5rVXBkYXRlLFxuICBMaW5rVXBkYXRlc0hhbmRsZXJcbn0gZnJvbSAnQG9ic2lkaWFuLXR5cGluZ3Mvb2JzaWRpYW4tcHVibGljLWxhdGVzdCc7XG5pbXBvcnQgdHlwZSB7XG4gIEFwcCxcbiAgQ2FjaGVkTWV0YWRhdGEsXG4gIFJlZmVyZW5jZSxcbiAgVEFic3RyYWN0RmlsZSxcbiAgVEZpbGVcbn0gZnJvbSAnb2JzaWRpYW4nO1xuXG4vKiB2OCBpZ25vcmUgc3RhcnQgLS0gRGVlcGx5IGNvdXBsZWQgdG8gT2JzaWRpYW4gcnVudGltZTsgcmVxdWlyZXMgcnVubmluZyB2YXVsdCBmb3IgbWVhbmluZ2Z1bCB0ZXN0aW5nLiAqL1xuaW1wb3J0IHtcbiAgZ2V0RGF0YUFkYXB0ZXJFeCxcbiAgSW50ZXJuYWxQbHVnaW5OYW1lXG59IGZyb20gJ0BvYnNpZGlhbi10eXBpbmdzL29ic2lkaWFuLXB1YmxpYy1sYXRlc3QvaW1wbGVtZW50YXRpb25zJztcbmltcG9ydCB7IHQgfSBmcm9tICdpMThuZXh0JztcbmltcG9ydCB7XG4gIE5vdGljZSxcbiAgVmF1bHRcbn0gZnJvbSAnb2JzaWRpYW4nO1xuXG5pbXBvcnQgdHlwZSB7XG4gIFVwZGF0ZUxpbmtQYXJhbXMsXG4gIFVwZGF0ZUxpbmtzSW5GaWxlUGFyYW1zXG59IGZyb20gJy4uL2xpbmsudHMnO1xuaW1wb3J0IHR5cGUgeyBBYm9ydFNpZ25hbENvbXBvbmVudCB9IGZyb20gJy4vYWJvcnQtc2lnbmFsLWNvbXBvbmVudC50cyc7XG5cbmltcG9ydCB7IGZpbHRlckluUGxhY2UgfSBmcm9tICcuLi8uLi9hcnJheS50cyc7XG5pbXBvcnQgeyBnZXRMaWJEZWJ1Z2dlciB9IGZyb20gJy4uLy4uL2RlYnVnLnRzJztcbmltcG9ydCB7XG4gIG5vcm1hbGl6ZU9wdGlvbmFsUHJvcGVydGllcyxcbiAgdG9Kc29uXG59IGZyb20gJy4uLy4uL29iamVjdC11dGlscy50cyc7XG5pbXBvcnQge1xuICBiYXNlbmFtZSxcbiAgZGlybmFtZSxcbiAgZXh0bmFtZSxcbiAgam9pbixcbiAgcmVsYXRpdmVcbn0gZnJvbSAnLi4vLi4vcGF0aC50cyc7XG5pbXBvcnQgeyBnZXRPYnNpZGlhbkRldlV0aWxzU3RhdGUgfSBmcm9tICcuLi9hcHAudHMnO1xuaW1wb3J0IHtcbiAgQXR0YWNobWVudFBhdGhDb250ZXh0LFxuICBnZXRBdHRhY2htZW50RmlsZVBhdGgsXG4gIGdldEF0dGFjaG1lbnRGb2xkZXJQYXRoLFxuICBoYXNPd25BdHRhY2htZW50Rm9sZGVyXG59IGZyb20gJy4uL2F0dGFjaG1lbnQtcGF0aC50cyc7XG5pbXBvcnQge1xuICBDQU5WQVNfRklMRV9FWFRFTlNJT04sXG4gIGdldEZpbGUsXG4gIGdldEZpbGVPck51bGwsXG4gIGdldEZvbGRlck9yTnVsbCxcbiAgaXNGaWxlLFxuICBpc01hcmtkb3duRmlsZSxcbiAgaXNOb3RlXG59IGZyb20gJy4uL2ZpbGUtc3lzdGVtLnRzJztcbmltcG9ydCB7XG4gIGVkaXRMaW5rcyxcbiAgZXh0cmFjdExpbmtGaWxlLFxuICB1cGRhdGVMaW5rLFxuICB1cGRhdGVMaW5rc0luRmlsZVxufSBmcm9tICcuLi9saW5rLnRzJztcbmltcG9ydCB7XG4gIGdldEFsbExpbmtzLFxuICBnZXRCYWNrbGlua3NGb3JGaWxlT3JQYXRoLFxuICBnZXRCYWNrbGlua3NGb3JGaWxlU2FmZSxcbiAgcmVnaXN0ZXJGaWxlQ2FjaGVGb3JOb25FeGlzdGluZ0ZpbGUsXG4gIHRlbXBSZWdpc3RlckZpbGVzQW5kUnVuLFxuICB0ZW1wUmVnaXN0ZXJGaWxlc0FuZFJ1bkFzeW5jLFxuICB1bnJlZ2lzdGVyRmlsZUNhY2hlRm9yTm9uRXhpc3RpbmdGaWxlXG59IGZyb20gJy4uL21ldGFkYXRhLWNhY2hlLnRzJztcbmltcG9ydCB7IGFkZFRvUXVldWUgfSBmcm9tICcuLi9xdWV1ZS50cyc7XG5pbXBvcnQgeyBkZWxldGVJZk5vdFVzZWQgfSBmcm9tICcuLi92YXVsdC1kZWxldGUudHMnO1xuaW1wb3J0IHtcbiAgZGVsZXRlRW1wdHlGb2xkZXIsXG4gIGRlbGV0ZUVtcHR5Rm9sZGVySGllcmFyY2h5LFxuICBnZXRTYWZlUmVuYW1lUGF0aCxcbiAgcmVuYW1lU2FmZSxcbiAgdHJhc2hTYWZlXG59IGZyb20gJy4uL3ZhdWx0LnRzJztcbmltcG9ydCB7IENvbXBvbmVudEV4IH0gZnJvbSAnLi9jb21wb25lbnQtZXgudHMnO1xuaW1wb3J0IHtcbiAgaGFzUGF0Y2hUb2tlbixcbiAgTW9ua2V5QXJvdW5kQ29tcG9uZW50XG59IGZyb20gJy4vbW9ua2V5LWFyb3VuZC1jb21wb25lbnQudHMnO1xuXG4vKipcbiAqIEEgYmVoYXZpb3Igb2YgdGhlIHJlbmFtZS9kZWxldGUgaGFuZGxlciB3aGVuIGRlbGV0aW5nIGVtcHR5IGZvbGRlcnMuXG4gKi9cbmV4cG9ydCBlbnVtIEVtcHR5Rm9sZGVyQmVoYXZpb3Ige1xuICAvKipcbiAgICogRGVsZXRlIHRoZSBlbXB0eSBmb2xkZXIuXG4gICAqL1xuICBEZWxldGUgPSAnRGVsZXRlJyxcblxuICAvKipcbiAgICogRGVsZXRlIHRoZSBlbXB0eSBmb2xkZXIgYW5kIGFsbCBpdHMgZW1wdHkgcGFyZW50cy5cbiAgICovXG4gIERlbGV0ZVdpdGhFbXB0eVBhcmVudHMgPSAnRGVsZXRlV2l0aEVtcHR5UGFyZW50cycsXG5cbiAgLyoqXG4gICAqIEtlZXAgdGhlIGVtcHR5IGZvbGRlci5cbiAgICovXG4gIEtlZXAgPSAnS2VlcCdcbn1cblxuLyoqXG4gKiBTZXR0aW5ncyBmb3IgdGhlIHJlbmFtZS9kZWxldGUgaGFuZGxlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3Mge1xuICAvKipcbiAgICogQSBiZWhhdmlvciBvZiB0aGUgcmVuYW1lL2RlbGV0ZSBoYW5kbGVyIHdoZW4gZGVsZXRpbmcgZW1wdHkgZm9sZGVycy5cbiAgICovXG4gIGVtcHR5Rm9sZGVyQmVoYXZpb3I6IEVtcHR5Rm9sZGVyQmVoYXZpb3I7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHBhdGggaXMgYSBub3RlLlxuICAgKi9cbiAgaXNOb3RlKHBhdGg6IHN0cmluZyk6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gaWdub3JlIHRoZSBwYXRoLlxuICAgKi9cbiAgaXNQYXRoSWdub3JlZChwYXRoOiBzdHJpbmcpOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGRlbGV0ZSBjb25mbGljdGluZyBhdHRhY2htZW50cy5cbiAgICovXG4gIHNob3VsZERlbGV0ZUNvbmZsaWN0aW5nQXR0YWNobWVudHM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gaGFuZGxlIGRlbGV0aW9ucy5cbiAgICovXG4gIHNob3VsZEhhbmRsZURlbGV0aW9uczogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBoYW5kbGUgcmVuYW1lcy5cbiAgICovXG4gIHNob3VsZEhhbmRsZVJlbmFtZXM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gcmVuYW1lIGF0dGFjaG1lbnQgZmlsZXMgd2hlbiBhIG5vdGUgaXMgcmVuYW1lZC5cbiAgICovXG4gIHNob3VsZFJlbmFtZUF0dGFjaG1lbnRGaWxlczogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byByZW5hbWUgYXR0YWNobWVudCBmb2xkZXIgd2hlbiBhIG5vdGUgaXMgcmVuYW1lZC5cbiAgICovXG4gIHNob3VsZFJlbmFtZUF0dGFjaG1lbnRGb2xkZXI6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gdXBkYXRlIGZpbGUgbmFtZSBhbGlhc2VzIHdoZW4gYSBub3RlIGlzIHJlbmFtZWQuXG4gICAqL1xuICBzaG91bGRVcGRhdGVGaWxlTmFtZUFsaWFzZXM6IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBIYW5kbGVkUmVuYW1lS2V5IHtcbiAgbmV3UGF0aDogc3RyaW5nO1xuICBvbGRQYXRoOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBJbnRlcnJ1cHRlZFJlbmFtZSB7XG4gIGNvbWJpbmVkQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PjtcbiAgb2xkUGF0aDogc3RyaW5nO1xufVxuXG5pbnRlcmZhY2UgUmVuYW1lSGFuZGxlckNvbnN0cnVjdG9yUGFyYW1zIHtcbiAgcmVhZG9ubHkgYWJvcnRTaWduYWw6IEFib3J0U2lnbmFsO1xuICByZWFkb25seSBhcHA6IEFwcDtcbiAgcmVhZG9ubHkgaGFuZGxlZFJlbmFtZXM6IEhhbmRsZWRSZW5hbWVzO1xuICByZWFkb25seSBpbnRlcnJ1cHRlZENvbWJpbmVkQmFja2xpbmtzTWFwPzogTWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nPj47XG4gIHJlYWRvbmx5IGludGVycnVwdGVkUmVuYW1lc01hcDogTWFwPHN0cmluZywgSW50ZXJydXB0ZWRSZW5hbWVbXT47XG4gIHJlYWRvbmx5IG5ld1BhdGg6IHN0cmluZztcbiAgcmVhZG9ubHkgb2xkQ2FjaGU6IENhY2hlZE1ldGFkYXRhIHwgbnVsbDtcbiAgcmVhZG9ubHkgb2xkUGF0aDogc3RyaW5nO1xuICByZWFkb25seSBvbGRQYXRoQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBSZWZlcmVuY2VbXT47XG4gIHJlYWRvbmx5IHNldHRpbmdzTWFuYWdlcjogU2V0dGluZ3NNYW5hZ2VyO1xufVxuXG5pbnRlcmZhY2UgUmVuYW1lTWFwQ29uc3RydWN0b3JQYXJhbXMge1xuICByZWFkb25seSBhYm9ydFNpZ25hbDogQWJvcnRTaWduYWw7XG4gIHJlYWRvbmx5IGFwcDogQXBwO1xuICByZWFkb25seSBuZXdQYXRoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG9sZENhY2hlOiBDYWNoZWRNZXRhZGF0YSB8IG51bGw7XG4gIHJlYWRvbmx5IG9sZFBhdGg6IHN0cmluZztcbiAgcmVhZG9ubHkgc2V0dGluZ3NNYW5hZ2VyOiBTZXR0aW5nc01hbmFnZXI7XG59XG5cbmNvbnN0IFBBVENIX1RPS0VOID0gU3ltYm9sLmZvcigncmVuYW1lRGVsZXRlSGFuZGxlcicpO1xuXG5pbnRlcmZhY2UgUmVuYW1lRGVsZXRlSGFuZGxlckNvbXBvbmVudENvbnN0cnVjdG9yUGFyYW1zIHtcbiAgcmVhZG9ubHkgYWJvcnRTaWduYWxDb21wb25lbnQ6IEFib3J0U2lnbmFsQ29tcG9uZW50O1xuICByZWFkb25seSBhcHA6IEFwcDtcbiAgcmVhZG9ubHkgcGx1Z2luSWQ6IHN0cmluZztcbiAgc2V0dGluZ3NCdWlsZGVyKHRoaXM6IHZvaWQpOiBQYXJ0aWFsPFJlbmFtZURlbGV0ZUhhbmRsZXJTZXR0aW5ncz47XG59XG5cbmNsYXNzIERlbGV0ZUhhbmRsZXIge1xuICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBhcHA6IEFwcCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGZpbGU6IFRBYnN0cmFjdEZpbGUsXG4gICAgcHJpdmF0ZSByZWFkb25seSBhYm9ydFNpZ25hbDogQWJvcnRTaWduYWwsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZXR0aW5nc01hbmFnZXI6IFNldHRpbmdzTWFuYWdlcixcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlbGV0ZWRNZXRhZGF0YUNhY2hlTWFwOiBNYXA8c3RyaW5nLCBDYWNoZWRNZXRhZGF0YT5cbiAgKSB7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgaGFuZGxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpoYW5kbGVEZWxldGUnKShgSGFuZGxlIERlbGV0ZSAke3RoaXMuZmlsZS5wYXRofWApO1xuICAgIGlmICghaXNOb3RlKHRoaXMuYXBwLCB0aGlzLmZpbGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpO1xuXG4gICAgaWYgKHNldHRpbmdzLmlzUGF0aElnbm9yZWQ/Lih0aGlzLmZpbGUucGF0aCkpIHtcbiAgICAgIGdldExpYkRlYnVnZ2VyKCdSZW5hbWVEZWxldGVIYW5kbGVyOmhhbmRsZURlbGV0ZScpKGBTa2lwcGluZyBkZWxldGUgaGFuZGxlciBvZiAke3RoaXMuZmlsZS5wYXRofSBhcyB0aGUgcGF0aCBpcyBpZ25vcmVkLmApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBhcmVudEZvbGRlclBhdGhzID0gbmV3IFNldDxzdHJpbmc+KFtkaXJuYW1lKHRoaXMuZmlsZS5wYXRoKV0pO1xuXG4gICAgaWYgKHNldHRpbmdzLnNob3VsZEhhbmRsZURlbGV0aW9ucykge1xuICAgICAgY29uc3QgY2FjaGUgPSB0aGlzLmRlbGV0ZWRNZXRhZGF0YUNhY2hlTWFwLmdldCh0aGlzLmZpbGUucGF0aCk7XG4gICAgICB0aGlzLmRlbGV0ZWRNZXRhZGF0YUNhY2hlTWFwLmRlbGV0ZSh0aGlzLmZpbGUucGF0aCk7XG4gICAgICBpZiAoY2FjaGUpIHtcbiAgICAgICAgY29uc3QgbGlua3MgPSBnZXRBbGxMaW5rcyhjYWNoZSk7XG5cbiAgICAgICAgZm9yIChjb25zdCBsaW5rIG9mIGxpbmtzKSB7XG4gICAgICAgICAgY29uc3QgYXR0YWNobWVudEZpbGUgPSBleHRyYWN0TGlua0ZpbGUodGhpcy5hcHAsIGxpbmssIHRoaXMuZmlsZS5wYXRoKTtcbiAgICAgICAgICBpZiAoIWF0dGFjaG1lbnRGaWxlKSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGhpcy5zZXR0aW5nc01hbmFnZXIuaXNOb3RlRXgoYXR0YWNobWVudEZpbGUucGF0aCkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHBhcmVudEZvbGRlclBhdGhzLmFkZChhdHRhY2htZW50RmlsZS5wYXJlbnQ/LnBhdGggPz8gJycpO1xuICAgICAgICAgIGF3YWl0IGRlbGV0ZUlmTm90VXNlZCh0aGlzLmFwcCwgYXR0YWNobWVudEZpbGUsIHRoaXMuZmlsZS5wYXRoLCBmYWxzZSwgc2V0dGluZ3MuZW1wdHlGb2xkZXJCZWhhdmlvciAhPT0gRW1wdHlGb2xkZXJCZWhhdmlvci5LZWVwKTtcbiAgICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBwYXJlbnRGb2xkZXJQYXRocy5kZWxldGUoJycpO1xuICAgIGF3YWl0IGNsZWFudXBQYXJlbnRGb2xkZXJzKHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpLCBBcnJheS5mcm9tKHBhcmVudEZvbGRlclBhdGhzKSk7XG4gICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuXG4gICAgaWYgKCFzZXR0aW5ncy5zaG91bGRIYW5kbGVEZWxldGlvbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBhdHRhY2htZW50Rm9sZGVyUGF0aCA9IGF3YWl0IGdldEF0dGFjaG1lbnRGb2xkZXJQYXRoKHRoaXMuYXBwLCB0aGlzLmZpbGUucGF0aCwgQXR0YWNobWVudFBhdGhDb250ZXh0LkRlbGV0ZU5vdGUpO1xuICAgIGNvbnN0IGF0dGFjaG1lbnRGb2xkZXIgPSBnZXRGb2xkZXJPck51bGwodGhpcy5hcHAsIGF0dGFjaG1lbnRGb2xkZXJQYXRoKTtcblxuICAgIGlmICghYXR0YWNobWVudEZvbGRlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghYXdhaXQgaGFzT3duQXR0YWNobWVudEZvbGRlcih0aGlzLmFwcCwgdGhpcy5maWxlLnBhdGgsIEF0dGFjaG1lbnRQYXRoQ29udGV4dC5EZWxldGVOb3RlKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcblxuICAgIGF3YWl0IGRlbGV0ZUlmTm90VXNlZCh0aGlzLmFwcCwgYXR0YWNobWVudEZvbGRlciwgdGhpcy5maWxlLnBhdGgsIGZhbHNlLCBzZXR0aW5ncy5lbXB0eUZvbGRlckJlaGF2aW9yICE9PSBFbXB0eUZvbGRlckJlaGF2aW9yLktlZXApO1xuICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgfVxufVxuXG5jbGFzcyBIYW5kbGVkUmVuYW1lcyB7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWFwID0gbmV3IE1hcDxzdHJpbmcsIEhhbmRsZWRSZW5hbWVLZXk+KCk7XG5cbiAgcHVibGljIGFkZChvbGRQYXRoOiBzdHJpbmcsIG5ld1BhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMubWFwLnNldCh0aGlzLmtleVRvU3RyaW5nKG9sZFBhdGgsIG5ld1BhdGgpLCB7IG5ld1BhdGgsIG9sZFBhdGggfSk7XG4gIH1cblxuICBwdWJsaWMgZGVsZXRlKG9sZFBhdGg6IHN0cmluZywgbmV3UGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5tYXAuZGVsZXRlKHRoaXMua2V5VG9TdHJpbmcob2xkUGF0aCwgbmV3UGF0aCkpO1xuICB9XG5cbiAgcHVibGljIGhhcyhvbGRQYXRoOiBzdHJpbmcsIG5ld1BhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1hcC5oYXModGhpcy5rZXlUb1N0cmluZyhvbGRQYXRoLCBuZXdQYXRoKSk7XG4gIH1cblxuICBwdWJsaWMga2V5cygpOiBJdGVyYWJsZUl0ZXJhdG9yPEhhbmRsZWRSZW5hbWVLZXk+IHtcbiAgICByZXR1cm4gdGhpcy5tYXAudmFsdWVzKCk7XG4gIH1cblxuICBwcml2YXRlIGtleVRvU3RyaW5nKG9sZFBhdGg6IHN0cmluZywgbmV3UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7b2xkUGF0aH0gLT4gJHtuZXdQYXRofWA7XG4gIH1cbn1cblxuY2xhc3MgTWV0YWRhdGFEZWxldGVkSGFuZGxlciB7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IGFwcDogQXBwLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZmlsZTogVEFic3RyYWN0RmlsZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHByZXZDYWNoZTogQ2FjaGVkTWV0YWRhdGEgfCBudWxsLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2V0dGluZ3NNYW5hZ2VyOiBTZXR0aW5nc01hbmFnZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBkZWxldGVkTWV0YWRhdGFDYWNoZU1hcDogTWFwPHN0cmluZywgQ2FjaGVkTWV0YWRhdGE+XG4gICkge1xuICB9XG5cbiAgcHVibGljIGhhbmRsZSgpOiB2b2lkIHtcbiAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuc2V0dGluZ3NNYW5hZ2VyLmdldFNldHRpbmdzKCk7XG5cbiAgICBpZiAoIXNldHRpbmdzLnNob3VsZEhhbmRsZURlbGV0aW9ucykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChzZXR0aW5ncy5pc1BhdGhJZ25vcmVkPy4odGhpcy5maWxlLnBhdGgpKSB7XG4gICAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpoYW5kbGVNZXRhZGF0YURlbGV0ZWQnKShgU2tpcHBpbmcgbWV0YWRhdGEgZGVsZXRlIGhhbmRsZXIgb2YgJHt0aGlzLmZpbGUucGF0aH0gYXMgdGhlIHBhdGggaXMgaWdub3JlZC5gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoaXNNYXJrZG93bkZpbGUodGhpcy5hcHAsIHRoaXMuZmlsZSkgJiYgdGhpcy5wcmV2Q2FjaGUpIHtcbiAgICAgIHRoaXMuZGVsZXRlZE1ldGFkYXRhQ2FjaGVNYXAuc2V0KHRoaXMuZmlsZS5wYXRoLCB0aGlzLnByZXZDYWNoZSk7XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIFNldHRpbmdzTWFuYWdlciB7XG4gIHB1YmxpYyByZWFkb25seSByZW5hbWVEZWxldGVIYW5kbGVyc01hcDogTWFwPHN0cmluZywgKCkgPT4gUGFydGlhbDxSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3M+PjtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBhcHA6IEFwcCkge1xuICAgIHRoaXMucmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAgPVxuICAgICAgZ2V0T2JzaWRpYW5EZXZVdGlsc1N0YXRlKGFwcCwgJ3JlbmFtZURlbGV0ZUhhbmRsZXJzTWFwJywgbmV3IE1hcDxzdHJpbmcsICgpID0+IFBhcnRpYWw8UmVuYW1lRGVsZXRlSGFuZGxlclNldHRpbmdzPj4oKSkudmFsdWU7XG4gIH1cblxuICBwdWJsaWMgZ2V0U2V0dGluZ3MoKTogUGFydGlhbDxSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3M+IHtcbiAgICBjb25zdCBzZXR0aW5nc0J1aWxkZXJzID0gQXJyYXkuZnJvbSh0aGlzLnJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwLnZhbHVlcygpKS5yZXZlcnNlKCk7XG5cbiAgICBjb25zdCBzZXR0aW5nczogUGFydGlhbDxSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3M+ID0ge307XG4gICAgc2V0dGluZ3MuaXNOb3RlID0gKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4gPT4gaXNOb3RlKHRoaXMuYXBwLCBwYXRoKTtcbiAgICBzZXR0aW5ncy5pc1BhdGhJZ25vcmVkID0gKCk6IGJvb2xlYW4gPT4gZmFsc2U7XG5cbiAgICBmb3IgKGNvbnN0IHNldHRpbmdzQnVpbGRlciBvZiBzZXR0aW5nc0J1aWxkZXJzKSB7XG4gICAgICBjb25zdCBuZXdTZXR0aW5ncyA9IHNldHRpbmdzQnVpbGRlcigpO1xuICAgICAgc2V0dGluZ3Muc2hvdWxkRGVsZXRlQ29uZmxpY3RpbmdBdHRhY2htZW50cyB8fD0gbmV3U2V0dGluZ3Muc2hvdWxkRGVsZXRlQ29uZmxpY3RpbmdBdHRhY2htZW50cyA/PyBmYWxzZTtcbiAgICAgIGlmIChuZXdTZXR0aW5ncy5lbXB0eUZvbGRlckJlaGF2aW9yKSB7XG4gICAgICAgIHNldHRpbmdzLmVtcHR5Rm9sZGVyQmVoYXZpb3IgPz89IG5ld1NldHRpbmdzLmVtcHR5Rm9sZGVyQmVoYXZpb3I7XG4gICAgICB9XG4gICAgICBzZXR0aW5ncy5zaG91bGRIYW5kbGVEZWxldGlvbnMgfHw9IG5ld1NldHRpbmdzLnNob3VsZEhhbmRsZURlbGV0aW9ucyA/PyBmYWxzZTtcbiAgICAgIHNldHRpbmdzLnNob3VsZEhhbmRsZVJlbmFtZXMgfHw9IG5ld1NldHRpbmdzLnNob3VsZEhhbmRsZVJlbmFtZXMgPz8gZmFsc2U7XG4gICAgICBzZXR0aW5ncy5zaG91bGRSZW5hbWVBdHRhY2htZW50RmlsZXMgfHw9IG5ld1NldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGaWxlcyA/PyBmYWxzZTtcbiAgICAgIHNldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGb2xkZXIgfHw9IG5ld1NldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGb2xkZXIgPz8gZmFsc2U7XG4gICAgICBzZXR0aW5ncy5zaG91bGRVcGRhdGVGaWxlTmFtZUFsaWFzZXMgfHw9IG5ld1NldHRpbmdzLnNob3VsZFVwZGF0ZUZpbGVOYW1lQWxpYXNlcyA/PyBmYWxzZTtcbiAgICAgIGNvbnN0IGlzUGF0aElnbm9yZWQgPSBzZXR0aW5ncy5pc1BhdGhJZ25vcmVkO1xuICAgICAgc2V0dGluZ3MuaXNQYXRoSWdub3JlZCA9IChwYXRoOiBzdHJpbmcpOiBib29sZWFuID0+IGlzUGF0aElnbm9yZWQocGF0aCkgfHwgKG5ld1NldHRpbmdzLmlzUGF0aElnbm9yZWQ/LihwYXRoKSA/PyBmYWxzZSk7XG4gICAgICBjb25zdCBjdXJyZW50SXNOb3RlID0gc2V0dGluZ3MuaXNOb3RlO1xuICAgICAgc2V0dGluZ3MuaXNOb3RlID0gKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4gPT4gY3VycmVudElzTm90ZShwYXRoKSAmJiAobmV3U2V0dGluZ3MuaXNOb3RlPy4ocGF0aCkgPz8gdHJ1ZSk7XG4gICAgfVxuXG4gICAgc2V0dGluZ3MuZW1wdHlGb2xkZXJCZWhhdmlvciA/Pz0gRW1wdHlGb2xkZXJCZWhhdmlvci5LZWVwO1xuICAgIHJldHVybiBzZXR0aW5ncztcbiAgfVxuXG4gIHB1YmxpYyBpc05vdGVFeChwYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuZ2V0U2V0dGluZ3MoKTtcbiAgICByZXR1cm4gc2V0dGluZ3MuaXNOb3RlPy4ocGF0aCkgPz8gZmFsc2U7XG4gIH1cbn1cblxuY2xhc3MgUmVuYW1lSGFuZGxlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYWJvcnRTaWduYWw6IEFib3J0U2lnbmFsO1xuICBwcml2YXRlIHJlYWRvbmx5IGFwcDogQXBwO1xuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZWRSZW5hbWVzOiBIYW5kbGVkUmVuYW1lcztcbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlcnJ1cHRlZENvbWJpbmVkQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PjtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlcnJ1cHRlZFJlbmFtZXNNYXA6IE1hcDxzdHJpbmcsIEludGVycnVwdGVkUmVuYW1lW10+O1xuICBwcml2YXRlIHJlYWRvbmx5IG5ld1BhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRDYWNoZTogQ2FjaGVkTWV0YWRhdGEgfCBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQYXRoQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBSZWZlcmVuY2VbXT47XG4gIHByaXZhdGUgcmVhZG9ubHkgb2xkUGF0aExpbmtzOiBSZWZlcmVuY2VbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBzZXR0aW5nc01hbmFnZXI6IFNldHRpbmdzTWFuYWdlcjtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocGFyYW1zOiBSZW5hbWVIYW5kbGVyQ29uc3RydWN0b3JQYXJhbXMpIHtcbiAgICB0aGlzLmFwcCA9IHBhcmFtcy5hcHA7XG4gICAgdGhpcy5vbGRQYXRoID0gcGFyYW1zLm9sZFBhdGg7XG4gICAgdGhpcy5uZXdQYXRoID0gcGFyYW1zLm5ld1BhdGg7XG4gICAgdGhpcy5vbGRQYXRoQmFja2xpbmtzTWFwID0gcGFyYW1zLm9sZFBhdGhCYWNrbGlua3NNYXA7XG4gICAgdGhpcy5vbGRDYWNoZSA9IHBhcmFtcy5vbGRDYWNoZTtcbiAgICB0aGlzLmFib3J0U2lnbmFsID0gcGFyYW1zLmFib3J0U2lnbmFsO1xuICAgIHRoaXMuc2V0dGluZ3NNYW5hZ2VyID0gcGFyYW1zLnNldHRpbmdzTWFuYWdlcjtcbiAgICB0aGlzLmludGVycnVwdGVkUmVuYW1lc01hcCA9IHBhcmFtcy5pbnRlcnJ1cHRlZFJlbmFtZXNNYXA7XG4gICAgdGhpcy5vbGRQYXRoTGlua3MgPSB0aGlzLm9sZENhY2hlID8gZ2V0QWxsTGlua3ModGhpcy5vbGRDYWNoZSkgOiBbXTtcbiAgICB0aGlzLmhhbmRsZWRSZW5hbWVzID0gcGFyYW1zLmhhbmRsZWRSZW5hbWVzO1xuICAgIHRoaXMuaW50ZXJydXB0ZWRDb21iaW5lZEJhY2tsaW5rc01hcCA9IHBhcmFtcy5pbnRlcnJ1cHRlZENvbWJpbmVkQmFja2xpbmtzTWFwID8/IG5ldyBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PigpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGhhbmRsZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5vbGRQYXRoID09PSB0aGlzLm5ld1BhdGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgIGF3YWl0IHRoaXMuY29udGludWVJbnRlcnJ1cHRlZFJlbmFtZXMoKTtcbiAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgYXdhaXQgdGhpcy5yZWZyZXNoTGlua3MoKTtcbiAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgaWYgKGF3YWl0IHRoaXMuaGFuZGxlQ2FzZUNvbGxpc2lvbigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuXG4gICAgY29uc3QgcmVuYW1lZEZpbGVQYXRocyA9IGdldE9ic2lkaWFuRGV2VXRpbHNTdGF0ZSh0aGlzLmFwcCwgJ3JlbmFtZWRGaWxlUGF0aHMnLCBuZXcgU2V0PHN0cmluZz4oKSkudmFsdWU7XG4gICAgY29uc3QgcmVuYW1lZExpbmtzID0gZ2V0T2JzaWRpYW5EZXZVdGlsc1N0YXRlKHRoaXMuYXBwLCAncmVuYW1lZExpbmtQYXRocycsIG5ldyBTZXQ8c3RyaW5nPigpKS52YWx1ZTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZW5hbWVNYXAgPSBuZXcgUmVuYW1lTWFwKHtcbiAgICAgICAgYWJvcnRTaWduYWw6IHRoaXMuYWJvcnRTaWduYWwsXG4gICAgICAgIGFwcDogdGhpcy5hcHAsXG4gICAgICAgIG5ld1BhdGg6IHRoaXMubmV3UGF0aCxcbiAgICAgICAgb2xkQ2FjaGU6IHRoaXMub2xkQ2FjaGUsXG4gICAgICAgIG9sZFBhdGg6IHRoaXMub2xkUGF0aCxcbiAgICAgICAgc2V0dGluZ3NNYW5hZ2VyOiB0aGlzLnNldHRpbmdzTWFuYWdlclxuICAgICAgfSk7XG4gICAgICBhd2FpdCByZW5hbWVNYXAuZmlsbCgpO1xuICAgICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuXG4gICAgICBjb25zdCBjb21iaW5lZEJhY2tsaW5rc01hcCA9IG5ldyBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PigpO1xuICAgICAgcmVuYW1lTWFwLmluaXRPcmlnaW5hbExpbmtzTWFwKGNvbWJpbmVkQmFja2xpbmtzTWFwKTtcbiAgICAgIHJlbmFtZU1hcC5pbml0QmFja2xpbmtzTWFwKHRoaXMub2xkUGF0aEJhY2tsaW5rc01hcCwgY29tYmluZWRCYWNrbGlua3NNYXAsIHRoaXMub2xkUGF0aCk7XG5cbiAgICAgIGZvciAoY29uc3QgYXR0YWNobWVudE9sZFBhdGggb2YgcmVuYW1lTWFwLmtleXMoKSkge1xuICAgICAgICBpZiAoYXR0YWNobWVudE9sZFBhdGggPT09IHRoaXMub2xkUGF0aCkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGF0dGFjaG1lbnRPbGRQYXRoQmFja2xpbmtzTWFwID0gKGF3YWl0IGdldEJhY2tsaW5rc0ZvckZpbGVTYWZlKHRoaXMuYXBwLCBhdHRhY2htZW50T2xkUGF0aCkpLmRhdGE7XG4gICAgICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICAgICAgcmVuYW1lTWFwLmluaXRCYWNrbGlua3NNYXAoYXR0YWNobWVudE9sZFBhdGhCYWNrbGlua3NNYXAsIGNvbWJpbmVkQmFja2xpbmtzTWFwLCBhdHRhY2htZW50T2xkUGF0aCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHBhcmVudEZvbGRlclBhdGhzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgICAgIGZvciAoY29uc3QgW29sZEF0dGFjaG1lbnRQYXRoLCBuZXdBdHRhY2htZW50UGF0aF0gb2YgcmVuYW1lTWFwLmVudHJpZXMoKSkge1xuICAgICAgICBpZiAob2xkQXR0YWNobWVudFBhdGggIT09IHRoaXMub2xkUGF0aCkge1xuICAgICAgICAgIGNvbnN0IGZpeGVkTmV3QXR0YWNobWVudFBhdGggPSBhd2FpdCB0aGlzLnJlbmFtZUhhbmRsZWQob2xkQXR0YWNobWVudFBhdGgsIG5ld0F0dGFjaG1lbnRQYXRoKTtcbiAgICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICAgICAgcmVuYW1lTWFwLnNldChvbGRBdHRhY2htZW50UGF0aCwgZml4ZWROZXdBdHRhY2htZW50UGF0aCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnNldHRpbmdzTWFuYWdlci5pc05vdGVFeChvbGRBdHRhY2htZW50UGF0aCkpIHtcbiAgICAgICAgICBwYXJlbnRGb2xkZXJQYXRocy5hZGQoZGlybmFtZShvbGRBdHRhY2htZW50UGF0aCkpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGNsZWFudXBQYXJlbnRGb2xkZXJzKHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpLCBBcnJheS5mcm9tKHBhcmVudEZvbGRlclBhdGhzKSk7XG4gICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuc2V0dGluZ3NNYW5hZ2VyLmdldFNldHRpbmdzKCk7XG5cbiAgICAgIGZvciAoXG4gICAgICAgIGNvbnN0IFtuZXdCYWNrbGlua1BhdGgsIGxpbmtKc29uVG9QYXRoTWFwXSBvZiBBcnJheS5mcm9tKGNvbWJpbmVkQmFja2xpbmtzTWFwLmVudHJpZXMoKSkuY29uY2F0KFxuICAgICAgICAgIEFycmF5LmZyb20odGhpcy5pbnRlcnJ1cHRlZENvbWJpbmVkQmFja2xpbmtzTWFwLmVudHJpZXMoKSlcbiAgICAgICAgKVxuICAgICAgKSB7XG4gICAgICAgIGxldCBsaW5rSW5kZXggPSAwO1xuICAgICAgICBhd2FpdCBlZGl0TGlua3ModGhpcy5hcHAsIG5ld0JhY2tsaW5rUGF0aCwgKGxpbmspID0+IHtcbiAgICAgICAgICBsaW5rSW5kZXgrKztcbiAgICAgICAgICBjb25zdCBvbGRBdHRhY2htZW50UGF0aCA9IGxpbmtKc29uVG9QYXRoTWFwLmdldCh0b0pzb24obGluaykpO1xuICAgICAgICAgIGlmICghb2xkQXR0YWNobWVudFBhdGgpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBuZXdBdHRhY2htZW50UGF0aCA9IHJlbmFtZU1hcC5nZXQob2xkQXR0YWNobWVudFBhdGgpID8/IG9sZEF0dGFjaG1lbnRQYXRoO1xuXG4gICAgICAgICAgcmVuYW1lZEZpbGVQYXRocy5hZGQobmV3QmFja2xpbmtQYXRoKTtcbiAgICAgICAgICByZW5hbWVkTGlua3MuYWRkKGAke25ld0JhY2tsaW5rUGF0aH0vLyR7U3RyaW5nKGxpbmtJbmRleCl9YCk7XG5cbiAgICAgICAgICByZXR1cm4gdXBkYXRlTGluayhub3JtYWxpemVPcHRpb25hbFByb3BlcnRpZXM8VXBkYXRlTGlua1BhcmFtcz4oe1xuICAgICAgICAgICAgYXBwOiB0aGlzLmFwcCxcbiAgICAgICAgICAgIGxpbmssXG4gICAgICAgICAgICBuZXdTb3VyY2VQYXRoT3JGaWxlOiBuZXdCYWNrbGlua1BhdGgsXG4gICAgICAgICAgICBuZXdUYXJnZXRQYXRoT3JGaWxlOiBuZXdBdHRhY2htZW50UGF0aCxcbiAgICAgICAgICAgIG9sZFRhcmdldFBhdGhPckZpbGU6IG9sZEF0dGFjaG1lbnRQYXRoLFxuICAgICAgICAgICAgc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhczogc2V0dGluZ3Muc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhc2VzXG4gICAgICAgICAgfSkpO1xuICAgICAgICB9LCB7XG4gICAgICAgICAgc2hvdWxkRmFpbE9uTWlzc2luZ0ZpbGU6IGZhbHNlXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc05vdGUodGhpcy5hcHAsIHRoaXMubmV3UGF0aCkpIHtcbiAgICAgICAgYXdhaXQgdXBkYXRlTGlua3NJbkZpbGUobm9ybWFsaXplT3B0aW9uYWxQcm9wZXJ0aWVzPFVwZGF0ZUxpbmtzSW5GaWxlUGFyYW1zPih7XG4gICAgICAgICAgYXBwOiB0aGlzLmFwcCxcbiAgICAgICAgICBuZXdTb3VyY2VQYXRoT3JGaWxlOiB0aGlzLm5ld1BhdGgsXG4gICAgICAgICAgb2xkU291cmNlUGF0aE9yRmlsZTogdGhpcy5vbGRQYXRoLFxuICAgICAgICAgIHNob3VsZEZhaWxPbk1pc3NpbmdGaWxlOiBmYWxzZSxcbiAgICAgICAgICBzaG91bGRVcGRhdGVGaWxlTmFtZUFsaWFzOiBzZXR0aW5ncy5zaG91bGRVcGRhdGVGaWxlTmFtZUFsaWFzZXNcbiAgICAgICAgfSkpO1xuICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICB9XG5cbiAgICAgIGlmICghZ2V0RmlsZU9yTnVsbCh0aGlzLmFwcCwgdGhpcy5uZXdQYXRoKSkge1xuICAgICAgICBsZXQgaW50ZXJydXB0ZWRSZW5hbWVzID0gdGhpcy5pbnRlcnJ1cHRlZFJlbmFtZXNNYXAuZ2V0KHRoaXMubmV3UGF0aCk7XG4gICAgICAgIGlmICghaW50ZXJydXB0ZWRSZW5hbWVzKSB7XG4gICAgICAgICAgaW50ZXJydXB0ZWRSZW5hbWVzID0gW107XG4gICAgICAgICAgdGhpcy5pbnRlcnJ1cHRlZFJlbmFtZXNNYXAuc2V0KHRoaXMubmV3UGF0aCwgaW50ZXJydXB0ZWRSZW5hbWVzKTtcbiAgICAgICAgfVxuICAgICAgICBpbnRlcnJ1cHRlZFJlbmFtZXMucHVzaCh7XG4gICAgICAgICAgY29tYmluZWRCYWNrbGlua3NNYXAsXG4gICAgICAgICAgb2xkUGF0aDogdGhpcy5vbGRQYXRoXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBjb25zdCBvcnBoYW5LZXlzID0gQXJyYXkuZnJvbSh0aGlzLmhhbmRsZWRSZW5hbWVzLmtleXMoKSk7XG4gICAgICBhZGRUb1F1ZXVlKHtcbiAgICAgICAgYWJvcnRTaWduYWw6IHRoaXMuYWJvcnRTaWduYWwsXG4gICAgICAgIGFwcDogdGhpcy5hcHAsXG4gICAgICAgIG9wZXJhdGlvbkZuOiAoKSA9PiB7XG4gICAgICAgICAgZm9yIChjb25zdCBvcnBoYW5LZXkgb2Ygb3JwaGFuS2V5cykge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVkUmVuYW1lcy5kZWxldGUob3JwaGFuS2V5Lm9sZFBhdGgsIG9ycGhhbktleS5uZXdQYXRoKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocmVuYW1lZExpbmtzLnNpemUgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgbmV3IE5vdGljZSh0KCgkKSA9PiAkLm9ic2lkaWFuRGV2VXRpbHMucmVuYW1lRGVsZXRlSGFuZGxlci51cGRhdGVkTGlua3MsIHsgZmlsZXNDb3VudDogcmVuYW1lZEZpbGVQYXRocy5zaXplLCBsaW5rc0NvdW50OiByZW5hbWVkTGlua3Muc2l6ZSB9KSk7XG4gICAgICAgICAgcmVuYW1lZEZpbGVQYXRocy5jbGVhcigpO1xuICAgICAgICAgIHJlbmFtZWRMaW5rcy5jbGVhcigpO1xuICAgICAgICB9LFxuICAgICAgICBvcGVyYXRpb25OYW1lOiB0KCgkKSA9PiAkLm9ic2lkaWFuRGV2VXRpbHMucmVuYW1lRGVsZXRlSGFuZGxlci5oYW5kbGVPcnBoYW5lZFJlbmFtZXMpXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNvbnRpbnVlSW50ZXJydXB0ZWRSZW5hbWVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGludGVycnVwdGVkUmVuYW1lcyA9IHRoaXMuaW50ZXJydXB0ZWRSZW5hbWVzTWFwLmdldCh0aGlzLm9sZFBhdGgpO1xuICAgIGlmIChpbnRlcnJ1cHRlZFJlbmFtZXMpIHtcbiAgICAgIHRoaXMuaW50ZXJydXB0ZWRSZW5hbWVzTWFwLmRlbGV0ZSh0aGlzLm9sZFBhdGgpO1xuICAgICAgZm9yIChjb25zdCBpbnRlcnJ1cHRlZFJlbmFtZSBvZiBpbnRlcnJ1cHRlZFJlbmFtZXMpIHtcbiAgICAgICAgYXdhaXQgbmV3IFJlbmFtZUhhbmRsZXIoe1xuICAgICAgICAgIGFib3J0U2lnbmFsOiB0aGlzLmFib3J0U2lnbmFsLFxuICAgICAgICAgIGFwcDogdGhpcy5hcHAsXG4gICAgICAgICAgaGFuZGxlZFJlbmFtZXM6IHRoaXMuaGFuZGxlZFJlbmFtZXMsXG4gICAgICAgICAgaW50ZXJydXB0ZWRDb21iaW5lZEJhY2tsaW5rc01hcDogaW50ZXJydXB0ZWRSZW5hbWUuY29tYmluZWRCYWNrbGlua3NNYXAsXG4gICAgICAgICAgaW50ZXJydXB0ZWRSZW5hbWVzTWFwOiB0aGlzLmludGVycnVwdGVkUmVuYW1lc01hcCxcbiAgICAgICAgICBuZXdQYXRoOiB0aGlzLm5ld1BhdGgsXG4gICAgICAgICAgb2xkQ2FjaGU6IHRoaXMub2xkQ2FjaGUsXG4gICAgICAgICAgb2xkUGF0aDogaW50ZXJydXB0ZWRSZW5hbWUub2xkUGF0aCxcbiAgICAgICAgICBvbGRQYXRoQmFja2xpbmtzTWFwOiB0aGlzLm9sZFBhdGhCYWNrbGlua3NNYXAsXG4gICAgICAgICAgc2V0dGluZ3NNYW5hZ2VyOiB0aGlzLnNldHRpbmdzTWFuYWdlclxuICAgICAgICB9KS5oYW5kbGUoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGhhbmRsZUNhc2VDb2xsaXNpb24oKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgaWYgKCFnZXREYXRhQWRhcHRlckV4KHRoaXMuYXBwKS5pbnNlbnNpdGl2ZSB8fCB0aGlzLm9sZFBhdGgudG9Mb3dlckNhc2UoKSAhPT0gdGhpcy5uZXdQYXRoLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCB0ZW1wUGF0aCA9IGpvaW4oZGlybmFtZSh0aGlzLm5ld1BhdGgpLCBgX190ZW1wX18ke2Jhc2VuYW1lKHRoaXMubmV3UGF0aCl9YCk7XG4gICAgYXdhaXQgdGhpcy5yZW5hbWVIYW5kbGVkKHRoaXMubmV3UGF0aCwgdGVtcFBhdGgpO1xuXG4gICAgYXdhaXQgbmV3IFJlbmFtZUhhbmRsZXIoe1xuICAgICAgYWJvcnRTaWduYWw6IHRoaXMuYWJvcnRTaWduYWwsXG4gICAgICBhcHA6IHRoaXMuYXBwLFxuICAgICAgaGFuZGxlZFJlbmFtZXM6IHRoaXMuaGFuZGxlZFJlbmFtZXMsXG4gICAgICBpbnRlcnJ1cHRlZFJlbmFtZXNNYXA6IHRoaXMuaW50ZXJydXB0ZWRSZW5hbWVzTWFwLFxuICAgICAgbmV3UGF0aDogdGVtcFBhdGgsXG4gICAgICBvbGRDYWNoZTogdGhpcy5vbGRDYWNoZSxcbiAgICAgIG9sZFBhdGg6IHRoaXMub2xkUGF0aCxcbiAgICAgIG9sZFBhdGhCYWNrbGlua3NNYXA6IHRoaXMub2xkUGF0aEJhY2tsaW5rc01hcCxcbiAgICAgIHNldHRpbmdzTWFuYWdlcjogdGhpcy5zZXR0aW5nc01hbmFnZXJcbiAgICB9KS5oYW5kbGUoKTtcblxuICAgIGF3YWl0IHRoaXMuYXBwLmZpbGVNYW5hZ2VyLnJlbmFtZUZpbGUoZ2V0RmlsZSh0aGlzLmFwcCwgdGVtcFBhdGgpLCB0aGlzLm5ld1BhdGgpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWZyZXNoTGlua3MoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY2FjaGUgPSB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldENhY2hlKHRoaXMub2xkUGF0aCkgPz8gdGhpcy5hcHAubWV0YWRhdGFDYWNoZS5nZXRDYWNoZSh0aGlzLm5ld1BhdGgpO1xuICAgIGNvbnN0IG9sZFBhdGhMaW5rc1JlZnJlc2hlZCA9IGNhY2hlID8gZ2V0QWxsTGlua3MoY2FjaGUpIDogW107XG4gICAgY29uc3QgZmFrZU9sZEZpbGUgPSBnZXRGaWxlKHRoaXMuYXBwLCB0aGlzLm9sZFBhdGgsIHRydWUpO1xuICAgIGxldCBvbGRQYXRoQmFja2xpbmtzTWFwUmVmcmVzaGVkID0gbmV3IE1hcDxzdHJpbmcsIFJlZmVyZW5jZVtdPigpO1xuICAgIGF3YWl0IHRlbXBSZWdpc3RlckZpbGVzQW5kUnVuKHRoaXMuYXBwLCBbZmFrZU9sZEZpbGVdLCBhc3luYyAoKSA9PiB7XG4gICAgICBvbGRQYXRoQmFja2xpbmtzTWFwUmVmcmVzaGVkID0gKGF3YWl0IGdldEJhY2tsaW5rc0ZvckZpbGVTYWZlKHRoaXMuYXBwLCBmYWtlT2xkRmlsZSkpLmRhdGE7XG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IGxpbmsgb2Ygb2xkUGF0aExpbmtzUmVmcmVzaGVkKSB7XG4gICAgICBpZiAodGhpcy5vbGRQYXRoTGlua3MuaW5jbHVkZXMobGluaykpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICB0aGlzLm9sZFBhdGhMaW5rcy5wdXNoKGxpbmspO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgW2JhY2tsaW5rUGF0aCwgcmVmcmVzaGVkTGlua3NdIG9mIG9sZFBhdGhCYWNrbGlua3NNYXBSZWZyZXNoZWQuZW50cmllcygpKSB7XG4gICAgICBsZXQgb2xkTGlua3MgPSB0aGlzLm9sZFBhdGhCYWNrbGlua3NNYXAuZ2V0KGJhY2tsaW5rUGF0aCk7XG4gICAgICBpZiAoIW9sZExpbmtzKSB7XG4gICAgICAgIG9sZExpbmtzID0gW107XG4gICAgICAgIHRoaXMub2xkUGF0aEJhY2tsaW5rc01hcC5zZXQoYmFja2xpbmtQYXRoLCBvbGRMaW5rcyk7XG4gICAgICB9XG5cbiAgICAgIGZvciAoY29uc3QgbGluayBvZiByZWZyZXNoZWRMaW5rcykge1xuICAgICAgICBpZiAob2xkTGlua3MuaW5jbHVkZXMobGluaykpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBvbGRMaW5rcy5wdXNoKGxpbmspO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVuYW1lSGFuZGxlZChvbGRQYXRoOiBzdHJpbmcsIG5ld1BhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgbmV3UGF0aCA9IGdldFNhZmVSZW5hbWVQYXRoKHRoaXMuYXBwLCBvbGRQYXRoLCBuZXdQYXRoKTtcbiAgICBpZiAob2xkUGF0aCA9PT0gbmV3UGF0aCkge1xuICAgICAgcmV0dXJuIG5ld1BhdGg7XG4gICAgfVxuICAgIHRoaXMuaGFuZGxlZFJlbmFtZXMuYWRkKG9sZFBhdGgsIG5ld1BhdGgpO1xuICAgIG5ld1BhdGggPSBhd2FpdCByZW5hbWVTYWZlKHRoaXMuYXBwLCBvbGRQYXRoLCBuZXdQYXRoKTtcbiAgICByZXR1cm4gbmV3UGF0aDtcbiAgfVxufVxuXG5jbGFzcyBSZW5hbWVNYXAge1xuICBwcml2YXRlIHJlYWRvbmx5IGFib3J0U2lnbmFsOiBBYm9ydFNpZ25hbDtcbiAgcHJpdmF0ZSByZWFkb25seSBhcHA6IEFwcDtcbiAgcHJpdmF0ZSByZWFkb25seSBtYXAgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IG5ld1BhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRDYWNoZTogQ2FjaGVkTWV0YWRhdGEgfCBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQYXRoTGlua3M6IFJlZmVyZW5jZVtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHNldHRpbmdzTWFuYWdlcjogU2V0dGluZ3NNYW5hZ2VyO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJhbXM6IFJlbmFtZU1hcENvbnN0cnVjdG9yUGFyYW1zKSB7XG4gICAgdGhpcy5hYm9ydFNpZ25hbCA9IHBhcmFtcy5hYm9ydFNpZ25hbDtcbiAgICB0aGlzLmFwcCA9IHBhcmFtcy5hcHA7XG4gICAgdGhpcy5zZXR0aW5nc01hbmFnZXIgPSBwYXJhbXMuc2V0dGluZ3NNYW5hZ2VyO1xuICAgIHRoaXMub2xkQ2FjaGUgPSBwYXJhbXMub2xkQ2FjaGU7XG4gICAgdGhpcy5vbGRQYXRoID0gcGFyYW1zLm9sZFBhdGg7XG4gICAgdGhpcy5uZXdQYXRoID0gcGFyYW1zLm5ld1BhdGg7XG4gICAgdGhpcy5vbGRQYXRoTGlua3MgPSB0aGlzLm9sZENhY2hlID8gZ2V0QWxsTGlua3ModGhpcy5vbGRDYWNoZSkgOiBbXTtcbiAgfVxuXG4gIHB1YmxpYyBlbnRyaWVzKCk6IEl0ZXJhYmxlSXRlcmF0b3I8W3N0cmluZywgc3RyaW5nXT4ge1xuICAgIHJldHVybiB0aGlzLm1hcC5lbnRyaWVzKCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZmlsbCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgdGhpcy5tYXAuc2V0KHRoaXMub2xkUGF0aCwgdGhpcy5uZXdQYXRoKTtcblxuICAgIGlmICghaXNOb3RlKHRoaXMuYXBwLCB0aGlzLm9sZFBhdGgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpO1xuXG4gICAgY29uc3Qgb2xkRmlsZSA9IGdldEZpbGUodGhpcy5hcHAsIHRoaXMub2xkUGF0aCwgdHJ1ZSk7XG4gICAgbGV0IG9sZEF0dGFjaG1lbnRGb2xkZXJQYXRoID0gJyc7XG4gICAgYXdhaXQgdGVtcFJlZ2lzdGVyRmlsZXNBbmRSdW5Bc3luYyh0aGlzLmFwcCwgW29sZEZpbGVdLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzaG91bGRGYWtlT2xkUGF0aENhY2hlID0gdGhpcy5vbGRDYWNoZSAmJiBvbGRGaWxlLmRlbGV0ZWQ7XG4gICAgICBpZiAoc2hvdWxkRmFrZU9sZFBhdGhDYWNoZSkge1xuICAgICAgICByZWdpc3RlckZpbGVDYWNoZUZvck5vbkV4aXN0aW5nRmlsZSh0aGlzLmFwcCwgb2xkRmlsZSwgdGhpcy5vbGRDYWNoZSk7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIG9sZEF0dGFjaG1lbnRGb2xkZXJQYXRoID0gYXdhaXQgZ2V0QXR0YWNobWVudEZvbGRlclBhdGgodGhpcy5hcHAsIHRoaXMub2xkUGF0aCwgQXR0YWNobWVudFBhdGhDb250ZXh0LlJlbmFtZU5vdGUpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgaWYgKHNob3VsZEZha2VPbGRQYXRoQ2FjaGUpIHtcbiAgICAgICAgICB1bnJlZ2lzdGVyRmlsZUNhY2hlRm9yTm9uRXhpc3RpbmdGaWxlKHRoaXMuYXBwLCBvbGRGaWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgbmV3QXR0YWNobWVudEZvbGRlclBhdGggPSBzZXR0aW5ncy5zaG91bGRSZW5hbWVBdHRhY2htZW50Rm9sZGVyXG4gICAgICA/IGF3YWl0IGdldEF0dGFjaG1lbnRGb2xkZXJQYXRoKHRoaXMuYXBwLCB0aGlzLm5ld1BhdGgsIEF0dGFjaG1lbnRQYXRoQ29udGV4dC5SZW5hbWVOb3RlKVxuICAgICAgOiBvbGRBdHRhY2htZW50Rm9sZGVyUGF0aDtcblxuICAgIGNvbnN0IGlzT2xkQXR0YWNobWVudEZvbGRlckF0Um9vdCA9IG9sZEF0dGFjaG1lbnRGb2xkZXJQYXRoID09PSAnLyc7XG5cbiAgICBjb25zdCBvbGRBdHRhY2htZW50Rm9sZGVyID0gZ2V0Rm9sZGVyT3JOdWxsKHRoaXMuYXBwLCBvbGRBdHRhY2htZW50Rm9sZGVyUGF0aCk7XG5cbiAgICBpZiAoIW9sZEF0dGFjaG1lbnRGb2xkZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAob2xkQXR0YWNobWVudEZvbGRlclBhdGggPT09IG5ld0F0dGFjaG1lbnRGb2xkZXJQYXRoICYmICFzZXR0aW5ncy5zaG91bGRSZW5hbWVBdHRhY2htZW50RmlsZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBvbGRBdHRhY2htZW50RmlsZXM6IFRGaWxlW10gPSBbXTtcblxuICAgIGlmIChhd2FpdCBoYXNPd25BdHRhY2htZW50Rm9sZGVyKHRoaXMuYXBwLCB0aGlzLm9sZFBhdGgsIEF0dGFjaG1lbnRQYXRoQ29udGV4dC5SZW5hbWVOb3RlKSkge1xuICAgICAgVmF1bHQucmVjdXJzZUNoaWxkcmVuKG9sZEF0dGFjaG1lbnRGb2xkZXIsIChvbGRBdHRhY2htZW50RmlsZSkgPT4ge1xuICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICAgIGlmIChpc0ZpbGUob2xkQXR0YWNobWVudEZpbGUpKSB7XG4gICAgICAgICAgb2xkQXR0YWNobWVudEZpbGVzLnB1c2gob2xkQXR0YWNobWVudEZpbGUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChjb25zdCBvbGRQYXRoTGluayBvZiB0aGlzLm9sZFBhdGhMaW5rcykge1xuICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICAgIGNvbnN0IG9sZEF0dGFjaG1lbnRGaWxlID0gZXh0cmFjdExpbmtGaWxlKHRoaXMuYXBwLCBvbGRQYXRoTGluaywgdGhpcy5vbGRQYXRoKTtcbiAgICAgICAgaWYgKCFvbGRBdHRhY2htZW50RmlsZSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzT2xkQXR0YWNobWVudEZvbGRlckF0Um9vdCB8fCBvbGRBdHRhY2htZW50RmlsZS5wYXRoLnN0YXJ0c1dpdGgob2xkQXR0YWNobWVudEZvbGRlclBhdGgpKSB7XG4gICAgICAgICAgY29uc3Qgb2xkQXR0YWNobWVudEJhY2tsaW5rcyA9IGF3YWl0IGdldEJhY2tsaW5rc0ZvckZpbGVTYWZlKHRoaXMuYXBwLCBvbGRBdHRhY2htZW50RmlsZSk7XG4gICAgICAgICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgICAgIGNvbnN0IGtleXMgPSBuZXcgU2V0PHN0cmluZz4ob2xkQXR0YWNobWVudEJhY2tsaW5rcy5rZXlzKCkpO1xuICAgICAgICAgIGtleXMuZGVsZXRlKHRoaXMub2xkUGF0aCk7XG4gICAgICAgICAga2V5cy5kZWxldGUodGhpcy5uZXdQYXRoKTtcbiAgICAgICAgICBpZiAoa2V5cy5zaXplID09PSAwKSB7XG4gICAgICAgICAgICBvbGRBdHRhY2htZW50RmlsZXMucHVzaChvbGRBdHRhY2htZW50RmlsZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBvbGRBdHRhY2htZW50RmlsZSBvZiBvbGRBdHRhY2htZW50RmlsZXMpIHtcbiAgICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICAgIGlmICh0aGlzLnNldHRpbmdzTWFuYWdlci5pc05vdGVFeChvbGRBdHRhY2htZW50RmlsZS5wYXRoKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgbGV0IG5ld0F0dGFjaG1lbnRGaWxlUGF0aDogc3RyaW5nO1xuICAgICAgaWYgKHNldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGaWxlcykge1xuICAgICAgICBuZXdBdHRhY2htZW50RmlsZVBhdGggPSBhd2FpdCBnZXRBdHRhY2htZW50RmlsZVBhdGgoe1xuICAgICAgICAgIGFwcDogdGhpcy5hcHAsXG4gICAgICAgICAgY29udGV4dDogQXR0YWNobWVudFBhdGhDb250ZXh0LlJlbmFtZU5vdGUsXG4gICAgICAgICAgbm90ZVBhdGhPckZpbGU6IHRoaXMubmV3UGF0aCxcbiAgICAgICAgICBvbGRBdHRhY2htZW50UGF0aE9yRmlsZTogb2xkQXR0YWNobWVudEZpbGUsXG4gICAgICAgICAgb2xkTm90ZVBhdGhPckZpbGU6IHRoaXMub2xkUGF0aCxcbiAgICAgICAgICBzaG91bGRTa2lwRHVwbGljYXRlQ2hlY2s6IHRydWVcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IGlzT2xkQXR0YWNobWVudEZvbGRlckF0Um9vdCA/IG9sZEF0dGFjaG1lbnRGaWxlLnBhdGggOiByZWxhdGl2ZShvbGRBdHRhY2htZW50Rm9sZGVyUGF0aCwgb2xkQXR0YWNobWVudEZpbGUucGF0aCk7XG4gICAgICAgIGNvbnN0IG5ld0ZvbGRlciA9IGpvaW4obmV3QXR0YWNobWVudEZvbGRlclBhdGgsIGRpcm5hbWUocmVsYXRpdmVQYXRoKSk7XG4gICAgICAgIG5ld0F0dGFjaG1lbnRGaWxlUGF0aCA9IGpvaW4obmV3Rm9sZGVyLCBvbGRBdHRhY2htZW50RmlsZS5uYW1lKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9sZEF0dGFjaG1lbnRGaWxlLnBhdGggPT09IG5ld0F0dGFjaG1lbnRGaWxlUGF0aCkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGlmIChzZXR0aW5ncy5zaG91bGREZWxldGVDb25mbGljdGluZ0F0dGFjaG1lbnRzKSB7XG4gICAgICAgIGNvbnN0IG5ld0F0dGFjaG1lbnRGaWxlID0gZ2V0RmlsZU9yTnVsbCh0aGlzLmFwcCwgbmV3QXR0YWNobWVudEZpbGVQYXRoKTtcbiAgICAgICAgaWYgKG5ld0F0dGFjaG1lbnRGaWxlKSB7XG4gICAgICAgICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6ZmlsbFJlbmFtZU1hcCcpKGBSZW1vdmluZyBjb25mbGljdGluZyBhdHRhY2htZW50ICR7bmV3QXR0YWNobWVudEZpbGUucGF0aH0uYCk7XG4gICAgICAgICAgYXdhaXQgdHJhc2hTYWZlKHRoaXMuYXBwLCBuZXdBdHRhY2htZW50RmlsZSk7XG4gICAgICAgICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBkaXIgPSBkaXJuYW1lKG5ld0F0dGFjaG1lbnRGaWxlUGF0aCk7XG4gICAgICAgIGNvbnN0IGV4dCA9IGV4dG5hbWUobmV3QXR0YWNobWVudEZpbGVQYXRoKTtcbiAgICAgICAgY29uc3QgYmFzZU5hbWUgPSBiYXNlbmFtZShuZXdBdHRhY2htZW50RmlsZVBhdGgsIGV4dCk7XG4gICAgICAgIG5ld0F0dGFjaG1lbnRGaWxlUGF0aCA9IHRoaXMuYXBwLnZhdWx0LmdldEF2YWlsYWJsZVBhdGgoam9pbihkaXIsIGJhc2VOYW1lKSwgZXh0LnNsaWNlKDEpKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubWFwLnNldChvbGRBdHRhY2htZW50RmlsZS5wYXRoLCBuZXdBdHRhY2htZW50RmlsZVBhdGgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXQob2xkUGF0aDogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5tYXAuZ2V0KG9sZFBhdGgpO1xuICB9XG5cbiAgcHVibGljIGluaXRCYWNrbGlua3NNYXAoXG4gICAgc2luZ2xlQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBSZWZlcmVuY2VbXT4sXG4gICAgY29tYmluZWRCYWNrbGlua3NNYXA6IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIHN0cmluZz4+LFxuICAgIHBhdGg6IHN0cmluZ1xuICApOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IFtiYWNrbGlua1BhdGgsIGxpbmtzXSBvZiBzaW5nbGVCYWNrbGlua3NNYXAuZW50cmllcygpKSB7XG4gICAgICBjb25zdCBuZXdCYWNrbGlua1BhdGggPSB0aGlzLm1hcC5nZXQoYmFja2xpbmtQYXRoKSA/PyBiYWNrbGlua1BhdGg7XG4gICAgICBjb25zdCBsaW5rSnNvblRvUGF0aE1hcCA9IGNvbWJpbmVkQmFja2xpbmtzTWFwLmdldChuZXdCYWNrbGlua1BhdGgpID8/IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgICBjb21iaW5lZEJhY2tsaW5rc01hcC5zZXQobmV3QmFja2xpbmtQYXRoLCBsaW5rSnNvblRvUGF0aE1hcCk7XG4gICAgICBmb3IgKGNvbnN0IGxpbmsgb2YgbGlua3MpIHtcbiAgICAgICAgbGlua0pzb25Ub1BhdGhNYXAuc2V0KHRvSnNvbihsaW5rKSwgcGF0aCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGluaXRPcmlnaW5hbExpbmtzTWFwKGNvbWJpbmVkQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+Pik6IHZvaWQge1xuICAgIGZvciAoY29uc3Qgb2xkUGF0aExpbmsgb2YgdGhpcy5vbGRQYXRoTGlua3MpIHtcbiAgICAgIGNvbnN0IG9sZEF0dGFjaG1lbnRGaWxlID0gZXh0cmFjdExpbmtGaWxlKHRoaXMuYXBwLCBvbGRQYXRoTGluaywgdGhpcy5vbGRQYXRoKTtcbiAgICAgIGlmICghb2xkQXR0YWNobWVudEZpbGUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBiYWNrbGlua3NNYXAgPSBuZXcgTWFwPHN0cmluZywgUmVmZXJlbmNlW10+KCk7XG4gICAgICBiYWNrbGlua3NNYXAuc2V0KHRoaXMubmV3UGF0aCwgW29sZFBhdGhMaW5rXSk7XG4gICAgICB0aGlzLmluaXRCYWNrbGlua3NNYXAoYmFja2xpbmtzTWFwLCBjb21iaW5lZEJhY2tsaW5rc01hcCwgb2xkQXR0YWNobWVudEZpbGUucGF0aCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGtleXMoKTogSXRlcmFibGVJdGVyYXRvcjxzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5tYXAua2V5cygpO1xuICB9XG5cbiAgcHVibGljIHNldChvbGRQYXRoOiBzdHJpbmcsIG5ld1BhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMubWFwLnNldChvbGRQYXRoLCBuZXdQYXRoKTtcbiAgfVxufVxuXG4vKiogKi9cbmV4cG9ydCBjbGFzcyBSZW5hbWVEZWxldGVIYW5kbGVyQ29tcG9uZW50IGV4dGVuZHMgQ29tcG9uZW50RXgge1xuICBwcml2YXRlIHJlYWRvbmx5IGFib3J0U2lnbmFsQ29tcG9uZW50OiBBYm9ydFNpZ25hbENvbXBvbmVudDtcbiAgcHJpdmF0ZSByZWFkb25seSBhcHA6IEFwcDtcbiAgcHJpdmF0ZSByZWFkb25seSBkZWxldGVkTWV0YWRhdGFDYWNoZU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBDYWNoZWRNZXRhZGF0YT4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBoYW5kbGVkUmVuYW1lcyA9IG5ldyBIYW5kbGVkUmVuYW1lcygpO1xuICBwcml2YXRlIHJlYWRvbmx5IGludGVycnVwdGVkUmVuYW1lc01hcCA9IG5ldyBNYXA8c3RyaW5nLCBJbnRlcnJ1cHRlZFJlbmFtZVtdPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IHBsdWdpbklkOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2V0dGluZ3NCdWlsZGVyOiAoKSA9PiBQYXJ0aWFsPFJlbmFtZURlbGV0ZUhhbmRsZXJTZXR0aW5ncz47XG4gIHByaXZhdGUgcmVhZG9ubHkgc2V0dGluZ3NNYW5hZ2VyOiBTZXR0aW5nc01hbmFnZXI7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgUmVuYW1lRGVsZXRlSGFuZGxlckNvbXBvbmVudC5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgUmVuYW1lRGVsZXRlSGFuZGxlckNvbXBvbmVudC5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJhbXM6IFJlbmFtZURlbGV0ZUhhbmRsZXJDb21wb25lbnRDb25zdHJ1Y3RvclBhcmFtcykge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5hYm9ydFNpZ25hbENvbXBvbmVudCA9IHBhcmFtcy5hYm9ydFNpZ25hbENvbXBvbmVudDtcbiAgICB0aGlzLmFwcCA9IHBhcmFtcy5hcHA7XG4gICAgdGhpcy5wbHVnaW5JZCA9IHBhcmFtcy5wbHVnaW5JZDtcbiAgICB0aGlzLnNldHRpbmdzQnVpbGRlciA9IHBhcmFtcy5zZXR0aW5nc0J1aWxkZXI7XG4gICAgdGhpcy5zZXR0aW5nc01hbmFnZXIgPSBuZXcgU2V0dGluZ3NNYW5hZ2VyKHRoaXMuYXBwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2FkcyB0aGUgY29tcG9uZW50XG4gICAqL1xuICBwdWJsaWMgb3ZlcnJpZGUgb25sb2FkKCk6IHZvaWQge1xuICAgIGNvbnN0IHJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwID0gdGhpcy5zZXR0aW5nc01hbmFnZXIucmVuYW1lRGVsZXRlSGFuZGxlcnNNYXA7XG5cbiAgICByZW5hbWVEZWxldGVIYW5kbGVyc01hcC5zZXQodGhpcy5wbHVnaW5JZCwgdGhpcy5zZXR0aW5nc0J1aWxkZXIpO1xuICAgIHRoaXMubG9nUmVnaXN0ZXJlZEhhbmRsZXJzKCk7XG5cbiAgICB0aGlzLnJlZ2lzdGVyKCgpID0+IHtcbiAgICAgIHJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwLmRlbGV0ZSh0aGlzLnBsdWdpbklkKTtcbiAgICAgIHRoaXMubG9nUmVnaXN0ZXJlZEhhbmRsZXJzKCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnJlZ2lzdGVyRXZlbnQodGhpcy5hcHAudmF1bHQub24oJ2RlbGV0ZScsIHRoaXMuaGFuZGxlRGVsZXRlLmJpbmQodGhpcykpKTtcbiAgICB0aGlzLnJlZ2lzdGVyRXZlbnQodGhpcy5hcHAudmF1bHQub24oJ3JlbmFtZScsIHRoaXMuaGFuZGxlUmVuYW1lLmJpbmQodGhpcykpKTtcbiAgICB0aGlzLnJlZ2lzdGVyRXZlbnQodGhpcy5hcHAubWV0YWRhdGFDYWNoZS5vbignZGVsZXRlZCcsIHRoaXMuaGFuZGxlTWV0YWRhdGFEZWxldGVkLmJpbmQodGhpcykpKTtcblxuICAgIGNvbnN0IHBhdGNoID0gdGhpcy5hZGRDaGlsZChuZXcgTW9ua2V5QXJvdW5kQ29tcG9uZW50KCkpO1xuXG4gICAgcGF0Y2gucmVnaXN0ZXJNZXRob2RQYXRjaCh7XG4gICAgICBtZXRob2ROYW1lOiAncnVuQXN5bmNMaW5rVXBkYXRlJyxcbiAgICAgIG9iajogdGhpcy5hcHAuZmlsZU1hbmFnZXIsXG4gICAgICBwYXRjaEhhbmRsZXI6ICh7XG4gICAgICAgIGZhbGxiYWNrLFxuICAgICAgICBvcmlnaW5hbEFyZ3M6IFtsaW5rVXBkYXRlc0hhbmRsZXJdLFxuICAgICAgICBvcmlnaW5hbE1ldGhvZCxcbiAgICAgICAgb3JpZ2luYWxNZXRob2RCb3VuZFxuICAgICAgfSkgPT4ge1xuICAgICAgICBpZiAoaGFzUGF0Y2hUb2tlbihvcmlnaW5hbE1ldGhvZCwgUEFUQ0hfVE9LRU4pKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbGxiYWNrKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBuZXdIYW5kbGVyOiBMaW5rVXBkYXRlc0hhbmRsZXIgPSAobGlua1VwZGF0ZXMpID0+IHRoaXMud3JhcExpbmtVcGRhdGVzSGFuZGxlcihsaW5rVXBkYXRlcywgbGlua1VwZGF0ZXNIYW5kbGVyKTtcbiAgICAgICAgcmV0dXJuIG9yaWdpbmFsTWV0aG9kQm91bmQobmV3SGFuZGxlcik7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZURlbGV0ZShmaWxlOiBUQWJzdHJhY3RGaWxlKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3VsZEludm9rZUhhbmRsZXIoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhZGRUb1F1ZXVlKHtcbiAgICAgIGFwcDogdGhpcy5hcHAsXG4gICAgICBvcGVyYXRpb25GbjogKGFib3J0U2lnbmFsKSA9PiBuZXcgRGVsZXRlSGFuZGxlcih0aGlzLmFwcCwgZmlsZSwgYWJvcnRTaWduYWwsIHRoaXMuc2V0dGluZ3NNYW5hZ2VyLCB0aGlzLmRlbGV0ZWRNZXRhZGF0YUNhY2hlTWFwKS5oYW5kbGUoKSxcbiAgICAgIG9wZXJhdGlvbk5hbWU6IHQoKCQpID0+ICQub2JzaWRpYW5EZXZVdGlscy5yZW5hbWVEZWxldGVIYW5kbGVyLmhhbmRsZURlbGV0ZSwgeyBmaWxlUGF0aDogZmlsZS5wYXRoIH0pXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZU1ldGFkYXRhRGVsZXRlZChmaWxlOiBUQWJzdHJhY3RGaWxlLCBwcmV2Q2FjaGU6IENhY2hlZE1ldGFkYXRhIHwgbnVsbCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5zaG91bGRJbnZva2VIYW5kbGVyKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbmV3IE1ldGFkYXRhRGVsZXRlZEhhbmRsZXIodGhpcy5hcHAsIGZpbGUsIHByZXZDYWNoZSwgdGhpcy5zZXR0aW5nc01hbmFnZXIsIHRoaXMuZGVsZXRlZE1ldGFkYXRhQ2FjaGVNYXApLmhhbmRsZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBoYW5kbGVSZW5hbWUoZmlsZTogVEFic3RyYWN0RmlsZSwgb2xkUGF0aDogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3VsZEludm9rZUhhbmRsZXIoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghaXNGaWxlKGZpbGUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbmV3UGF0aCA9IGZpbGUucGF0aDtcblxuICAgIGdldExpYkRlYnVnZ2VyKCdSZW5hbWVEZWxldGVIYW5kbGVyOmhhbmRsZVJlbmFtZScpKGBIYW5kbGUgUmVuYW1lICR7b2xkUGF0aH0gLT4gJHtuZXdQYXRofWApO1xuICAgIGlmICh0aGlzLmhhbmRsZWRSZW5hbWVzLmhhcyhvbGRQYXRoLCBuZXdQYXRoKSkge1xuICAgICAgdGhpcy5oYW5kbGVkUmVuYW1lcy5kZWxldGUob2xkUGF0aCwgbmV3UGF0aCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpO1xuICAgIGlmICghc2V0dGluZ3Muc2hvdWxkSGFuZGxlUmVuYW1lcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChzZXR0aW5ncy5pc1BhdGhJZ25vcmVkPy4ob2xkUGF0aCkpIHtcbiAgICAgIGdldExpYkRlYnVnZ2VyKCdSZW5hbWVEZWxldGVIYW5kbGVyOmhhbmRsZVJlbmFtZScpKGBTa2lwcGluZyByZW5hbWUgaGFuZGxlciBvZiBvbGQgcGF0aCAke29sZFBhdGh9IGFzIHRoZSBwYXRoIGlzIGlnbm9yZWQuYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHNldHRpbmdzLmlzUGF0aElnbm9yZWQ/LihuZXdQYXRoKSkge1xuICAgICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6aGFuZGxlUmVuYW1lJykoYFNraXBwaW5nIHJlbmFtZSBoYW5kbGVyIG9mIG5ldyBwYXRoICR7bmV3UGF0aH0gYXMgdGhlIHBhdGggaXMgaWdub3JlZC5gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBvbGRDYWNoZSA9IHRoaXMuYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0Q2FjaGUob2xkUGF0aCkgPz8gdGhpcy5hcHAubWV0YWRhdGFDYWNoZS5nZXRDYWNoZShuZXdQYXRoKTtcbiAgICBjb25zdCBvbGRQYXRoQmFja2xpbmtzTWFwID0gZ2V0QmFja2xpbmtzRm9yRmlsZU9yUGF0aCh0aGlzLmFwcCwgb2xkUGF0aCkuZGF0YTtcbiAgICBhZGRUb1F1ZXVlKHtcbiAgICAgIGFib3J0U2lnbmFsOiB0aGlzLmFib3J0U2lnbmFsQ29tcG9uZW50LmFib3J0U2lnbmFsLFxuICAgICAgYXBwOiB0aGlzLmFwcCxcbiAgICAgIG9wZXJhdGlvbkZuOiAoYWJvcnRTaWduYWwpID0+XG4gICAgICAgIG5ldyBSZW5hbWVIYW5kbGVyKHtcbiAgICAgICAgICBhYm9ydFNpZ25hbCxcbiAgICAgICAgICBhcHA6IHRoaXMuYXBwLFxuICAgICAgICAgIGhhbmRsZWRSZW5hbWVzOiB0aGlzLmhhbmRsZWRSZW5hbWVzLFxuICAgICAgICAgIGludGVycnVwdGVkUmVuYW1lc01hcDogdGhpcy5pbnRlcnJ1cHRlZFJlbmFtZXNNYXAsXG4gICAgICAgICAgbmV3UGF0aCxcbiAgICAgICAgICBvbGRDYWNoZSxcbiAgICAgICAgICBvbGRQYXRoLFxuICAgICAgICAgIG9sZFBhdGhCYWNrbGlua3NNYXAsXG4gICAgICAgICAgc2V0dGluZ3NNYW5hZ2VyOiB0aGlzLnNldHRpbmdzTWFuYWdlclxuICAgICAgICB9KS5oYW5kbGUoKSxcbiAgICAgIG9wZXJhdGlvbk5hbWU6IHQoKCQpID0+ICQub2JzaWRpYW5EZXZVdGlscy5yZW5hbWVEZWxldGVIYW5kbGVyLmhhbmRsZVJlbmFtZSwgeyBuZXdQYXRoLCBvbGRQYXRoIH0pXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGxvZ1JlZ2lzdGVyZWRIYW5kbGVycygpOiB2b2lkIHtcbiAgICBjb25zdCByZW5hbWVEZWxldGVIYW5kbGVyc01hcCA9IHRoaXMuc2V0dGluZ3NNYW5hZ2VyLnJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwO1xuICAgIGdldExpYkRlYnVnZ2VyKCdSZW5hbWVEZWxldGVIYW5kbGVyOmxvZ1JlZ2lzdGVyZWRIYW5kbGVycycpKFxuICAgICAgYFBsdWdpbnMgd2l0aCByZWdpc3RlcmVkIHJlbmFtZS9kZWxldGUgaGFuZGxlcnM6ICR7SlNPTi5zdHJpbmdpZnkoQXJyYXkuZnJvbShyZW5hbWVEZWxldGVIYW5kbGVyc01hcC5rZXlzKCkpKX1gXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc2hvdWxkSW52b2tlSGFuZGxlcigpOiBib29sZWFuIHtcbiAgICBjb25zdCByZW5hbWVEZWxldGVIYW5kbGVyc01hcCA9IHRoaXMuc2V0dGluZ3NNYW5hZ2VyLnJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwO1xuICAgIGNvbnN0IG1haW5QbHVnaW5JZCA9IEFycmF5LmZyb20ocmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAua2V5cygpKVswXTtcbiAgICByZXR1cm4gbWFpblBsdWdpbklkID09PSB0aGlzLnBsdWdpbklkO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyB3cmFwTGlua1VwZGF0ZXNIYW5kbGVyKGxpbmtVcGRhdGVzOiBMaW5rVXBkYXRlW10sIGxpbmtVcGRhdGVzSGFuZGxlcjogTGlua1VwZGF0ZXNIYW5kbGVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGlzUmVuYW1lQ2FsbGVkID0gZmFsc2U7XG4gICAgY29uc3QgZXZlbnRSZWYgPSB0aGlzLmFwcC52YXVsdC5vbigncmVuYW1lJywgKCkgPT4ge1xuICAgICAgaXNSZW5hbWVDYWxsZWQgPSB0cnVlO1xuICAgIH0pO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBsaW5rVXBkYXRlc0hhbmRsZXIobGlua1VwZGF0ZXMpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmFwcC52YXVsdC5vZmZyZWYoZXZlbnRSZWYpO1xuICAgIH1cbiAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuc2V0dGluZ3NNYW5hZ2VyLmdldFNldHRpbmdzKCk7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bm5lY2Vzc2FyeS1jb25kaXRpb24gLS0gSXQgbWlnaHQgY2hhbmdlZCBpbiBgcmVuYW1lYCBldmVudCBoYW5kbGVyLiBFU0xpbnQgbWlzdGFrZW5seSBkb2VzIG5vdCByZWNvZ25pemUgaXQuXG4gICAgaWYgKCFpc1JlbmFtZUNhbGxlZCB8fCAhc2V0dGluZ3Muc2hvdWxkSGFuZGxlUmVuYW1lcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZpbHRlckluUGxhY2UoXG4gICAgICBsaW5rVXBkYXRlcyxcbiAgICAgIChsaW5rVXBkYXRlKSA9PiB7XG4gICAgICAgIGlmIChzZXR0aW5ncy5pc1BhdGhJZ25vcmVkPy4obGlua1VwZGF0ZS5zb3VyY2VGaWxlLnBhdGgpKSB7XG4gICAgICAgICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6cnVuQXN5bmNMaW5rVXBkYXRlJykoXG4gICAgICAgICAgICBgUm9sbCBiYWNrIHRvIGRlZmF1bHQgbGluayB1cGRhdGUgb2Ygc291cmNlIGZpbGUgJHtsaW5rVXBkYXRlLnNvdXJjZUZpbGUucGF0aH0gYXMgdGhlIHBhdGggaXMgaWdub3JlZC5gXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZXR0aW5ncy5pc1BhdGhJZ25vcmVkPy4obGlua1VwZGF0ZS5yZXNvbHZlZEZpbGUucGF0aCkpIHtcbiAgICAgICAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpydW5Bc3luY0xpbmtVcGRhdGUnKShcbiAgICAgICAgICAgIGBSb2xsIGJhY2sgdG8gZGVmYXVsdCBsaW5rIHVwZGF0ZSBvZiByZXNvbHZlZCBmaWxlICR7bGlua1VwZGF0ZS5yZXNvbHZlZEZpbGUucGF0aH0gYXMgdGhlIHBhdGggaXMgaWdub3JlZC5gXG4gICAgICAgICAgKTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5hcHAuaW50ZXJuYWxQbHVnaW5zLmdldEVuYWJsZWRQbHVnaW5CeUlkKEludGVybmFsUGx1Z2luTmFtZS5DYW52YXMpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuYXBwLnBsdWdpbnMuZ2V0UGx1Z2luKCdiYWNrbGluay1jYWNoZScpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxpbmtVcGRhdGUuc291cmNlRmlsZS5leHRlbnNpb24gPT09IENBTlZBU19GSUxFX0VYVEVOU0lPTikge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxpbmtVcGRhdGUucmVzb2x2ZWRGaWxlLmV4dGVuc2lvbiA9PT0gQ0FOVkFTX0ZJTEVfRVhURU5TSU9OKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgKTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBjbGVhbnVwUGFyZW50Rm9sZGVycyhhcHA6IEFwcCwgc2V0dGluZ3M6IFBhcnRpYWw8UmVuYW1lRGVsZXRlSGFuZGxlclNldHRpbmdzPiwgcGFyZW50Rm9sZGVyUGF0aHM6IHN0cmluZ1tdKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChzZXR0aW5ncy5lbXB0eUZvbGRlckJlaGF2aW9yID09PSBFbXB0eUZvbGRlckJlaGF2aW9yLktlZXApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgZm9yIChjb25zdCBwYXJlbnRGb2xkZXJQYXRoIG9mIHBhcmVudEZvbGRlclBhdGhzKSB7XG4gICAgc3dpdGNoIChzZXR0aW5ncy5lbXB0eUZvbGRlckJlaGF2aW9yKSB7XG4gICAgICBjYXNlIEVtcHR5Rm9sZGVyQmVoYXZpb3IuRGVsZXRlOlxuICAgICAgICBhd2FpdCBkZWxldGVFbXB0eUZvbGRlcihhcHAsIHBhcmVudEZvbGRlclBhdGgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgRW1wdHlGb2xkZXJCZWhhdmlvci5EZWxldGVXaXRoRW1wdHlQYXJlbnRzOlxuICAgICAgICBhd2FpdCBkZWxldGVFbXB0eUZvbGRlckhpZXJhcmNoeShhcHAsIHBhcmVudEZvbGRlclBhdGgpO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxufVxuXG4vKiB2OCBpZ25vcmUgc3RvcCAqL1xuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFtQkEsNkJBR087QUFDUCxxQkFBa0I7QUFDbEIsc0JBR087QUFRUCxtQkFBOEI7QUFDOUIsbUJBQStCO0FBQy9C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