obsidian-dev-utils 40.9.1 → 40.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,512 +45,656 @@ var import_MonkeyAround = require('./MonkeyAround.cjs');
45
45
  var import_Queue = require('./Queue.cjs');
46
46
  var import_Vault = require('./Vault.cjs');
47
47
  var import_VaultEx = require('./VaultEx.cjs');
48
- const deletedMetadataCacheMap = /* @__PURE__ */ new Map();
49
- const handledRenames = /* @__PURE__ */ new Set();
50
- const interruptedRenamesMap = /* @__PURE__ */ new Map();
51
48
  var EmptyAttachmentFolderBehavior = /* @__PURE__ */ ((EmptyAttachmentFolderBehavior2) => {
52
49
  EmptyAttachmentFolderBehavior2["Delete"] = "Delete";
53
50
  EmptyAttachmentFolderBehavior2["DeleteWithEmptyParents"] = "DeleteWithEmptyParents";
54
51
  EmptyAttachmentFolderBehavior2["Keep"] = "Keep";
55
52
  return EmptyAttachmentFolderBehavior2;
56
53
  })(EmptyAttachmentFolderBehavior || {});
57
- function registerRenameDeleteHandlers(plugin, settingsBuilder) {
58
- const renameDeleteHandlersMap = getRenameDeleteHandlersMap(plugin.app);
59
- const pluginId = plugin.manifest.id;
60
- renameDeleteHandlersMap.set(pluginId, settingsBuilder);
61
- logRegisteredHandlers(plugin.app);
62
- plugin.register(() => {
63
- renameDeleteHandlersMap.delete(pluginId);
64
- logRegisteredHandlers(plugin.app);
65
- });
66
- const app = plugin.app;
67
- const abortSignal = plugin.abortSignal ?? (0, import_AbortController.abortSignalNever)();
68
- plugin.registerEvent(
69
- app.vault.on("delete", (file) => {
70
- handleDeleteIfEnabled(plugin, file, abortSignal);
71
- })
72
- );
73
- plugin.registerEvent(
74
- app.vault.on("rename", (file, oldPath) => {
75
- handleRenameIfEnabled(plugin, file, oldPath, abortSignal);
76
- })
77
- );
78
- plugin.registerEvent(
79
- app.metadataCache.on("deleted", (file, prevCache) => {
80
- handleMetadataDeletedIfEnabled(plugin, file, prevCache);
81
- })
82
- );
83
- (0, import_MonkeyAround.registerPatch)(plugin, app.fileManager, {
84
- runAsyncLinkUpdate: (next) => {
85
- return (linkUpdatesHandler) => runAsyncLinkUpdate(app, next, linkUpdatesHandler);
86
- }
87
- });
88
- }
89
- async function cleanupParentFolders(app, parentFolderPaths, notePath) {
90
- const settings = getSettings(app);
91
- if (settings.emptyAttachmentFolderBehavior === "Keep" /* Keep */) {
92
- return;
93
- }
94
- for (const parentFolderPath of parentFolderPaths) {
95
- switch (settings.emptyAttachmentFolderBehavior) {
96
- case "Delete" /* Delete */:
97
- await (0, import_VaultEx.deleteSafe)(app, parentFolderPath, notePath, void 0, true);
98
- break;
99
- case "DeleteWithEmptyParents" /* DeleteWithEmptyParents */:
100
- await (0, import_VaultEx.deleteEmptyFolderHierarchy)(app, parentFolderPath);
101
- break;
102
- default:
103
- break;
54
+ class DeleteHandler {
55
+ constructor(app, file, abortSignal, settingsManager, deletedMetadataCacheMap) {
56
+ this.app = app;
57
+ this.file = file;
58
+ this.abortSignal = abortSignal;
59
+ this.settingsManager = settingsManager;
60
+ this.deletedMetadataCacheMap = deletedMetadataCacheMap;
61
+ }
62
+ async handle() {
63
+ this.abortSignal.throwIfAborted();
64
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleDelete")(`Handle Delete ${this.file.path}`);
65
+ if (!this.settingsManager.isNoteEx(this.file.path)) {
66
+ return;
104
67
  }
105
- }
106
- }
107
- async function continueInterruptedRenames(app, oldPath, newPath, oldPathBacklinksMap, oldPathLinks) {
108
- const interruptedRenames = interruptedRenamesMap.get(oldPath);
109
- if (interruptedRenames) {
110
- interruptedRenamesMap.delete(oldPath);
111
- for (const interruptedRename of interruptedRenames) {
112
- await handleRenameAsync(app, interruptedRename.oldPath, newPath, oldPathBacklinksMap, oldPathLinks, interruptedRename.combinedBacklinksMap);
68
+ const settings = this.settingsManager.getSettings();
69
+ if (!settings.shouldHandleDeletions) {
70
+ return;
113
71
  }
114
- }
115
- }
116
- async function fillRenameMap(app, oldPath, newPath, renameMap, oldPathLinks, abortSignal) {
117
- abortSignal.throwIfAborted();
118
- renameMap.set(oldPath, newPath);
119
- if (!isNoteEx(app, oldPath)) {
120
- return;
121
- }
122
- const settings = getSettings(app);
123
- const oldAttachmentFolderPath = await (0, import_AttachmentPath.getAttachmentFolderPath)(app, oldPath, import_AttachmentPath.AttachmentPathContext.RenameNote);
124
- const newAttachmentFolderPath = settings.shouldRenameAttachmentFolder ? await (0, import_AttachmentPath.getAttachmentFolderPath)(app, newPath, import_AttachmentPath.AttachmentPathContext.RenameNote) : oldAttachmentFolderPath;
125
- const isOldAttachmentFolderAtRoot = oldAttachmentFolderPath === "/";
126
- const oldAttachmentFolder = (0, import_FileSystem.getFolderOrNull)(app, oldAttachmentFolderPath);
127
- if (!oldAttachmentFolder) {
128
- return;
129
- }
130
- if (oldAttachmentFolderPath === newAttachmentFolderPath && !settings.shouldRenameAttachmentFiles) {
131
- return;
132
- }
133
- const oldAttachmentFiles = [];
134
- if (await (0, import_AttachmentPath.hasOwnAttachmentFolder)(app, oldPath, import_AttachmentPath.AttachmentPathContext.RenameNote)) {
135
- import_obsidian.Vault.recurseChildren(oldAttachmentFolder, (oldAttachmentFile) => {
136
- abortSignal.throwIfAborted();
137
- if ((0, import_FileSystem.isFile)(oldAttachmentFile)) {
138
- oldAttachmentFiles.push(oldAttachmentFile);
139
- }
140
- });
141
- } else {
142
- for (const oldPathLink of oldPathLinks) {
143
- abortSignal.throwIfAborted();
144
- const oldAttachmentFile = (0, import_Link.extractLinkFile)(app, oldPathLink, oldPath);
145
- if (!oldAttachmentFile) {
146
- continue;
147
- }
148
- if (isOldAttachmentFolderAtRoot || oldAttachmentFile.path.startsWith(oldAttachmentFolderPath)) {
149
- const oldAttachmentBacklinks = await (0, import_MetadataCache.getBacklinksForFileSafe)(app, oldAttachmentFile);
150
- abortSignal.throwIfAborted();
151
- if (oldAttachmentBacklinks.keys().length === 1) {
152
- oldAttachmentFiles.push(oldAttachmentFile);
72
+ if (settings.isPathIgnored?.(this.file.path)) {
73
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleDelete")(`Skipping delete handler of ${this.file.path} as the path is ignored.`);
74
+ return;
75
+ }
76
+ const cache = this.deletedMetadataCacheMap.get(this.file.path);
77
+ this.deletedMetadataCacheMap.delete(this.file.path);
78
+ const parentFolderPaths = /* @__PURE__ */ new Set();
79
+ if (cache) {
80
+ const links = (0, import_MetadataCache.getAllLinks)(cache);
81
+ for (const link of links) {
82
+ const attachmentFile = (0, import_Link.extractLinkFile)(this.app, link, this.file.path);
83
+ if (!attachmentFile) {
84
+ continue;
85
+ }
86
+ if (this.settingsManager.isNoteEx(attachmentFile.path)) {
87
+ continue;
153
88
  }
89
+ parentFolderPaths.add(attachmentFile.parent?.path ?? "");
90
+ await (0, import_VaultEx.deleteSafe)(this.app, attachmentFile, this.file.path, false, settings.emptyAttachmentFolderBehavior !== "Keep" /* Keep */);
154
91
  }
155
92
  }
156
- }
157
- for (const oldAttachmentFile of oldAttachmentFiles) {
158
- abortSignal.throwIfAborted();
159
- if (isNoteEx(app, oldAttachmentFile.path)) {
160
- continue;
161
- }
162
- let newAttachmentFilePath;
163
- if (settings.shouldRenameAttachmentFiles) {
164
- newAttachmentFilePath = await (0, import_AttachmentPath.getAttachmentFilePath)({
165
- app,
166
- attachmentPathOrFile: oldAttachmentFile,
167
- context: import_AttachmentPath.AttachmentPathContext.RenameNote,
168
- notePathOrFile: newPath,
169
- oldNotePathOrFile: oldPath,
170
- shouldSkipDuplicateCheck: true
171
- });
172
- abortSignal.throwIfAborted();
173
- } else {
174
- const relativePath = isOldAttachmentFolderAtRoot ? oldAttachmentFile.path : (0, import_Path.relative)(oldAttachmentFolderPath, oldAttachmentFile.path);
175
- const newFolder = (0, import_Path.join)(newAttachmentFolderPath, (0, import_Path.dirname)(relativePath));
176
- newAttachmentFilePath = (0, import_Path.join)(newFolder, oldAttachmentFile.name);
177
- }
178
- if (oldAttachmentFile.path === newAttachmentFilePath) {
179
- continue;
180
- }
181
- if (settings.shouldDeleteConflictingAttachments) {
182
- const newAttachmentFile = (0, import_FileSystem.getFileOrNull)(app, newAttachmentFilePath);
183
- if (newAttachmentFile) {
184
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:fillRenameMap")(`Removing conflicting attachment ${newAttachmentFile.path}.`);
185
- await app.fileManager.trashFile(newAttachmentFile);
186
- abortSignal.throwIfAborted();
187
- }
188
- } else {
189
- const dir = (0, import_Path.dirname)(newAttachmentFilePath);
190
- const ext = (0, import_Path.extname)(newAttachmentFilePath);
191
- const baseName = (0, import_Path.basename)(newAttachmentFilePath, ext);
192
- newAttachmentFilePath = app.vault.getAvailablePath((0, import_Path.join)(dir, baseName), ext.slice(1));
93
+ await cleanupParentFolders(this.app, this.settingsManager.getSettings(), Array.from(parentFolderPaths), this.file.path);
94
+ this.abortSignal.throwIfAborted();
95
+ const attachmentFolderPath = await (0, import_AttachmentPath.getAttachmentFolderPath)(this.app, this.file.path, import_AttachmentPath.AttachmentPathContext.DeleteNote);
96
+ const attachmentFolder = (0, import_FileSystem.getFolderOrNull)(this.app, attachmentFolderPath);
97
+ if (!attachmentFolder) {
98
+ return;
99
+ }
100
+ if (!await (0, import_AttachmentPath.hasOwnAttachmentFolder)(this.app, this.file.path, import_AttachmentPath.AttachmentPathContext.DeleteNote)) {
101
+ return;
193
102
  }
194
- renameMap.set(oldAttachmentFile.path, newAttachmentFilePath);
103
+ this.abortSignal.throwIfAborted();
104
+ await (0, import_VaultEx.deleteSafe)(this.app, attachmentFolder, this.file.path, false, settings.emptyAttachmentFolderBehavior !== "Keep" /* Keep */);
105
+ this.abortSignal.throwIfAborted();
195
106
  }
196
107
  }
197
- function getRenameDeleteHandlersMap(app) {
198
- return (0, import_App.getObsidianDevUtilsState)(app, "renameDeleteHandlersMap", /* @__PURE__ */ new Map()).value;
199
- }
200
- function getSettings(app) {
201
- const renameDeleteHandlersMap = getRenameDeleteHandlersMap(app);
202
- const settingsBuilders = Array.from(renameDeleteHandlersMap.values()).reverse();
203
- const settings = {};
204
- settings.isNote = (path) => (0, import_FileSystem.isNote)(app, path);
205
- settings.isPathIgnored = () => false;
206
- for (const settingsBuilder of settingsBuilders) {
207
- const newSettings = settingsBuilder();
208
- settings.shouldDeleteConflictingAttachments ||= newSettings.shouldDeleteConflictingAttachments ?? false;
209
- if (newSettings.emptyAttachmentFolderBehavior) {
210
- settings.emptyAttachmentFolderBehavior ??= newSettings.emptyAttachmentFolderBehavior;
211
- }
212
- settings.shouldHandleDeletions ||= newSettings.shouldHandleDeletions ?? false;
213
- settings.shouldHandleRenames ||= newSettings.shouldHandleRenames ?? false;
214
- settings.shouldRenameAttachmentFiles ||= newSettings.shouldRenameAttachmentFiles ?? false;
215
- settings.shouldRenameAttachmentFolder ||= newSettings.shouldRenameAttachmentFolder ?? false;
216
- settings.shouldUpdateFileNameAliases ||= newSettings.shouldUpdateFileNameAliases ?? false;
217
- const isPathIgnored = settings.isPathIgnored;
218
- settings.isPathIgnored = (path) => isPathIgnored(path) || (newSettings.isPathIgnored?.(path) ?? false);
219
- const currentIsNote = settings.isNote;
220
- settings.isNote = (path) => currentIsNote(path) && (newSettings.isNote?.(path) ?? true);
221
- }
222
- settings.emptyAttachmentFolderBehavior ??= "Keep" /* Keep */;
223
- return settings;
224
- }
225
- async function handleCaseCollision(app, oldPath, newPath, oldPathBacklinksMap, oldPathLinks) {
226
- if (!app.vault.adapter.insensitive || oldPath.toLowerCase() !== newPath.toLowerCase()) {
227
- return false;
228
- }
229
- const tempPath = (0, import_Path.join)((0, import_Path.dirname)(newPath), `__temp__${(0, import_Path.basename)(newPath)}`);
230
- await renameHandled(app, newPath, tempPath);
231
- await handleRenameAsync(app, oldPath, tempPath, oldPathBacklinksMap, oldPathLinks);
232
- await app.vault.rename((0, import_FileSystem.getFile)(app, tempPath), newPath);
233
- return true;
234
- }
235
- async function handleDelete(app, path, abortSignal) {
236
- abortSignal.throwIfAborted();
237
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleDelete")(`Handle Delete ${path}`);
238
- if (!isNoteEx(app, path)) {
239
- return;
108
+ class HandledRenames {
109
+ map = /* @__PURE__ */ new Map();
110
+ add(oldPath, newPath) {
111
+ this.map.set(this.keyToString(oldPath, newPath), { newPath, oldPath });
240
112
  }
241
- const settings = getSettings(app);
242
- if (!settings.shouldHandleDeletions) {
243
- return;
244
- }
245
- if (settings.isPathIgnored?.(path)) {
246
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleDelete")(`Skipping delete handler of ${path} as the path is ignored.`);
247
- return;
113
+ delete(oldPath, newPath) {
114
+ this.map.delete(this.keyToString(oldPath, newPath));
248
115
  }
249
- const cache = deletedMetadataCacheMap.get(path);
250
- deletedMetadataCacheMap.delete(path);
251
- const parentFolderPaths = /* @__PURE__ */ new Set();
252
- if (cache) {
253
- const links = (0, import_MetadataCache.getAllLinks)(cache);
254
- for (const link of links) {
255
- const attachmentFile = (0, import_Link.extractLinkFile)(app, link, path);
256
- if (!attachmentFile) {
257
- continue;
258
- }
259
- if (isNoteEx(app, attachmentFile.path)) {
260
- continue;
261
- }
262
- parentFolderPaths.add(attachmentFile.parent?.path ?? "");
263
- await (0, import_VaultEx.deleteSafe)(app, attachmentFile, path, false, settings.emptyAttachmentFolderBehavior !== "Keep" /* Keep */);
264
- abortSignal.throwIfAborted();
265
- }
116
+ has(oldPath, newPath) {
117
+ return this.map.has(this.keyToString(oldPath, newPath));
266
118
  }
267
- await cleanupParentFolders(app, Array.from(parentFolderPaths), path);
268
- abortSignal.throwIfAborted();
269
- const attachmentFolderPath = await (0, import_AttachmentPath.getAttachmentFolderPath)(app, path, import_AttachmentPath.AttachmentPathContext.DeleteNote);
270
- const attachmentFolder = (0, import_FileSystem.getFolderOrNull)(app, attachmentFolderPath);
271
- if (!attachmentFolder) {
272
- return;
119
+ keys() {
120
+ return this.map.values();
273
121
  }
274
- if (!await (0, import_AttachmentPath.hasOwnAttachmentFolder)(app, path, import_AttachmentPath.AttachmentPathContext.DeleteNote)) {
275
- return;
122
+ keyToString(oldPath, newPath) {
123
+ return `${oldPath} -> ${newPath}`;
276
124
  }
277
- abortSignal.throwIfAborted();
278
- await (0, import_VaultEx.deleteSafe)(app, attachmentFolder, path, false, settings.emptyAttachmentFolderBehavior !== "Keep" /* Keep */);
279
- abortSignal.throwIfAborted();
280
125
  }
281
- function handleDeleteIfEnabled(plugin, file, abortSignal) {
282
- const app = plugin.app;
283
- if (!shouldInvokeHandler(plugin)) {
284
- return;
126
+ class MetadataDeletedHandler {
127
+ constructor(app, file, prevCache, settingsManager, deletedMetadataCacheMap) {
128
+ this.app = app;
129
+ this.file = file;
130
+ this.prevCache = prevCache;
131
+ this.settingsManager = settingsManager;
132
+ this.deletedMetadataCacheMap = deletedMetadataCacheMap;
133
+ }
134
+ handle() {
135
+ const settings = this.settingsManager.getSettings();
136
+ if (!settings.shouldHandleDeletions) {
137
+ return;
138
+ }
139
+ if (settings.isPathIgnored?.(this.file.path)) {
140
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleMetadataDeleted")(`Skipping metadata delete handler of ${this.file.path} as the path is ignored.`);
141
+ return;
142
+ }
143
+ if ((0, import_FileSystem.isMarkdownFile)(this.app, this.file) && this.prevCache) {
144
+ this.deletedMetadataCacheMap.set(this.file.path, this.prevCache);
145
+ }
285
146
  }
286
- const path = file.path;
287
- (0, import_Queue.addToQueue)(app, (abortSignal2) => handleDelete(app, path, abortSignal2), abortSignal);
288
147
  }
289
- function handleMetadataDeleted(app, file, prevCache) {
290
- const settings = getSettings(app);
291
- if (settings.isPathIgnored?.(file.path)) {
292
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleMetadataDeleted")(`Skipping metadata delete handler of ${file.path} as the path is ignored.`);
293
- return;
148
+ class Registry {
149
+ constructor(plugin, settingsBuilder, settingsManager) {
150
+ this.plugin = plugin;
151
+ this.settingsBuilder = settingsBuilder;
152
+ this.settingsManager = settingsManager;
153
+ this.app = plugin.app;
154
+ this.pluginId = plugin.manifest.id;
155
+ this.abortSignal = plugin.abortSignal ?? (0, import_AbortController.abortSignalNever)();
156
+ }
157
+ abortSignal;
158
+ app;
159
+ deletedMetadataCacheMap = /* @__PURE__ */ new Map();
160
+ handledRenames = new HandledRenames();
161
+ interruptedRenamesMap = /* @__PURE__ */ new Map();
162
+ pluginId;
163
+ register() {
164
+ const renameDeleteHandlersMap = this.settingsManager.renameDeleteHandlersMap;
165
+ renameDeleteHandlersMap.set(this.pluginId, this.settingsBuilder);
166
+ this.logRegisteredHandlers();
167
+ this.plugin.register(() => {
168
+ renameDeleteHandlersMap.delete(this.pluginId);
169
+ this.logRegisteredHandlers();
170
+ });
171
+ this.plugin.registerEvent(this.app.vault.on("delete", this.handleDelete.bind(this)));
172
+ this.plugin.registerEvent(this.app.vault.on("rename", this.handleRename.bind(this)));
173
+ this.plugin.registerEvent(this.app.metadataCache.on("deleted", this.handleMetadataDeleted.bind(this)));
174
+ (0, import_MonkeyAround.registerPatch)(this.plugin, this.app.fileManager, {
175
+ runAsyncLinkUpdate: (next) => {
176
+ return Object.assign((linkUpdatesHandler) => this.runAsyncLinkUpdate(next, linkUpdatesHandler), { renameDeleteHandlerPatched: true });
177
+ }
178
+ });
294
179
  }
295
- if (!settings.shouldHandleDeletions) {
296
- return;
180
+ handleDelete(file) {
181
+ if (!this.shouldInvokeHandler()) {
182
+ return;
183
+ }
184
+ (0, import_Queue.addToQueue)(
185
+ this.app,
186
+ (abortSignal) => new DeleteHandler(this.app, file, abortSignal, this.settingsManager, this.deletedMetadataCacheMap).handle(),
187
+ this.abortSignal
188
+ );
189
+ }
190
+ handleMetadataDeleted(file, prevCache) {
191
+ if (!this.shouldInvokeHandler()) {
192
+ return;
193
+ }
194
+ (0, import_Queue.addToQueue)(this.app, () => {
195
+ new MetadataDeletedHandler(this.app, file, prevCache, this.settingsManager, this.deletedMetadataCacheMap).handle();
196
+ }, this.abortSignal);
297
197
  }
298
- if ((0, import_FileSystem.isMarkdownFile)(app, file) && prevCache) {
299
- deletedMetadataCacheMap.set(file.path, prevCache);
198
+ handleRename(file, oldPath) {
199
+ if (!this.shouldInvokeHandler()) {
200
+ return;
201
+ }
202
+ if (!(0, import_FileSystem.isFile)(file)) {
203
+ return;
204
+ }
205
+ const newPath = file.path;
206
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Handle Rename ${oldPath} -> ${newPath}`);
207
+ if (this.handledRenames.has(oldPath, newPath)) {
208
+ this.handledRenames.delete(oldPath, newPath);
209
+ return;
210
+ }
211
+ const settings = this.settingsManager.getSettings();
212
+ if (!settings.shouldHandleRenames) {
213
+ return;
214
+ }
215
+ if (settings.isPathIgnored?.(oldPath)) {
216
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Skipping rename handler of old path ${oldPath} as the path is ignored.`);
217
+ return;
218
+ }
219
+ if (settings.isPathIgnored?.(newPath)) {
220
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Skipping rename handler of new path ${newPath} as the path is ignored.`);
221
+ return;
222
+ }
223
+ const oldCache = this.app.metadataCache.getCache(oldPath) ?? this.app.metadataCache.getCache(newPath);
224
+ const oldPathBacklinksMap = (0, import_MetadataCache.getBacklinksForFileOrPath)(this.app, oldPath).data;
225
+ (0, import_Queue.addToQueue)(this.app, (abortSignal) => new RenameHandler({
226
+ abortSignal,
227
+ app: this.app,
228
+ handledRenames: this.handledRenames,
229
+ interruptedRenamesMap: this.interruptedRenamesMap,
230
+ newPath,
231
+ oldCache,
232
+ oldPath,
233
+ oldPathBacklinksMap,
234
+ settingsManager: this.settingsManager
235
+ }).handle(), this.abortSignal);
236
+ }
237
+ logRegisteredHandlers() {
238
+ const renameDeleteHandlersMap = this.settingsManager.renameDeleteHandlersMap;
239
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:logRegisteredHandlers")(
240
+ `Plugins with registered rename/delete handlers: ${JSON.stringify(Array.from(renameDeleteHandlersMap.keys()))}`
241
+ );
242
+ }
243
+ async runAsyncLinkUpdate(next, linkUpdatesHandler) {
244
+ if (next.renameDeleteHandlerPatched) {
245
+ await next.call(this.app.fileManager, linkUpdatesHandler);
246
+ return;
247
+ }
248
+ await next.call(this.app.fileManager, (linkUpdates) => this.wrapLinkUpdatesHandler(linkUpdates, linkUpdatesHandler));
300
249
  }
301
- }
302
- function handleMetadataDeletedIfEnabled(plugin, file, prevCache) {
303
- if (!shouldInvokeHandler(plugin)) {
304
- return;
250
+ shouldInvokeHandler() {
251
+ const pluginId = this.plugin.manifest.id;
252
+ const renameDeleteHandlersMap = this.settingsManager.renameDeleteHandlersMap;
253
+ const mainPluginId = Array.from(renameDeleteHandlersMap.keys())[0];
254
+ return mainPluginId === pluginId;
255
+ }
256
+ async wrapLinkUpdatesHandler(linkUpdates, linkUpdatesHandler) {
257
+ let isRenameCalled = false;
258
+ const eventRef = this.app.vault.on("rename", () => {
259
+ isRenameCalled = true;
260
+ });
261
+ try {
262
+ await linkUpdatesHandler(linkUpdates);
263
+ } finally {
264
+ this.app.vault.offref(eventRef);
265
+ }
266
+ const settings = this.settingsManager.getSettings();
267
+ if (!isRenameCalled || !settings.shouldHandleRenames) {
268
+ return;
269
+ }
270
+ (0, import_Array.filterInPlace)(
271
+ linkUpdates,
272
+ (linkUpdate) => {
273
+ if (settings.isPathIgnored?.(linkUpdate.sourceFile.path)) {
274
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:runAsyncLinkUpdate")(
275
+ `Roll back to default link update of source file ${linkUpdate.sourceFile.path} as the path is ignored.`
276
+ );
277
+ return true;
278
+ }
279
+ if (settings.isPathIgnored?.(linkUpdate.resolvedFile.path)) {
280
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:runAsyncLinkUpdate")(
281
+ `Roll back to default link update of resolved file ${linkUpdate.resolvedFile.path} as the path is ignored.`
282
+ );
283
+ return true;
284
+ }
285
+ if (!this.app.internalPlugins.getEnabledPluginById(import_implementations.InternalPluginName.Canvas)) {
286
+ return false;
287
+ }
288
+ if (this.app.plugins.getPlugin("backlink-cache")) {
289
+ return false;
290
+ }
291
+ if (linkUpdate.sourceFile.extension === import_FileSystem.CANVAS_FILE_EXTENSION) {
292
+ return true;
293
+ }
294
+ if (linkUpdate.resolvedFile.extension === import_FileSystem.CANVAS_FILE_EXTENSION) {
295
+ return true;
296
+ }
297
+ return false;
298
+ }
299
+ );
305
300
  }
306
- handleMetadataDeleted(plugin.app, file, prevCache);
307
301
  }
308
- function handleRename(app, oldPath, newPath, abortSignal) {
309
- const key = makeKey(oldPath, newPath);
310
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Handle Rename ${key}`);
311
- if (handledRenames.has(key)) {
312
- handledRenames.delete(key);
313
- return;
302
+ class RenameHandler {
303
+ abortSignal;
304
+ app;
305
+ handledRenames;
306
+ interruptedCombinedBacklinksMap;
307
+ interruptedRenamesMap;
308
+ newPath;
309
+ oldCache;
310
+ oldPath;
311
+ oldPathBacklinksMap;
312
+ oldPathLinks;
313
+ settingsManager;
314
+ constructor(options) {
315
+ this.app = options.app;
316
+ this.oldPath = options.oldPath;
317
+ this.newPath = options.newPath;
318
+ this.oldPathBacklinksMap = options.oldPathBacklinksMap;
319
+ this.oldCache = options.oldCache;
320
+ this.abortSignal = options.abortSignal;
321
+ this.settingsManager = options.settingsManager;
322
+ this.interruptedRenamesMap = options.interruptedRenamesMap;
323
+ this.oldPathLinks = this.oldCache ? (0, import_MetadataCache.getAllLinks)(this.oldCache) : [];
324
+ this.handledRenames = options.handledRenames;
325
+ this.interruptedCombinedBacklinksMap = options.interruptedCombinedBacklinksMap ?? /* @__PURE__ */ new Map();
326
+ }
327
+ async handle() {
328
+ this.abortSignal.throwIfAborted();
329
+ await this.continueInterruptedRenames();
330
+ this.abortSignal.throwIfAborted();
331
+ await this.refreshLinks();
332
+ this.abortSignal.throwIfAborted();
333
+ if (await this.handleCaseCollision()) {
334
+ return;
335
+ }
336
+ this.abortSignal.throwIfAborted();
337
+ try {
338
+ const renameMap = new RenameMap({
339
+ abortSignal: this.abortSignal,
340
+ app: this.app,
341
+ newPath: this.newPath,
342
+ oldCache: this.oldCache,
343
+ oldPath: this.oldPath,
344
+ settingsManager: this.settingsManager
345
+ });
346
+ await renameMap.fill();
347
+ this.abortSignal.throwIfAborted();
348
+ const combinedBacklinksMap = /* @__PURE__ */ new Map();
349
+ renameMap.initBacklinksMap(this.oldPathBacklinksMap, combinedBacklinksMap, this.oldPath);
350
+ for (const attachmentOldPath of renameMap.keys()) {
351
+ if (attachmentOldPath === this.oldPath) {
352
+ continue;
353
+ }
354
+ const attachmentOldPathBacklinksMap = (await (0, import_MetadataCache.getBacklinksForFileSafe)(this.app, attachmentOldPath)).data;
355
+ this.abortSignal.throwIfAborted();
356
+ renameMap.initBacklinksMap(attachmentOldPathBacklinksMap, combinedBacklinksMap, attachmentOldPath);
357
+ }
358
+ const parentFolderPaths = /* @__PURE__ */ new Set();
359
+ for (const [oldAttachmentPath, newAttachmentPath] of renameMap.entries()) {
360
+ if (oldAttachmentPath === this.oldPath) {
361
+ continue;
362
+ }
363
+ const fixedNewAttachmentPath = await this.renameHandled(oldAttachmentPath, newAttachmentPath);
364
+ this.abortSignal.throwIfAborted();
365
+ renameMap.set(oldAttachmentPath, fixedNewAttachmentPath);
366
+ parentFolderPaths.add((0, import_Path.dirname)(oldAttachmentPath));
367
+ }
368
+ await cleanupParentFolders(this.app, this.settingsManager.getSettings(), Array.from(parentFolderPaths), this.oldPath);
369
+ this.abortSignal.throwIfAborted();
370
+ const settings = this.settingsManager.getSettings();
371
+ for (const [newBacklinkPath, linkJsonToPathMap] of Array.from(combinedBacklinksMap.entries()).concat(
372
+ Array.from(this.interruptedCombinedBacklinksMap.entries())
373
+ )) {
374
+ await (0, import_Link.editLinks)(this.app, newBacklinkPath, (link) => {
375
+ const oldAttachmentPath = linkJsonToPathMap.get((0, import_ObjectUtils.toJson)(link));
376
+ if (!oldAttachmentPath) {
377
+ return;
378
+ }
379
+ const newAttachmentPath = renameMap.get(oldAttachmentPath);
380
+ if (!newAttachmentPath) {
381
+ return;
382
+ }
383
+ return (0, import_Link.updateLink)((0, import_ObjectUtils.normalizeOptionalProperties)({
384
+ app: this.app,
385
+ link,
386
+ newSourcePathOrFile: newBacklinkPath,
387
+ newTargetPathOrFile: newAttachmentPath,
388
+ oldTargetPathOrFile: oldAttachmentPath,
389
+ shouldUpdateFileNameAlias: settings.shouldUpdateFileNameAliases
390
+ }));
391
+ }, {
392
+ shouldFailOnMissingFile: false
393
+ });
394
+ this.abortSignal.throwIfAborted();
395
+ }
396
+ if (this.settingsManager.isNoteEx(this.newPath)) {
397
+ await (0, import_Link.updateLinksInFile)((0, import_ObjectUtils.normalizeOptionalProperties)({
398
+ app: this.app,
399
+ newSourcePathOrFile: this.newPath,
400
+ oldSourcePathOrFile: this.oldPath,
401
+ shouldFailOnMissingFile: false,
402
+ shouldUpdateFileNameAlias: settings.shouldUpdateFileNameAliases
403
+ }));
404
+ this.abortSignal.throwIfAborted();
405
+ }
406
+ if (!(0, import_FileSystem.getFileOrNull)(this.app, this.newPath)) {
407
+ let interruptedRenames = this.interruptedRenamesMap.get(this.newPath);
408
+ if (!interruptedRenames) {
409
+ interruptedRenames = [];
410
+ this.interruptedRenamesMap.set(this.newPath, interruptedRenames);
411
+ }
412
+ interruptedRenames.push({
413
+ combinedBacklinksMap,
414
+ oldPath: this.oldPath
415
+ });
416
+ }
417
+ } finally {
418
+ const orphanKeys = Array.from(this.handledRenames.keys());
419
+ (0, import_Queue.addToQueue)(this.app, () => {
420
+ for (const orphanKey of orphanKeys) {
421
+ this.handledRenames.delete(orphanKey.oldPath, orphanKey.newPath);
422
+ }
423
+ }, this.abortSignal);
424
+ }
314
425
  }
315
- const settings = getSettings(app);
316
- if (!settings.shouldHandleRenames) {
317
- return;
426
+ async continueInterruptedRenames() {
427
+ const interruptedRenames = this.interruptedRenamesMap.get(this.oldPath);
428
+ if (interruptedRenames) {
429
+ this.interruptedRenamesMap.delete(this.oldPath);
430
+ for (const interruptedRename of interruptedRenames) {
431
+ await new RenameHandler({
432
+ abortSignal: this.abortSignal,
433
+ app: this.app,
434
+ handledRenames: this.handledRenames,
435
+ interruptedCombinedBacklinksMap: interruptedRename.combinedBacklinksMap,
436
+ interruptedRenamesMap: this.interruptedRenamesMap,
437
+ newPath: this.newPath,
438
+ oldCache: this.oldCache,
439
+ oldPath: interruptedRename.oldPath,
440
+ oldPathBacklinksMap: this.oldPathBacklinksMap,
441
+ settingsManager: this.settingsManager
442
+ }).handle();
443
+ }
444
+ }
318
445
  }
319
- if (settings.isPathIgnored?.(oldPath)) {
320
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Skipping rename handler of old path ${oldPath} as the path is ignored.`);
321
- return;
446
+ async handleCaseCollision() {
447
+ if (!this.app.vault.adapter.insensitive || this.oldPath.toLowerCase() !== this.newPath.toLowerCase()) {
448
+ return false;
449
+ }
450
+ const tempPath = (0, import_Path.join)((0, import_Path.dirname)(this.newPath), `__temp__${(0, import_Path.basename)(this.newPath)}`);
451
+ await this.renameHandled(this.newPath, tempPath);
452
+ await new RenameHandler({
453
+ abortSignal: this.abortSignal,
454
+ app: this.app,
455
+ handledRenames: this.handledRenames,
456
+ interruptedRenamesMap: this.interruptedRenamesMap,
457
+ newPath: tempPath,
458
+ oldCache: this.oldCache,
459
+ oldPath: this.oldPath,
460
+ oldPathBacklinksMap: this.oldPathBacklinksMap,
461
+ settingsManager: this.settingsManager
462
+ }).handle();
463
+ await this.app.vault.rename((0, import_FileSystem.getFile)(this.app, tempPath), this.newPath);
464
+ return true;
465
+ }
466
+ async refreshLinks() {
467
+ const cache = this.app.metadataCache.getCache(this.oldPath) ?? this.app.metadataCache.getCache(this.newPath);
468
+ const oldPathLinksRefreshed = cache ? (0, import_MetadataCache.getAllLinks)(cache) : [];
469
+ const fakeOldFile = (0, import_FileSystem.getFile)(this.app, this.oldPath, true);
470
+ let oldPathBacklinksMapRefreshed = /* @__PURE__ */ new Map();
471
+ await (0, import_MetadataCache.tempRegisterFilesAndRun)(this.app, [fakeOldFile], async () => {
472
+ oldPathBacklinksMapRefreshed = (await (0, import_MetadataCache.getBacklinksForFileSafe)(this.app, fakeOldFile)).data;
473
+ });
474
+ for (const link of oldPathLinksRefreshed) {
475
+ if (this.oldPathLinks.includes(link)) {
476
+ continue;
477
+ }
478
+ this.oldPathLinks.push(link);
479
+ }
480
+ for (const [backlinkPath, refreshedLinks] of oldPathBacklinksMapRefreshed.entries()) {
481
+ let oldLinks = this.oldPathBacklinksMap.get(backlinkPath);
482
+ if (!oldLinks) {
483
+ oldLinks = [];
484
+ this.oldPathBacklinksMap.set(backlinkPath, oldLinks);
485
+ }
486
+ for (const link of refreshedLinks) {
487
+ if (oldLinks.includes(link)) {
488
+ continue;
489
+ }
490
+ oldLinks.push(link);
491
+ }
492
+ }
322
493
  }
323
- if (settings.isPathIgnored?.(newPath)) {
324
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:handleRename")(`Skipping rename handler of new path ${newPath} as the path is ignored.`);
325
- return;
494
+ async renameHandled(oldPath, newPath) {
495
+ newPath = (0, import_Vault.getSafeRenamePath)(this.app, oldPath, newPath);
496
+ if (oldPath === newPath) {
497
+ return newPath;
498
+ }
499
+ this.handledRenames.add(oldPath, newPath);
500
+ newPath = await (0, import_Vault.renameSafe)(this.app, oldPath, newPath);
501
+ return newPath;
326
502
  }
327
- const cache = app.metadataCache.getCache(oldPath) ?? app.metadataCache.getCache(newPath);
328
- const oldPathLinks = cache ? (0, import_MetadataCache.getAllLinks)(cache) : [];
329
- const oldPathBacklinksMap = (0, import_MetadataCache.getBacklinksForFileOrPath)(app, oldPath).data;
330
- (0, import_Queue.addToQueue)(app, (abortSignal2) => handleRenameAsync(app, oldPath, newPath, oldPathBacklinksMap, oldPathLinks, void 0, abortSignal2), abortSignal);
331
503
  }
332
- async function handleRenameAsync(app, oldPath, newPath, oldPathBacklinksMap, oldPathLinks, interruptedCombinedBacklinksMap, abortSignal) {
333
- abortSignal ??= (0, import_AbortController.abortSignalNever)();
334
- abortSignal.throwIfAborted();
335
- await continueInterruptedRenames(app, oldPath, newPath, oldPathBacklinksMap, oldPathLinks);
336
- abortSignal.throwIfAborted();
337
- await refreshLinks(app, oldPath, newPath, oldPathBacklinksMap, oldPathLinks);
338
- abortSignal.throwIfAborted();
339
- if (await handleCaseCollision(app, oldPath, newPath, oldPathBacklinksMap, oldPathLinks)) {
340
- return;
341
- }
342
- abortSignal.throwIfAborted();
343
- try {
344
- const renameMap = /* @__PURE__ */ new Map();
345
- await fillRenameMap(app, oldPath, newPath, renameMap, oldPathLinks, abortSignal);
346
- abortSignal.throwIfAborted();
347
- const combinedBacklinksMap = /* @__PURE__ */ new Map();
348
- initBacklinksMap(oldPathBacklinksMap, renameMap, combinedBacklinksMap, oldPath);
349
- for (const attachmentOldPath of renameMap.keys()) {
350
- if (attachmentOldPath === oldPath) {
351
- continue;
352
- }
353
- const attachmentOldPathBacklinksMap = (await (0, import_MetadataCache.getBacklinksForFileSafe)(app, attachmentOldPath)).data;
354
- initBacklinksMap(attachmentOldPathBacklinksMap, renameMap, combinedBacklinksMap, attachmentOldPath);
504
+ class RenameMap {
505
+ abortSignal;
506
+ app;
507
+ map = /* @__PURE__ */ new Map();
508
+ newPath;
509
+ oldCache;
510
+ oldPath;
511
+ oldPathLinks;
512
+ settingsManager;
513
+ constructor(options) {
514
+ this.abortSignal = options.abortSignal;
515
+ this.app = options.app;
516
+ this.settingsManager = options.settingsManager;
517
+ this.oldCache = options.oldCache;
518
+ this.oldPath = options.oldPath;
519
+ this.newPath = options.newPath;
520
+ this.oldPathLinks = this.oldCache ? (0, import_MetadataCache.getAllLinks)(this.oldCache) : [];
521
+ }
522
+ entries() {
523
+ return this.map.entries();
524
+ }
525
+ async fill() {
526
+ this.abortSignal.throwIfAborted();
527
+ this.map.set(this.oldPath, this.newPath);
528
+ if (!this.settingsManager.isNoteEx(this.oldPath)) {
529
+ return;
355
530
  }
356
- const parentFolderPaths = /* @__PURE__ */ new Set();
357
- for (const [oldAttachmentPath, newAttachmentPath] of renameMap.entries()) {
358
- if (oldAttachmentPath === oldPath) {
359
- continue;
531
+ const settings = this.settingsManager.getSettings();
532
+ const oldFile = (0, import_FileSystem.getFile)(this.app, this.oldPath, true);
533
+ let oldAttachmentFolderPath = "";
534
+ await (0, import_MetadataCache.tempRegisterFilesAndRunAsync)(this.app, [oldFile], async () => {
535
+ const shouldFakeOldPathCache = this.oldCache && oldFile.deleted;
536
+ if (shouldFakeOldPathCache) {
537
+ (0, import_MetadataCache.registerFileCacheForNonExistingFile)(this.app, oldFile, this.oldCache);
360
538
  }
361
- const fixedNewAttachmentPath = await renameHandled(app, oldAttachmentPath, newAttachmentPath);
362
- renameMap.set(oldAttachmentPath, fixedNewAttachmentPath);
363
- parentFolderPaths.add((0, import_Path.dirname)(oldAttachmentPath));
364
- }
365
- await cleanupParentFolders(app, Array.from(parentFolderPaths), oldPath);
366
- abortSignal.throwIfAborted();
367
- const settings = getSettings(app);
368
- for (const [newBacklinkPath, linkJsonToPathMap] of Array.from(combinedBacklinksMap.entries()).concat(
369
- Array.from(interruptedCombinedBacklinksMap?.entries() ?? [])
370
- )) {
371
- await (0, import_Link.editLinks)(app, newBacklinkPath, (link) => {
372
- const oldAttachmentPath = linkJsonToPathMap.get((0, import_ObjectUtils.toJson)(link));
373
- if (!oldAttachmentPath) {
374
- return;
539
+ try {
540
+ oldAttachmentFolderPath = await (0, import_AttachmentPath.getAttachmentFolderPath)(this.app, this.oldPath, import_AttachmentPath.AttachmentPathContext.RenameNote);
541
+ } finally {
542
+ if (shouldFakeOldPathCache) {
543
+ (0, import_MetadataCache.unregisterFileCacheForNonExistingFile)(this.app, oldFile);
375
544
  }
376
- const newAttachmentPath = renameMap.get(oldAttachmentPath);
377
- if (!newAttachmentPath) {
378
- return;
545
+ }
546
+ });
547
+ const newAttachmentFolderPath = settings.shouldRenameAttachmentFolder ? await (0, import_AttachmentPath.getAttachmentFolderPath)(this.app, this.newPath, import_AttachmentPath.AttachmentPathContext.RenameNote) : oldAttachmentFolderPath;
548
+ const isOldAttachmentFolderAtRoot = oldAttachmentFolderPath === "/";
549
+ const oldAttachmentFolder = (0, import_FileSystem.getFolderOrNull)(this.app, oldAttachmentFolderPath);
550
+ if (!oldAttachmentFolder) {
551
+ return;
552
+ }
553
+ if (oldAttachmentFolderPath === newAttachmentFolderPath && !settings.shouldRenameAttachmentFiles) {
554
+ return;
555
+ }
556
+ const oldAttachmentFiles = [];
557
+ if (await (0, import_AttachmentPath.hasOwnAttachmentFolder)(this.app, this.oldPath, import_AttachmentPath.AttachmentPathContext.RenameNote)) {
558
+ import_obsidian.Vault.recurseChildren(oldAttachmentFolder, (oldAttachmentFile) => {
559
+ this.abortSignal.throwIfAborted();
560
+ if ((0, import_FileSystem.isFile)(oldAttachmentFile)) {
561
+ oldAttachmentFiles.push(oldAttachmentFile);
379
562
  }
380
- return (0, import_Link.updateLink)((0, import_ObjectUtils.normalizeOptionalProperties)({
381
- app,
382
- link,
383
- newSourcePathOrFile: newBacklinkPath,
384
- newTargetPathOrFile: newAttachmentPath,
385
- oldTargetPathOrFile: oldAttachmentPath,
386
- shouldUpdateFileNameAlias: settings.shouldUpdateFileNameAliases
387
- }));
388
- }, {
389
- shouldFailOnMissingFile: false
390
563
  });
391
- abortSignal.throwIfAborted();
392
- }
393
- if (isNoteEx(app, newPath)) {
394
- await (0, import_Link.updateLinksInFile)((0, import_ObjectUtils.normalizeOptionalProperties)({
395
- app,
396
- newSourcePathOrFile: newPath,
397
- oldSourcePathOrFile: oldPath,
398
- shouldFailOnMissingFile: false,
399
- shouldUpdateFileNameAlias: settings.shouldUpdateFileNameAliases
400
- }));
401
- abortSignal.throwIfAborted();
402
- }
403
- if (!(0, import_FileSystem.getFileOrNull)(app, newPath)) {
404
- let interruptedRenames = interruptedRenamesMap.get(newPath);
405
- if (!interruptedRenames) {
406
- interruptedRenames = [];
407
- interruptedRenamesMap.set(newPath, interruptedRenames);
564
+ } else {
565
+ for (const oldPathLink of this.oldPathLinks) {
566
+ this.abortSignal.throwIfAborted();
567
+ const oldAttachmentFile = (0, import_Link.extractLinkFile)(this.app, oldPathLink, this.oldPath);
568
+ if (!oldAttachmentFile) {
569
+ continue;
570
+ }
571
+ if (isOldAttachmentFolderAtRoot || oldAttachmentFile.path.startsWith(oldAttachmentFolderPath)) {
572
+ const oldAttachmentBacklinks = await (0, import_MetadataCache.getBacklinksForFileSafe)(this.app, oldAttachmentFile);
573
+ this.abortSignal.throwIfAborted();
574
+ if (oldAttachmentBacklinks.keys().length === 1) {
575
+ oldAttachmentFiles.push(oldAttachmentFile);
576
+ }
577
+ }
408
578
  }
409
- interruptedRenames.push({
410
- combinedBacklinksMap,
411
- oldPath
412
- });
413
579
  }
414
- } finally {
415
- const orphanKeys = Array.from(handledRenames);
416
- (0, import_Queue.addToQueue)(app, () => {
417
- for (const key of orphanKeys) {
418
- handledRenames.delete(key);
580
+ for (const oldAttachmentFile of oldAttachmentFiles) {
581
+ this.abortSignal.throwIfAborted();
582
+ if (this.settingsManager.isNoteEx(oldAttachmentFile.path)) {
583
+ continue;
419
584
  }
420
- }, abortSignal);
421
- }
422
- }
423
- function handleRenameIfEnabled(plugin, file, oldPath, abortSignal) {
424
- if (!shouldInvokeHandler(plugin)) {
425
- return;
585
+ let newAttachmentFilePath;
586
+ if (settings.shouldRenameAttachmentFiles) {
587
+ newAttachmentFilePath = await (0, import_AttachmentPath.getAttachmentFilePath)({
588
+ app: this.app,
589
+ attachmentPathOrFile: oldAttachmentFile,
590
+ context: import_AttachmentPath.AttachmentPathContext.RenameNote,
591
+ notePathOrFile: this.newPath,
592
+ oldNotePathOrFile: this.oldPath,
593
+ shouldSkipDuplicateCheck: true
594
+ });
595
+ this.abortSignal.throwIfAborted();
596
+ } else {
597
+ const relativePath = isOldAttachmentFolderAtRoot ? oldAttachmentFile.path : (0, import_Path.relative)(oldAttachmentFolderPath, oldAttachmentFile.path);
598
+ const newFolder = (0, import_Path.join)(newAttachmentFolderPath, (0, import_Path.dirname)(relativePath));
599
+ newAttachmentFilePath = (0, import_Path.join)(newFolder, oldAttachmentFile.name);
600
+ }
601
+ if (oldAttachmentFile.path === newAttachmentFilePath) {
602
+ continue;
603
+ }
604
+ if (settings.shouldDeleteConflictingAttachments) {
605
+ const newAttachmentFile = (0, import_FileSystem.getFileOrNull)(this.app, newAttachmentFilePath);
606
+ if (newAttachmentFile) {
607
+ (0, import_Debug.getLibDebugger)("RenameDeleteHandler:fillRenameMap")(`Removing conflicting attachment ${newAttachmentFile.path}.`);
608
+ await this.app.fileManager.trashFile(newAttachmentFile);
609
+ this.abortSignal.throwIfAborted();
610
+ }
611
+ } else {
612
+ const dir = (0, import_Path.dirname)(newAttachmentFilePath);
613
+ const ext = (0, import_Path.extname)(newAttachmentFilePath);
614
+ const baseName = (0, import_Path.basename)(newAttachmentFilePath, ext);
615
+ newAttachmentFilePath = this.app.vault.getAvailablePath((0, import_Path.join)(dir, baseName), ext.slice(1));
616
+ }
617
+ this.map.set(oldAttachmentFile.path, newAttachmentFilePath);
618
+ }
426
619
  }
427
- if (!(0, import_FileSystem.isFile)(file)) {
428
- return;
620
+ get(oldPath) {
621
+ return this.map.get(oldPath);
429
622
  }
430
- const newPath = file.path;
431
- handleRename(plugin.app, oldPath, newPath, abortSignal);
432
- }
433
- function initBacklinksMap(singleBacklinksMap, renameMap, combinedBacklinksMap, path) {
434
- for (const [backlinkPath, links] of singleBacklinksMap.entries()) {
435
- const newBacklinkPath = renameMap.get(backlinkPath) ?? backlinkPath;
436
- const linkJsonToPathMap = combinedBacklinksMap.get(newBacklinkPath) ?? /* @__PURE__ */ new Map();
437
- combinedBacklinksMap.set(newBacklinkPath, linkJsonToPathMap);
438
- for (const link of links) {
439
- linkJsonToPathMap.set((0, import_ObjectUtils.toJson)(link), path);
623
+ initBacklinksMap(singleBacklinksMap, combinedBacklinksMap, path) {
624
+ for (const [backlinkPath, links] of singleBacklinksMap.entries()) {
625
+ const newBacklinkPath = this.map.get(backlinkPath) ?? backlinkPath;
626
+ const linkJsonToPathMap = combinedBacklinksMap.get(newBacklinkPath) ?? /* @__PURE__ */ new Map();
627
+ combinedBacklinksMap.set(newBacklinkPath, linkJsonToPathMap);
628
+ for (const link of links) {
629
+ linkJsonToPathMap.set((0, import_ObjectUtils.toJson)(link), path);
630
+ }
440
631
  }
441
632
  }
633
+ keys() {
634
+ return this.map.keys();
635
+ }
636
+ set(oldPath, newPath) {
637
+ this.map.set(oldPath, newPath);
638
+ }
442
639
  }
443
- function isNoteEx(app, path) {
444
- const settings = getSettings(app);
445
- return settings.isNote?.(path) ?? false;
446
- }
447
- function logRegisteredHandlers(app) {
448
- const renameDeleteHandlersMap = getRenameDeleteHandlersMap(app);
449
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:logRegisteredHandlers")(
450
- `Plugins with registered rename/delete handlers: ${JSON.stringify(Array.from(renameDeleteHandlersMap.keys()))}`
451
- );
452
- }
453
- function makeKey(oldPath, newPath) {
454
- return `${oldPath} -> ${newPath}`;
455
- }
456
- async function refreshLinks(app, oldPath, newPath, oldPathBacklinksMap, oldPathLinks) {
457
- const cache = app.metadataCache.getCache(oldPath) ?? app.metadataCache.getCache(newPath);
458
- const oldPathLinksRefreshed = cache ? (0, import_MetadataCache.getAllLinks)(cache) : [];
459
- const fakeOldFile = (0, import_FileSystem.getFile)(app, oldPath, true);
460
- let oldPathBacklinksMapRefreshed = /* @__PURE__ */ new Map();
461
- await (0, import_MetadataCache.tempRegisterFilesAndRun)(app, [fakeOldFile], async () => {
462
- oldPathBacklinksMapRefreshed = (await (0, import_MetadataCache.getBacklinksForFileSafe)(app, fakeOldFile)).data;
463
- });
464
- for (const link of oldPathLinksRefreshed) {
465
- if (oldPathLinks.includes(link)) {
466
- continue;
467
- }
468
- oldPathLinks.push(link);
469
- }
470
- for (const [backlinkPath, refreshedLinks] of oldPathBacklinksMapRefreshed.entries()) {
471
- let oldLinks = oldPathBacklinksMap.get(backlinkPath);
472
- if (!oldLinks) {
473
- oldLinks = [];
474
- oldPathBacklinksMap.set(backlinkPath, oldLinks);
475
- }
476
- for (const link of refreshedLinks) {
477
- if (oldLinks.includes(link)) {
478
- continue;
640
+ class SettingsManager {
641
+ constructor(app) {
642
+ this.app = app;
643
+ this.renameDeleteHandlersMap = (0, import_App.getObsidianDevUtilsState)(app, "renameDeleteHandlersMap", /* @__PURE__ */ new Map()).value;
644
+ }
645
+ renameDeleteHandlersMap;
646
+ getSettings() {
647
+ const settingsBuilders = Array.from(this.renameDeleteHandlersMap.values()).reverse();
648
+ const settings = {};
649
+ settings.isNote = (path) => (0, import_FileSystem.isNote)(this.app, path);
650
+ settings.isPathIgnored = () => false;
651
+ for (const settingsBuilder of settingsBuilders) {
652
+ const newSettings = settingsBuilder();
653
+ settings.shouldDeleteConflictingAttachments ||= newSettings.shouldDeleteConflictingAttachments ?? false;
654
+ if (newSettings.emptyAttachmentFolderBehavior) {
655
+ settings.emptyAttachmentFolderBehavior ??= newSettings.emptyAttachmentFolderBehavior;
479
656
  }
480
- oldLinks.push(link);
657
+ settings.shouldHandleDeletions ||= newSettings.shouldHandleDeletions ?? false;
658
+ settings.shouldHandleRenames ||= newSettings.shouldHandleRenames ?? false;
659
+ settings.shouldRenameAttachmentFiles ||= newSettings.shouldRenameAttachmentFiles ?? false;
660
+ settings.shouldRenameAttachmentFolder ||= newSettings.shouldRenameAttachmentFolder ?? false;
661
+ settings.shouldUpdateFileNameAliases ||= newSettings.shouldUpdateFileNameAliases ?? false;
662
+ const isPathIgnored = settings.isPathIgnored;
663
+ settings.isPathIgnored = (path) => isPathIgnored(path) || (newSettings.isPathIgnored?.(path) ?? false);
664
+ const currentIsNote = settings.isNote;
665
+ settings.isNote = (path) => currentIsNote(path) && (newSettings.isNote?.(path) ?? true);
481
666
  }
667
+ settings.emptyAttachmentFolderBehavior ??= "Keep" /* Keep */;
668
+ return settings;
482
669
  }
483
- }
484
- async function renameHandled(app, oldPath, newPath) {
485
- newPath = (0, import_Vault.getSafeRenamePath)(app, oldPath, newPath);
486
- if (oldPath === newPath) {
487
- return newPath;
670
+ isNoteEx(path) {
671
+ const settings = this.getSettings();
672
+ return settings.isNote?.(path) ?? false;
488
673
  }
489
- const key = makeKey(oldPath, newPath);
490
- handledRenames.add(key);
491
- newPath = await (0, import_Vault.renameSafe)(app, oldPath, newPath);
492
- return newPath;
493
674
  }
494
- async function runAsyncLinkUpdate(app, next, linkUpdatesHandler) {
495
- await next.call(app.fileManager, wrappedHandler);
496
- async function wrappedHandler(linkUpdates) {
497
- let isRenameCalled = false;
498
- const eventRef = app.vault.on("rename", () => {
499
- isRenameCalled = true;
500
- });
501
- try {
502
- await linkUpdatesHandler(linkUpdates);
503
- } finally {
504
- app.vault.offref(eventRef);
505
- }
506
- const settings = getSettings(app);
507
- if (isRenameCalled && settings.shouldHandleRenames) {
508
- (0, import_Array.filterInPlace)(
509
- linkUpdates,
510
- (linkUpdate) => {
511
- if (settings.isPathIgnored?.(linkUpdate.sourceFile.path)) {
512
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:runAsyncLinkUpdate")(
513
- `Roll back to default link update of source file ${linkUpdate.sourceFile.path} as the path is ignored.`
514
- );
515
- return true;
516
- }
517
- if (settings.isPathIgnored?.(linkUpdate.resolvedFile.path)) {
518
- (0, import_Debug.getLibDebugger)("RenameDeleteHandler:runAsyncLinkUpdate")(
519
- `Roll back to default link update of resolved file ${linkUpdate.resolvedFile.path} as the path is ignored.`
520
- );
521
- return true;
522
- }
523
- if (!app.internalPlugins.getEnabledPluginById(import_implementations.InternalPluginName.Canvas)) {
524
- return false;
525
- }
526
- if (app.plugins.getPlugin("backlink-cache")) {
527
- return false;
528
- }
529
- if (linkUpdate.sourceFile.extension === "canvas") {
530
- return true;
531
- }
532
- if (linkUpdate.resolvedFile.extension === "canvas") {
533
- return true;
534
- }
535
- return false;
536
- }
537
- );
675
+ function registerRenameDeleteHandlers(plugin, settingsBuilder) {
676
+ new Registry(plugin, settingsBuilder, new SettingsManager(plugin.app)).register();
677
+ }
678
+ async function cleanupParentFolders(app, settings, parentFolderPaths, notePath) {
679
+ if (settings.emptyAttachmentFolderBehavior === "Keep" /* Keep */) {
680
+ return;
681
+ }
682
+ for (const parentFolderPath of parentFolderPaths) {
683
+ switch (settings.emptyAttachmentFolderBehavior) {
684
+ case "Delete" /* Delete */:
685
+ await (0, import_VaultEx.deleteSafe)(app, parentFolderPath, notePath, void 0, true);
686
+ break;
687
+ case "DeleteWithEmptyParents" /* DeleteWithEmptyParents */:
688
+ await (0, import_VaultEx.deleteEmptyFolderHierarchy)(app, parentFolderPath);
689
+ break;
690
+ default:
691
+ break;
538
692
  }
539
693
  }
540
694
  }
541
- function shouldInvokeHandler(plugin) {
542
- const app = plugin.app;
543
- const pluginId = plugin.manifest.id;
544
- const renameDeleteHandlerPluginIds = getRenameDeleteHandlersMap(app);
545
- const mainPluginId = Array.from(renameDeleteHandlerPluginIds.keys())[0];
546
- if (mainPluginId !== pluginId) {
547
- return false;
548
- }
549
- return true;
550
- }
551
695
  // Annotate the CommonJS export names for ESM import in node:
552
696
  0 && (module.exports = {
553
697
  EmptyAttachmentFolderBehavior,
554
698
  registerRenameDeleteHandlers
555
699
  });
556
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL1JlbmFtZURlbGV0ZUhhbmRsZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKlxuICogQ29udGFpbnMgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIGhhbmRsaW5nIHJlbmFtZSBhbmQgZGVsZXRlIGV2ZW50cyBpbiBPYnNpZGlhbi5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7XG4gIEFwcCxcbiAgQ2FjaGVkTWV0YWRhdGEsXG4gIEZpbGVNYW5hZ2VyLFxuICBQbHVnaW4sXG4gIFJlZmVyZW5jZSxcbiAgVEFic3RyYWN0RmlsZSxcbiAgVEZpbGVcbn0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHR5cGUge1xuICBMaW5rVXBkYXRlLFxuICBMaW5rVXBkYXRlc0hhbmRsZXJcbn0gZnJvbSAnb2JzaWRpYW4tdHlwaW5ncyc7XG5cbmltcG9ydCB7IFZhdWx0IH0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHsgSW50ZXJuYWxQbHVnaW5OYW1lIH0gZnJvbSAnb2JzaWRpYW4tdHlwaW5ncy9pbXBsZW1lbnRhdGlvbnMnO1xuXG5pbXBvcnQgdHlwZSB7XG4gIFVwZGF0ZUxpbmtPcHRpb25zLFxuICBVcGRhdGVMaW5rc0luRmlsZU9wdGlvbnNcbn0gZnJvbSAnLi9MaW5rLnRzJztcblxuaW1wb3J0IHsgYWJvcnRTaWduYWxOZXZlciB9IGZyb20gJy4uL0Fib3J0Q29udHJvbGxlci50cyc7XG5pbXBvcnQgeyBmaWx0ZXJJblBsYWNlIH0gZnJvbSAnLi4vQXJyYXkudHMnO1xuaW1wb3J0IHsgZ2V0TGliRGVidWdnZXIgfSBmcm9tICcuLi9EZWJ1Zy50cyc7XG5pbXBvcnQge1xuICBub3JtYWxpemVPcHRpb25hbFByb3BlcnRpZXMsXG4gIHRvSnNvblxufSBmcm9tICcuLi9PYmplY3RVdGlscy50cyc7XG5pbXBvcnQge1xuICBiYXNlbmFtZSxcbiAgZGlybmFtZSxcbiAgZXh0bmFtZSxcbiAgam9pbixcbiAgcmVsYXRpdmVcbn0gZnJvbSAnLi4vUGF0aC50cyc7XG5pbXBvcnQgeyBnZXRPYnNpZGlhbkRldlV0aWxzU3RhdGUgfSBmcm9tICcuL0FwcC50cyc7XG5pbXBvcnQge1xuICBBdHRhY2htZW50UGF0aENvbnRleHQsXG4gIGdldEF0dGFjaG1lbnRGaWxlUGF0aCxcbiAgZ2V0QXR0YWNobWVudEZvbGRlclBhdGgsXG4gIGhhc093bkF0dGFjaG1lbnRGb2xkZXJcbn0gZnJvbSAnLi9BdHRhY2htZW50UGF0aC50cyc7XG5pbXBvcnQge1xuICBnZXRGaWxlLFxuICBnZXRGaWxlT3JOdWxsLFxuICBnZXRGb2xkZXJPck51bGwsXG4gIGlzRmlsZSxcbiAgaXNNYXJrZG93bkZpbGUsXG4gIGlzTm90ZVxufSBmcm9tICcuL0ZpbGVTeXN0ZW0udHMnO1xuaW1wb3J0IHtcbiAgZWRpdExpbmtzLFxuICBleHRyYWN0TGlua0ZpbGUsXG4gIHVwZGF0ZUxpbmssXG4gIHVwZGF0ZUxpbmtzSW5GaWxlXG59IGZyb20gJy4vTGluay50cyc7XG5pbXBvcnQge1xuICBnZXRBbGxMaW5rcyxcbiAgZ2V0QmFja2xpbmtzRm9yRmlsZU9yUGF0aCxcbiAgZ2V0QmFja2xpbmtzRm9yRmlsZVNhZmUsXG4gIHRlbXBSZWdpc3RlckZpbGVzQW5kUnVuXG59IGZyb20gJy4vTWV0YWRhdGFDYWNoZS50cyc7XG5pbXBvcnQgeyByZWdpc3RlclBhdGNoIH0gZnJvbSAnLi9Nb25rZXlBcm91bmQudHMnO1xuaW1wb3J0IHsgYWRkVG9RdWV1ZSB9IGZyb20gJy4vUXVldWUudHMnO1xuaW1wb3J0IHtcbiAgZ2V0U2FmZVJlbmFtZVBhdGgsXG4gIHJlbmFtZVNhZmVcbn0gZnJvbSAnLi9WYXVsdC50cyc7XG5pbXBvcnQge1xuICBkZWxldGVFbXB0eUZvbGRlckhpZXJhcmNoeSxcbiAgZGVsZXRlU2FmZVxufSBmcm9tICcuL1ZhdWx0RXgudHMnO1xuXG5jb25zdCBkZWxldGVkTWV0YWRhdGFDYWNoZU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBDYWNoZWRNZXRhZGF0YT4oKTtcbmNvbnN0IGhhbmRsZWRSZW5hbWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5jb25zdCBpbnRlcnJ1cHRlZFJlbmFtZXNNYXAgPSBuZXcgTWFwPHN0cmluZywgSW50ZXJydXB0ZWRSZW5hbWVbXT4oKTtcblxuLyoqXG4gKiBBIGJlaGF2aW9yIG9mIHRoZSByZW5hbWUvZGVsZXRlIGhhbmRsZXIgd2hlbiBkZWxldGluZyBlbXB0eSBhdHRhY2htZW50IGZvbGRlcnMuXG4gKi9cbmV4cG9ydCBlbnVtIEVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yIHtcbiAgLyoqXG4gICAqIERlbGV0ZSB0aGUgZW1wdHkgYXR0YWNobWVudCBmb2xkZXIuXG4gICAqL1xuICBEZWxldGUgPSAnRGVsZXRlJyxcblxuICAvKipcbiAgICogRGVsZXRlIHRoZSBlbXB0eSBhdHRhY2htZW50IGZvbGRlciBhbmQgYWxsIGl0cyBlbXB0eSBwYXJlbnRzLlxuICAgKi9cbiAgRGVsZXRlV2l0aEVtcHR5UGFyZW50cyA9ICdEZWxldGVXaXRoRW1wdHlQYXJlbnRzJyxcblxuICAvKipcbiAgICogS2VlcCB0aGUgZW1wdHkgYXR0YWNobWVudCBmb2xkZXIuXG4gICAqL1xuICBLZWVwID0gJ0tlZXAnXG59XG5cbi8qKlxuICogU2V0dGluZ3MgZm9yIHRoZSByZW5hbWUvZGVsZXRlIGhhbmRsZXIuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVuYW1lRGVsZXRlSGFuZGxlclNldHRpbmdzIHtcbiAgLyoqXG4gICAqIEEgYmVoYXZpb3Igb2YgdGhlIHJlbmFtZS9kZWxldGUgaGFuZGxlciB3aGVuIGRlbGV0aW5nIGVtcHR5IGF0dGFjaG1lbnQgZm9sZGVycy5cbiAgICovXG4gIGVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yOiBFbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvcjtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgcGF0aCBpcyBhIG5vdGUuXG4gICAqL1xuICBpc05vdGUocGF0aDogc3RyaW5nKTogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBpZ25vcmUgdGhlIHBhdGguXG4gICAqL1xuICBpc1BhdGhJZ25vcmVkKHBhdGg6IHN0cmluZyk6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZGVsZXRlIGNvbmZsaWN0aW5nIGF0dGFjaG1lbnRzLlxuICAgKi9cbiAgc2hvdWxkRGVsZXRlQ29uZmxpY3RpbmdBdHRhY2htZW50czogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBoYW5kbGUgZGVsZXRpb25zLlxuICAgKi9cbiAgc2hvdWxkSGFuZGxlRGVsZXRpb25zOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGhhbmRsZSByZW5hbWVzLlxuICAgKi9cbiAgc2hvdWxkSGFuZGxlUmVuYW1lczogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byByZW5hbWUgYXR0YWNobWVudCBmaWxlcyB3aGVuIGEgbm90ZSBpcyByZW5hbWVkLlxuICAgKi9cbiAgc2hvdWxkUmVuYW1lQXR0YWNobWVudEZpbGVzOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHJlbmFtZSBhdHRhY2htZW50IGZvbGRlciB3aGVuIGEgbm90ZSBpcyByZW5hbWVkLlxuICAgKi9cbiAgc2hvdWxkUmVuYW1lQXR0YWNobWVudEZvbGRlcjogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byB1cGRhdGUgZmlsZSBuYW1lIGFsaWFzZXMgd2hlbiBhIG5vdGUgaXMgcmVuYW1lZC5cbiAgICovXG4gIHNob3VsZFVwZGF0ZUZpbGVOYW1lQWxpYXNlczogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIEFib3J0YWJsZVBsdWdpbiBleHRlbmRzIFBsdWdpbiB7XG4gIGFib3J0U2lnbmFsPzogQWJvcnRTaWduYWw7XG59XG5cbmludGVyZmFjZSBJbnRlcnJ1cHRlZFJlbmFtZSB7XG4gIGNvbWJpbmVkQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PjtcbiAgb2xkUGF0aDogc3RyaW5nO1xufVxuXG50eXBlIFJ1bkFzeW5jTGlua1VwZGF0ZUZuID0gRmlsZU1hbmFnZXJbJ3J1bkFzeW5jTGlua1VwZGF0ZSddO1xuXG4vKipcbiAqIFJlZ2lzdGVycyB0aGUgcmVuYW1lL2RlbGV0ZSBoYW5kbGVycy5cbiAqXG4gKiBAcGFyYW0gcGx1Z2luIC0gVGhlIHBsdWdpbiBpbnN0YW5jZS5cbiAqIEBwYXJhbSBzZXR0aW5nc0J1aWxkZXIgLSBBIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgc2V0dGluZ3MgZm9yIHRoZSByZW5hbWUgZGVsZXRlIGhhbmRsZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlclJlbmFtZURlbGV0ZUhhbmRsZXJzKHBsdWdpbjogQWJvcnRhYmxlUGx1Z2luLCBzZXR0aW5nc0J1aWxkZXI6ICgpID0+IFBhcnRpYWw8UmVuYW1lRGVsZXRlSGFuZGxlclNldHRpbmdzPik6IHZvaWQge1xuICBjb25zdCByZW5hbWVEZWxldGVIYW5kbGVyc01hcCA9IGdldFJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwKHBsdWdpbi5hcHApO1xuICBjb25zdCBwbHVnaW5JZCA9IHBsdWdpbi5tYW5pZmVzdC5pZDtcblxuICByZW5hbWVEZWxldGVIYW5kbGVyc01hcC5zZXQocGx1Z2luSWQsIHNldHRpbmdzQnVpbGRlcik7XG4gIGxvZ1JlZ2lzdGVyZWRIYW5kbGVycyhwbHVnaW4uYXBwKTtcblxuICBwbHVnaW4ucmVnaXN0ZXIoKCkgPT4ge1xuICAgIHJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwLmRlbGV0ZShwbHVnaW5JZCk7XG4gICAgbG9nUmVnaXN0ZXJlZEhhbmRsZXJzKHBsdWdpbi5hcHApO1xuICB9KTtcblxuICBjb25zdCBhcHAgPSBwbHVnaW4uYXBwO1xuICBjb25zdCBhYm9ydFNpZ25hbCA9IHBsdWdpbi5hYm9ydFNpZ25hbCA/PyBhYm9ydFNpZ25hbE5ldmVyKCk7XG5cbiAgcGx1Z2luLnJlZ2lzdGVyRXZlbnQoXG4gICAgYXBwLnZhdWx0Lm9uKCdkZWxldGUnLCAoZmlsZSkgPT4ge1xuICAgICAgaGFuZGxlRGVsZXRlSWZFbmFibGVkKHBsdWdpbiwgZmlsZSwgYWJvcnRTaWduYWwpO1xuICAgIH0pXG4gICk7XG5cbiAgcGx1Z2luLnJlZ2lzdGVyRXZlbnQoXG4gICAgYXBwLnZhdWx0Lm9uKCdyZW5hbWUnLCAoZmlsZSwgb2xkUGF0aCkgPT4ge1xuICAgICAgaGFuZGxlUmVuYW1lSWZFbmFibGVkKHBsdWdpbiwgZmlsZSwgb2xkUGF0aCwgYWJvcnRTaWduYWwpO1xuICAgIH0pXG4gICk7XG5cbiAgcGx1Z2luLnJlZ2lzdGVyRXZlbnQoXG4gICAgYXBwLm1ldGFkYXRhQ2FjaGUub24oJ2RlbGV0ZWQnLCAoZmlsZSwgcHJldkNhY2hlKSA9PiB7XG4gICAgICBoYW5kbGVNZXRhZGF0YURlbGV0ZWRJZkVuYWJsZWQocGx1Z2luLCBmaWxlLCBwcmV2Q2FjaGUpO1xuICAgIH0pXG4gICk7XG5cbiAgcmVnaXN0ZXJQYXRjaChwbHVnaW4sIGFwcC5maWxlTWFuYWdlciwge1xuICAgIHJ1bkFzeW5jTGlua1VwZGF0ZTogKG5leHQ6IFJ1bkFzeW5jTGlua1VwZGF0ZUZuKTogUnVuQXN5bmNMaW5rVXBkYXRlRm4gPT4ge1xuICAgICAgcmV0dXJuIChsaW5rVXBkYXRlc0hhbmRsZXIpID0+IHJ1bkFzeW5jTGlua1VwZGF0ZShhcHAsIG5leHQsIGxpbmtVcGRhdGVzSGFuZGxlcik7XG4gICAgfVxuICB9KTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2xlYW51cFBhcmVudEZvbGRlcnMoYXBwOiBBcHAsIHBhcmVudEZvbGRlclBhdGhzOiBzdHJpbmdbXSwgbm90ZVBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBzZXR0aW5ncyA9IGdldFNldHRpbmdzKGFwcCk7XG4gIGlmIChzZXR0aW5ncy5lbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvciA9PT0gRW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3IuS2VlcCkge1xuICAgIHJldHVybjtcbiAgfVxuICBmb3IgKGNvbnN0IHBhcmVudEZvbGRlclBhdGggb2YgcGFyZW50Rm9sZGVyUGF0aHMpIHtcbiAgICBzd2l0Y2ggKHNldHRpbmdzLmVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yKSB7XG4gICAgICBjYXNlIEVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yLkRlbGV0ZTpcbiAgICAgICAgYXdhaXQgZGVsZXRlU2FmZShhcHAsIHBhcmVudEZvbGRlclBhdGgsIG5vdGVQYXRoLCB1bmRlZmluZWQsIHRydWUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgRW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3IuRGVsZXRlV2l0aEVtcHR5UGFyZW50czpcbiAgICAgICAgYXdhaXQgZGVsZXRlRW1wdHlGb2xkZXJIaWVyYXJjaHkoYXBwLCBwYXJlbnRGb2xkZXJQYXRoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gY29udGludWVJbnRlcnJ1cHRlZFJlbmFtZXMoXG4gIGFwcDogQXBwLFxuICBvbGRQYXRoOiBzdHJpbmcsXG4gIG5ld1BhdGg6IHN0cmluZyxcbiAgb2xkUGF0aEJhY2tsaW5rc01hcDogTWFwPHN0cmluZywgUmVmZXJlbmNlW10+LFxuICBvbGRQYXRoTGlua3M6IFJlZmVyZW5jZVtdXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgaW50ZXJydXB0ZWRSZW5hbWVzID0gaW50ZXJydXB0ZWRSZW5hbWVzTWFwLmdldChvbGRQYXRoKTtcbiAgaWYgKGludGVycnVwdGVkUmVuYW1lcykge1xuICAgIGludGVycnVwdGVkUmVuYW1lc01hcC5kZWxldGUob2xkUGF0aCk7XG4gICAgZm9yIChjb25zdCBpbnRlcnJ1cHRlZFJlbmFtZSBvZiBpbnRlcnJ1cHRlZFJlbmFtZXMpIHtcbiAgICAgIGF3YWl0IGhhbmRsZVJlbmFtZUFzeW5jKGFwcCwgaW50ZXJydXB0ZWRSZW5hbWUub2xkUGF0aCwgbmV3UGF0aCwgb2xkUGF0aEJhY2tsaW5rc01hcCwgb2xkUGF0aExpbmtzLCBpbnRlcnJ1cHRlZFJlbmFtZS5jb21iaW5lZEJhY2tsaW5rc01hcCk7XG4gICAgfVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGZpbGxSZW5hbWVNYXAoXG4gIGFwcDogQXBwLFxuICBvbGRQYXRoOiBzdHJpbmcsXG4gIG5ld1BhdGg6IHN0cmluZyxcbiAgcmVuYW1lTWFwOiBNYXA8c3RyaW5nLCBzdHJpbmc+LFxuICBvbGRQYXRoTGlua3M6IFJlZmVyZW5jZVtdLFxuICBhYm9ydFNpZ25hbDogQWJvcnRTaWduYWxcbik6IFByb21pc2U8dm9pZD4ge1xuICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICByZW5hbWVNYXAuc2V0KG9sZFBhdGgsIG5ld1BhdGgpO1xuXG4gIGlmICghaXNOb3RlRXgoYXBwLCBvbGRQYXRoKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHNldHRpbmdzID0gZ2V0U2V0dGluZ3MoYXBwKTtcblxuICBjb25zdCBvbGRBdHRhY2htZW50Rm9sZGVyUGF0aCA9IGF3YWl0IGdldEF0dGFjaG1lbnRGb2xkZXJQYXRoKGFwcCwgb2xkUGF0aCwgQXR0YWNobWVudFBhdGhDb250ZXh0LlJlbmFtZU5vdGUpO1xuICBjb25zdCBuZXdBdHRhY2htZW50Rm9sZGVyUGF0aCA9IHNldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGb2xkZXJcbiAgICA/IGF3YWl0IGdldEF0dGFjaG1lbnRGb2xkZXJQYXRoKGFwcCwgbmV3UGF0aCwgQXR0YWNobWVudFBhdGhDb250ZXh0LlJlbmFtZU5vdGUpXG4gICAgOiBvbGRBdHRhY2htZW50Rm9sZGVyUGF0aDtcblxuICBjb25zdCBpc09sZEF0dGFjaG1lbnRGb2xkZXJBdFJvb3QgPSBvbGRBdHRhY2htZW50Rm9sZGVyUGF0aCA9PT0gJy8nO1xuXG4gIGNvbnN0IG9sZEF0dGFjaG1lbnRGb2xkZXIgPSBnZXRGb2xkZXJPck51bGwoYXBwLCBvbGRBdHRhY2htZW50Rm9sZGVyUGF0aCk7XG5cbiAgaWYgKCFvbGRBdHRhY2htZW50Rm9sZGVyKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKG9sZEF0dGFjaG1lbnRGb2xkZXJQYXRoID09PSBuZXdBdHRhY2htZW50Rm9sZGVyUGF0aCAmJiAhc2V0dGluZ3Muc2hvdWxkUmVuYW1lQXR0YWNobWVudEZpbGVzKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3Qgb2xkQXR0YWNobWVudEZpbGVzOiBURmlsZVtdID0gW107XG5cbiAgaWYgKGF3YWl0IGhhc093bkF0dGFjaG1lbnRGb2xkZXIoYXBwLCBvbGRQYXRoLCBBdHRhY2htZW50UGF0aENvbnRleHQuUmVuYW1lTm90ZSkpIHtcbiAgICBWYXVsdC5yZWN1cnNlQ2hpbGRyZW4ob2xkQXR0YWNobWVudEZvbGRlciwgKG9sZEF0dGFjaG1lbnRGaWxlKSA9PiB7XG4gICAgICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgaWYgKGlzRmlsZShvbGRBdHRhY2htZW50RmlsZSkpIHtcbiAgICAgICAgb2xkQXR0YWNobWVudEZpbGVzLnB1c2gob2xkQXR0YWNobWVudEZpbGUpO1xuICAgICAgfVxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGZvciAoY29uc3Qgb2xkUGF0aExpbmsgb2Ygb2xkUGF0aExpbmtzKSB7XG4gICAgICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgY29uc3Qgb2xkQXR0YWNobWVudEZpbGUgPSBleHRyYWN0TGlua0ZpbGUoYXBwLCBvbGRQYXRoTGluaywgb2xkUGF0aCk7XG4gICAgICBpZiAoIW9sZEF0dGFjaG1lbnRGaWxlKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNPbGRBdHRhY2htZW50Rm9sZGVyQXRSb290IHx8IG9sZEF0dGFjaG1lbnRGaWxlLnBhdGguc3RhcnRzV2l0aChvbGRBdHRhY2htZW50Rm9sZGVyUGF0aCkpIHtcbiAgICAgICAgY29uc3Qgb2xkQXR0YWNobWVudEJhY2tsaW5rcyA9IGF3YWl0IGdldEJhY2tsaW5rc0ZvckZpbGVTYWZlKGFwcCwgb2xkQXR0YWNobWVudEZpbGUpO1xuICAgICAgICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgICBpZiAob2xkQXR0YWNobWVudEJhY2tsaW5rcy5rZXlzKCkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgb2xkQXR0YWNobWVudEZpbGVzLnB1c2gob2xkQXR0YWNobWVudEZpbGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCBvbGRBdHRhY2htZW50RmlsZSBvZiBvbGRBdHRhY2htZW50RmlsZXMpIHtcbiAgICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgIGlmIChpc05vdGVFeChhcHAsIG9sZEF0dGFjaG1lbnRGaWxlLnBhdGgpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBsZXQgbmV3QXR0YWNobWVudEZpbGVQYXRoOiBzdHJpbmc7XG4gICAgaWYgKHNldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGaWxlcykge1xuICAgICAgbmV3QXR0YWNobWVudEZpbGVQYXRoID0gYXdhaXQgZ2V0QXR0YWNobWVudEZpbGVQYXRoKHtcbiAgICAgICAgYXBwLFxuICAgICAgICBhdHRhY2htZW50UGF0aE9yRmlsZTogb2xkQXR0YWNobWVudEZpbGUsXG4gICAgICAgIGNvbnRleHQ6IEF0dGFjaG1lbnRQYXRoQ29udGV4dC5SZW5hbWVOb3RlLFxuICAgICAgICBub3RlUGF0aE9yRmlsZTogbmV3UGF0aCxcbiAgICAgICAgb2xkTm90ZVBhdGhPckZpbGU6IG9sZFBhdGgsXG4gICAgICAgIHNob3VsZFNraXBEdXBsaWNhdGVDaGVjazogdHJ1ZVxuICAgICAgfSk7XG4gICAgICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCByZWxhdGl2ZVBhdGggPSBpc09sZEF0dGFjaG1lbnRGb2xkZXJBdFJvb3QgPyBvbGRBdHRhY2htZW50RmlsZS5wYXRoIDogcmVsYXRpdmUob2xkQXR0YWNobWVudEZvbGRlclBhdGgsIG9sZEF0dGFjaG1lbnRGaWxlLnBhdGgpO1xuICAgICAgY29uc3QgbmV3Rm9sZGVyID0gam9pbihuZXdBdHRhY2htZW50Rm9sZGVyUGF0aCwgZGlybmFtZShyZWxhdGl2ZVBhdGgpKTtcbiAgICAgIG5ld0F0dGFjaG1lbnRGaWxlUGF0aCA9IGpvaW4obmV3Rm9sZGVyLCBvbGRBdHRhY2htZW50RmlsZS5uYW1lKTtcbiAgICB9XG5cbiAgICBpZiAob2xkQXR0YWNobWVudEZpbGUucGF0aCA9PT0gbmV3QXR0YWNobWVudEZpbGVQYXRoKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKHNldHRpbmdzLnNob3VsZERlbGV0ZUNvbmZsaWN0aW5nQXR0YWNobWVudHMpIHtcbiAgICAgIGNvbnN0IG5ld0F0dGFjaG1lbnRGaWxlID0gZ2V0RmlsZU9yTnVsbChhcHAsIG5ld0F0dGFjaG1lbnRGaWxlUGF0aCk7XG4gICAgICBpZiAobmV3QXR0YWNobWVudEZpbGUpIHtcbiAgICAgICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6ZmlsbFJlbmFtZU1hcCcpKGBSZW1vdmluZyBjb25mbGljdGluZyBhdHRhY2htZW50ICR7bmV3QXR0YWNobWVudEZpbGUucGF0aH0uYCk7XG4gICAgICAgIGF3YWl0IGFwcC5maWxlTWFuYWdlci50cmFzaEZpbGUobmV3QXR0YWNobWVudEZpbGUpO1xuICAgICAgICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBkaXIgPSBkaXJuYW1lKG5ld0F0dGFjaG1lbnRGaWxlUGF0aCk7XG4gICAgICBjb25zdCBleHQgPSBleHRuYW1lKG5ld0F0dGFjaG1lbnRGaWxlUGF0aCk7XG4gICAgICBjb25zdCBiYXNlTmFtZSA9IGJhc2VuYW1lKG5ld0F0dGFjaG1lbnRGaWxlUGF0aCwgZXh0KTtcbiAgICAgIG5ld0F0dGFjaG1lbnRGaWxlUGF0aCA9IGFwcC52YXVsdC5nZXRBdmFpbGFibGVQYXRoKGpvaW4oZGlyLCBiYXNlTmFtZSksIGV4dC5zbGljZSgxKSk7XG4gICAgfVxuICAgIHJlbmFtZU1hcC5zZXQob2xkQXR0YWNobWVudEZpbGUucGF0aCwgbmV3QXR0YWNobWVudEZpbGVQYXRoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRSZW5hbWVEZWxldGVIYW5kbGVyc01hcChhcHA6IEFwcCk6IE1hcDxzdHJpbmcsICgpID0+IFBhcnRpYWw8UmVuYW1lRGVsZXRlSGFuZGxlclNldHRpbmdzPj4ge1xuICByZXR1cm4gZ2V0T2JzaWRpYW5EZXZVdGlsc1N0YXRlKGFwcCwgJ3JlbmFtZURlbGV0ZUhhbmRsZXJzTWFwJywgbmV3IE1hcDxzdHJpbmcsICgpID0+IFBhcnRpYWw8UmVuYW1lRGVsZXRlSGFuZGxlclNldHRpbmdzPj4oKSkudmFsdWU7XG59XG5cbmZ1bmN0aW9uIGdldFNldHRpbmdzKGFwcDogQXBwKTogUGFydGlhbDxSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3M+IHtcbiAgY29uc3QgcmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAgPSBnZXRSZW5hbWVEZWxldGVIYW5kbGVyc01hcChhcHApO1xuICBjb25zdCBzZXR0aW5nc0J1aWxkZXJzID0gQXJyYXkuZnJvbShyZW5hbWVEZWxldGVIYW5kbGVyc01hcC52YWx1ZXMoKSkucmV2ZXJzZSgpO1xuXG4gIGNvbnN0IHNldHRpbmdzOiBQYXJ0aWFsPFJlbmFtZURlbGV0ZUhhbmRsZXJTZXR0aW5ncz4gPSB7fTtcbiAgc2V0dGluZ3MuaXNOb3RlID0gKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4gPT4gaXNOb3RlKGFwcCwgcGF0aCk7XG4gIHNldHRpbmdzLmlzUGF0aElnbm9yZWQgPSAoKTogYm9vbGVhbiA9PiBmYWxzZTtcblxuICBmb3IgKGNvbnN0IHNldHRpbmdzQnVpbGRlciBvZiBzZXR0aW5nc0J1aWxkZXJzKSB7XG4gICAgY29uc3QgbmV3U2V0dGluZ3MgPSBzZXR0aW5nc0J1aWxkZXIoKTtcbiAgICBzZXR0aW5ncy5zaG91bGREZWxldGVDb25mbGljdGluZ0F0dGFjaG1lbnRzIHx8PSBuZXdTZXR0aW5ncy5zaG91bGREZWxldGVDb25mbGljdGluZ0F0dGFjaG1lbnRzID8/IGZhbHNlO1xuICAgIGlmIChuZXdTZXR0aW5ncy5lbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvcikge1xuICAgICAgc2V0dGluZ3MuZW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3IgPz89IG5ld1NldHRpbmdzLmVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yO1xuICAgIH1cbiAgICBzZXR0aW5ncy5zaG91bGRIYW5kbGVEZWxldGlvbnMgfHw9IG5ld1NldHRpbmdzLnNob3VsZEhhbmRsZURlbGV0aW9ucyA/PyBmYWxzZTtcbiAgICBzZXR0aW5ncy5zaG91bGRIYW5kbGVSZW5hbWVzIHx8PSBuZXdTZXR0aW5ncy5zaG91bGRIYW5kbGVSZW5hbWVzID8/IGZhbHNlO1xuICAgIHNldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGaWxlcyB8fD0gbmV3U2V0dGluZ3Muc2hvdWxkUmVuYW1lQXR0YWNobWVudEZpbGVzID8/IGZhbHNlO1xuICAgIHNldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGb2xkZXIgfHw9IG5ld1NldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGb2xkZXIgPz8gZmFsc2U7XG4gICAgc2V0dGluZ3Muc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhc2VzIHx8PSBuZXdTZXR0aW5ncy5zaG91bGRVcGRhdGVGaWxlTmFtZUFsaWFzZXMgPz8gZmFsc2U7XG4gICAgY29uc3QgaXNQYXRoSWdub3JlZCA9IHNldHRpbmdzLmlzUGF0aElnbm9yZWQ7XG4gICAgc2V0dGluZ3MuaXNQYXRoSWdub3JlZCA9IChwYXRoOiBzdHJpbmcpOiBib29sZWFuID0+IGlzUGF0aElnbm9yZWQocGF0aCkgfHwgKG5ld1NldHRpbmdzLmlzUGF0aElnbm9yZWQ/LihwYXRoKSA/PyBmYWxzZSk7XG4gICAgY29uc3QgY3VycmVudElzTm90ZSA9IHNldHRpbmdzLmlzTm90ZTtcbiAgICBzZXR0aW5ncy5pc05vdGUgPSAocGF0aDogc3RyaW5nKTogYm9vbGVhbiA9PiBjdXJyZW50SXNOb3RlKHBhdGgpICYmIChuZXdTZXR0aW5ncy5pc05vdGU/LihwYXRoKSA/PyB0cnVlKTtcbiAgfVxuXG4gIHNldHRpbmdzLmVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yID8/PSBFbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvci5LZWVwO1xuICByZXR1cm4gc2V0dGluZ3M7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZUNhc2VDb2xsaXNpb24oXG4gIGFwcDogQXBwLFxuICBvbGRQYXRoOiBzdHJpbmcsXG4gIG5ld1BhdGg6IHN0cmluZyxcbiAgb2xkUGF0aEJhY2tsaW5rc01hcDogTWFwPHN0cmluZywgUmVmZXJlbmNlW10+LFxuICBvbGRQYXRoTGlua3M6IFJlZmVyZW5jZVtdXG4pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgaWYgKCFhcHAudmF1bHQuYWRhcHRlci5pbnNlbnNpdGl2ZSB8fCBvbGRQYXRoLnRvTG93ZXJDYXNlKCkgIT09IG5ld1BhdGgudG9Mb3dlckNhc2UoKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGNvbnN0IHRlbXBQYXRoID0gam9pbihkaXJuYW1lKG5ld1BhdGgpLCBgX190ZW1wX18ke2Jhc2VuYW1lKG5ld1BhdGgpfWApO1xuICBhd2FpdCByZW5hbWVIYW5kbGVkKGFwcCwgbmV3UGF0aCwgdGVtcFBhdGgpO1xuICBhd2FpdCBoYW5kbGVSZW5hbWVBc3luYyhhcHAsIG9sZFBhdGgsIHRlbXBQYXRoLCBvbGRQYXRoQmFja2xpbmtzTWFwLCBvbGRQYXRoTGlua3MpO1xuICBhd2FpdCBhcHAudmF1bHQucmVuYW1lKGdldEZpbGUoYXBwLCB0ZW1wUGF0aCksIG5ld1BhdGgpO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gaGFuZGxlRGVsZXRlKGFwcDogQXBwLCBwYXRoOiBzdHJpbmcsIGFib3J0U2lnbmFsOiBBYm9ydFNpZ25hbCk6IFByb21pc2U8dm9pZD4ge1xuICBhYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpoYW5kbGVEZWxldGUnKShgSGFuZGxlIERlbGV0ZSAke3BhdGh9YCk7XG4gIGlmICghaXNOb3RlRXgoYXBwLCBwYXRoKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHNldHRpbmdzID0gZ2V0U2V0dGluZ3MoYXBwKTtcbiAgaWYgKCFzZXR0aW5ncy5zaG91bGRIYW5kbGVEZWxldGlvbnMpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoc2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKHBhdGgpKSB7XG4gICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6aGFuZGxlRGVsZXRlJykoYFNraXBwaW5nIGRlbGV0ZSBoYW5kbGVyIG9mICR7cGF0aH0gYXMgdGhlIHBhdGggaXMgaWdub3JlZC5gKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBjYWNoZSA9IGRlbGV0ZWRNZXRhZGF0YUNhY2hlTWFwLmdldChwYXRoKTtcbiAgZGVsZXRlZE1ldGFkYXRhQ2FjaGVNYXAuZGVsZXRlKHBhdGgpO1xuICBjb25zdCBwYXJlbnRGb2xkZXJQYXRocyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBpZiAoY2FjaGUpIHtcbiAgICBjb25zdCBsaW5rcyA9IGdldEFsbExpbmtzKGNhY2hlKTtcblxuICAgIGZvciAoY29uc3QgbGluayBvZiBsaW5rcykge1xuICAgICAgY29uc3QgYXR0YWNobWVudEZpbGUgPSBleHRyYWN0TGlua0ZpbGUoYXBwLCBsaW5rLCBwYXRoKTtcbiAgICAgIGlmICghYXR0YWNobWVudEZpbGUpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc05vdGVFeChhcHAsIGF0dGFjaG1lbnRGaWxlLnBhdGgpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBwYXJlbnRGb2xkZXJQYXRocy5hZGQoYXR0YWNobWVudEZpbGUucGFyZW50Py5wYXRoID8/ICcnKTtcbiAgICAgIGF3YWl0IGRlbGV0ZVNhZmUoYXBwLCBhdHRhY2htZW50RmlsZSwgcGF0aCwgZmFsc2UsIHNldHRpbmdzLmVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yICE9PSBFbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvci5LZWVwKTtcbiAgICAgIGFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgfVxuICB9XG5cbiAgYXdhaXQgY2xlYW51cFBhcmVudEZvbGRlcnMoYXBwLCBBcnJheS5mcm9tKHBhcmVudEZvbGRlclBhdGhzKSwgcGF0aCk7XG4gIGFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG5cbiAgY29uc3QgYXR0YWNobWVudEZvbGRlclBhdGggPSBhd2FpdCBnZXRBdHRhY2htZW50Rm9sZGVyUGF0aChhcHAsIHBhdGgsIEF0dGFjaG1lbnRQYXRoQ29udGV4dC5EZWxldGVOb3RlKTtcbiAgY29uc3QgYXR0YWNobWVudEZvbGRlciA9IGdldEZvbGRlck9yTnVsbChhcHAsIGF0dGFjaG1lbnRGb2xkZXJQYXRoKTtcblxuICBpZiAoIWF0dGFjaG1lbnRGb2xkZXIpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIShhd2FpdCBoYXNPd25BdHRhY2htZW50Rm9sZGVyKGFwcCwgcGF0aCwgQXR0YWNobWVudFBhdGhDb250ZXh0LkRlbGV0ZU5vdGUpKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG5cbiAgYXdhaXQgZGVsZXRlU2FmZShhcHAsIGF0dGFjaG1lbnRGb2xkZXIsIHBhdGgsIGZhbHNlLCBzZXR0aW5ncy5lbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvciAhPT0gRW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3IuS2VlcCk7XG4gIGFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZURlbGV0ZUlmRW5hYmxlZChwbHVnaW46IEFib3J0YWJsZVBsdWdpbiwgZmlsZTogVEFic3RyYWN0RmlsZSwgYWJvcnRTaWduYWw6IEFib3J0U2lnbmFsKTogdm9pZCB7XG4gIGNvbnN0IGFwcCA9IHBsdWdpbi5hcHA7XG4gIGlmICghc2hvdWxkSW52b2tlSGFuZGxlcihwbHVnaW4pKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnN0IHBhdGggPSBmaWxlLnBhdGg7XG4gIGFkZFRvUXVldWUoYXBwLCAoYWJvcnRTaWduYWwyKSA9PiBoYW5kbGVEZWxldGUoYXBwLCBwYXRoLCBhYm9ydFNpZ25hbDIpLCBhYm9ydFNpZ25hbCk7XG59XG5cbmZ1bmN0aW9uIGhhbmRsZU1ldGFkYXRhRGVsZXRlZChhcHA6IEFwcCwgZmlsZTogVEFic3RyYWN0RmlsZSwgcHJldkNhY2hlOiBDYWNoZWRNZXRhZGF0YSB8IG51bGwpOiB2b2lkIHtcbiAgY29uc3Qgc2V0dGluZ3MgPSBnZXRTZXR0aW5ncyhhcHApO1xuICBpZiAoc2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKGZpbGUucGF0aCkpIHtcbiAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpoYW5kbGVNZXRhZGF0YURlbGV0ZWQnKShgU2tpcHBpbmcgbWV0YWRhdGEgZGVsZXRlIGhhbmRsZXIgb2YgJHtmaWxlLnBhdGh9IGFzIHRoZSBwYXRoIGlzIGlnbm9yZWQuYCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFzZXR0aW5ncy5zaG91bGRIYW5kbGVEZWxldGlvbnMpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGlzTWFya2Rvd25GaWxlKGFwcCwgZmlsZSkgJiYgcHJldkNhY2hlKSB7XG4gICAgZGVsZXRlZE1ldGFkYXRhQ2FjaGVNYXAuc2V0KGZpbGUucGF0aCwgcHJldkNhY2hlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBoYW5kbGVNZXRhZGF0YURlbGV0ZWRJZkVuYWJsZWQocGx1Z2luOiBQbHVnaW4sIGZpbGU6IFRBYnN0cmFjdEZpbGUsIHByZXZDYWNoZTogQ2FjaGVkTWV0YWRhdGEgfCBudWxsKTogdm9pZCB7XG4gIGlmICghc2hvdWxkSW52b2tlSGFuZGxlcihwbHVnaW4pKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGhhbmRsZU1ldGFkYXRhRGVsZXRlZChwbHVnaW4uYXBwLCBmaWxlLCBwcmV2Q2FjaGUpO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVSZW5hbWUoYXBwOiBBcHAsIG9sZFBhdGg6IHN0cmluZywgbmV3UGF0aDogc3RyaW5nLCBhYm9ydFNpZ25hbDogQWJvcnRTaWduYWwpOiB2b2lkIHtcbiAgY29uc3Qga2V5ID0gbWFrZUtleShvbGRQYXRoLCBuZXdQYXRoKTtcbiAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6aGFuZGxlUmVuYW1lJykoYEhhbmRsZSBSZW5hbWUgJHtrZXl9YCk7XG4gIGlmIChoYW5kbGVkUmVuYW1lcy5oYXMoa2V5KSkge1xuICAgIGhhbmRsZWRSZW5hbWVzLmRlbGV0ZShrZXkpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHNldHRpbmdzID0gZ2V0U2V0dGluZ3MoYXBwKTtcbiAgaWYgKCFzZXR0aW5ncy5zaG91bGRIYW5kbGVSZW5hbWVzKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKHNldHRpbmdzLmlzUGF0aElnbm9yZWQ/LihvbGRQYXRoKSkge1xuICAgIGdldExpYkRlYnVnZ2VyKCdSZW5hbWVEZWxldGVIYW5kbGVyOmhhbmRsZVJlbmFtZScpKGBTa2lwcGluZyByZW5hbWUgaGFuZGxlciBvZiBvbGQgcGF0aCAke29sZFBhdGh9IGFzIHRoZSBwYXRoIGlzIGlnbm9yZWQuYCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKHNldHRpbmdzLmlzUGF0aElnbm9yZWQ/LihuZXdQYXRoKSkge1xuICAgIGdldExpYkRlYnVnZ2VyKCdSZW5hbWVEZWxldGVIYW5kbGVyOmhhbmRsZVJlbmFtZScpKGBTa2lwcGluZyByZW5hbWUgaGFuZGxlciBvZiBuZXcgcGF0aCAke25ld1BhdGh9IGFzIHRoZSBwYXRoIGlzIGlnbm9yZWQuYCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgY2FjaGUgPSBhcHAubWV0YWRhdGFDYWNoZS5nZXRDYWNoZShvbGRQYXRoKSA/PyBhcHAubWV0YWRhdGFDYWNoZS5nZXRDYWNoZShuZXdQYXRoKTtcbiAgY29uc3Qgb2xkUGF0aExpbmtzID0gY2FjaGUgPyBnZXRBbGxMaW5rcyhjYWNoZSkgOiBbXTtcbiAgY29uc3Qgb2xkUGF0aEJhY2tsaW5rc01hcCA9IGdldEJhY2tsaW5rc0ZvckZpbGVPclBhdGgoYXBwLCBvbGRQYXRoKS5kYXRhO1xuICBhZGRUb1F1ZXVlKGFwcCwgKGFib3J0U2lnbmFsMikgPT4gaGFuZGxlUmVuYW1lQXN5bmMoYXBwLCBvbGRQYXRoLCBuZXdQYXRoLCBvbGRQYXRoQmFja2xpbmtzTWFwLCBvbGRQYXRoTGlua3MsIHVuZGVmaW5lZCwgYWJvcnRTaWduYWwyKSwgYWJvcnRTaWduYWwpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVSZW5hbWVBc3luYyhcbiAgYXBwOiBBcHAsXG4gIG9sZFBhdGg6IHN0cmluZyxcbiAgbmV3UGF0aDogc3RyaW5nLFxuICBvbGRQYXRoQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBSZWZlcmVuY2VbXT4sXG4gIG9sZFBhdGhMaW5rczogUmVmZXJlbmNlW10sXG4gIGludGVycnVwdGVkQ29tYmluZWRCYWNrbGlua3NNYXA/OiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PixcbiAgYWJvcnRTaWduYWw/OiBBYm9ydFNpZ25hbFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGFib3J0U2lnbmFsID8/PSBhYm9ydFNpZ25hbE5ldmVyKCk7XG4gIGFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gIGF3YWl0IGNvbnRpbnVlSW50ZXJydXB0ZWRSZW5hbWVzKGFwcCwgb2xkUGF0aCwgbmV3UGF0aCwgb2xkUGF0aEJhY2tsaW5rc01hcCwgb2xkUGF0aExpbmtzKTtcbiAgYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgYXdhaXQgcmVmcmVzaExpbmtzKGFwcCwgb2xkUGF0aCwgbmV3UGF0aCwgb2xkUGF0aEJhY2tsaW5rc01hcCwgb2xkUGF0aExpbmtzKTtcbiAgYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgaWYgKGF3YWl0IGhhbmRsZUNhc2VDb2xsaXNpb24oYXBwLCBvbGRQYXRoLCBuZXdQYXRoLCBvbGRQYXRoQmFja2xpbmtzTWFwLCBvbGRQYXRoTGlua3MpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcblxuICB0cnkge1xuICAgIGNvbnN0IHJlbmFtZU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgYXdhaXQgZmlsbFJlbmFtZU1hcChhcHAsIG9sZFBhdGgsIG5ld1BhdGgsIHJlbmFtZU1hcCwgb2xkUGF0aExpbmtzLCBhYm9ydFNpZ25hbCk7XG4gICAgYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcblxuICAgIGNvbnN0IGNvbWJpbmVkQmFja2xpbmtzTWFwID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIHN0cmluZz4+KCk7XG4gICAgaW5pdEJhY2tsaW5rc01hcChvbGRQYXRoQmFja2xpbmtzTWFwLCByZW5hbWVNYXAsIGNvbWJpbmVkQmFja2xpbmtzTWFwLCBvbGRQYXRoKTtcblxuICAgIGZvciAoY29uc3QgYXR0YWNobWVudE9sZFBhdGggb2YgcmVuYW1lTWFwLmtleXMoKSkge1xuICAgICAgaWYgKGF0dGFjaG1lbnRPbGRQYXRoID09PSBvbGRQYXRoKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgYXR0YWNobWVudE9sZFBhdGhCYWNrbGlua3NNYXAgPSAoYXdhaXQgZ2V0QmFja2xpbmtzRm9yRmlsZVNhZmUoYXBwLCBhdHRhY2htZW50T2xkUGF0aCkpLmRhdGE7XG4gICAgICBpbml0QmFja2xpbmtzTWFwKGF0dGFjaG1lbnRPbGRQYXRoQmFja2xpbmtzTWFwLCByZW5hbWVNYXAsIGNvbWJpbmVkQmFja2xpbmtzTWFwLCBhdHRhY2htZW50T2xkUGF0aCk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFyZW50Rm9sZGVyUGF0aHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICAgIGZvciAoY29uc3QgW29sZEF0dGFjaG1lbnRQYXRoLCBuZXdBdHRhY2htZW50UGF0aF0gb2YgcmVuYW1lTWFwLmVudHJpZXMoKSkge1xuICAgICAgaWYgKG9sZEF0dGFjaG1lbnRQYXRoID09PSBvbGRQYXRoKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgY29uc3QgZml4ZWROZXdBdHRhY2htZW50UGF0aCA9IGF3YWl0IHJlbmFtZUhhbmRsZWQoYXBwLCBvbGRBdHRhY2htZW50UGF0aCwgbmV3QXR0YWNobWVudFBhdGgpO1xuICAgICAgcmVuYW1lTWFwLnNldChvbGRBdHRhY2htZW50UGF0aCwgZml4ZWROZXdBdHRhY2htZW50UGF0aCk7XG4gICAgICBwYXJlbnRGb2xkZXJQYXRocy5hZGQoZGlybmFtZShvbGRBdHRhY2htZW50UGF0aCkpO1xuICAgIH1cblxuICAgIGF3YWl0IGNsZWFudXBQYXJlbnRGb2xkZXJzKGFwcCwgQXJyYXkuZnJvbShwYXJlbnRGb2xkZXJQYXRocyksIG9sZFBhdGgpO1xuICAgIGFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgY29uc3Qgc2V0dGluZ3MgPSBnZXRTZXR0aW5ncyhhcHApO1xuXG4gICAgZm9yIChcbiAgICAgIGNvbnN0IFtuZXdCYWNrbGlua1BhdGgsIGxpbmtKc29uVG9QYXRoTWFwXSBvZiBBcnJheS5mcm9tKGNvbWJpbmVkQmFja2xpbmtzTWFwLmVudHJpZXMoKSkuY29uY2F0KFxuICAgICAgICBBcnJheS5mcm9tKGludGVycnVwdGVkQ29tYmluZWRCYWNrbGlua3NNYXA/LmVudHJpZXMoKSA/PyBbXSlcbiAgICAgIClcbiAgICApIHtcbiAgICAgIGF3YWl0IGVkaXRMaW5rcyhhcHAsIG5ld0JhY2tsaW5rUGF0aCwgKGxpbmspID0+IHtcbiAgICAgICAgY29uc3Qgb2xkQXR0YWNobWVudFBhdGggPSBsaW5rSnNvblRvUGF0aE1hcC5nZXQodG9Kc29uKGxpbmspKTtcbiAgICAgICAgaWYgKCFvbGRBdHRhY2htZW50UGF0aCkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5ld0F0dGFjaG1lbnRQYXRoID0gcmVuYW1lTWFwLmdldChvbGRBdHRhY2htZW50UGF0aCk7XG4gICAgICAgIGlmICghbmV3QXR0YWNobWVudFBhdGgpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdXBkYXRlTGluayhub3JtYWxpemVPcHRpb25hbFByb3BlcnRpZXM8VXBkYXRlTGlua09wdGlvbnM+KHtcbiAgICAgICAgICBhcHAsXG4gICAgICAgICAgbGluayxcbiAgICAgICAgICBuZXdTb3VyY2VQYXRoT3JGaWxlOiBuZXdCYWNrbGlua1BhdGgsXG4gICAgICAgICAgbmV3VGFyZ2V0UGF0aE9yRmlsZTogbmV3QXR0YWNobWVudFBhdGgsXG4gICAgICAgICAgb2xkVGFyZ2V0UGF0aE9yRmlsZTogb2xkQXR0YWNobWVudFBhdGgsXG4gICAgICAgICAgc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhczogc2V0dGluZ3Muc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhc2VzXG4gICAgICAgIH0pKTtcbiAgICAgIH0sIHtcbiAgICAgICAgc2hvdWxkRmFpbE9uTWlzc2luZ0ZpbGU6IGZhbHNlXG4gICAgICB9KTtcbiAgICAgIGFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgfVxuXG4gICAgaWYgKGlzTm90ZUV4KGFwcCwgbmV3UGF0aCkpIHtcbiAgICAgIGF3YWl0IHVwZGF0ZUxpbmtzSW5GaWxlKG5vcm1hbGl6ZU9wdGlvbmFsUHJvcGVydGllczxVcGRhdGVMaW5rc0luRmlsZU9wdGlvbnM+KHtcbiAgICAgICAgYXBwLFxuICAgICAgICBuZXdTb3VyY2VQYXRoT3JGaWxlOiBuZXdQYXRoLFxuICAgICAgICBvbGRTb3VyY2VQYXRoT3JGaWxlOiBvbGRQYXRoLFxuICAgICAgICBzaG91bGRGYWlsT25NaXNzaW5nRmlsZTogZmFsc2UsXG4gICAgICAgIHNob3VsZFVwZGF0ZUZpbGVOYW1lQWxpYXM6IHNldHRpbmdzLnNob3VsZFVwZGF0ZUZpbGVOYW1lQWxpYXNlc1xuICAgICAgfSkpO1xuICAgICAgYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICB9XG5cbiAgICBpZiAoIWdldEZpbGVPck51bGwoYXBwLCBuZXdQYXRoKSkge1xuICAgICAgbGV0IGludGVycnVwdGVkUmVuYW1lcyA9IGludGVycnVwdGVkUmVuYW1lc01hcC5nZXQobmV3UGF0aCk7XG4gICAgICBpZiAoIWludGVycnVwdGVkUmVuYW1lcykge1xuICAgICAgICBpbnRlcnJ1cHRlZFJlbmFtZXMgPSBbXTtcbiAgICAgICAgaW50ZXJydXB0ZWRSZW5hbWVzTWFwLnNldChuZXdQYXRoLCBpbnRlcnJ1cHRlZFJlbmFtZXMpO1xuICAgICAgfVxuICAgICAgaW50ZXJydXB0ZWRSZW5hbWVzLnB1c2goe1xuICAgICAgICBjb21iaW5lZEJhY2tsaW5rc01hcCxcbiAgICAgICAgb2xkUGF0aFxuICAgICAgfSk7XG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIGNvbnN0IG9ycGhhbktleXMgPSBBcnJheS5mcm9tKGhhbmRsZWRSZW5hbWVzKTtcbiAgICBhZGRUb1F1ZXVlKGFwcCwgKCkgPT4ge1xuICAgICAgZm9yIChjb25zdCBrZXkgb2Ygb3JwaGFuS2V5cykge1xuICAgICAgICBoYW5kbGVkUmVuYW1lcy5kZWxldGUoa2V5KTtcbiAgICAgIH1cbiAgICB9LCBhYm9ydFNpZ25hbCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaGFuZGxlUmVuYW1lSWZFbmFibGVkKHBsdWdpbjogUGx1Z2luLCBmaWxlOiBUQWJzdHJhY3RGaWxlLCBvbGRQYXRoOiBzdHJpbmcsIGFib3J0U2lnbmFsOiBBYm9ydFNpZ25hbCk6IHZvaWQge1xuICBpZiAoIXNob3VsZEludm9rZUhhbmRsZXIocGx1Z2luKSkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoIWlzRmlsZShmaWxlKSkge1xuICAgIHJldHVybjtcbiAgfVxuICBjb25zdCBuZXdQYXRoID0gZmlsZS5wYXRoO1xuICBoYW5kbGVSZW5hbWUocGx1Z2luLmFwcCwgb2xkUGF0aCwgbmV3UGF0aCwgYWJvcnRTaWduYWwpO1xufVxuXG5mdW5jdGlvbiBpbml0QmFja2xpbmtzTWFwKFxuICBzaW5nbGVCYWNrbGlua3NNYXA6IE1hcDxzdHJpbmcsIFJlZmVyZW5jZVtdPixcbiAgcmVuYW1lTWFwOiBNYXA8c3RyaW5nLCBzdHJpbmc+LFxuICBjb21iaW5lZEJhY2tsaW5rc01hcDogTWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nPj4sXG4gIHBhdGg6IHN0cmluZ1xuKTogdm9pZCB7XG4gIGZvciAoY29uc3QgW2JhY2tsaW5rUGF0aCwgbGlua3NdIG9mIHNpbmdsZUJhY2tsaW5rc01hcC5lbnRyaWVzKCkpIHtcbiAgICBjb25zdCBuZXdCYWNrbGlua1BhdGggPSByZW5hbWVNYXAuZ2V0KGJhY2tsaW5rUGF0aCkgPz8gYmFja2xpbmtQYXRoO1xuICAgIGNvbnN0IGxpbmtKc29uVG9QYXRoTWFwID0gY29tYmluZWRCYWNrbGlua3NNYXAuZ2V0KG5ld0JhY2tsaW5rUGF0aCkgPz8gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgICBjb21iaW5lZEJhY2tsaW5rc01hcC5zZXQobmV3QmFja2xpbmtQYXRoLCBsaW5rSnNvblRvUGF0aE1hcCk7XG4gICAgZm9yIChjb25zdCBsaW5rIG9mIGxpbmtzKSB7XG4gICAgICBsaW5rSnNvblRvUGF0aE1hcC5zZXQodG9Kc29uKGxpbmspLCBwYXRoKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNOb3RlRXgoYXBwOiBBcHAsIHBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBzZXR0aW5ncyA9IGdldFNldHRpbmdzKGFwcCk7XG4gIHJldHVybiBzZXR0aW5ncy5pc05vdGU/LihwYXRoKSA/PyBmYWxzZTtcbn1cblxuZnVuY3Rpb24gbG9nUmVnaXN0ZXJlZEhhbmRsZXJzKGFwcDogQXBwKTogdm9pZCB7XG4gIGNvbnN0IHJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwID0gZ2V0UmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAoYXBwKTtcbiAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6bG9nUmVnaXN0ZXJlZEhhbmRsZXJzJykoXG4gICAgYFBsdWdpbnMgd2l0aCByZWdpc3RlcmVkIHJlbmFtZS9kZWxldGUgaGFuZGxlcnM6ICR7SlNPTi5zdHJpbmdpZnkoQXJyYXkuZnJvbShyZW5hbWVEZWxldGVIYW5kbGVyc01hcC5rZXlzKCkpKX1gXG4gICk7XG59XG5cbmZ1bmN0aW9uIG1ha2VLZXkob2xkUGF0aDogc3RyaW5nLCBuZXdQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7b2xkUGF0aH0gLT4gJHtuZXdQYXRofWA7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlZnJlc2hMaW5rcyhcbiAgYXBwOiBBcHAsXG4gIG9sZFBhdGg6IHN0cmluZyxcbiAgbmV3UGF0aDogc3RyaW5nLFxuICBvbGRQYXRoQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBSZWZlcmVuY2VbXT4sXG4gIG9sZFBhdGhMaW5rczogUmVmZXJlbmNlW11cbik6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjYWNoZSA9IGFwcC5tZXRhZGF0YUNhY2hlLmdldENhY2hlKG9sZFBhdGgpID8/IGFwcC5tZXRhZGF0YUNhY2hlLmdldENhY2hlKG5ld1BhdGgpO1xuICBjb25zdCBvbGRQYXRoTGlua3NSZWZyZXNoZWQgPSBjYWNoZSA/IGdldEFsbExpbmtzKGNhY2hlKSA6IFtdO1xuICBjb25zdCBmYWtlT2xkRmlsZSA9IGdldEZpbGUoYXBwLCBvbGRQYXRoLCB0cnVlKTtcbiAgbGV0IG9sZFBhdGhCYWNrbGlua3NNYXBSZWZyZXNoZWQgPSBuZXcgTWFwPHN0cmluZywgUmVmZXJlbmNlW10+KCk7XG4gIGF3YWl0IHRlbXBSZWdpc3RlckZpbGVzQW5kUnVuKGFwcCwgW2Zha2VPbGRGaWxlXSwgYXN5bmMgKCkgPT4ge1xuICAgIG9sZFBhdGhCYWNrbGlua3NNYXBSZWZyZXNoZWQgPSAoYXdhaXQgZ2V0QmFja2xpbmtzRm9yRmlsZVNhZmUoYXBwLCBmYWtlT2xkRmlsZSkpLmRhdGE7XG4gIH0pO1xuXG4gIGZvciAoY29uc3QgbGluayBvZiBvbGRQYXRoTGlua3NSZWZyZXNoZWQpIHtcbiAgICBpZiAob2xkUGF0aExpbmtzLmluY2x1ZGVzKGxpbmspKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgb2xkUGF0aExpbmtzLnB1c2gobGluayk7XG4gIH1cblxuICBmb3IgKGNvbnN0IFtiYWNrbGlua1BhdGgsIHJlZnJlc2hlZExpbmtzXSBvZiBvbGRQYXRoQmFja2xpbmtzTWFwUmVmcmVzaGVkLmVudHJpZXMoKSkge1xuICAgIGxldCBvbGRMaW5rcyA9IG9sZFBhdGhCYWNrbGlua3NNYXAuZ2V0KGJhY2tsaW5rUGF0aCk7XG4gICAgaWYgKCFvbGRMaW5rcykge1xuICAgICAgb2xkTGlua3MgPSBbXTtcbiAgICAgIG9sZFBhdGhCYWNrbGlua3NNYXAuc2V0KGJhY2tsaW5rUGF0aCwgb2xkTGlua3MpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgbGluayBvZiByZWZyZXNoZWRMaW5rcykge1xuICAgICAgaWYgKG9sZExpbmtzLmluY2x1ZGVzKGxpbmspKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgb2xkTGlua3MucHVzaChsaW5rKTtcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmVuYW1lSGFuZGxlZChhcHA6IEFwcCwgb2xkUGF0aDogc3RyaW5nLCBuZXdQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBuZXdQYXRoID0gZ2V0U2FmZVJlbmFtZVBhdGgoYXBwLCBvbGRQYXRoLCBuZXdQYXRoKTtcbiAgaWYgKG9sZFBhdGggPT09IG5ld1BhdGgpIHtcbiAgICByZXR1cm4gbmV3UGF0aDtcbiAgfVxuICBjb25zdCBrZXkgPSBtYWtlS2V5KG9sZFBhdGgsIG5ld1BhdGgpO1xuICBoYW5kbGVkUmVuYW1lcy5hZGQoa2V5KTtcbiAgbmV3UGF0aCA9IGF3YWl0IHJlbmFtZVNhZmUoYXBwLCBvbGRQYXRoLCBuZXdQYXRoKTtcbiAgcmV0dXJuIG5ld1BhdGg7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJ1bkFzeW5jTGlua1VwZGF0ZShhcHA6IEFwcCwgbmV4dDogUnVuQXN5bmNMaW5rVXBkYXRlRm4sIGxpbmtVcGRhdGVzSGFuZGxlcjogTGlua1VwZGF0ZXNIYW5kbGVyKTogUHJvbWlzZTx2b2lkPiB7XG4gIGF3YWl0IG5leHQuY2FsbChhcHAuZmlsZU1hbmFnZXIsIHdyYXBwZWRIYW5kbGVyKTtcblxuICBhc3luYyBmdW5jdGlvbiB3cmFwcGVkSGFuZGxlcihsaW5rVXBkYXRlczogTGlua1VwZGF0ZVtdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGlzUmVuYW1lQ2FsbGVkID0gZmFsc2U7XG4gICAgY29uc3QgZXZlbnRSZWYgPSBhcHAudmF1bHQub24oJ3JlbmFtZScsICgpID0+IHtcbiAgICAgIGlzUmVuYW1lQ2FsbGVkID0gdHJ1ZTtcbiAgICB9KTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgbGlua1VwZGF0ZXNIYW5kbGVyKGxpbmtVcGRhdGVzKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXBwLnZhdWx0Lm9mZnJlZihldmVudFJlZik7XG4gICAgfVxuICAgIGNvbnN0IHNldHRpbmdzID0gZ2V0U2V0dGluZ3MoYXBwKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVubmVjZXNzYXJ5LWNvbmRpdGlvblxuICAgIGlmIChpc1JlbmFtZUNhbGxlZCAmJiBzZXR0aW5ncy5zaG91bGRIYW5kbGVSZW5hbWVzKSB7XG4gICAgICBmaWx0ZXJJblBsYWNlKFxuICAgICAgICBsaW5rVXBkYXRlcyxcbiAgICAgICAgKGxpbmtVcGRhdGUpID0+IHtcbiAgICAgICAgICBpZiAoc2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKGxpbmtVcGRhdGUuc291cmNlRmlsZS5wYXRoKSkge1xuICAgICAgICAgICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6cnVuQXN5bmNMaW5rVXBkYXRlJykoXG4gICAgICAgICAgICAgIGBSb2xsIGJhY2sgdG8gZGVmYXVsdCBsaW5rIHVwZGF0ZSBvZiBzb3VyY2UgZmlsZSAke2xpbmtVcGRhdGUuc291cmNlRmlsZS5wYXRofSBhcyB0aGUgcGF0aCBpcyBpZ25vcmVkLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoc2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKGxpbmtVcGRhdGUucmVzb2x2ZWRGaWxlLnBhdGgpKSB7XG4gICAgICAgICAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpydW5Bc3luY0xpbmtVcGRhdGUnKShcbiAgICAgICAgICAgICAgYFJvbGwgYmFjayB0byBkZWZhdWx0IGxpbmsgdXBkYXRlIG9mIHJlc29sdmVkIGZpbGUgJHtsaW5rVXBkYXRlLnJlc29sdmVkRmlsZS5wYXRofSBhcyB0aGUgcGF0aCBpcyBpZ25vcmVkLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoIWFwcC5pbnRlcm5hbFBsdWdpbnMuZ2V0RW5hYmxlZFBsdWdpbkJ5SWQoSW50ZXJuYWxQbHVnaW5OYW1lLkNhbnZhcykpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoYXBwLnBsdWdpbnMuZ2V0UGx1Z2luKCdiYWNrbGluay1jYWNoZScpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGxpbmtVcGRhdGUuc291cmNlRmlsZS5leHRlbnNpb24gPT09ICdjYW52YXMnKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobGlua1VwZGF0ZS5yZXNvbHZlZEZpbGUuZXh0ZW5zaW9uID09PSAnY2FudmFzJykge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBzaG91bGRJbnZva2VIYW5kbGVyKHBsdWdpbjogUGx1Z2luKTogYm9vbGVhbiB7XG4gIGNvbnN0IGFwcCA9IHBsdWdpbi5hcHA7XG4gIGNvbnN0IHBsdWdpbklkID0gcGx1Z2luLm1hbmlmZXN0LmlkO1xuXG4gIGNvbnN0IHJlbmFtZURlbGV0ZUhhbmRsZXJQbHVnaW5JZHMgPSBnZXRSZW5hbWVEZWxldGVIYW5kbGVyc01hcChhcHApO1xuICBjb25zdCBtYWluUGx1Z2luSWQgPSBBcnJheS5mcm9tKHJlbmFtZURlbGV0ZUhhbmRsZXJQbHVnaW5JZHMua2V5cygpKVswXTtcbiAgaWYgKG1haW5QbHVnaW5JZCAhPT0gcGx1Z2luSWQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJu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QUFNLE1BQU0sUUFBUSxTQUFTLE9BQU87QUFDcEMsaUJBQWUsSUFBSSxHQUFHO0FBQ3RCLFlBQVUsVUFBTSx5QkFBVyxLQUFLLFNBQVMsT0FBTztBQUNoRCxTQUFPO0FBQ1Q7QUFFQSxlQUFlLG1CQUFtQixLQUFVLE1BQTRCLG9CQUF1RDtBQUM3SCxRQUFNLEtBQUssS0FBSyxJQUFJLGFBQWEsY0FBYztBQUUvQyxpQkFBZSxlQUFlLGFBQTBDO0FBQ3RFLFFBQUksaUJBQWlCO0FBQ3JCLFVBQU0sV0FBVyxJQUFJLE1BQU0sR0FBRyxVQUFVLE1BQU07QUFDNUMsdUJBQWlCO0FBQUEsSUFDbkIsQ0FBQztBQUNELFFBQUk7QUFDRixZQUFNLG1CQUFtQixXQUFXO0FBQUEsSUFDdEMsVUFBRTtBQUNBLFVBQUksTUFBTSxPQUFPLFFBQVE7QUFBQSxJQUMzQjtBQUNBLFVBQU0sV0FBVyxZQUFZLEdBQUc7QUFFaEMsUUFBSSxrQkFBa0IsU0FBUyxxQkFBcUI7QUFDbEQ7QUFBQSxRQUNFO0FBQUEsUUFDQSxDQUFDLGVBQWU7QUFDZCxjQUFJLFNBQVMsZ0JBQWdCLFdBQVcsV0FBVyxJQUFJLEdBQUc7QUFDeEQsNkNBQWUsd0NBQXdDO0FBQUEsY0FDckQsbURBQW1ELFdBQVcsV0FBVyxJQUFJO0FBQUEsWUFDL0U7QUFDQSxtQkFBTztBQUFBLFVBQ1Q7QUFFQSxjQUFJLFNBQVMsZ0JBQWdCLFdBQVcsYUFBYSxJQUFJLEdBQUc7QUFDMUQsNkNBQWUsd0NBQXdDO0FBQUEsY0FDckQscURBQXFELFdBQVcsYUFBYSxJQUFJO0FBQUEsWUFDbkY7QUFDQSxtQkFBTztBQUFBLFVBQ1Q7QUFFQSxjQUFJLENBQUMsSUFBSSxnQkFBZ0IscUJBQXFCLDBDQUFtQixNQUFNLEdBQUc7QUFDeEUsbUJBQU87QUFBQSxVQUNUO0FBRUEsY0FBSSxJQUFJLFFBQVEsVUFBVSxnQkFBZ0IsR0FBRztBQUMzQyxtQkFBTztBQUFBLFVBQ1Q7QUFFQSxjQUFJLFdBQVcsV0FBVyxjQUFjLFVBQVU7QUFDaEQsbUJBQU87QUFBQSxVQUNUO0FBRUEsY0FBSSxXQUFXLGFBQWEsY0FBYyxVQUFVO0FBQ2xELG1CQUFPO0FBQUEsVUFDVDtBQUVBLGlCQUFPO0FBQUEsUUFDVDtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGO0FBRUEsU0FBUyxvQkFBb0IsUUFBeUI7QUFDcEQsUUFBTSxNQUFNLE9BQU87QUFDbkIsUUFBTSxXQUFXLE9BQU8sU0FBUztBQUVqQyxRQUFNLCtCQUErQiwyQkFBMkIsR0FBRztBQUNuRSxRQUFNLGVBQWUsTUFBTSxLQUFLLDZCQUE2QixLQUFLLENBQUMsRUFBRSxDQUFDO0FBQ3RFLE1BQUksaUJBQWlCLFVBQVU7QUFDN0IsV0FBTztBQUFBLEVBQ1Q7QUFDQSxTQUFPO0FBQ1Q7IiwKICAibmFtZXMiOiBbIkVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yIl0KfQo=
700
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL29ic2lkaWFuL1JlbmFtZURlbGV0ZUhhbmRsZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQHBhY2thZ2VEb2N1bWVudGF0aW9uXG4gKlxuICogQ29udGFpbnMgdXRpbGl0eSBmdW5jdGlvbnMgZm9yIGhhbmRsaW5nIHJlbmFtZSBhbmQgZGVsZXRlIGV2ZW50cyBpbiBPYnNpZGlhbi5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7XG4gIEFwcCxcbiAgQ2FjaGVkTWV0YWRhdGEsXG4gIEZpbGVNYW5hZ2VyLFxuICBQbHVnaW4sXG4gIFJlZmVyZW5jZSxcbiAgVEFic3RyYWN0RmlsZSxcbiAgVEZpbGVcbn0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHR5cGUge1xuICBMaW5rVXBkYXRlLFxuICBMaW5rVXBkYXRlc0hhbmRsZXJcbn0gZnJvbSAnb2JzaWRpYW4tdHlwaW5ncyc7XG5cbmltcG9ydCB7IFZhdWx0IH0gZnJvbSAnb2JzaWRpYW4nO1xuaW1wb3J0IHsgSW50ZXJuYWxQbHVnaW5OYW1lIH0gZnJvbSAnb2JzaWRpYW4tdHlwaW5ncy9pbXBsZW1lbnRhdGlvbnMnO1xuXG5pbXBvcnQgdHlwZSB7XG4gIFVwZGF0ZUxpbmtPcHRpb25zLFxuICBVcGRhdGVMaW5rc0luRmlsZU9wdGlvbnNcbn0gZnJvbSAnLi9MaW5rLnRzJztcblxuaW1wb3J0IHsgYWJvcnRTaWduYWxOZXZlciB9IGZyb20gJy4uL0Fib3J0Q29udHJvbGxlci50cyc7XG5pbXBvcnQgeyBmaWx0ZXJJblBsYWNlIH0gZnJvbSAnLi4vQXJyYXkudHMnO1xuaW1wb3J0IHsgZ2V0TGliRGVidWdnZXIgfSBmcm9tICcuLi9EZWJ1Zy50cyc7XG5pbXBvcnQge1xuICBub3JtYWxpemVPcHRpb25hbFByb3BlcnRpZXMsXG4gIHRvSnNvblxufSBmcm9tICcuLi9PYmplY3RVdGlscy50cyc7XG5pbXBvcnQge1xuICBiYXNlbmFtZSxcbiAgZGlybmFtZSxcbiAgZXh0bmFtZSxcbiAgam9pbixcbiAgcmVsYXRpdmVcbn0gZnJvbSAnLi4vUGF0aC50cyc7XG5pbXBvcnQgeyBnZXRPYnNpZGlhbkRldlV0aWxzU3RhdGUgfSBmcm9tICcuL0FwcC50cyc7XG5pbXBvcnQge1xuICBBdHRhY2htZW50UGF0aENvbnRleHQsXG4gIGdldEF0dGFjaG1lbnRGaWxlUGF0aCxcbiAgZ2V0QXR0YWNobWVudEZvbGRlclBhdGgsXG4gIGhhc093bkF0dGFjaG1lbnRGb2xkZXJcbn0gZnJvbSAnLi9BdHRhY2htZW50UGF0aC50cyc7XG5pbXBvcnQge1xuICBDQU5WQVNfRklMRV9FWFRFTlNJT04sXG4gIGdldEZpbGUsXG4gIGdldEZpbGVPck51bGwsXG4gIGdldEZvbGRlck9yTnVsbCxcbiAgaXNGaWxlLFxuICBpc01hcmtkb3duRmlsZSxcbiAgaXNOb3RlXG59IGZyb20gJy4vRmlsZVN5c3RlbS50cyc7XG5pbXBvcnQge1xuICBlZGl0TGlua3MsXG4gIGV4dHJhY3RMaW5rRmlsZSxcbiAgdXBkYXRlTGluayxcbiAgdXBkYXRlTGlua3NJbkZpbGVcbn0gZnJvbSAnLi9MaW5rLnRzJztcbmltcG9ydCB7XG4gIGdldEFsbExpbmtzLFxuICBnZXRCYWNrbGlua3NGb3JGaWxlT3JQYXRoLFxuICBnZXRCYWNrbGlua3NGb3JGaWxlU2FmZSxcbiAgcmVnaXN0ZXJGaWxlQ2FjaGVGb3JOb25FeGlzdGluZ0ZpbGUsXG4gIHRlbXBSZWdpc3RlckZpbGVzQW5kUnVuLFxuICB0ZW1wUmVnaXN0ZXJGaWxlc0FuZFJ1bkFzeW5jLFxuICB1bnJlZ2lzdGVyRmlsZUNhY2hlRm9yTm9uRXhpc3RpbmdGaWxlXG59IGZyb20gJy4vTWV0YWRhdGFDYWNoZS50cyc7XG5pbXBvcnQgeyByZWdpc3RlclBhdGNoIH0gZnJvbSAnLi9Nb25rZXlBcm91bmQudHMnO1xuaW1wb3J0IHsgYWRkVG9RdWV1ZSB9IGZyb20gJy4vUXVldWUudHMnO1xuaW1wb3J0IHtcbiAgZ2V0U2FmZVJlbmFtZVBhdGgsXG4gIHJlbmFtZVNhZmVcbn0gZnJvbSAnLi9WYXVsdC50cyc7XG5pbXBvcnQge1xuICBkZWxldGVFbXB0eUZvbGRlckhpZXJhcmNoeSxcbiAgZGVsZXRlU2FmZVxufSBmcm9tICcuL1ZhdWx0RXgudHMnO1xuXG4vKipcbiAqIEEgYmVoYXZpb3Igb2YgdGhlIHJlbmFtZS9kZWxldGUgaGFuZGxlciB3aGVuIGRlbGV0aW5nIGVtcHR5IGF0dGFjaG1lbnQgZm9sZGVycy5cbiAqL1xuZXhwb3J0IGVudW0gRW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3Ige1xuICAvKipcbiAgICogRGVsZXRlIHRoZSBlbXB0eSBhdHRhY2htZW50IGZvbGRlci5cbiAgICovXG4gIERlbGV0ZSA9ICdEZWxldGUnLFxuXG4gIC8qKlxuICAgKiBEZWxldGUgdGhlIGVtcHR5IGF0dGFjaG1lbnQgZm9sZGVyIGFuZCBhbGwgaXRzIGVtcHR5IHBhcmVudHMuXG4gICAqL1xuICBEZWxldGVXaXRoRW1wdHlQYXJlbnRzID0gJ0RlbGV0ZVdpdGhFbXB0eVBhcmVudHMnLFxuXG4gIC8qKlxuICAgKiBLZWVwIHRoZSBlbXB0eSBhdHRhY2htZW50IGZvbGRlci5cbiAgICovXG4gIEtlZXAgPSAnS2VlcCdcbn1cblxuLyoqXG4gKiBTZXR0aW5ncyBmb3IgdGhlIHJlbmFtZS9kZWxldGUgaGFuZGxlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3Mge1xuICAvKipcbiAgICogQSBiZWhhdmlvciBvZiB0aGUgcmVuYW1lL2RlbGV0ZSBoYW5kbGVyIHdoZW4gZGVsZXRpbmcgZW1wdHkgYXR0YWNobWVudCBmb2xkZXJzLlxuICAgKi9cbiAgZW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3I6IEVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBwYXRoIGlzIGEgbm90ZS5cbiAgICovXG4gIGlzTm90ZShwYXRoOiBzdHJpbmcpOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGlnbm9yZSB0aGUgcGF0aC5cbiAgICovXG4gIGlzUGF0aElnbm9yZWQocGF0aDogc3RyaW5nKTogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0byBkZWxldGUgY29uZmxpY3RpbmcgYXR0YWNobWVudHMuXG4gICAqL1xuICBzaG91bGREZWxldGVDb25mbGljdGluZ0F0dGFjaG1lbnRzOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGhhbmRsZSBkZWxldGlvbnMuXG4gICAqL1xuICBzaG91bGRIYW5kbGVEZWxldGlvbnM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gaGFuZGxlIHJlbmFtZXMuXG4gICAqL1xuICBzaG91bGRIYW5kbGVSZW5hbWVzOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHJlbmFtZSBhdHRhY2htZW50IGZpbGVzIHdoZW4gYSBub3RlIGlzIHJlbmFtZWQuXG4gICAqL1xuICBzaG91bGRSZW5hbWVBdHRhY2htZW50RmlsZXM6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gcmVuYW1lIGF0dGFjaG1lbnQgZm9sZGVyIHdoZW4gYSBub3RlIGlzIHJlbmFtZWQuXG4gICAqL1xuICBzaG91bGRSZW5hbWVBdHRhY2htZW50Rm9sZGVyOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIHVwZGF0ZSBmaWxlIG5hbWUgYWxpYXNlcyB3aGVuIGEgbm90ZSBpcyByZW5hbWVkLlxuICAgKi9cbiAgc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhc2VzOiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgQWJvcnRhYmxlUGx1Z2luIGV4dGVuZHMgUGx1Z2luIHtcbiAgYWJvcnRTaWduYWw/OiBBYm9ydFNpZ25hbDtcbn1cblxuaW50ZXJmYWNlIEhhbmRsZWRSZW5hbWVLZXkge1xuICBuZXdQYXRoOiBzdHJpbmc7XG4gIG9sZFBhdGg6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIEludGVycnVwdGVkUmVuYW1lIHtcbiAgY29tYmluZWRCYWNrbGlua3NNYXA6IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIHN0cmluZz4+O1xuICBvbGRQYXRoOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBSZW5hbWVIYW5kbGVyT3B0aW9ucyB7XG4gIGFib3J0U2lnbmFsOiBBYm9ydFNpZ25hbDtcbiAgYXBwOiBBcHA7XG4gIGhhbmRsZWRSZW5hbWVzOiBIYW5kbGVkUmVuYW1lcztcbiAgaW50ZXJydXB0ZWRDb21iaW5lZEJhY2tsaW5rc01hcD86IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIHN0cmluZz4+O1xuICBpbnRlcnJ1cHRlZFJlbmFtZXNNYXA6IE1hcDxzdHJpbmcsIEludGVycnVwdGVkUmVuYW1lW10+O1xuICBuZXdQYXRoOiBzdHJpbmc7XG4gIG9sZENhY2hlOiBDYWNoZWRNZXRhZGF0YSB8IG51bGw7XG4gIG9sZFBhdGg6IHN0cmluZztcbiAgb2xkUGF0aEJhY2tsaW5rc01hcDogTWFwPHN0cmluZywgUmVmZXJlbmNlW10+O1xuICBzZXR0aW5nc01hbmFnZXI6IFNldHRpbmdzTWFuYWdlcjtcbn1cblxuaW50ZXJmYWNlIFJlbmFtZU1hcE9wdGlvbnMge1xuICBhYm9ydFNpZ25hbDogQWJvcnRTaWduYWw7XG4gIGFwcDogQXBwO1xuICBuZXdQYXRoOiBzdHJpbmc7XG4gIG9sZENhY2hlOiBDYWNoZWRNZXRhZGF0YSB8IG51bGw7XG4gIG9sZFBhdGg6IHN0cmluZztcbiAgc2V0dGluZ3NNYW5hZ2VyOiBTZXR0aW5nc01hbmFnZXI7XG59XG5cbnR5cGUgUnVuQXN5bmNMaW5rVXBkYXRlRm4gPSB7IHJlbmFtZURlbGV0ZUhhbmRsZXJQYXRjaGVkPzogYm9vbGVhbiB9ICYgRmlsZU1hbmFnZXJbJ3J1bkFzeW5jTGlua1VwZGF0ZSddO1xuXG5jbGFzcyBEZWxldGVIYW5kbGVyIHtcbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgYXBwOiBBcHAsXG4gICAgcHJpdmF0ZSByZWFkb25seSBmaWxlOiBUQWJzdHJhY3RGaWxlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgYWJvcnRTaWduYWw6IEFib3J0U2lnbmFsLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2V0dGluZ3NNYW5hZ2VyOiBTZXR0aW5nc01hbmFnZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBkZWxldGVkTWV0YWRhdGFDYWNoZU1hcDogTWFwPHN0cmluZywgQ2FjaGVkTWV0YWRhdGE+XG4gICkge1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGhhbmRsZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6aGFuZGxlRGVsZXRlJykoYEhhbmRsZSBEZWxldGUgJHt0aGlzLmZpbGUucGF0aH1gKTtcbiAgICBpZiAoIXRoaXMuc2V0dGluZ3NNYW5hZ2VyLmlzTm90ZUV4KHRoaXMuZmlsZS5wYXRoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHNldHRpbmdzID0gdGhpcy5zZXR0aW5nc01hbmFnZXIuZ2V0U2V0dGluZ3MoKTtcbiAgICBpZiAoIXNldHRpbmdzLnNob3VsZEhhbmRsZURlbGV0aW9ucykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChzZXR0aW5ncy5pc1BhdGhJZ25vcmVkPy4odGhpcy5maWxlLnBhdGgpKSB7XG4gICAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpoYW5kbGVEZWxldGUnKShgU2tpcHBpbmcgZGVsZXRlIGhhbmRsZXIgb2YgJHt0aGlzLmZpbGUucGF0aH0gYXMgdGhlIHBhdGggaXMgaWdub3JlZC5gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjYWNoZSA9IHRoaXMuZGVsZXRlZE1ldGFkYXRhQ2FjaGVNYXAuZ2V0KHRoaXMuZmlsZS5wYXRoKTtcbiAgICB0aGlzLmRlbGV0ZWRNZXRhZGF0YUNhY2hlTWFwLmRlbGV0ZSh0aGlzLmZpbGUucGF0aCk7XG4gICAgY29uc3QgcGFyZW50Rm9sZGVyUGF0aHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBpZiAoY2FjaGUpIHtcbiAgICAgIGNvbnN0IGxpbmtzID0gZ2V0QWxsTGlua3MoY2FjaGUpO1xuXG4gICAgICBmb3IgKGNvbnN0IGxpbmsgb2YgbGlua3MpIHtcbiAgICAgICAgY29uc3QgYXR0YWNobWVudEZpbGUgPSBleHRyYWN0TGlua0ZpbGUodGhpcy5hcHAsIGxpbmssIHRoaXMuZmlsZS5wYXRoKTtcbiAgICAgICAgaWYgKCFhdHRhY2htZW50RmlsZSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3NNYW5hZ2VyLmlzTm90ZUV4KGF0dGFjaG1lbnRGaWxlLnBhdGgpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBwYXJlbnRGb2xkZXJQYXRocy5hZGQoYXR0YWNobWVudEZpbGUucGFyZW50Py5wYXRoID8/ICcnKTtcbiAgICAgICAgYXdhaXQgZGVsZXRlU2FmZSh0aGlzLmFwcCwgYXR0YWNobWVudEZpbGUsIHRoaXMuZmlsZS5wYXRoLCBmYWxzZSwgc2V0dGluZ3MuZW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3IgIT09IEVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yLktlZXApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGF3YWl0IGNsZWFudXBQYXJlbnRGb2xkZXJzKHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpLCBBcnJheS5mcm9tKHBhcmVudEZvbGRlclBhdGhzKSwgdGhpcy5maWxlLnBhdGgpO1xuICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcblxuICAgIGNvbnN0IGF0dGFjaG1lbnRGb2xkZXJQYXRoID0gYXdhaXQgZ2V0QXR0YWNobWVudEZvbGRlclBhdGgodGhpcy5hcHAsIHRoaXMuZmlsZS5wYXRoLCBBdHRhY2htZW50UGF0aENvbnRleHQuRGVsZXRlTm90ZSk7XG4gICAgY29uc3QgYXR0YWNobWVudEZvbGRlciA9IGdldEZvbGRlck9yTnVsbCh0aGlzLmFwcCwgYXR0YWNobWVudEZvbGRlclBhdGgpO1xuXG4gICAgaWYgKCFhdHRhY2htZW50Rm9sZGVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCEoYXdhaXQgaGFzT3duQXR0YWNobWVudEZvbGRlcih0aGlzLmFwcCwgdGhpcy5maWxlLnBhdGgsIEF0dGFjaG1lbnRQYXRoQ29udGV4dC5EZWxldGVOb3RlKSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG5cbiAgICBhd2FpdCBkZWxldGVTYWZlKHRoaXMuYXBwLCBhdHRhY2htZW50Rm9sZGVyLCB0aGlzLmZpbGUucGF0aCwgZmFsc2UsIHNldHRpbmdzLmVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yICE9PSBFbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvci5LZWVwKTtcbiAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gIH1cbn1cblxuY2xhc3MgSGFuZGxlZFJlbmFtZXMge1xuICBwcml2YXRlIHJlYWRvbmx5IG1hcCA9IG5ldyBNYXA8c3RyaW5nLCBIYW5kbGVkUmVuYW1lS2V5PigpO1xuXG4gIHB1YmxpYyBhZGQob2xkUGF0aDogc3RyaW5nLCBuZXdQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLm1hcC5zZXQodGhpcy5rZXlUb1N0cmluZyhvbGRQYXRoLCBuZXdQYXRoKSwgeyBuZXdQYXRoLCBvbGRQYXRoIH0pO1xuICB9XG5cbiAgcHVibGljIGRlbGV0ZShvbGRQYXRoOiBzdHJpbmcsIG5ld1BhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMubWFwLmRlbGV0ZSh0aGlzLmtleVRvU3RyaW5nKG9sZFBhdGgsIG5ld1BhdGgpKTtcbiAgfVxuXG4gIHB1YmxpYyBoYXMob2xkUGF0aDogc3RyaW5nLCBuZXdQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tYXAuaGFzKHRoaXMua2V5VG9TdHJpbmcob2xkUGF0aCwgbmV3UGF0aCkpO1xuICB9XG5cbiAgcHVibGljIGtleXMoKTogSXRlcmFibGVJdGVyYXRvcjxIYW5kbGVkUmVuYW1lS2V5PiB7XG4gICAgcmV0dXJuIHRoaXMubWFwLnZhbHVlcygpO1xuICB9XG5cbiAgcHJpdmF0ZSBrZXlUb1N0cmluZyhvbGRQYXRoOiBzdHJpbmcsIG5ld1BhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke29sZFBhdGh9IC0+ICR7bmV3UGF0aH1gO1xuICB9XG59XG5cbmNsYXNzIE1ldGFkYXRhRGVsZXRlZEhhbmRsZXIge1xuICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBhcHA6IEFwcCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGZpbGU6IFRBYnN0cmFjdEZpbGUsXG4gICAgcHJpdmF0ZSByZWFkb25seSBwcmV2Q2FjaGU6IENhY2hlZE1ldGFkYXRhIHwgbnVsbCxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNldHRpbmdzTWFuYWdlcjogU2V0dGluZ3NNYW5hZ2VyLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgZGVsZXRlZE1ldGFkYXRhQ2FjaGVNYXA6IE1hcDxzdHJpbmcsIENhY2hlZE1ldGFkYXRhPlxuICApIHtcbiAgfVxuXG4gIHB1YmxpYyBoYW5kbGUoKTogdm9pZCB7XG4gICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpO1xuXG4gICAgaWYgKCFzZXR0aW5ncy5zaG91bGRIYW5kbGVEZWxldGlvbnMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoc2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKHRoaXMuZmlsZS5wYXRoKSkge1xuICAgICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6aGFuZGxlTWV0YWRhdGFEZWxldGVkJykoYFNraXBwaW5nIG1ldGFkYXRhIGRlbGV0ZSBoYW5kbGVyIG9mICR7dGhpcy5maWxlLnBhdGh9IGFzIHRoZSBwYXRoIGlzIGlnbm9yZWQuYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGlzTWFya2Rvd25GaWxlKHRoaXMuYXBwLCB0aGlzLmZpbGUpICYmIHRoaXMucHJldkNhY2hlKSB7XG4gICAgICB0aGlzLmRlbGV0ZWRNZXRhZGF0YUNhY2hlTWFwLnNldCh0aGlzLmZpbGUucGF0aCwgdGhpcy5wcmV2Q2FjaGUpO1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBSZWdpc3RyeSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYWJvcnRTaWduYWw6IEFib3J0U2lnbmFsO1xuICBwcml2YXRlIHJlYWRvbmx5IGFwcDogQXBwO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlbGV0ZWRNZXRhZGF0YUNhY2hlTWFwID0gbmV3IE1hcDxzdHJpbmcsIENhY2hlZE1ldGFkYXRhPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZWRSZW5hbWVzID0gbmV3IEhhbmRsZWRSZW5hbWVzKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgaW50ZXJydXB0ZWRSZW5hbWVzTWFwID0gbmV3IE1hcDxzdHJpbmcsIEludGVycnVwdGVkUmVuYW1lW10+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGx1Z2luSWQ6IHN0cmluZztcblxuICBwdWJsaWMgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBwbHVnaW46IEFib3J0YWJsZVBsdWdpbixcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNldHRpbmdzQnVpbGRlcjogKCkgPT4gUGFydGlhbDxSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3M+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgc2V0dGluZ3NNYW5hZ2VyOiBTZXR0aW5nc01hbmFnZXJcbiAgKSB7XG4gICAgdGhpcy5hcHAgPSBwbHVnaW4uYXBwO1xuICAgIHRoaXMucGx1Z2luSWQgPSBwbHVnaW4ubWFuaWZlc3QuaWQ7XG4gICAgdGhpcy5hYm9ydFNpZ25hbCA9IHBsdWdpbi5hYm9ydFNpZ25hbCA/PyBhYm9ydFNpZ25hbE5ldmVyKCk7XG4gIH1cblxuICBwdWJsaWMgcmVnaXN0ZXIoKTogdm9pZCB7XG4gICAgY29uc3QgcmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAgPSB0aGlzLnNldHRpbmdzTWFuYWdlci5yZW5hbWVEZWxldGVIYW5kbGVyc01hcDtcblxuICAgIHJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwLnNldCh0aGlzLnBsdWdpbklkLCB0aGlzLnNldHRpbmdzQnVpbGRlcik7XG4gICAgdGhpcy5sb2dSZWdpc3RlcmVkSGFuZGxlcnMoKTtcblxuICAgIHRoaXMucGx1Z2luLnJlZ2lzdGVyKCgpID0+IHtcbiAgICAgIHJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwLmRlbGV0ZSh0aGlzLnBsdWdpbklkKTtcbiAgICAgIHRoaXMubG9nUmVnaXN0ZXJlZEhhbmRsZXJzKCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLnBsdWdpbi5yZWdpc3RlckV2ZW50KHRoaXMuYXBwLnZhdWx0Lm9uKCdkZWxldGUnLCB0aGlzLmhhbmRsZURlbGV0ZS5iaW5kKHRoaXMpKSk7XG4gICAgdGhpcy5wbHVnaW4ucmVnaXN0ZXJFdmVudCh0aGlzLmFwcC52YXVsdC5vbigncmVuYW1lJywgdGhpcy5oYW5kbGVSZW5hbWUuYmluZCh0aGlzKSkpO1xuICAgIHRoaXMucGx1Z2luLnJlZ2lzdGVyRXZlbnQodGhpcy5hcHAubWV0YWRhdGFDYWNoZS5vbignZGVsZXRlZCcsIHRoaXMuaGFuZGxlTWV0YWRhdGFEZWxldGVkLmJpbmQodGhpcykpKTtcblxuICAgIHJlZ2lzdGVyUGF0Y2godGhpcy5wbHVnaW4sIHRoaXMuYXBwLmZpbGVNYW5hZ2VyLCB7XG4gICAgICBydW5Bc3luY0xpbmtVcGRhdGU6IChuZXh0OiBSdW5Bc3luY0xpbmtVcGRhdGVGbik6IFJ1bkFzeW5jTGlua1VwZGF0ZUZuID0+IHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oKGxpbmtVcGRhdGVzSGFuZGxlcikgPT4gdGhpcy5ydW5Bc3luY0xpbmtVcGRhdGUobmV4dCwgbGlua1VwZGF0ZXNIYW5kbGVyKSwgeyByZW5hbWVEZWxldGVIYW5kbGVyUGF0Y2hlZDogdHJ1ZSB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlRGVsZXRlKGZpbGU6IFRBYnN0cmFjdEZpbGUpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkSW52b2tlSGFuZGxlcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGFkZFRvUXVldWUoXG4gICAgICB0aGlzLmFwcCxcbiAgICAgIChhYm9ydFNpZ25hbCkgPT4gbmV3IERlbGV0ZUhhbmRsZXIodGhpcy5hcHAsIGZpbGUsIGFib3J0U2lnbmFsLCB0aGlzLnNldHRpbmdzTWFuYWdlciwgdGhpcy5kZWxldGVkTWV0YWRhdGFDYWNoZU1hcCkuaGFuZGxlKCksXG4gICAgICB0aGlzLmFib3J0U2lnbmFsXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlTWV0YWRhdGFEZWxldGVkKGZpbGU6IFRBYnN0cmFjdEZpbGUsIHByZXZDYWNoZTogQ2FjaGVkTWV0YWRhdGEgfCBudWxsKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3VsZEludm9rZUhhbmRsZXIoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhZGRUb1F1ZXVlKHRoaXMuYXBwLCAoKSA9PiB7XG4gICAgICBuZXcgTWV0YWRhdGFEZWxldGVkSGFuZGxlcih0aGlzLmFwcCwgZmlsZSwgcHJldkNhY2hlLCB0aGlzLnNldHRpbmdzTWFuYWdlciwgdGhpcy5kZWxldGVkTWV0YWRhdGFDYWNoZU1hcCkuaGFuZGxlKCk7XG4gICAgfSwgdGhpcy5hYm9ydFNpZ25hbCk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVJlbmFtZShmaWxlOiBUQWJzdHJhY3RGaWxlLCBvbGRQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2hvdWxkSW52b2tlSGFuZGxlcigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCFpc0ZpbGUoZmlsZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBuZXdQYXRoID0gZmlsZS5wYXRoO1xuXG4gICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6aGFuZGxlUmVuYW1lJykoYEhhbmRsZSBSZW5hbWUgJHtvbGRQYXRofSAtPiAke25ld1BhdGh9YCk7XG4gICAgaWYgKHRoaXMuaGFuZGxlZFJlbmFtZXMuaGFzKG9sZFBhdGgsIG5ld1BhdGgpKSB7XG4gICAgICB0aGlzLmhhbmRsZWRSZW5hbWVzLmRlbGV0ZShvbGRQYXRoLCBuZXdQYXRoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzZXR0aW5ncyA9IHRoaXMuc2V0dGluZ3NNYW5hZ2VyLmdldFNldHRpbmdzKCk7XG4gICAgaWYgKCFzZXR0aW5ncy5zaG91bGRIYW5kbGVSZW5hbWVzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHNldHRpbmdzLmlzUGF0aElnbm9yZWQ/LihvbGRQYXRoKSkge1xuICAgICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6aGFuZGxlUmVuYW1lJykoYFNraXBwaW5nIHJlbmFtZSBoYW5kbGVyIG9mIG9sZCBwYXRoICR7b2xkUGF0aH0gYXMgdGhlIHBhdGggaXMgaWdub3JlZC5gKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoc2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKG5ld1BhdGgpKSB7XG4gICAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpoYW5kbGVSZW5hbWUnKShgU2tpcHBpbmcgcmVuYW1lIGhhbmRsZXIgb2YgbmV3IHBhdGggJHtuZXdQYXRofSBhcyB0aGUgcGF0aCBpcyBpZ25vcmVkLmApO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG9sZENhY2hlID0gdGhpcy5hcHAubWV0YWRhdGFDYWNoZS5nZXRDYWNoZShvbGRQYXRoKSA/PyB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldENhY2hlKG5ld1BhdGgpO1xuICAgIGNvbnN0IG9sZFBhdGhCYWNrbGlua3NNYXAgPSBnZXRCYWNrbGlua3NGb3JGaWxlT3JQYXRoKHRoaXMuYXBwLCBvbGRQYXRoKS5kYXRhO1xuICAgIGFkZFRvUXVldWUodGhpcy5hcHAsIChhYm9ydFNpZ25hbCkgPT5cbiAgICAgIG5ldyBSZW5hbWVIYW5kbGVyKHtcbiAgICAgICAgYWJvcnRTaWduYWwsXG4gICAgICAgIGFwcDogdGhpcy5hcHAsXG4gICAgICAgIGhhbmRsZWRSZW5hbWVzOiB0aGlzLmhhbmRsZWRSZW5hbWVzLFxuICAgICAgICBpbnRlcnJ1cHRlZFJlbmFtZXNNYXA6IHRoaXMuaW50ZXJydXB0ZWRSZW5hbWVzTWFwLFxuICAgICAgICBuZXdQYXRoLFxuICAgICAgICBvbGRDYWNoZSxcbiAgICAgICAgb2xkUGF0aCxcbiAgICAgICAgb2xkUGF0aEJhY2tsaW5rc01hcCxcbiAgICAgICAgc2V0dGluZ3NNYW5hZ2VyOiB0aGlzLnNldHRpbmdzTWFuYWdlclxuICAgICAgfSkuaGFuZGxlKCksIHRoaXMuYWJvcnRTaWduYWwpO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2dSZWdpc3RlcmVkSGFuZGxlcnMoKTogdm9pZCB7XG4gICAgY29uc3QgcmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAgPSB0aGlzLnNldHRpbmdzTWFuYWdlci5yZW5hbWVEZWxldGVIYW5kbGVyc01hcDtcbiAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpsb2dSZWdpc3RlcmVkSGFuZGxlcnMnKShcbiAgICAgIGBQbHVnaW5zIHdpdGggcmVnaXN0ZXJlZCByZW5hbWUvZGVsZXRlIGhhbmRsZXJzOiAke0pTT04uc3RyaW5naWZ5KEFycmF5LmZyb20ocmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAua2V5cygpKSl9YFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJ1bkFzeW5jTGlua1VwZGF0ZShuZXh0OiBSdW5Bc3luY0xpbmtVcGRhdGVGbiwgbGlua1VwZGF0ZXNIYW5kbGVyOiBMaW5rVXBkYXRlc0hhbmRsZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAobmV4dC5yZW5hbWVEZWxldGVIYW5kbGVyUGF0Y2hlZCkge1xuICAgICAgYXdhaXQgbmV4dC5jYWxsKHRoaXMuYXBwLmZpbGVNYW5hZ2VyLCBsaW5rVXBkYXRlc0hhbmRsZXIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCBuZXh0LmNhbGwodGhpcy5hcHAuZmlsZU1hbmFnZXIsIChsaW5rVXBkYXRlcykgPT4gdGhpcy53cmFwTGlua1VwZGF0ZXNIYW5kbGVyKGxpbmtVcGRhdGVzLCBsaW5rVXBkYXRlc0hhbmRsZXIpKTtcbiAgfVxuXG4gIHByaXZhdGUgc2hvdWxkSW52b2tlSGFuZGxlcigpOiBib29sZWFuIHtcbiAgICBjb25zdCBwbHVnaW5JZCA9IHRoaXMucGx1Z2luLm1hbmlmZXN0LmlkO1xuXG4gICAgY29uc3QgcmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAgPSB0aGlzLnNldHRpbmdzTWFuYWdlci5yZW5hbWVEZWxldGVIYW5kbGVyc01hcDtcbiAgICBjb25zdCBtYWluUGx1Z2luSWQgPSBBcnJheS5mcm9tKHJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwLmtleXMoKSlbMF07XG4gICAgcmV0dXJuIG1haW5QbHVnaW5JZCA9PT0gcGx1Z2luSWQ7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHdyYXBMaW5rVXBkYXRlc0hhbmRsZXIobGlua1VwZGF0ZXM6IExpbmtVcGRhdGVbXSwgbGlua1VwZGF0ZXNIYW5kbGVyOiBMaW5rVXBkYXRlc0hhbmRsZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgaXNSZW5hbWVDYWxsZWQgPSBmYWxzZTtcbiAgICBjb25zdCBldmVudFJlZiA9IHRoaXMuYXBwLnZhdWx0Lm9uKCdyZW5hbWUnLCAoKSA9PiB7XG4gICAgICBpc1JlbmFtZUNhbGxlZCA9IHRydWU7XG4gICAgfSk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGxpbmtVcGRhdGVzSGFuZGxlcihsaW5rVXBkYXRlcyk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuYXBwLnZhdWx0Lm9mZnJlZihldmVudFJlZik7XG4gICAgfVxuICAgIGNvbnN0IHNldHRpbmdzID0gdGhpcy5zZXR0aW5nc01hbmFnZXIuZ2V0U2V0dGluZ3MoKTtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVubmVjZXNzYXJ5LWNvbmRpdGlvblxuICAgIGlmICghaXNSZW5hbWVDYWxsZWQgfHwgIXNldHRpbmdzLnNob3VsZEhhbmRsZVJlbmFtZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmaWx0ZXJJblBsYWNlKFxuICAgICAgbGlua1VwZGF0ZXMsXG4gICAgICAobGlua1VwZGF0ZSkgPT4ge1xuICAgICAgICBpZiAoc2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKGxpbmtVcGRhdGUuc291cmNlRmlsZS5wYXRoKSkge1xuICAgICAgICAgIGdldExpYkRlYnVnZ2VyKCdSZW5hbWVEZWxldGVIYW5kbGVyOnJ1bkFzeW5jTGlua1VwZGF0ZScpKFxuICAgICAgICAgICAgYFJvbGwgYmFjayB0byBkZWZhdWx0IGxpbmsgdXBkYXRlIG9mIHNvdXJjZSBmaWxlICR7bGlua1VwZGF0ZS5zb3VyY2VGaWxlLnBhdGh9IGFzIHRoZSBwYXRoIGlzIGlnbm9yZWQuYFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKGxpbmtVcGRhdGUucmVzb2x2ZWRGaWxlLnBhdGgpKSB7XG4gICAgICAgICAgZ2V0TGliRGVidWdnZXIoJ1JlbmFtZURlbGV0ZUhhbmRsZXI6cnVuQXN5bmNMaW5rVXBkYXRlJykoXG4gICAgICAgICAgICBgUm9sbCBiYWNrIHRvIGRlZmF1bHQgbGluayB1cGRhdGUgb2YgcmVzb2x2ZWQgZmlsZSAke2xpbmtVcGRhdGUucmVzb2x2ZWRGaWxlLnBhdGh9IGFzIHRoZSBwYXRoIGlzIGlnbm9yZWQuYFxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuYXBwLmludGVybmFsUGx1Z2lucy5nZXRFbmFibGVkUGx1Z2luQnlJZChJbnRlcm5hbFBsdWdpbk5hbWUuQ2FudmFzKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmFwcC5wbHVnaW5zLmdldFBsdWdpbignYmFja2xpbmstY2FjaGUnKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsaW5rVXBkYXRlLnNvdXJjZUZpbGUuZXh0ZW5zaW9uID09PSBDQU5WQVNfRklMRV9FWFRFTlNJT04pIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsaW5rVXBkYXRlLnJlc29sdmVkRmlsZS5leHRlbnNpb24gPT09IENBTlZBU19GSUxFX0VYVEVOU0lPTikge1xuICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICk7XG4gIH1cbn1cblxuY2xhc3MgUmVuYW1lSGFuZGxlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYWJvcnRTaWduYWw6IEFib3J0U2lnbmFsO1xuICBwcml2YXRlIHJlYWRvbmx5IGFwcDogQXBwO1xuICBwcml2YXRlIHJlYWRvbmx5IGhhbmRsZWRSZW5hbWVzOiBIYW5kbGVkUmVuYW1lcztcbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlcnJ1cHRlZENvbWJpbmVkQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PjtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnRlcnJ1cHRlZFJlbmFtZXNNYXA6IE1hcDxzdHJpbmcsIEludGVycnVwdGVkUmVuYW1lW10+O1xuICBwcml2YXRlIHJlYWRvbmx5IG5ld1BhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRDYWNoZTogQ2FjaGVkTWV0YWRhdGEgfCBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBvbGRQYXRoQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBSZWZlcmVuY2VbXT47XG4gIHByaXZhdGUgcmVhZG9ubHkgb2xkUGF0aExpbmtzOiBSZWZlcmVuY2VbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBzZXR0aW5nc01hbmFnZXI6IFNldHRpbmdzTWFuYWdlcjtcblxuICBwdWJsaWMgY29uc3RydWN0b3Iob3B0aW9uczogUmVuYW1lSGFuZGxlck9wdGlvbnMpIHtcbiAgICB0aGlzLmFwcCA9IG9wdGlvbnMuYXBwO1xuICAgIHRoaXMub2xkUGF0aCA9IG9wdGlvbnMub2xkUGF0aDtcbiAgICB0aGlzLm5ld1BhdGggPSBvcHRpb25zLm5ld1BhdGg7XG4gICAgdGhpcy5vbGRQYXRoQmFja2xpbmtzTWFwID0gb3B0aW9ucy5vbGRQYXRoQmFja2xpbmtzTWFwO1xuICAgIHRoaXMub2xkQ2FjaGUgPSBvcHRpb25zLm9sZENhY2hlO1xuICAgIHRoaXMuYWJvcnRTaWduYWwgPSBvcHRpb25zLmFib3J0U2lnbmFsO1xuICAgIHRoaXMuc2V0dGluZ3NNYW5hZ2VyID0gb3B0aW9ucy5zZXR0aW5nc01hbmFnZXI7XG4gICAgdGhpcy5pbnRlcnJ1cHRlZFJlbmFtZXNNYXAgPSBvcHRpb25zLmludGVycnVwdGVkUmVuYW1lc01hcDtcbiAgICB0aGlzLm9sZFBhdGhMaW5rcyA9IHRoaXMub2xkQ2FjaGUgPyBnZXRBbGxMaW5rcyh0aGlzLm9sZENhY2hlKSA6IFtdO1xuICAgIHRoaXMuaGFuZGxlZFJlbmFtZXMgPSBvcHRpb25zLmhhbmRsZWRSZW5hbWVzO1xuICAgIHRoaXMuaW50ZXJydXB0ZWRDb21iaW5lZEJhY2tsaW5rc01hcCA9IG9wdGlvbnMuaW50ZXJydXB0ZWRDb21iaW5lZEJhY2tsaW5rc01hcCA/PyBuZXcgTWFwPHN0cmluZywgTWFwPHN0cmluZywgc3RyaW5nPj4oKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBoYW5kbGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgIGF3YWl0IHRoaXMuY29udGludWVJbnRlcnJ1cHRlZFJlbmFtZXMoKTtcbiAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgYXdhaXQgdGhpcy5yZWZyZXNoTGlua3MoKTtcbiAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgaWYgKGF3YWl0IHRoaXMuaGFuZGxlQ2FzZUNvbGxpc2lvbigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlbmFtZU1hcCA9IG5ldyBSZW5hbWVNYXAoe1xuICAgICAgICBhYm9ydFNpZ25hbDogdGhpcy5hYm9ydFNpZ25hbCxcbiAgICAgICAgYXBwOiB0aGlzLmFwcCxcbiAgICAgICAgbmV3UGF0aDogdGhpcy5uZXdQYXRoLFxuICAgICAgICBvbGRDYWNoZTogdGhpcy5vbGRDYWNoZSxcbiAgICAgICAgb2xkUGF0aDogdGhpcy5vbGRQYXRoLFxuICAgICAgICBzZXR0aW5nc01hbmFnZXI6IHRoaXMuc2V0dGluZ3NNYW5hZ2VyXG4gICAgICB9KTtcbiAgICAgIGF3YWl0IHJlbmFtZU1hcC5maWxsKCk7XG4gICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG5cbiAgICAgIGNvbnN0IGNvbWJpbmVkQmFja2xpbmtzTWFwID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIHN0cmluZz4+KCk7XG4gICAgICByZW5hbWVNYXAuaW5pdEJhY2tsaW5rc01hcCh0aGlzLm9sZFBhdGhCYWNrbGlua3NNYXAsIGNvbWJpbmVkQmFja2xpbmtzTWFwLCB0aGlzLm9sZFBhdGgpO1xuXG4gICAgICBmb3IgKGNvbnN0IGF0dGFjaG1lbnRPbGRQYXRoIG9mIHJlbmFtZU1hcC5rZXlzKCkpIHtcbiAgICAgICAgaWYgKGF0dGFjaG1lbnRPbGRQYXRoID09PSB0aGlzLm9sZFBhdGgpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBhdHRhY2htZW50T2xkUGF0aEJhY2tsaW5rc01hcCA9IChhd2FpdCBnZXRCYWNrbGlua3NGb3JGaWxlU2FmZSh0aGlzLmFwcCwgYXR0YWNobWVudE9sZFBhdGgpKS5kYXRhO1xuICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICAgIHJlbmFtZU1hcC5pbml0QmFja2xpbmtzTWFwKGF0dGFjaG1lbnRPbGRQYXRoQmFja2xpbmtzTWFwLCBjb21iaW5lZEJhY2tsaW5rc01hcCwgYXR0YWNobWVudE9sZFBhdGgpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJlbnRGb2xkZXJQYXRocyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgICBmb3IgKGNvbnN0IFtvbGRBdHRhY2htZW50UGF0aCwgbmV3QXR0YWNobWVudFBhdGhdIG9mIHJlbmFtZU1hcC5lbnRyaWVzKCkpIHtcbiAgICAgICAgaWYgKG9sZEF0dGFjaG1lbnRQYXRoID09PSB0aGlzLm9sZFBhdGgpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBmaXhlZE5ld0F0dGFjaG1lbnRQYXRoID0gYXdhaXQgdGhpcy5yZW5hbWVIYW5kbGVkKG9sZEF0dGFjaG1lbnRQYXRoLCBuZXdBdHRhY2htZW50UGF0aCk7XG4gICAgICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICAgICAgcmVuYW1lTWFwLnNldChvbGRBdHRhY2htZW50UGF0aCwgZml4ZWROZXdBdHRhY2htZW50UGF0aCk7XG4gICAgICAgIHBhcmVudEZvbGRlclBhdGhzLmFkZChkaXJuYW1lKG9sZEF0dGFjaG1lbnRQYXRoKSk7XG4gICAgICB9XG5cbiAgICAgIGF3YWl0IGNsZWFudXBQYXJlbnRGb2xkZXJzKHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpLCBBcnJheS5mcm9tKHBhcmVudEZvbGRlclBhdGhzKSwgdGhpcy5vbGRQYXRoKTtcbiAgICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICAgIGNvbnN0IHNldHRpbmdzID0gdGhpcy5zZXR0aW5nc01hbmFnZXIuZ2V0U2V0dGluZ3MoKTtcblxuICAgICAgZm9yIChcbiAgICAgICAgY29uc3QgW25ld0JhY2tsaW5rUGF0aCwgbGlua0pzb25Ub1BhdGhNYXBdIG9mIEFycmF5LmZyb20oY29tYmluZWRCYWNrbGlua3NNYXAuZW50cmllcygpKS5jb25jYXQoXG4gICAgICAgICAgQXJyYXkuZnJvbSh0aGlzLmludGVycnVwdGVkQ29tYmluZWRCYWNrbGlua3NNYXAuZW50cmllcygpKVxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgYXdhaXQgZWRpdExpbmtzKHRoaXMuYXBwLCBuZXdCYWNrbGlua1BhdGgsIChsaW5rKSA9PiB7XG4gICAgICAgICAgY29uc3Qgb2xkQXR0YWNobWVudFBhdGggPSBsaW5rSnNvblRvUGF0aE1hcC5nZXQodG9Kc29uKGxpbmspKTtcbiAgICAgICAgICBpZiAoIW9sZEF0dGFjaG1lbnRQYXRoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgbmV3QXR0YWNobWVudFBhdGggPSByZW5hbWVNYXAuZ2V0KG9sZEF0dGFjaG1lbnRQYXRoKTtcbiAgICAgICAgICBpZiAoIW5ld0F0dGFjaG1lbnRQYXRoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcmV0dXJuIHVwZGF0ZUxpbmsobm9ybWFsaXplT3B0aW9uYWxQcm9wZXJ0aWVzPFVwZGF0ZUxpbmtPcHRpb25zPih7XG4gICAgICAgICAgICBhcHA6IHRoaXMuYXBwLFxuICAgICAgICAgICAgbGluayxcbiAgICAgICAgICAgIG5ld1NvdXJjZVBhdGhPckZpbGU6IG5ld0JhY2tsaW5rUGF0aCxcbiAgICAgICAgICAgIG5ld1RhcmdldFBhdGhPckZpbGU6IG5ld0F0dGFjaG1lbnRQYXRoLFxuICAgICAgICAgICAgb2xkVGFyZ2V0UGF0aE9yRmlsZTogb2xkQXR0YWNobWVudFBhdGgsXG4gICAgICAgICAgICBzaG91bGRVcGRhdGVGaWxlTmFtZUFsaWFzOiBzZXR0aW5ncy5zaG91bGRVcGRhdGVGaWxlTmFtZUFsaWFzZXNcbiAgICAgICAgICB9KSk7XG4gICAgICAgIH0sIHtcbiAgICAgICAgICBzaG91bGRGYWlsT25NaXNzaW5nRmlsZTogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuc2V0dGluZ3NNYW5hZ2VyLmlzTm90ZUV4KHRoaXMubmV3UGF0aCkpIHtcbiAgICAgICAgYXdhaXQgdXBkYXRlTGlua3NJbkZpbGUobm9ybWFsaXplT3B0aW9uYWxQcm9wZXJ0aWVzPFVwZGF0ZUxpbmtzSW5GaWxlT3B0aW9ucz4oe1xuICAgICAgICAgIGFwcDogdGhpcy5hcHAsXG4gICAgICAgICAgbmV3U291cmNlUGF0aE9yRmlsZTogdGhpcy5uZXdQYXRoLFxuICAgICAgICAgIG9sZFNvdXJjZVBhdGhPckZpbGU6IHRoaXMub2xkUGF0aCxcbiAgICAgICAgICBzaG91bGRGYWlsT25NaXNzaW5nRmlsZTogZmFsc2UsXG4gICAgICAgICAgc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhczogc2V0dGluZ3Muc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhc2VzXG4gICAgICAgIH0pKTtcbiAgICAgICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIWdldEZpbGVPck51bGwodGhpcy5hcHAsIHRoaXMubmV3UGF0aCkpIHtcbiAgICAgICAgbGV0IGludGVycnVwdGVkUmVuYW1lcyA9IHRoaXMuaW50ZXJydXB0ZWRSZW5hbWVzTWFwLmdldCh0aGlzLm5ld1BhdGgpO1xuICAgICAgICBpZiAoIWludGVycnVwdGVkUmVuYW1lcykge1xuICAgICAgICAgIGludGVycnVwdGVkUmVuYW1lcyA9IFtdO1xuICAgICAgICAgIHRoaXMuaW50ZXJydXB0ZWRSZW5hbWVzTWFwLnNldCh0aGlzLm5ld1BhdGgsIGludGVycnVwdGVkUmVuYW1lcyk7XG4gICAgICAgIH1cbiAgICAgICAgaW50ZXJydXB0ZWRSZW5hbWVzLnB1c2goe1xuICAgICAgICAgIGNvbWJpbmVkQmFja2xpbmtzTWFwLFxuICAgICAgICAgIG9sZFBhdGg6IHRoaXMub2xkUGF0aFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGZpbmFsbHkge1xuICAgICAgY29uc3Qgb3JwaGFuS2V5cyA9IEFycmF5LmZyb20odGhpcy5oYW5kbGVkUmVuYW1lcy5rZXlzKCkpO1xuICAgICAgYWRkVG9RdWV1ZSh0aGlzLmFwcCwgKCkgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IG9ycGhhbktleSBvZiBvcnBoYW5LZXlzKSB7XG4gICAgICAgICAgdGhpcy5oYW5kbGVkUmVuYW1lcy5kZWxldGUob3JwaGFuS2V5Lm9sZFBhdGgsIG9ycGhhbktleS5uZXdQYXRoKTtcbiAgICAgICAgfVxuICAgICAgfSwgdGhpcy5hYm9ydFNpZ25hbCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBjb250aW51ZUludGVycnVwdGVkUmVuYW1lcygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBpbnRlcnJ1cHRlZFJlbmFtZXMgPSB0aGlzLmludGVycnVwdGVkUmVuYW1lc01hcC5nZXQodGhpcy5vbGRQYXRoKTtcbiAgICBpZiAoaW50ZXJydXB0ZWRSZW5hbWVzKSB7XG4gICAgICB0aGlzLmludGVycnVwdGVkUmVuYW1lc01hcC5kZWxldGUodGhpcy5vbGRQYXRoKTtcbiAgICAgIGZvciAoY29uc3QgaW50ZXJydXB0ZWRSZW5hbWUgb2YgaW50ZXJydXB0ZWRSZW5hbWVzKSB7XG4gICAgICAgIGF3YWl0IG5ldyBSZW5hbWVIYW5kbGVyKHtcbiAgICAgICAgICBhYm9ydFNpZ25hbDogdGhpcy5hYm9ydFNpZ25hbCxcbiAgICAgICAgICBhcHA6IHRoaXMuYXBwLFxuICAgICAgICAgIGhhbmRsZWRSZW5hbWVzOiB0aGlzLmhhbmRsZWRSZW5hbWVzLFxuICAgICAgICAgIGludGVycnVwdGVkQ29tYmluZWRCYWNrbGlua3NNYXA6IGludGVycnVwdGVkUmVuYW1lLmNvbWJpbmVkQmFja2xpbmtzTWFwLFxuICAgICAgICAgIGludGVycnVwdGVkUmVuYW1lc01hcDogdGhpcy5pbnRlcnJ1cHRlZFJlbmFtZXNNYXAsXG4gICAgICAgICAgbmV3UGF0aDogdGhpcy5uZXdQYXRoLFxuICAgICAgICAgIG9sZENhY2hlOiB0aGlzLm9sZENhY2hlLFxuICAgICAgICAgIG9sZFBhdGg6IGludGVycnVwdGVkUmVuYW1lLm9sZFBhdGgsXG4gICAgICAgICAgb2xkUGF0aEJhY2tsaW5rc01hcDogdGhpcy5vbGRQYXRoQmFja2xpbmtzTWFwLFxuICAgICAgICAgIHNldHRpbmdzTWFuYWdlcjogdGhpcy5zZXR0aW5nc01hbmFnZXJcbiAgICAgICAgfSkuaGFuZGxlKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBoYW5kbGVDYXNlQ29sbGlzaW9uKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmICghdGhpcy5hcHAudmF1bHQuYWRhcHRlci5pbnNlbnNpdGl2ZSB8fCB0aGlzLm9sZFBhdGgudG9Mb3dlckNhc2UoKSAhPT0gdGhpcy5uZXdQYXRoLnRvTG93ZXJDYXNlKCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCB0ZW1wUGF0aCA9IGpvaW4oZGlybmFtZSh0aGlzLm5ld1BhdGgpLCBgX190ZW1wX18ke2Jhc2VuYW1lKHRoaXMubmV3UGF0aCl9YCk7XG4gICAgYXdhaXQgdGhpcy5yZW5hbWVIYW5kbGVkKHRoaXMubmV3UGF0aCwgdGVtcFBhdGgpO1xuXG4gICAgYXdhaXQgbmV3IFJlbmFtZUhhbmRsZXIoe1xuICAgICAgYWJvcnRTaWduYWw6IHRoaXMuYWJvcnRTaWduYWwsXG4gICAgICBhcHA6IHRoaXMuYXBwLFxuICAgICAgaGFuZGxlZFJlbmFtZXM6IHRoaXMuaGFuZGxlZFJlbmFtZXMsXG4gICAgICBpbnRlcnJ1cHRlZFJlbmFtZXNNYXA6IHRoaXMuaW50ZXJydXB0ZWRSZW5hbWVzTWFwLFxuICAgICAgbmV3UGF0aDogdGVtcFBhdGgsXG4gICAgICBvbGRDYWNoZTogdGhpcy5vbGRDYWNoZSxcbiAgICAgIG9sZFBhdGg6IHRoaXMub2xkUGF0aCxcbiAgICAgIG9sZFBhdGhCYWNrbGlua3NNYXA6IHRoaXMub2xkUGF0aEJhY2tsaW5rc01hcCxcbiAgICAgIHNldHRpbmdzTWFuYWdlcjogdGhpcy5zZXR0aW5nc01hbmFnZXJcbiAgICB9KS5oYW5kbGUoKTtcblxuICAgIGF3YWl0IHRoaXMuYXBwLnZhdWx0LnJlbmFtZShnZXRGaWxlKHRoaXMuYXBwLCB0ZW1wUGF0aCksIHRoaXMubmV3UGF0aCk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlZnJlc2hMaW5rcygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjYWNoZSA9IHRoaXMuYXBwLm1ldGFkYXRhQ2FjaGUuZ2V0Q2FjaGUodGhpcy5vbGRQYXRoKSA/PyB0aGlzLmFwcC5tZXRhZGF0YUNhY2hlLmdldENhY2hlKHRoaXMubmV3UGF0aCk7XG4gICAgY29uc3Qgb2xkUGF0aExpbmtzUmVmcmVzaGVkID0gY2FjaGUgPyBnZXRBbGxMaW5rcyhjYWNoZSkgOiBbXTtcbiAgICBjb25zdCBmYWtlT2xkRmlsZSA9IGdldEZpbGUodGhpcy5hcHAsIHRoaXMub2xkUGF0aCwgdHJ1ZSk7XG4gICAgbGV0IG9sZFBhdGhCYWNrbGlua3NNYXBSZWZyZXNoZWQgPSBuZXcgTWFwPHN0cmluZywgUmVmZXJlbmNlW10+KCk7XG4gICAgYXdhaXQgdGVtcFJlZ2lzdGVyRmlsZXNBbmRSdW4odGhpcy5hcHAsIFtmYWtlT2xkRmlsZV0sIGFzeW5jICgpID0+IHtcbiAgICAgIG9sZFBhdGhCYWNrbGlua3NNYXBSZWZyZXNoZWQgPSAoYXdhaXQgZ2V0QmFja2xpbmtzRm9yRmlsZVNhZmUodGhpcy5hcHAsIGZha2VPbGRGaWxlKSkuZGF0YTtcbiAgICB9KTtcblxuICAgIGZvciAoY29uc3QgbGluayBvZiBvbGRQYXRoTGlua3NSZWZyZXNoZWQpIHtcbiAgICAgIGlmICh0aGlzLm9sZFBhdGhMaW5rcy5pbmNsdWRlcyhsaW5rKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHRoaXMub2xkUGF0aExpbmtzLnB1c2gobGluayk7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBbYmFja2xpbmtQYXRoLCByZWZyZXNoZWRMaW5rc10gb2Ygb2xkUGF0aEJhY2tsaW5rc01hcFJlZnJlc2hlZC5lbnRyaWVzKCkpIHtcbiAgICAgIGxldCBvbGRMaW5rcyA9IHRoaXMub2xkUGF0aEJhY2tsaW5rc01hcC5nZXQoYmFja2xpbmtQYXRoKTtcbiAgICAgIGlmICghb2xkTGlua3MpIHtcbiAgICAgICAgb2xkTGlua3MgPSBbXTtcbiAgICAgICAgdGhpcy5vbGRQYXRoQmFja2xpbmtzTWFwLnNldChiYWNrbGlua1BhdGgsIG9sZExpbmtzKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChjb25zdCBsaW5rIG9mIHJlZnJlc2hlZExpbmtzKSB7XG4gICAgICAgIGlmIChvbGRMaW5rcy5pbmNsdWRlcyhsaW5rKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIG9sZExpbmtzLnB1c2gobGluayk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZW5hbWVIYW5kbGVkKG9sZFBhdGg6IHN0cmluZywgbmV3UGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBuZXdQYXRoID0gZ2V0U2FmZVJlbmFtZVBhdGgodGhpcy5hcHAsIG9sZFBhdGgsIG5ld1BhdGgpO1xuICAgIGlmIChvbGRQYXRoID09PSBuZXdQYXRoKSB7XG4gICAgICByZXR1cm4gbmV3UGF0aDtcbiAgICB9XG4gICAgdGhpcy5oYW5kbGVkUmVuYW1lcy5hZGQob2xkUGF0aCwgbmV3UGF0aCk7XG4gICAgbmV3UGF0aCA9IGF3YWl0IHJlbmFtZVNhZmUodGhpcy5hcHAsIG9sZFBhdGgsIG5ld1BhdGgpO1xuICAgIHJldHVybiBuZXdQYXRoO1xuICB9XG59XG5cbmNsYXNzIFJlbmFtZU1hcCB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYWJvcnRTaWduYWw6IEFib3J0U2lnbmFsO1xuICBwcml2YXRlIHJlYWRvbmx5IGFwcDogQXBwO1xuICBwcml2YXRlIHJlYWRvbmx5IG1hcCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbmV3UGF0aDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZENhY2hlOiBDYWNoZWRNZXRhZGF0YSB8IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgb2xkUGF0aDogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IG9sZFBhdGhMaW5rczogUmVmZXJlbmNlW107XG4gIHByaXZhdGUgcmVhZG9ubHkgc2V0dGluZ3NNYW5hZ2VyOiBTZXR0aW5nc01hbmFnZXI7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM6IFJlbmFtZU1hcE9wdGlvbnMpIHtcbiAgICB0aGlzLmFib3J0U2lnbmFsID0gb3B0aW9ucy5hYm9ydFNpZ25hbDtcbiAgICB0aGlzLmFwcCA9IG9wdGlvbnMuYXBwO1xuICAgIHRoaXMuc2V0dGluZ3NNYW5hZ2VyID0gb3B0aW9ucy5zZXR0aW5nc01hbmFnZXI7XG4gICAgdGhpcy5vbGRDYWNoZSA9IG9wdGlvbnMub2xkQ2FjaGU7XG4gICAgdGhpcy5vbGRQYXRoID0gb3B0aW9ucy5vbGRQYXRoO1xuICAgIHRoaXMubmV3UGF0aCA9IG9wdGlvbnMubmV3UGF0aDtcbiAgICB0aGlzLm9sZFBhdGhMaW5rcyA9IHRoaXMub2xkQ2FjaGUgPyBnZXRBbGxMaW5rcyh0aGlzLm9sZENhY2hlKSA6IFtdO1xuICB9XG5cbiAgcHVibGljIGVudHJpZXMoKTogSXRlcmFibGVJdGVyYXRvcjxbc3RyaW5nLCBzdHJpbmddPiB7XG4gICAgcmV0dXJuIHRoaXMubWFwLmVudHJpZXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBmaWxsKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICB0aGlzLm1hcC5zZXQodGhpcy5vbGRQYXRoLCB0aGlzLm5ld1BhdGgpO1xuXG4gICAgaWYgKCF0aGlzLnNldHRpbmdzTWFuYWdlci5pc05vdGVFeCh0aGlzLm9sZFBhdGgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLnNldHRpbmdzTWFuYWdlci5nZXRTZXR0aW5ncygpO1xuXG4gICAgY29uc3Qgb2xkRmlsZSA9IGdldEZpbGUodGhpcy5hcHAsIHRoaXMub2xkUGF0aCwgdHJ1ZSk7XG4gICAgbGV0IG9sZEF0dGFjaG1lbnRGb2xkZXJQYXRoID0gJyc7XG4gICAgYXdhaXQgdGVtcFJlZ2lzdGVyRmlsZXNBbmRSdW5Bc3luYyh0aGlzLmFwcCwgW29sZEZpbGVdLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCBzaG91bGRGYWtlT2xkUGF0aENhY2hlID0gdGhpcy5vbGRDYWNoZSAmJiBvbGRGaWxlLmRlbGV0ZWQ7XG4gICAgICBpZiAoc2hvdWxkRmFrZU9sZFBhdGhDYWNoZSkge1xuICAgICAgICByZWdpc3RlckZpbGVDYWNoZUZvck5vbkV4aXN0aW5nRmlsZSh0aGlzLmFwcCwgb2xkRmlsZSwgdGhpcy5vbGRDYWNoZSk7XG4gICAgICB9XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIG9sZEF0dGFjaG1lbnRGb2xkZXJQYXRoID0gYXdhaXQgZ2V0QXR0YWNobWVudEZvbGRlclBhdGgodGhpcy5hcHAsIHRoaXMub2xkUGF0aCwgQXR0YWNobWVudFBhdGhDb250ZXh0LlJlbmFtZU5vdGUpO1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgaWYgKHNob3VsZEZha2VPbGRQYXRoQ2FjaGUpIHtcbiAgICAgICAgICB1bnJlZ2lzdGVyRmlsZUNhY2hlRm9yTm9uRXhpc3RpbmdGaWxlKHRoaXMuYXBwLCBvbGRGaWxlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgbmV3QXR0YWNobWVudEZvbGRlclBhdGggPSBzZXR0aW5ncy5zaG91bGRSZW5hbWVBdHRhY2htZW50Rm9sZGVyXG4gICAgICA/IGF3YWl0IGdldEF0dGFjaG1lbnRGb2xkZXJQYXRoKHRoaXMuYXBwLCB0aGlzLm5ld1BhdGgsIEF0dGFjaG1lbnRQYXRoQ29udGV4dC5SZW5hbWVOb3RlKVxuICAgICAgOiBvbGRBdHRhY2htZW50Rm9sZGVyUGF0aDtcblxuICAgIGNvbnN0IGlzT2xkQXR0YWNobWVudEZvbGRlckF0Um9vdCA9IG9sZEF0dGFjaG1lbnRGb2xkZXJQYXRoID09PSAnLyc7XG5cbiAgICBjb25zdCBvbGRBdHRhY2htZW50Rm9sZGVyID0gZ2V0Rm9sZGVyT3JOdWxsKHRoaXMuYXBwLCBvbGRBdHRhY2htZW50Rm9sZGVyUGF0aCk7XG5cbiAgICBpZiAoIW9sZEF0dGFjaG1lbnRGb2xkZXIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAob2xkQXR0YWNobWVudEZvbGRlclBhdGggPT09IG5ld0F0dGFjaG1lbnRGb2xkZXJQYXRoICYmICFzZXR0aW5ncy5zaG91bGRSZW5hbWVBdHRhY2htZW50RmlsZXMpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBvbGRBdHRhY2htZW50RmlsZXM6IFRGaWxlW10gPSBbXTtcblxuICAgIGlmIChhd2FpdCBoYXNPd25BdHRhY2htZW50Rm9sZGVyKHRoaXMuYXBwLCB0aGlzLm9sZFBhdGgsIEF0dGFjaG1lbnRQYXRoQ29udGV4dC5SZW5hbWVOb3RlKSkge1xuICAgICAgVmF1bHQucmVjdXJzZUNoaWxkcmVuKG9sZEF0dGFjaG1lbnRGb2xkZXIsIChvbGRBdHRhY2htZW50RmlsZSkgPT4ge1xuICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICAgIGlmIChpc0ZpbGUob2xkQXR0YWNobWVudEZpbGUpKSB7XG4gICAgICAgICAgb2xkQXR0YWNobWVudEZpbGVzLnB1c2gob2xkQXR0YWNobWVudEZpbGUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChjb25zdCBvbGRQYXRoTGluayBvZiB0aGlzLm9sZFBhdGhMaW5rcykge1xuICAgICAgICB0aGlzLmFib3J0U2lnbmFsLnRocm93SWZBYm9ydGVkKCk7XG4gICAgICAgIGNvbnN0IG9sZEF0dGFjaG1lbnRGaWxlID0gZXh0cmFjdExpbmtGaWxlKHRoaXMuYXBwLCBvbGRQYXRoTGluaywgdGhpcy5vbGRQYXRoKTtcbiAgICAgICAgaWYgKCFvbGRBdHRhY2htZW50RmlsZSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzT2xkQXR0YWNobWVudEZvbGRlckF0Um9vdCB8fCBvbGRBdHRhY2htZW50RmlsZS5wYXRoLnN0YXJ0c1dpdGgob2xkQXR0YWNobWVudEZvbGRlclBhdGgpKSB7XG4gICAgICAgICAgY29uc3Qgb2xkQXR0YWNobWVudEJhY2tsaW5rcyA9IGF3YWl0IGdldEJhY2tsaW5rc0ZvckZpbGVTYWZlKHRoaXMuYXBwLCBvbGRBdHRhY2htZW50RmlsZSk7XG4gICAgICAgICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgICAgIGlmIChvbGRBdHRhY2htZW50QmFja2xpbmtzLmtleXMoKS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIG9sZEF0dGFjaG1lbnRGaWxlcy5wdXNoKG9sZEF0dGFjaG1lbnRGaWxlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IG9sZEF0dGFjaG1lbnRGaWxlIG9mIG9sZEF0dGFjaG1lbnRGaWxlcykge1xuICAgICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgaWYgKHRoaXMuc2V0dGluZ3NNYW5hZ2VyLmlzTm90ZUV4KG9sZEF0dGFjaG1lbnRGaWxlLnBhdGgpKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBsZXQgbmV3QXR0YWNobWVudEZpbGVQYXRoOiBzdHJpbmc7XG4gICAgICBpZiAoc2V0dGluZ3Muc2hvdWxkUmVuYW1lQXR0YWNobWVudEZpbGVzKSB7XG4gICAgICAgIG5ld0F0dGFjaG1lbnRGaWxlUGF0aCA9IGF3YWl0IGdldEF0dGFjaG1lbnRGaWxlUGF0aCh7XG4gICAgICAgICAgYXBwOiB0aGlzLmFwcCxcbiAgICAgICAgICBhdHRhY2htZW50UGF0aE9yRmlsZTogb2xkQXR0YWNobWVudEZpbGUsXG4gICAgICAgICAgY29udGV4dDogQXR0YWNobWVudFBhdGhDb250ZXh0LlJlbmFtZU5vdGUsXG4gICAgICAgICAgbm90ZVBhdGhPckZpbGU6IHRoaXMubmV3UGF0aCxcbiAgICAgICAgICBvbGROb3RlUGF0aE9yRmlsZTogdGhpcy5vbGRQYXRoLFxuICAgICAgICAgIHNob3VsZFNraXBEdXBsaWNhdGVDaGVjazogdHJ1ZVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5hYm9ydFNpZ25hbC50aHJvd0lmQWJvcnRlZCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gaXNPbGRBdHRhY2htZW50Rm9sZGVyQXRSb290ID8gb2xkQXR0YWNobWVudEZpbGUucGF0aCA6IHJlbGF0aXZlKG9sZEF0dGFjaG1lbnRGb2xkZXJQYXRoLCBvbGRBdHRhY2htZW50RmlsZS5wYXRoKTtcbiAgICAgICAgY29uc3QgbmV3Rm9sZGVyID0gam9pbihuZXdBdHRhY2htZW50Rm9sZGVyUGF0aCwgZGlybmFtZShyZWxhdGl2ZVBhdGgpKTtcbiAgICAgICAgbmV3QXR0YWNobWVudEZpbGVQYXRoID0gam9pbihuZXdGb2xkZXIsIG9sZEF0dGFjaG1lbnRGaWxlLm5hbWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAob2xkQXR0YWNobWVudEZpbGUucGF0aCA9PT0gbmV3QXR0YWNobWVudEZpbGVQYXRoKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKHNldHRpbmdzLnNob3VsZERlbGV0ZUNvbmZsaWN0aW5nQXR0YWNobWVudHMpIHtcbiAgICAgICAgY29uc3QgbmV3QXR0YWNobWVudEZpbGUgPSBnZXRGaWxlT3JOdWxsKHRoaXMuYXBwLCBuZXdBdHRhY2htZW50RmlsZVBhdGgpO1xuICAgICAgICBpZiAobmV3QXR0YWNobWVudEZpbGUpIHtcbiAgICAgICAgICBnZXRMaWJEZWJ1Z2dlcignUmVuYW1lRGVsZXRlSGFuZGxlcjpmaWxsUmVuYW1lTWFwJykoYFJlbW92aW5nIGNvbmZsaWN0aW5nIGF0dGFjaG1lbnQgJHtuZXdBdHRhY2htZW50RmlsZS5wYXRofS5gKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLmFwcC5maWxlTWFuYWdlci50cmFzaEZpbGUobmV3QXR0YWNobWVudEZpbGUpO1xuICAgICAgICAgIHRoaXMuYWJvcnRTaWduYWwudGhyb3dJZkFib3J0ZWQoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgZGlyID0gZGlybmFtZShuZXdBdHRhY2htZW50RmlsZVBhdGgpO1xuICAgICAgICBjb25zdCBleHQgPSBleHRuYW1lKG5ld0F0dGFjaG1lbnRGaWxlUGF0aCk7XG4gICAgICAgIGNvbnN0IGJhc2VOYW1lID0gYmFzZW5hbWUobmV3QXR0YWNobWVudEZpbGVQYXRoLCBleHQpO1xuICAgICAgICBuZXdBdHRhY2htZW50RmlsZVBhdGggPSB0aGlzLmFwcC52YXVsdC5nZXRBdmFpbGFibGVQYXRoKGpvaW4oZGlyLCBiYXNlTmFtZSksIGV4dC5zbGljZSgxKSk7XG4gICAgICB9XG4gICAgICB0aGlzLm1hcC5zZXQob2xkQXR0YWNobWVudEZpbGUucGF0aCwgbmV3QXR0YWNobWVudEZpbGVQYXRoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0KG9sZFBhdGg6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMubWFwLmdldChvbGRQYXRoKTtcbiAgfVxuXG4gIHB1YmxpYyBpbml0QmFja2xpbmtzTWFwKFxuICAgIHNpbmdsZUJhY2tsaW5rc01hcDogTWFwPHN0cmluZywgUmVmZXJlbmNlW10+LFxuICAgIGNvbWJpbmVkQmFja2xpbmtzTWFwOiBNYXA8c3RyaW5nLCBNYXA8c3RyaW5nLCBzdHJpbmc+PixcbiAgICBwYXRoOiBzdHJpbmdcbiAgKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBbYmFja2xpbmtQYXRoLCBsaW5rc10gb2Ygc2luZ2xlQmFja2xpbmtzTWFwLmVudHJpZXMoKSkge1xuICAgICAgY29uc3QgbmV3QmFja2xpbmtQYXRoID0gdGhpcy5tYXAuZ2V0KGJhY2tsaW5rUGF0aCkgPz8gYmFja2xpbmtQYXRoO1xuICAgICAgY29uc3QgbGlua0pzb25Ub1BhdGhNYXAgPSBjb21iaW5lZEJhY2tsaW5rc01hcC5nZXQobmV3QmFja2xpbmtQYXRoKSA/PyBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAgICAgY29tYmluZWRCYWNrbGlua3NNYXAuc2V0KG5ld0JhY2tsaW5rUGF0aCwgbGlua0pzb25Ub1BhdGhNYXApO1xuICAgICAgZm9yIChjb25zdCBsaW5rIG9mIGxpbmtzKSB7XG4gICAgICAgIGxpbmtKc29uVG9QYXRoTWFwLnNldCh0b0pzb24obGluayksIHBhdGgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBrZXlzKCk6IEl0ZXJhYmxlSXRlcmF0b3I8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMubWFwLmtleXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXQob2xkUGF0aDogc3RyaW5nLCBuZXdQYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLm1hcC5zZXQob2xkUGF0aCwgbmV3UGF0aCk7XG4gIH1cbn1cblxuY2xhc3MgU2V0dGluZ3NNYW5hZ2VyIHtcbiAgcHVibGljIHJlYWRvbmx5IHJlbmFtZURlbGV0ZUhhbmRsZXJzTWFwOiBNYXA8c3RyaW5nLCAoKSA9PiBQYXJ0aWFsPFJlbmFtZURlbGV0ZUhhbmRsZXJTZXR0aW5ncz4+O1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGFwcDogQXBwKSB7XG4gICAgdGhpcy5yZW5hbWVEZWxldGVIYW5kbGVyc01hcCA9XG4gICAgICBnZXRPYnNpZGlhbkRldlV0aWxzU3RhdGUoYXBwLCAncmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAnLCBuZXcgTWFwPHN0cmluZywgKCkgPT4gUGFydGlhbDxSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3M+PigpKS52YWx1ZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRTZXR0aW5ncygpOiBQYXJ0aWFsPFJlbmFtZURlbGV0ZUhhbmRsZXJTZXR0aW5ncz4ge1xuICAgIGNvbnN0IHNldHRpbmdzQnVpbGRlcnMgPSBBcnJheS5mcm9tKHRoaXMucmVuYW1lRGVsZXRlSGFuZGxlcnNNYXAudmFsdWVzKCkpLnJldmVyc2UoKTtcblxuICAgIGNvbnN0IHNldHRpbmdzOiBQYXJ0aWFsPFJlbmFtZURlbGV0ZUhhbmRsZXJTZXR0aW5ncz4gPSB7fTtcbiAgICBzZXR0aW5ncy5pc05vdGUgPSAocGF0aDogc3RyaW5nKTogYm9vbGVhbiA9PiBpc05vdGUodGhpcy5hcHAsIHBhdGgpO1xuICAgIHNldHRpbmdzLmlzUGF0aElnbm9yZWQgPSAoKTogYm9vbGVhbiA9PiBmYWxzZTtcblxuICAgIGZvciAoY29uc3Qgc2V0dGluZ3NCdWlsZGVyIG9mIHNldHRpbmdzQnVpbGRlcnMpIHtcbiAgICAgIGNvbnN0IG5ld1NldHRpbmdzID0gc2V0dGluZ3NCdWlsZGVyKCk7XG4gICAgICBzZXR0aW5ncy5zaG91bGREZWxldGVDb25mbGljdGluZ0F0dGFjaG1lbnRzIHx8PSBuZXdTZXR0aW5ncy5zaG91bGREZWxldGVDb25mbGljdGluZ0F0dGFjaG1lbnRzID8/IGZhbHNlO1xuICAgICAgaWYgKG5ld1NldHRpbmdzLmVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yKSB7XG4gICAgICAgIHNldHRpbmdzLmVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yID8/PSBuZXdTZXR0aW5ncy5lbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvcjtcbiAgICAgIH1cbiAgICAgIHNldHRpbmdzLnNob3VsZEhhbmRsZURlbGV0aW9ucyB8fD0gbmV3U2V0dGluZ3Muc2hvdWxkSGFuZGxlRGVsZXRpb25zID8/IGZhbHNlO1xuICAgICAgc2V0dGluZ3Muc2hvdWxkSGFuZGxlUmVuYW1lcyB8fD0gbmV3U2V0dGluZ3Muc2hvdWxkSGFuZGxlUmVuYW1lcyA/PyBmYWxzZTtcbiAgICAgIHNldHRpbmdzLnNob3VsZFJlbmFtZUF0dGFjaG1lbnRGaWxlcyB8fD0gbmV3U2V0dGluZ3Muc2hvdWxkUmVuYW1lQXR0YWNobWVudEZpbGVzID8/IGZhbHNlO1xuICAgICAgc2V0dGluZ3Muc2hvdWxkUmVuYW1lQXR0YWNobWVudEZvbGRlciB8fD0gbmV3U2V0dGluZ3Muc2hvdWxkUmVuYW1lQXR0YWNobWVudEZvbGRlciA/PyBmYWxzZTtcbiAgICAgIHNldHRpbmdzLnNob3VsZFVwZGF0ZUZpbGVOYW1lQWxpYXNlcyB8fD0gbmV3U2V0dGluZ3Muc2hvdWxkVXBkYXRlRmlsZU5hbWVBbGlhc2VzID8/IGZhbHNlO1xuICAgICAgY29uc3QgaXNQYXRoSWdub3JlZCA9IHNldHRpbmdzLmlzUGF0aElnbm9yZWQ7XG4gICAgICBzZXR0aW5ncy5pc1BhdGhJZ25vcmVkID0gKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4gPT4gaXNQYXRoSWdub3JlZChwYXRoKSB8fCAobmV3U2V0dGluZ3MuaXNQYXRoSWdub3JlZD8uKHBhdGgpID8/IGZhbHNlKTtcbiAgICAgIGNvbnN0IGN1cnJlbnRJc05vdGUgPSBzZXR0aW5ncy5pc05vdGU7XG4gICAgICBzZXR0aW5ncy5pc05vdGUgPSAocGF0aDogc3RyaW5nKTogYm9vbGVhbiA9PiBjdXJyZW50SXNOb3RlKHBhdGgpICYmIChuZXdTZXR0aW5ncy5pc05vdGU/LihwYXRoKSA/PyB0cnVlKTtcbiAgICB9XG5cbiAgICBzZXR0aW5ncy5lbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvciA/Pz0gRW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3IuS2VlcDtcbiAgICByZXR1cm4gc2V0dGluZ3M7XG4gIH1cblxuICBwdWJsaWMgaXNOb3RlRXgocGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLmdldFNldHRpbmdzKCk7XG4gICAgcmV0dXJuIHNldHRpbmdzLmlzTm90ZT8uKHBhdGgpID8/IGZhbHNlO1xuICB9XG59XG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSByZW5hbWUvZGVsZXRlIGhhbmRsZXJzLlxuICpcbiAqIEBwYXJhbSBwbHVnaW4gLSBUaGUgcGx1Z2luIGluc3RhbmNlLlxuICogQHBhcmFtIHNldHRpbmdzQnVpbGRlciAtIEEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBzZXR0aW5ncyBmb3IgdGhlIHJlbmFtZSBkZWxldGUgaGFuZGxlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyUmVuYW1lRGVsZXRlSGFuZGxlcnMocGx1Z2luOiBBYm9ydGFibGVQbHVnaW4sIHNldHRpbmdzQnVpbGRlcjogKCkgPT4gUGFydGlhbDxSZW5hbWVEZWxldGVIYW5kbGVyU2V0dGluZ3M+KTogdm9pZCB7XG4gIG5ldyBSZWdpc3RyeShwbHVnaW4sIHNldHRpbmdzQnVpbGRlciwgbmV3IFNldHRpbmdzTWFuYWdlcihwbHVnaW4uYXBwKSkucmVnaXN0ZXIoKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2xlYW51cFBhcmVudEZvbGRlcnMoYXBwOiBBcHAsIHNldHRpbmdzOiBQYXJ0aWFsPFJlbmFtZURlbGV0ZUhhbmRsZXJTZXR0aW5ncz4sIHBhcmVudEZvbGRlclBhdGhzOiBzdHJpbmdbXSwgbm90ZVBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAoc2V0dGluZ3MuZW1wdHlBdHRhY2htZW50Rm9sZGVyQmVoYXZpb3IgPT09IEVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yLktlZXApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgZm9yIChjb25zdCBwYXJlbnRGb2xkZXJQYXRoIG9mIHBhcmVudEZvbGRlclBhdGhzKSB7XG4gICAgc3dpdGNoIChzZXR0aW5ncy5lbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvcikge1xuICAgICAgY2FzZSBFbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvci5EZWxldGU6XG4gICAgICAgIGF3YWl0IGRlbGV0ZVNhZmUoYXBwLCBwYXJlbnRGb2xkZXJQYXRoLCBub3RlUGF0aCwgdW5kZWZpbmVkLCB0cnVlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEVtcHR5QXR0YWNobWVudEZvbGRlckJlaGF2aW9yLkRlbGV0ZVdpdGhFbXB0eVBhcmVudHM6XG4gICAgICAgIGF3YWl0IGRlbGV0ZUVtcHR5Rm9sZGVySGllcmFyY2h5KGFwcCwgcGFyZW50Rm9sZGVyUGF0aCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBb0JBLHNCQUFzQjtBQUN0Qiw2QkFBbUM7QUFPbkMsNkJBQWlDO0FBQ2pDLG1CQUE4QjtBQUM5QixtQkFBK0I7QUFDL0IseUJBR087QUFDUCxrQkFNTztBQUNQLGlCQUF5QztBQUN6Qyw0QkFLTztBQUNQLHdCQVFPO0FBQ1Asa0JBS087QUFDUCwyQkFRTztBQUNQLDBCQUE4QjtBQUM5QixtQkFBMkI7QUFDM0IsbUJBR087QUFDUCxxQkFHTztBQUtBLElBQUssZ0NBQUwsa0JBQUtBLG1DQUFMO0FBSUwsRUFBQUEsK0JBQUEsWUFBUztBQUtULEVBQUFBLCtCQUFBLDRCQUF5QjtBQUt6QixFQUFBQSwrQkFBQSxVQUFPO0FBZEcsU0FBQUE7QUFBQSxHQUFBO0FBeUdaLE1BQU0sY0FBYztBQUFBLEVBQ1gsWUFDWSxLQUNBLE1BQ0EsYUFDQSxpQkFDQSx5QkFDakI7QUFMaUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBLEVBRW5CO0FBQUEsRUFFQSxNQUFhLFNBQXdCO0FBQ25DLFNBQUssWUFBWSxlQUFlO0FBQ2hDLHFDQUFlLGtDQUFrQyxFQUFFLGlCQUFpQixLQUFLLEtBQUssSUFBSSxFQUFFO0FBQ3BGLFFBQUksQ0FBQyxLQUFLLGdCQUFnQixTQUFTLEtBQUssS0FBSyxJQUFJLEdBQUc7QUFDbEQ7QUFBQSxJQUNGO0FBRUEsVUFBTSxXQUFXLEtBQUssZ0JBQWdCLFlBQVk7QUFDbEQsUUFBSSxDQUFDLFNBQVMsdUJBQXVCO0FBQ25DO0FBQUEsSUFDRjtBQUVBLFFBQUksU0FBUyxnQkFBZ0IsS0FBSyxLQUFLLElBQUksR0FBRztBQUM1Qyx1Q0FBZSxrQ0FBa0MsRUFBRSw4QkFBOEIsS0FBSyxLQUFLLElBQUksMEJBQTBC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O0FBQUEsRUFDNUg7QUFBQSxFQUxnQjtBQUFBLEVBT1QsY0FBb0Q7QUFDekQsVUFBTSxtQkFBbUIsTUFBTSxLQUFLLEtBQUssd0JBQXdCLE9BQU8sQ0FBQyxFQUFFLFFBQVE7QUFFbkYsVUFBTSxXQUFpRCxDQUFDO0FBQ3hELGFBQVMsU0FBUyxDQUFDLGFBQTBCLDBCQUFPLEtBQUssS0FBSyxJQUFJO0FBQ2xFLGFBQVMsZ0JBQWdCLE1BQWU7QUFFeEMsZUFBVyxtQkFBbUIsa0JBQWtCO0FBQzlDLFlBQU0sY0FBYyxnQkFBZ0I7QUFDcEMsZUFBUyx1Q0FBdUMsWUFBWSxzQ0FBc0M7QUFDbEcsVUFBSSxZQUFZLCtCQUErQjtBQUM3QyxpQkFBUyxrQ0FBa0MsWUFBWTtBQUFBLE1BQ3pEO0FBQ0EsZUFBUywwQkFBMEIsWUFBWSx5QkFBeUI7QUFDeEUsZUFBUyx3QkFBd0IsWUFBWSx1QkFBdUI7QUFDcEUsZUFBUyxnQ0FBZ0MsWUFBWSwrQkFBK0I7QUFDcEYsZUFBUyxpQ0FBaUMsWUFBWSxnQ0FBZ0M7QUFDdEYsZUFBUyxnQ0FBZ0MsWUFBWSwrQkFBK0I7QUFDcEYsWUFBTSxnQkFBZ0IsU0FBUztBQUMvQixlQUFTLGdCQUFnQixDQUFDLFNBQTBCLGNBQWMsSUFBSSxNQUFNLFlBQVksZ0JBQWdCLElBQUksS0FBSztBQUNqSCxZQUFNLGdCQUFnQixTQUFTO0FBQy9CLGVBQVMsU0FBUyxDQUFDLFNBQTBCLGNBQWMsSUFBSSxNQUFNLFlBQVksU0FBUyxJQUFJLEtBQUs7QUFBQSxJQUNyRztBQUVBLGFBQVMsa0NBQWtDO0FBQzNDLFdBQU87QUFBQSxFQUNUO0FBQUEsRUFFTyxTQUFTLE1BQXVCO0FBQ3JDLFVBQU0sV0FBVyxLQUFLLFlBQVk7QUFDbEMsV0FBTyxTQUFTLFNBQVMsSUFBSSxLQUFLO0FBQUEsRUFDcEM7QUFDRjtBQVFPLFNBQVMsNkJBQTZCLFFBQXlCLGlCQUFtRTtBQUN2SSxNQUFJLFNBQVMsUUFBUSxpQkFBaUIsSUFBSSxnQkFBZ0IsT0FBTyxHQUFHLENBQUMsRUFBRSxTQUFTO0FBQ2xGO0FBRUEsZUFBZSxxQkFBcUIsS0FBVSxVQUFnRCxtQkFBNkIsVUFBaUM7QUFDMUosTUFBSSxTQUFTLGtDQUFrQyxtQkFBb0M7QUFDakY7QUFBQSxFQUNGO0FBQ0EsYUFBVyxvQkFBb0IsbUJBQW1CO0FBQ2hELFlBQVEsU0FBUywrQkFBK0I7QUFBQSxNQUM5QyxLQUFLO0FBQ0gsa0JBQU0sMkJBQVcsS0FBSyxrQkFBa0IsVUFBVSxRQUFXLElBQUk7QUFDakU7QUFBQSxNQUNGLEtBQUs7QUFDSCxrQkFBTSwyQ0FBMkIsS0FBSyxnQkFBZ0I7QUFDdEQ7QUFBQSxNQUNGO0FBQ0U7QUFBQSxJQUNKO0FBQUEsRUFDRjtBQUNGOyIsCiAgIm5hbWVzIjogWyJFbXB0eUF0dGFjaG1lbnRGb2xkZXJCZWhhdmlvciJdCn0K