obsidian-dev-utils 91.0.0 → 92.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,13 +10,36 @@
10
10
  * The runtime behavior of the plugin is covered by its other integration tests, not by the demo vault; the
11
11
  * vault is a learning resource, and these checks only guard that it stays truthful.
12
12
  *
13
+ * They also enforce the demo-vault AUTHORING convention — every note opens with an `# H1` and a plain
14
+ * prose paragraph, every note is reachable from the start note, and no note uses a `[[wikilink]]` or a
15
+ * `[Docs](…)` line. These checks are unconditional: the demo vault is the published documentation, read
16
+ * in Obsidian AND on GitHub (where a wikilink does not render), so a note that breaks the convention is
17
+ * broken for real readers. `authoring` only tunes them (which note is the start, which notes sit outside
18
+ * the learning path); it cannot switch them off.
19
+ *
13
20
  * Two layers are exposed:
14
21
  * - {@link DemoVaultCoverageChecker} — a framework-agnostic core that reads the corpus, parses interface /
15
22
  * class / enum members and exported functions, and returns diagnostic arrays (what is undemonstrated / stale
16
- * / unlinked).
23
+ * / unlinked / off-convention).
17
24
  * - {@link registerDemoVaultCoverageSuite} — a thin wrapper that registers a `vitest` suite over the core, so
18
25
  * a plugin's `demo-vault.no-app.integration.test.ts` is a single declarative call.
19
26
  */
27
+ /**
28
+ * Tunes the always-on authoring checks. It cannot disable them — see the file overview.
29
+ */
30
+ export interface DemoVaultAuthoringSpec {
31
+ /**
32
+ * The notes (paths relative to the demo vault) that sit outside the learning path and are therefore
33
+ * exempt from every authoring check. Defaults to the vault's own `README.md`, which addresses someone
34
+ * browsing the repo on GitHub rather than a reader working through the vault.
35
+ */
36
+ readonly excludedNotes?: string[];
37
+ /**
38
+ * The note (path relative to the demo vault) every other note must be reachable from. Defaults to
39
+ * `00 Start.md`.
40
+ */
41
+ readonly startNote?: string;
42
+ }
20
43
  /**
21
44
  * Reflects a config interface whose options are demonstrated by their bare name.
22
45
  */
@@ -35,6 +58,11 @@ export interface DemoVaultConfigInterfaceCoverageSpec {
35
58
  * The parameters for the {@link DemoVaultCoverageChecker} constructor.
36
59
  */
37
60
  export interface DemoVaultCoverageCheckerConstructorParams {
61
+ /**
62
+ * The notes (paths relative to the demo vault) exempt from the authoring checks. Defaults to the
63
+ * vault's own `README.md`.
64
+ */
65
+ readonly excludedNotes?: string[];
38
66
  /**
39
67
  * The absolute path of the plugin repo root — the folder containing `demo-vault/` and the source being
40
68
  * reflected. Callers typically pass `getRootFolder() ?? process.cwd()`.
@@ -81,6 +109,15 @@ export interface DemoVaultCoverageCheckerFindUnlinkedFeatureDocsParams {
81
109
  */
82
110
  readonly nonFeatureDocs: string[];
83
111
  }
112
+ /**
113
+ * The parameters for {@link DemoVaultCoverageChecker.findUnreachableNotes}.
114
+ */
115
+ export interface DemoVaultCoverageCheckerFindUnreachableNotesParams {
116
+ /**
117
+ * The note (path relative to the demo vault) the walk starts from, e.g. `00 Start.md`.
118
+ */
119
+ readonly startNote: string;
120
+ }
84
121
  /**
85
122
  * The parameters for {@link DemoVaultCoverageChecker.getExportedFunctionNames}.
86
123
  */
@@ -174,6 +211,19 @@ export interface DemoVaultNonTrivialGuardSpec {
174
211
  */
175
212
  readonly sourcePath: string;
176
213
  }
214
+ /**
215
+ * A single demo note, as read from the demo vault.
216
+ */
217
+ export interface DemoVaultNote {
218
+ /**
219
+ * The note's raw Markdown content.
220
+ */
221
+ readonly content: string;
222
+ /**
223
+ * The note's path relative to the demo vault folder, e.g. `00 Start.md`.
224
+ */
225
+ readonly relativePath: string;
226
+ }
177
227
  /**
178
228
  * The parsed members of a source interface, class, or enum.
179
229
  */
@@ -195,6 +245,10 @@ export interface InterfaceMembers {
195
245
  * The parameters for {@link registerDemoVaultCoverageSuite}.
196
246
  */
197
247
  export interface RegisterDemoVaultCoverageSuiteParams {
248
+ /**
249
+ * Tunes the always-on authoring checks, or `undefined` to take their defaults. It cannot disable them.
250
+ */
251
+ readonly authoring?: DemoVaultAuthoringSpec;
198
252
  /**
199
253
  * The config interfaces whose options must each be demonstrated by their bare name.
200
254
  */
@@ -229,7 +283,9 @@ export interface RegisterDemoVaultCoverageSuiteParams {
229
283
  */
230
284
  export declare class DemoVaultCoverageChecker {
231
285
  private cachedCorpus;
286
+ private cachedNotes;
232
287
  private readonly demoVaultFolder;
288
+ private readonly excludedNotes;
233
289
  private readonly rootFolder;
234
290
  /**
235
291
  * Creates a checker rooted at a plugin repo.
@@ -243,6 +299,41 @@ export declare class DemoVaultCoverageChecker {
243
299
  * @returns The relative paths of every `*.md` note in the demo vault.
244
300
  */
245
301
  collectDemoNoteRelativePaths(): string[];
302
+ /**
303
+ * Reads and caches every demo note individually — the per-note view the authoring checks work on, as
304
+ * opposed to the concatenated {@link DemoVaultCoverageChecker.readCorpus}.
305
+ *
306
+ * @returns Every `*.md` note in the demo vault, excluded ones included.
307
+ */
308
+ collectNotes(): DemoVaultNote[];
309
+ /**
310
+ * Finds notes carrying a `[Docs](…)` link line. The note IS the documentation, so a line pointing
311
+ * elsewhere for the real explanation is the shape this convention exists to remove.
312
+ *
313
+ * @returns The relative paths of the offending notes.
314
+ */
315
+ findNotesWithDocsLinks(): string[];
316
+ /**
317
+ * Finds notes that do not open with an `# H1` (frontmatter aside).
318
+ *
319
+ * @returns The relative paths of the offending notes.
320
+ */
321
+ findNotesWithoutH1(): string[];
322
+ /**
323
+ * Finds notes with no prose paragraph before their first code fence — the 1-3 sentences saying what the
324
+ * feature does and why a reader would want it, without which the note is a button with no lesson.
325
+ *
326
+ * @returns The relative paths of the offending notes.
327
+ */
328
+ findNotesWithoutIntroProse(): string[];
329
+ /**
330
+ * Finds notes using an Obsidian `[[wikilink]]` outside a code fence. The demo vault is also read on
331
+ * GitHub, where a wikilink renders as literal brackets and leads nowhere. A wikilink shown INSIDE a
332
+ * fence is sample text, not navigation, so fenced blocks are skipped.
333
+ *
334
+ * @returns The relative paths of the offending notes.
335
+ */
336
+ findNotesWithWikilinks(): string[];
246
337
  /**
247
338
  * Finds members that the demo notes reference on a receiver but that no longer exist on it (rename drift).
248
339
  *
@@ -264,6 +355,19 @@ export declare class DemoVaultCoverageChecker {
264
355
  * @returns The feature-doc basenames (without `.md`) not linked from any demo note.
265
356
  */
266
357
  findUnlinkedFeatureDocs(params: DemoVaultCoverageCheckerFindUnlinkedFeatureDocsParams): string[];
358
+ /**
359
+ * Finds notes that cannot be reached from the start note by following Markdown links between notes.
360
+ *
361
+ * The walk starts at {@link DemoVaultCoverageCheckerFindUnreachableNotesParams.startNote} and follows
362
+ * every `[Text](<./NN Name.md>)` link outside a code fence, transitively. A note nothing links to is
363
+ * one a reader can only find by browsing the file list — which is exactly what the grouped index in the
364
+ * start note is meant to replace. When the start note itself is missing, EVERY note is unreachable,
365
+ * because there is nowhere to start from.
366
+ *
367
+ * @param params - The parameters for the walk.
368
+ * @returns The relative paths of the unreachable notes.
369
+ */
370
+ findUnreachableNotes(params: DemoVaultCoverageCheckerFindUnreachableNotesParams): string[];
267
371
  /**
268
372
  * Parses the names of the `export function`s (including `async` and generator declarations) in a source file.
269
373
  *
@@ -285,6 +389,7 @@ export declare class DemoVaultCoverageChecker {
285
389
  * @returns The concatenated demo-note contents.
286
390
  */
287
391
  readCorpus(): string;
392
+ private collectCheckableNotes;
288
393
  private collectMarkdownFiles;
289
394
  }
290
395
  /**
@@ -30,15 +30,20 @@ import {
30
30
  expect,
31
31
  it
32
32
  } from "vitest";
33
+ import { normalizeOptionalProperties } from "../object-utils.mjs";
33
34
  import { ObsidianPluginRepoPaths } from "../obsidian/plugin/obsidian-plugin-repo-paths.mjs";
34
35
  import {
36
+ dirname,
35
37
  join,
36
38
  relative
37
39
  } from "../path.mjs";
38
40
  import { getMandatoryNamedGroup } from "../reg-exp.mjs";
41
+ import { ensureNonNullable } from "../type-guards.mjs";
39
42
  class DemoVaultCoverageChecker {
40
43
  cachedCorpus = null;
44
+ cachedNotes = null;
41
45
  demoVaultFolder;
46
+ excludedNotes;
42
47
  rootFolder;
43
48
  /**
44
49
  * Creates a checker rooted at a plugin repo.
@@ -48,6 +53,7 @@ class DemoVaultCoverageChecker {
48
53
  constructor(params) {
49
54
  this.rootFolder = params.rootFolder;
50
55
  this.demoVaultFolder = join(this.rootFolder, ObsidianPluginRepoPaths.DemoVault);
56
+ this.excludedNotes = new Set(params.excludedNotes ?? DEFAULT_EXCLUDED_NOTES);
51
57
  }
52
58
  /**
53
59
  * Collects the demo notes as paths relative to the demo vault folder (for a non-trivial-surface guard).
@@ -55,7 +61,56 @@ class DemoVaultCoverageChecker {
55
61
  * @returns The relative paths of every `*.md` note in the demo vault.
56
62
  */
57
63
  collectDemoNoteRelativePaths() {
58
- return this.collectMarkdownFiles(this.demoVaultFolder).map((file) => relative(this.demoVaultFolder, file));
64
+ return this.collectNotes().map((note) => note.relativePath);
65
+ }
66
+ /**
67
+ * Reads and caches every demo note individually — the per-note view the authoring checks work on, as
68
+ * opposed to the concatenated {@link DemoVaultCoverageChecker.readCorpus}.
69
+ *
70
+ * @returns Every `*.md` note in the demo vault, excluded ones included.
71
+ */
72
+ collectNotes() {
73
+ this.cachedNotes ??= this.collectMarkdownFiles(this.demoVaultFolder).map((file) => ({
74
+ content: readFileSync(file, "utf-8"),
75
+ relativePath: relative(this.demoVaultFolder, file)
76
+ }));
77
+ return this.cachedNotes;
78
+ }
79
+ /**
80
+ * Finds notes carrying a `[Docs](…)` link line. The note IS the documentation, so a line pointing
81
+ * elsewhere for the real explanation is the shape this convention exists to remove.
82
+ *
83
+ * @returns The relative paths of the offending notes.
84
+ */
85
+ findNotesWithDocsLinks() {
86
+ return this.collectCheckableNotes().filter((note) => getLinesOutsideFences(note.content).some((line) => DOCS_LINK_REG_EXP.test(line))).map((note) => note.relativePath);
87
+ }
88
+ /**
89
+ * Finds notes that do not open with an `# H1` (frontmatter aside).
90
+ *
91
+ * @returns The relative paths of the offending notes.
92
+ */
93
+ findNotesWithoutH1() {
94
+ return this.collectCheckableNotes().filter((note) => !hasH1(note.content)).map((note) => note.relativePath);
95
+ }
96
+ /**
97
+ * Finds notes with no prose paragraph before their first code fence — the 1-3 sentences saying what the
98
+ * feature does and why a reader would want it, without which the note is a button with no lesson.
99
+ *
100
+ * @returns The relative paths of the offending notes.
101
+ */
102
+ findNotesWithoutIntroProse() {
103
+ return this.collectCheckableNotes().filter((note) => !hasIntroProse(note.content)).map((note) => note.relativePath);
104
+ }
105
+ /**
106
+ * Finds notes using an Obsidian `[[wikilink]]` outside a code fence. The demo vault is also read on
107
+ * GitHub, where a wikilink renders as literal brackets and leads nowhere. A wikilink shown INSIDE a
108
+ * fence is sample text, not navigation, so fenced blocks are skipped.
109
+ *
110
+ * @returns The relative paths of the offending notes.
111
+ */
112
+ findNotesWithWikilinks() {
113
+ return this.collectCheckableNotes().filter((note) => getLinesOutsideFences(note.content).some((line) => WIKILINK_REG_EXP.test(stripInlineCode(line)))).map((note) => note.relativePath);
59
114
  }
60
115
  /**
61
116
  * Finds members that the demo notes reference on a receiver but that no longer exist on it (rename drift).
@@ -95,6 +150,33 @@ class DemoVaultCoverageChecker {
95
150
  );
96
151
  return featureDocs.filter((doc) => !linkedDocs.has(doc));
97
152
  }
153
+ /**
154
+ * Finds notes that cannot be reached from the start note by following Markdown links between notes.
155
+ *
156
+ * The walk starts at {@link DemoVaultCoverageCheckerFindUnreachableNotesParams.startNote} and follows
157
+ * every `[Text](<./NN Name.md>)` link outside a code fence, transitively. A note nothing links to is
158
+ * one a reader can only find by browsing the file list — which is exactly what the grouped index in the
159
+ * start note is meant to replace. When the start note itself is missing, EVERY note is unreachable,
160
+ * because there is nowhere to start from.
161
+ *
162
+ * @param params - The parameters for the walk.
163
+ * @returns The relative paths of the unreachable notes.
164
+ */
165
+ findUnreachableNotes(params) {
166
+ const notesByRelativePath = new Map(this.collectNotes().map((note) => [note.relativePath, note]));
167
+ const reachedNotes = /* @__PURE__ */ new Set();
168
+ const pendingNotes = [params.startNote];
169
+ while (pendingNotes.length > 0) {
170
+ const notePath = ensureNonNullable(pendingNotes.pop());
171
+ const note = notesByRelativePath.get(notePath);
172
+ if (!note || reachedNotes.has(notePath)) {
173
+ continue;
174
+ }
175
+ reachedNotes.add(notePath);
176
+ pendingNotes.push(...collectNoteLinkTargets(note));
177
+ }
178
+ return this.collectCheckableNotes().map((note) => note.relativePath).filter((notePath) => !reachedNotes.has(notePath));
179
+ }
98
180
  /**
99
181
  * Parses the names of the `export function`s (including `async` and generator declarations) in a source file.
100
182
  *
@@ -126,9 +208,14 @@ class DemoVaultCoverageChecker {
126
208
  * @returns The concatenated demo-note contents.
127
209
  */
128
210
  readCorpus() {
129
- this.cachedCorpus ??= this.collectMarkdownFiles(this.demoVaultFolder).map((file) => readFileSync(file, "utf-8")).join("\n");
211
+ this.cachedCorpus ??= this.collectNotes().map((note) => note.content).join("\n");
130
212
  return this.cachedCorpus;
131
213
  }
214
+ // The notes the authoring checks apply to: every note except the ones declared outside the learning
215
+ // Path (the vault's own `README.md` by default).
216
+ collectCheckableNotes() {
217
+ return this.collectNotes().filter((note) => !this.excludedNotes.has(note.relativePath));
218
+ }
132
219
  collectMarkdownFiles(folder) {
133
220
  const result = [];
134
221
  for (const entry of readdirSync(folder, { withFileTypes: true })) {
@@ -145,7 +232,11 @@ class DemoVaultCoverageChecker {
145
232
  }
146
233
  }
147
234
  function registerDemoVaultCoverageSuite(params) {
148
- const checker = new DemoVaultCoverageChecker({ rootFolder: params.rootFolder });
235
+ const checker = new DemoVaultCoverageChecker(normalizeOptionalProperties({
236
+ excludedNotes: params.authoring?.excludedNotes,
237
+ rootFolder: params.rootFolder
238
+ }));
239
+ const startNote = params.authoring?.startNote ?? DEFAULT_START_NOTE;
149
240
  describe("demo-vault coverage", () => {
150
241
  for (const spec of params.interfaces) {
151
242
  it(`demonstrates every ${spec.interfaceName} ${spec.kind}`, () => {
@@ -179,6 +270,21 @@ function registerDemoVaultCoverageSuite(params) {
179
270
  expect(checker.findUnlinkedFeatureDocs({ docsFolder: docs.folder, nonFeatureDocs: docs.nonFeatureDocs })).toEqual([]);
180
271
  });
181
272
  }
273
+ it("opens every note with an H1", () => {
274
+ expect(checker.findNotesWithoutH1()).toEqual([]);
275
+ });
276
+ it("opens every note with a prose paragraph before its first code block", () => {
277
+ expect(checker.findNotesWithoutIntroProse()).toEqual([]);
278
+ });
279
+ it(`reaches every note from ${startNote}`, () => {
280
+ expect(checker.findUnreachableNotes({ startNote })).toEqual([]);
281
+ });
282
+ it("uses no wikilinks, which do not render on GitHub", () => {
283
+ expect(checker.findNotesWithWikilinks()).toEqual([]);
284
+ });
285
+ it("carries no Docs link line, because the note is the docs", () => {
286
+ expect(checker.findNotesWithDocsLinks()).toEqual([]);
287
+ });
182
288
  it("keeps the reflected surface non-trivial", () => {
183
289
  const guard = params.nonTrivialGuard;
184
290
  const members = checker.getInterfaceMembers(guard);
@@ -188,6 +294,18 @@ function registerDemoVaultCoverageSuite(params) {
188
294
  });
189
295
  }
190
296
  const CLASS_MEMBER_MODIFIERS = String.raw`(?:(?:public|private|protected|readonly|static|abstract|override)\s+)*`;
297
+ const ABSOLUTE_URL_REG_EXP = /^[a-z][\w+.-]*:/i;
298
+ const ANGLE_BRACKETS_REG_EXP = /^<|>$/g;
299
+ const CODE_FENCE_REG_EXP = /^\s*(?:```|~~~)/;
300
+ const DEFAULT_EXCLUDED_NOTES = ["README.md"];
301
+ const DEFAULT_START_NOTE = "00 Start.md";
302
+ const DOCS_LINK_REG_EXP = /^\s*\[Docs]\(/;
303
+ const FRONTMATTER_REG_EXP = /^---\r?\n[\s\S]*?\r?\n---[^\S\n]*\r?\n?/;
304
+ const H1_REG_EXP = /^# \S/;
305
+ const HEADING_REG_EXP = /^#{1,6} /;
306
+ const INLINE_CODE_REG_EXP = /`[^`\n]*`/g;
307
+ const MARKDOWN_LINK_REG_EXP = /\[[^\]]*]\((?<target>[^)]+)\)/g;
308
+ const WIKILINK_REG_EXP = /\[\[[^\]]+]]/;
191
309
  function buildMembers(methods, properties) {
192
310
  return {
193
311
  all: [...methods, ...properties],
@@ -195,6 +313,20 @@ function buildMembers(methods, properties) {
195
313
  properties
196
314
  };
197
315
  }
316
+ function collectNoteLinkTargets(note) {
317
+ const targets = [];
318
+ for (const line of getLinesOutsideFences(note.content)) {
319
+ for (const match of stripInlineCode(line).matchAll(MARKDOWN_LINK_REG_EXP)) {
320
+ const target = getMandatoryNamedGroup(match, "target").replaceAll(ANGLE_BRACKETS_REG_EXP, "");
321
+ const [notePath = ""] = target.split("#", 1);
322
+ if (ABSOLUTE_URL_REG_EXP.test(notePath) || !notePath.toLowerCase().endsWith(".md")) {
323
+ continue;
324
+ }
325
+ targets.push(join(dirname(note.relativePath), tryDecodeUriComponent(notePath)));
326
+ }
327
+ }
328
+ return targets;
329
+ }
198
330
  function extractClassMethodNames(classBody) {
199
331
  return [...classBody.matchAll(new RegExp(String.raw`^ {2}(?<modifiers>${CLASS_MEMBER_MODIFIERS})(?<name>\w+)(?:<[^>]*>)?\(`, "gm"))].filter((match) => !isNonPublicMember(getMandatoryNamedGroup(match, "modifiers"))).map((match) => getMandatoryNamedGroup(match, "name"));
200
332
  }
@@ -210,6 +342,43 @@ function extractMethodNames(interfaceBody) {
210
342
  function extractPropertyNames(interfaceBody) {
211
343
  return [...interfaceBody.matchAll(/^ {2}(?<name>\w+)\??:/gm)].map((match) => getMandatoryNamedGroup(match, "name"));
212
344
  }
345
+ function getLinesOutsideFences(content) {
346
+ const lines = [];
347
+ let isInsideFence = false;
348
+ for (const line of content.split("\n")) {
349
+ if (CODE_FENCE_REG_EXP.test(line)) {
350
+ isInsideFence = !isInsideFence;
351
+ continue;
352
+ }
353
+ if (!isInsideFence) {
354
+ lines.push(line);
355
+ }
356
+ }
357
+ return lines;
358
+ }
359
+ function hasH1(content) {
360
+ for (const line of stripFrontmatter(content).split("\n")) {
361
+ const trimmedLine = line.trim();
362
+ if (trimmedLine === "") {
363
+ continue;
364
+ }
365
+ return H1_REG_EXP.test(trimmedLine);
366
+ }
367
+ return false;
368
+ }
369
+ function hasIntroProse(content) {
370
+ for (const line of stripFrontmatter(content).split("\n")) {
371
+ if (CODE_FENCE_REG_EXP.test(line)) {
372
+ return false;
373
+ }
374
+ const trimmedLine = line.trim();
375
+ if (trimmedLine === "" || HEADING_REG_EXP.test(trimmedLine)) {
376
+ continue;
377
+ }
378
+ return true;
379
+ }
380
+ return false;
381
+ }
213
382
  function isNonPublicMember(modifiers) {
214
383
  return /\b(?:private|protected)\b/.test(modifiers);
215
384
  }
@@ -226,8 +395,21 @@ function parseMembers(keyword, body) {
226
395
  }
227
396
  }
228
397
  }
398
+ function stripFrontmatter(content) {
399
+ return content.replace(FRONTMATTER_REG_EXP, "");
400
+ }
401
+ function stripInlineCode(line) {
402
+ return line.replaceAll(INLINE_CODE_REG_EXP, "");
403
+ }
404
+ function tryDecodeUriComponent(value) {
405
+ try {
406
+ return decodeURIComponent(value);
407
+ } catch {
408
+ return value;
409
+ }
410
+ }
229
411
  export {
230
412
  DemoVaultCoverageChecker,
231
413
  registerDemoVaultCoverageSuite
232
414
  };
233
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL3NjcmlwdC11dGlscy9kZW1vLXZhdWx0LWNvdmVyYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogU3RhdGljIGNvdmVyYWdlL2ZyZXNobmVzcyBjaGVja3MgdGhhdCBrZWVwIGEgcGx1Z2luJ3MgaW4tcmVwbyBgZGVtby12YXVsdC9gIGluIHN5bmMgd2l0aCBpdHMgcHVibGljIHN1cmZhY2UuXG4gKlxuICogQSBwbHVnaW4gY2FuIHNoaXAgYSBjdXJhdGVkIGRlbW8gdmF1bHQgYXQgYGRlbW8tdmF1bHQvYCBpbiBpdHMgcmVwbyByb290LiBUaGVzZSBoZWxwZXJzIHJlZmxlY3QgdGhlIHJlYWxcbiAqIHB1YmxpYyBBUEkvY29uZmlnL2RvY3Mgc3RyYWlnaHQgZnJvbSBzb3VyY2UgYW5kIGFzc2VydCBcdTIwMTQgV0lUSE9VVCBsYXVuY2hpbmcgT2JzaWRpYW4gXHUyMDE0IHRoYXQgZXZlcnkgZmVhdHVyZSBpc1xuICogZGVtb25zdHJhdGVkIGluIHRoZSBub3RlcyBhbmQgdGhhdCB0aGUgbm90ZXMgcmVmZXJlbmNlIG5vIEFQSSBtZW1iZXIgdGhhdCBubyBsb25nZXIgZXhpc3RzIChyZW5hbWUgZHJpZnQpLlxuICogVGhlIHJ1bnRpbWUgYmVoYXZpb3Igb2YgdGhlIHBsdWdpbiBpcyBjb3ZlcmVkIGJ5IGl0cyBvdGhlciBpbnRlZ3JhdGlvbiB0ZXN0cywgbm90IGJ5IHRoZSBkZW1vIHZhdWx0OyB0aGVcbiAqIHZhdWx0IGlzIGEgbGVhcm5pbmcgcmVzb3VyY2UsIGFuZCB0aGVzZSBjaGVja3Mgb25seSBndWFyZCB0aGF0IGl0IHN0YXlzIHRydXRoZnVsLlxuICpcbiAqIFR3byBsYXllcnMgYXJlIGV4cG9zZWQ6XG4gKiAtIHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJ9IFx1MjAxNCBhIGZyYW1ld29yay1hZ25vc3RpYyBjb3JlIHRoYXQgcmVhZHMgdGhlIGNvcnB1cywgcGFyc2VzIGludGVyZmFjZSAvXG4gKiAgIGNsYXNzIC8gZW51bSBtZW1iZXJzIGFuZCBleHBvcnRlZCBmdW5jdGlvbnMsIGFuZCByZXR1cm5zIGRpYWdub3N0aWMgYXJyYXlzICh3aGF0IGlzIHVuZGVtb25zdHJhdGVkIC8gc3RhbGVcbiAqICAgLyB1bmxpbmtlZCkuXG4gKiAtIHtAbGluayByZWdpc3RlckRlbW9WYXVsdENvdmVyYWdlU3VpdGV9IFx1MjAxNCBhIHRoaW4gd3JhcHBlciB0aGF0IHJlZ2lzdGVycyBhIGB2aXRlc3RgIHN1aXRlIG92ZXIgdGhlIGNvcmUsIHNvXG4gKiAgIGEgcGx1Z2luJ3MgYGRlbW8tdmF1bHQubm8tYXBwLmludGVncmF0aW9uLnRlc3QudHNgIGlzIGEgc2luZ2xlIGRlY2xhcmF0aXZlIGNhbGwuXG4gKi9cblxuaW1wb3J0IHtcbiAgcmVhZGRpclN5bmMsXG4gIHJlYWRGaWxlU3luY1xufSBmcm9tICdub2RlOmZzJztcbmltcG9ydCB7XG4gIGRlc2NyaWJlLFxuICBleHBlY3QsXG4gIGl0XG59IGZyb20gJ3ZpdGVzdCc7XG5cbmltcG9ydCB7IE9ic2lkaWFuUGx1Z2luUmVwb1BhdGhzIH0gZnJvbSAnLi4vb2JzaWRpYW4vcGx1Z2luL29ic2lkaWFuLXBsdWdpbi1yZXBvLXBhdGhzLnRzJztcbmltcG9ydCB7XG4gIGpvaW4sXG4gIHJlbGF0aXZlXG59IGZyb20gJy4uL3BhdGgudHMnO1xuaW1wb3J0IHsgZ2V0TWFuZGF0b3J5TmFtZWRHcm91cCB9IGZyb20gJy4uL3JlZy1leHAudHMnO1xuXG4vKipcbiAqIFJlZmxlY3RzIGEgY29uZmlnIGludGVyZmFjZSB3aG9zZSBvcHRpb25zIGFyZSBkZW1vbnN0cmF0ZWQgYnkgdGhlaXIgYmFyZSBuYW1lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvbmZpZ0ludGVyZmFjZUNvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYGV4cG9ydCBpbnRlcmZhY2VgLCBgZXhwb3J0IGNsYXNzYCwgb3IgYGV4cG9ydCBlbnVtYCB3aG9zZSBwcm9wZXJ0aWVzIGFyZSB0aGUgY29uZmlnXG4gICAqIG9wdGlvbnMuXG4gICAqL1xuICByZWFkb25seSBpbnRlcmZhY2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB0aGF0IGRlY2xhcmVzIHRoZSBpbnRlcmZhY2UsIGNsYXNzLCBvciBlbnVtLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUge0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlcn0gY29uc3RydWN0b3IuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyQ29uc3RydWN0b3JQYXJhbXMge1xuICAvKipcbiAgICogVGhlIGFic29sdXRlIHBhdGggb2YgdGhlIHBsdWdpbiByZXBvIHJvb3QgXHUyMDE0IHRoZSBmb2xkZXIgY29udGFpbmluZyBgZGVtby12YXVsdC9gIGFuZCB0aGUgc291cmNlIGJlaW5nXG4gICAqIHJlZmxlY3RlZC4gQ2FsbGVycyB0eXBpY2FsbHkgcGFzcyBgZ2V0Um9vdEZvbGRlcigpID8/IHByb2Nlc3MuY3dkKClgLlxuICAgKi9cbiAgcmVhZG9ubHkgcm9vdEZvbGRlcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmZpbmRTdGFsZVJlZmVyZW5jZXN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRTdGFsZVJlZmVyZW5jZXNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIHJlY2VpdmVyIHdob3NlIGBgIGAke3JlY2VpdmVyfS48bWVtYmVyPmAgYGAgcmVmZXJlbmNlcyBhcmUgc2Nhbm5lZCBmb3IgaW4gdGhlIGRlbW8gY29ycHVzLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVjZWl2ZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG1lbWJlcnMgdGhhdCBjdXJyZW50bHkgZXhpc3Qgb24gdGhlIHJlY2VpdmVyOyBhbnkgcmVmZXJlbmNlZCBtZW1iZXIgbm90IGluIHRoaXMgc2V0IGlzIHN0YWxlLlxuICAgKi9cbiAgcmVhZG9ubHkgdmFsaWRNZW1iZXJzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUaGUgcGFyYW1ldGVycyBmb3Ige0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlci5maW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJGaW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBtZW1iZXIgbmFtZXMgdGhhdCBtdXN0IGVhY2ggYXBwZWFyIGluIHRoZSBkZW1vIGNvcnB1cy5cbiAgICovXG4gIHJlYWRvbmx5IG1lbWJlcnM6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBXaGVuIHNldCwgYSBtZW1iZXIgaXMgZGVtb25zdHJhdGVkIG9ubHkgaWYgYGAgYCR7cmVjZWl2ZXJ9LiR7bWVtYmVyfWAgYGAgYXBwZWFycyAoZS5nLiBhIGNvbnRleHQgb2JqZWN0J3NcbiAgICogbWV0aG9kcyk7IHdoZW4gYWJzZW50LCB0aGUgYmFyZSBtZW1iZXIgbmFtZSBpcyBsb29rZWQgdXAgKGUuZy4gYSBjb25maWcgb3B0aW9uKS5cbiAgICovXG4gIHJlYWRvbmx5IHJlY2VpdmVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmZpbmRVbmxpbmtlZEZlYXR1cmVEb2NzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJGaW5kVW5saW5rZWRGZWF0dXJlRG9jc1BhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgZG9jcyBmb2xkZXIgKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIHRvcC1sZXZlbCBgKi5tZGAgZmlsZXMgYXJlIHRoZSBmZWF0dXJlIGRvY3MuXG4gICAqL1xuICByZWFkb25seSBkb2NzRm9sZGVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBkb2MgYmFzZW5hbWVzICh3aXRob3V0IGAubWRgKSB0aGF0IGFyZSBOT1QgcGVyLWZlYXR1cmUgcGFnZXMgYW5kIHNvIG5lZWQgbm8gbGlua2luZyBkZW1vIG5vdGUuXG4gICAqL1xuICByZWFkb25seSBub25GZWF0dXJlRG9jczogc3RyaW5nW107XG59XG5cbi8qKlxuICogVGhlIHBhcmFtZXRlcnMgZm9yIHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXIuZ2V0RXhwb3J0ZWRGdW5jdGlvbk5hbWVzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJHZXRFeHBvcnRlZEZ1bmN0aW9uTmFtZXNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIHNvdXJjZSBmaWxlIHBhdGggKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIGBleHBvcnQgZnVuY3Rpb25gcyBhcmUgcGFyc2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmdldEludGVyZmFjZU1lbWJlcnN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckdldEludGVyZmFjZU1lbWJlcnNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGBleHBvcnQgaW50ZXJmYWNlYCwgYGV4cG9ydCBjbGFzc2AsIG9yIGBleHBvcnQgZW51bWAgdG8gcGFyc2UuXG4gICAqL1xuICByZWFkb25seSBpbnRlcmZhY2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB0aGF0IGRlY2xhcmVzIHRoZSBpbnRlcmZhY2UsIGNsYXNzLCBvciBlbnVtLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyZXMgdGhlIGZlYXR1cmUtZG9jIGxpbmtpbmcgY2hlY2suXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0RG9jc0NvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgZG9jcyBmb2xkZXIgKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIHRvcC1sZXZlbCBgKi5tZGAgZmlsZXMgYXJlIHRoZSBmZWF0dXJlIGRvY3MuXG4gICAqL1xuICByZWFkb25seSBmb2xkZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRvYyBiYXNlbmFtZXMgKHdpdGhvdXQgYC5tZGApIHRoYXQgYXJlIE5PVCBwZXItZmVhdHVyZSBwYWdlcyBhbmQgc28gbmVlZCBubyBsaW5raW5nIGRlbW8gbm90ZS5cbiAgICovXG4gIHJlYWRvbmx5IG5vbkZlYXR1cmVEb2NzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBSZWZsZWN0cyBhIG1vZHVsZSdzIGV4cG9ydGVkIGZ1bmN0aW9ucywgZWFjaCBkZW1vbnN0cmF0ZWQgYnkgaXRzIGJhcmUgbmFtZSBpbiB0aGUgZGVtbyBjb3JwdXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0RnVuY3Rpb25zQ292ZXJhZ2VTcGVjIHtcbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB3aG9zZSBgZXhwb3J0IGZ1bmN0aW9uYHMgbXVzdCBlYWNoIGJlIGRlbW9uc3RyYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZWZsZWN0cyBhIHNpbmdsZSBpbnRlcmZhY2UncyBtZW1iZXJzIGFuZCBkZW1vbnN0cmF0ZXMgdGhlbSB2aWEgYGAgYCR7cmVjZWl2ZXJ9LjxtZW1iZXI+YCBgYCByZWZlcmVuY2VzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdEludGVyZmFjZUNvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYGV4cG9ydCBpbnRlcmZhY2VgLCBgZXhwb3J0IGNsYXNzYCwgb3IgYGV4cG9ydCBlbnVtYCB0byByZWZsZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJmYWNlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBkZW1vbnN0cmF0ZWQgbWVtYmVycyBhcmUgdGhlIHJlZmxlY3RlZCB0eXBlJ3MgbWV0aG9kcyBvciBpdHMgcHJvcGVydGllcyAoZW51bSBtZW1iZXJzIGNvdW50IGFzXG4gICAqIHByb3BlcnRpZXMpLlxuICAgKi9cbiAgcmVhZG9ubHkga2luZDogRGVtb1ZhdWx0SW50ZXJmYWNlTWVtYmVyS2luZDtcblxuICAvKipcbiAgICogVGhlIGlkZW50aWZpZXIgdGhlIG5vdGVzIGNhbGwgdGhlIG1lbWJlcnMgb24gKGUuZy4gYGNvZGVCdXR0b25Db250ZXh0YCkuXG4gICAqL1xuICByZWFkb25seSByZWNlaXZlcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc291cmNlIGZpbGUgcGF0aCAocmVsYXRpdmUgdG8gdGhlIHJlcG8gcm9vdCkgdGhhdCBkZWNsYXJlcyB0aGUgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bS5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGFuIGludGVyZmFjZSdzIGRlbW9uc3RyYXRlZCBtZW1iZXJzIGFyZSBpdHMgbWV0aG9kcyBvciBpdHMgcHJvcGVydGllcy5cbiAqL1xuZXhwb3J0IHR5cGUgRGVtb1ZhdWx0SW50ZXJmYWNlTWVtYmVyS2luZCA9ICdtZXRob2RzJyB8ICdwcm9wZXJ0aWVzJztcblxuLyoqXG4gKiBDb25maWd1cmVzIHRoZSBndWFyZCB0aGF0IHRoZSByZWZsZWN0ZWQgc3VyZmFjZSBpcyBub24tdHJpdmlhbCAocHJvdGVjdHMgYWdhaW5zdCBhIHBhcnNpbmcgcmVncmVzc2lvblxuICogc2lsZW50bHkgZW1wdHlpbmcgZXZlcnkgb3RoZXIgY2hlY2spLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdE5vblRyaXZpYWxHdWFyZFNwZWMge1xuICAvKipcbiAgICogQSBkZW1vIG5vdGUgKHBhdGggcmVsYXRpdmUgdG8gdGhlIGRlbW8gdmF1bHQpIHRoYXQgbXVzdCBiZSBwcmVzZW50LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhwZWN0RGVtb05vdGU6IHN0cmluZztcblxuICAvKipcbiAgICogQSBtZW1iZXIgdGhhdCBtdXN0IGJlIHJlZmxlY3RlZCBmcm9tIHtAbGluayBEZW1vVmF1bHROb25Ucml2aWFsR3VhcmRTcGVjLmludGVyZmFjZU5hbWV9LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhwZWN0TWVtYmVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBgZXhwb3J0IGludGVyZmFjZWAsIGBleHBvcnQgY2xhc3NgLCBvciBgZXhwb3J0IGVudW1gIHdob3NlIG1lbWJlcnMgYXJlIHJlLXBhcnNlZCBmb3IgdGhlXG4gICAqIGd1YXJkLlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJmYWNlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc291cmNlIGZpbGUgcGF0aCAocmVsYXRpdmUgdG8gdGhlIHJlcG8gcm9vdCkgdGhhdCBkZWNsYXJlcyB0aGUgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bS5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBUaGUgcGFyc2VkIG1lbWJlcnMgb2YgYSBzb3VyY2UgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbnRlcmZhY2VNZW1iZXJzIHtcbiAgLyoqXG4gICAqIEV2ZXJ5IG1lbWJlciBcdTIwMTQge0BsaW5rIEludGVyZmFjZU1lbWJlcnMubWV0aG9kc30gZm9sbG93ZWQgYnkge0BsaW5rIEludGVyZmFjZU1lbWJlcnMucHJvcGVydGllc30uXG4gICAqL1xuICByZWFkb25seSBhbGw6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgbWV0aG9kIG1lbWJlcnMgKGRlY2xhcmVkIGFzIGBuYW1lKC4uLilgKS5cbiAgICovXG4gIHJlYWRvbmx5IG1ldGhvZHM6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgcHJvcGVydHkgbWVtYmVycyAoZGVjbGFyZWQgYXMgYG5hbWU/OiAuLi5gKS5cbiAgICovXG4gIHJlYWRvbmx5IHByb3BlcnRpZXM6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgcmVnaXN0ZXJEZW1vVmF1bHRDb3ZlcmFnZVN1aXRlfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWdpc3RlckRlbW9WYXVsdENvdmVyYWdlU3VpdGVQYXJhbXMge1xuICAvKipcbiAgICogVGhlIGNvbmZpZyBpbnRlcmZhY2VzIHdob3NlIG9wdGlvbnMgbXVzdCBlYWNoIGJlIGRlbW9uc3RyYXRlZCBieSB0aGVpciBiYXJlIG5hbWUuXG4gICAqL1xuICByZWFkb25seSBjb25maWdJbnRlcmZhY2VzOiBEZW1vVmF1bHRDb25maWdJbnRlcmZhY2VDb3ZlcmFnZVNwZWNbXTtcblxuICAvKipcbiAgICogVGhlIGZlYXR1cmUtZG9jIGxpbmtpbmcgY2hlY2ssIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlIHBsdWdpbiBzaGlwcyBubyBgZG9jcy9gIGZvbGRlci5cbiAgICovXG4gIHJlYWRvbmx5IGRvY3M/OiBEZW1vVmF1bHREb2NzQ292ZXJhZ2VTcGVjO1xuXG4gIC8qKlxuICAgKiBUaGUgbW9kdWxlcyB3aG9zZSBgZXhwb3J0IGZ1bmN0aW9uYHMgbXVzdCBlYWNoIGJlIGRlbW9uc3RyYXRlZCBieSB0aGVpciBiYXJlIG5hbWUsIG9yIGB1bmRlZmluZWRgIHdoZW4gdGhlXG4gICAqIHBsdWdpbiBleHBvc2VzIG5vIHN1Y2ggbW9kdWxlIHRvIGNoZWNrLlxuICAgKi9cbiAgcmVhZG9ubHkgZnVuY3Rpb25Nb2R1bGVzPzogRGVtb1ZhdWx0RnVuY3Rpb25zQ292ZXJhZ2VTcGVjW107XG5cbiAgLyoqXG4gICAqIFRoZSBpbnRlcmZhY2VzIHdob3NlIG1lbWJlcnMgbXVzdCBlYWNoIGJlIGRlbW9uc3RyYXRlZCAoYW5kIHJlZmVyZW5jZWQgd2l0aG91dCBkcmlmdCkuXG4gICAqL1xuICByZWFkb25seSBpbnRlcmZhY2VzOiBEZW1vVmF1bHRJbnRlcmZhY2VDb3ZlcmFnZVNwZWNbXTtcblxuICAvKipcbiAgICogVGhlIGd1YXJkIHRoYXQga2VlcHMgdGhlIHJlZmxlY3RlZCBzdXJmYWNlIG5vbi10cml2aWFsLlxuICAgKi9cbiAgcmVhZG9ubHkgbm9uVHJpdmlhbEd1YXJkOiBEZW1vVmF1bHROb25Ucml2aWFsR3VhcmRTcGVjO1xuXG4gIC8qKlxuICAgKiBUaGUgYWJzb2x1dGUgcGF0aCBvZiB0aGUgcGx1Z2luIHJlcG8gcm9vdC4gQ2FsbGVycyB0eXBpY2FsbHkgcGFzcyBgZ2V0Um9vdEZvbGRlcigpID8/IHByb2Nlc3MuY3dkKClgLlxuICAgKi9cbiAgcmVhZG9ubHkgcm9vdEZvbGRlcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlZmxlY3RzIGEgcGx1Z2luJ3MgcHVibGljIHN1cmZhY2UgZnJvbSBzb3VyY2UgYW5kIGNoZWNrcyBpdHMgaW4tcmVwbyBgZGVtby12YXVsdC9gIHN0YXlzIGluIHN5bmMgd2l0aCBpdC5cbiAqXG4gKiBFdmVyeSBtZXRob2QgaXMgYSBwdXJlIHF1ZXJ5IG92ZXIgZmlsZXMgdW5kZXIgdGhlIHJlcG8gcm9vdCAodGhlIGRlbW8gY29ycHVzIGlzIHJlYWQgb25jZSBhbmQgY2FjaGVkKSwgc29cbiAqIHRoZSBjaGVja2VyIGlzIHRyaXZpYWxseSB1bml0LXRlc3RhYmxlIGFnYWluc3QgYSBmaXh0dXJlIHJlcG8gYW5kIGNhcnJpZXMgbm8gdGVzdC1mcmFtZXdvcmsgZGVwZW5kZW5jeS5cbiAqL1xuZXhwb3J0IGNsYXNzIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlciB7XG4gIHByaXZhdGUgY2FjaGVkQ29ycHVzOiBudWxsIHwgc3RyaW5nID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSBkZW1vVmF1bHRGb2xkZXI6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSByb290Rm9sZGVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBjaGVja2VyIHJvb3RlZCBhdCBhIHBsdWdpbiByZXBvLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjb25zdHJ1Y3Rvci5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJhbXM6IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckNvbnN0cnVjdG9yUGFyYW1zKSB7XG4gICAgdGhpcy5yb290Rm9sZGVyID0gcGFyYW1zLnJvb3RGb2xkZXI7XG4gICAgdGhpcy5kZW1vVmF1bHRGb2xkZXIgPSBqb2luKHRoaXMucm9vdEZvbGRlciwgT2JzaWRpYW5QbHVnaW5SZXBvUGF0aHMuRGVtb1ZhdWx0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb2xsZWN0cyB0aGUgZGVtbyBub3RlcyBhcyBwYXRocyByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCBmb2xkZXIgKGZvciBhIG5vbi10cml2aWFsLXN1cmZhY2UgZ3VhcmQpLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgcmVsYXRpdmUgcGF0aHMgb2YgZXZlcnkgYCoubWRgIG5vdGUgaW4gdGhlIGRlbW8gdmF1bHQuXG4gICAqL1xuICBwdWJsaWMgY29sbGVjdERlbW9Ob3RlUmVsYXRpdmVQYXRocygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuY29sbGVjdE1hcmtkb3duRmlsZXModGhpcy5kZW1vVmF1bHRGb2xkZXIpLm1hcCgoZmlsZSkgPT4gcmVsYXRpdmUodGhpcy5kZW1vVmF1bHRGb2xkZXIsIGZpbGUpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBtZW1iZXJzIHRoYXQgdGhlIGRlbW8gbm90ZXMgcmVmZXJlbmNlIG9uIGEgcmVjZWl2ZXIgYnV0IHRoYXQgbm8gbG9uZ2VyIGV4aXN0IG9uIGl0IChyZW5hbWUgZHJpZnQpLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBsb29rdXAuXG4gICAqIEByZXR1cm5zIFRoZSBkaXN0aW5jdCBzdGFsZSBtZW1iZXIgbmFtZXMgcmVmZXJlbmNlZCBpbiB0aGUgZGVtbyBjb3JwdXMuXG4gICAqL1xuICBwdWJsaWMgZmluZFN0YWxlUmVmZXJlbmNlcyhwYXJhbXM6IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRTdGFsZVJlZmVyZW5jZXNQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgdmFsaWRNZW1iZXJzID0gbmV3IFNldChwYXJhbXMudmFsaWRNZW1iZXJzKTtcbiAgICBjb25zdCByZWZlcmVuY2VkID0gWy4uLnRoaXMucmVhZENvcnB1cygpLm1hdGNoQWxsKG5ldyBSZWdFeHAoU3RyaW5nLnJhd2Ake3BhcmFtcy5yZWNlaXZlcn1cXC4oPzxtZW1iZXI+XFx3KylgLCAnZycpKV1cbiAgICAgIC5tYXAoKG1hdGNoKSA9PiBnZXRNYW5kYXRvcnlOYW1lZEdyb3VwKG1hdGNoLCAnbWVtYmVyJykpO1xuICAgIHJldHVybiBbLi4ubmV3IFNldChyZWZlcmVuY2VkKV0uZmlsdGVyKChtZW1iZXIpID0+ICF2YWxpZE1lbWJlcnMuaGFzKG1lbWJlcikpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIG1lbWJlcnMgdGhhdCBhcmUgbm90IGRlbW9uc3RyYXRlZCBhbnl3aGVyZSBpbiB0aGUgZGVtbyBjb3JwdXMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGxvb2t1cC5cbiAgICogQHJldHVybnMgVGhlIG1lbWJlciBuYW1lcyB3aXRoIG5vIGRlbW9uc3RyYXRpb24uXG4gICAqL1xuICBwdWJsaWMgZmluZFVuZGVtb25zdHJhdGVkTWVtYmVycyhwYXJhbXM6IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRVbmRlbW9uc3RyYXRlZE1lbWJlcnNQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgY29ycHVzID0gdGhpcy5yZWFkQ29ycHVzKCk7XG4gICAgcmV0dXJuIHBhcmFtcy5tZW1iZXJzLmZpbHRlcigobWVtYmVyKSA9PiB7XG4gICAgICBjb25zdCBuZWVkbGUgPSBwYXJhbXMucmVjZWl2ZXIgPT09IHVuZGVmaW5lZCA/IG1lbWJlciA6IGAke3BhcmFtcy5yZWNlaXZlcn0uJHttZW1iZXJ9YDtcbiAgICAgIHJldHVybiAhY29ycHVzLmluY2x1ZGVzKG5lZWRsZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgZmVhdHVyZSBkb2NzIHRoYXQgbm8gZGVtbyBub3RlIGxpbmtzIHRvLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBsb29rdXAuXG4gICAqIEByZXR1cm5zIFRoZSBmZWF0dXJlLWRvYyBiYXNlbmFtZXMgKHdpdGhvdXQgYC5tZGApIG5vdCBsaW5rZWQgZnJvbSBhbnkgZGVtbyBub3RlLlxuICAgKi9cbiAgcHVibGljIGZpbmRVbmxpbmtlZEZlYXR1cmVEb2NzKHBhcmFtczogRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyRmluZFVubGlua2VkRmVhdHVyZURvY3NQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3Qgbm9uRmVhdHVyZURvY3MgPSBuZXcgU2V0KHBhcmFtcy5ub25GZWF0dXJlRG9jcyk7XG4gICAgY29uc3QgZmVhdHVyZURvY3MgPSByZWFkZGlyU3luYyhqb2luKHRoaXMucm9vdEZvbGRlciwgcGFyYW1zLmRvY3NGb2xkZXIpKVxuICAgICAgLmZpbHRlcigoZmlsZSkgPT4gZmlsZS5lbmRzV2l0aCgnLm1kJykpXG4gICAgICAubWFwKChmaWxlKSA9PiBmaWxlLnJlcGxhY2UoL1xcLm1kJC8sICcnKSlcbiAgICAgIC5maWx0ZXIoKG5hbWUpID0+ICFub25GZWF0dXJlRG9jcy5oYXMobmFtZSkpO1xuICAgIGNvbnN0IGxpbmtlZERvY3MgPSBuZXcgU2V0KFxuICAgICAgWy4uLnRoaXMucmVhZENvcnB1cygpLm1hdGNoQWxsKC9kb2NzXFwvKD88ZG9jPltcXHctXSspXFwubWQvZyldLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdkb2MnKSlcbiAgICApO1xuICAgIHJldHVybiBmZWF0dXJlRG9jcy5maWx0ZXIoKGRvYykgPT4gIWxpbmtlZERvY3MuaGFzKGRvYykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyB0aGUgbmFtZXMgb2YgdGhlIGBleHBvcnQgZnVuY3Rpb25gcyAoaW5jbHVkaW5nIGBhc3luY2AgYW5kIGdlbmVyYXRvciBkZWNsYXJhdGlvbnMpIGluIGEgc291cmNlIGZpbGUuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGxvb2t1cC5cbiAgICogQHJldHVybnMgVGhlIGV4cG9ydGVkIGZ1bmN0aW9uIG5hbWVzIGluIHNvdXJjZSBvcmRlci5cbiAgICovXG4gIHB1YmxpYyBnZXRFeHBvcnRlZEZ1bmN0aW9uTmFtZXMocGFyYW1zOiBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJHZXRFeHBvcnRlZEZ1bmN0aW9uTmFtZXNQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3Qgc291cmNlID0gcmVhZEZpbGVTeW5jKGpvaW4odGhpcy5yb290Rm9sZGVyLCBwYXJhbXMuc291cmNlUGF0aCksICd1dGYtOCcpO1xuICAgIHJldHVybiBbLi4uc291cmNlLm1hdGNoQWxsKC9eZXhwb3J0ICg/OmFzeW5jICk/ZnVuY3Rpb25cXCo/ICg/PG5hbWU+XFx3KykvZ20pXVxuICAgICAgLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyB0aGUgbWVtYmVycyBvZiBhbiBgZXhwb3J0IGludGVyZmFjZWAsIGBleHBvcnQgY2xhc3NgLCBvciBgZXhwb3J0IGVudW1gIGRlY2xhcmVkIGluIGEgc291cmNlIGZpbGUuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGxvb2t1cC5cbiAgICogQHJldHVybnMgVGhlIHBhcnNlZCB7QGxpbmsgSW50ZXJmYWNlTWVtYmVyc30uXG4gICAqIEB0aHJvd3MgV2hlbiB0aGUgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bSBjYW5ub3QgYmUgZm91bmQgaW4gdGhlIHNvdXJjZSBmaWxlLlxuICAgKi9cbiAgcHVibGljIGdldEludGVyZmFjZU1lbWJlcnMocGFyYW1zOiBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJHZXRJbnRlcmZhY2VNZW1iZXJzUGFyYW1zKTogSW50ZXJmYWNlTWVtYmVycyB7XG4gICAgY29uc3Qgc291cmNlID0gcmVhZEZpbGVTeW5jKGpvaW4odGhpcy5yb290Rm9sZGVyLCBwYXJhbXMuc291cmNlUGF0aCksICd1dGYtOCcpO1xuICAgIGNvbnN0IG1hdGNoID0gbmV3IFJlZ0V4cChTdHJpbmcucmF3YGV4cG9ydCAoPzxrZXl3b3JkPmludGVyZmFjZXxjbGFzc3xlbnVtKSAke3BhcmFtcy5pbnRlcmZhY2VOYW1lfVxcYltee10qXFx7KD88Ym9keT5bXFxzXFxTXSo/KVxcblxcfWApLmV4ZWMoc291cmNlKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kIGludGVyZmFjZSAke3BhcmFtcy5pbnRlcmZhY2VOYW1lfWApO1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VNZW1iZXJzKGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdrZXl3b3JkJyksIGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdib2R5JykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlYWRzIGFuZCBjYWNoZXMgdGhlIGRlbW8gY29ycHVzIFx1MjAxNCBldmVyeSBgKi5tZGAgbm90ZSBpbiB0aGUgZGVtbyB2YXVsdCBqb2luZWQgaW50byBvbmUgc3RyaW5nLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgY29uY2F0ZW5hdGVkIGRlbW8tbm90ZSBjb250ZW50cy5cbiAgICovXG4gIHB1YmxpYyByZWFkQ29ycHVzKCk6IHN0cmluZyB7XG4gICAgdGhpcy5jYWNoZWRDb3JwdXMgPz89IHRoaXMuY29sbGVjdE1hcmtkb3duRmlsZXModGhpcy5kZW1vVmF1bHRGb2xkZXIpXG4gICAgICAubWFwKChmaWxlKSA9PiByZWFkRmlsZVN5bmMoZmlsZSwgJ3V0Zi04JykpXG4gICAgICAuam9pbignXFxuJyk7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVkQ29ycHVzO1xuICB9XG5cbiAgcHJpdmF0ZSBjb2xsZWN0TWFya2Rvd25GaWxlcyhmb2xkZXI6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCByZXN1bHQ6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChjb25zdCBlbnRyeSBvZiByZWFkZGlyU3luYyhmb2xkZXIsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KSkge1xuICAgICAgaWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgaWYgKGVudHJ5Lm5hbWUgPT09IE9ic2lkaWFuUGx1Z2luUmVwb1BhdGhzLk5vZGVNb2R1bGVzIGFzIHN0cmluZykge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdC5wdXNoKC4uLnRoaXMuY29sbGVjdE1hcmtkb3duRmlsZXMoam9pbihmb2xkZXIsIGVudHJ5Lm5hbWUpKSk7XG4gICAgICB9IGVsc2UgaWYgKGVudHJ5Lm5hbWUuZW5kc1dpdGgoJy5tZCcpKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGpvaW4oZm9sZGVyLCBlbnRyeS5uYW1lKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBgdml0ZXN0YCBzdWl0ZSB0aGF0IGtlZXBzIGEgcGx1Z2luJ3MgaW4tcmVwbyBgZGVtby12YXVsdC9gIGluIHN5bmMgd2l0aCBpdHMgcHVibGljIHN1cmZhY2UuXG4gKlxuICogQ2FsbCBpdCBvbmNlIGZyb20gYSBwbHVnaW4ncyBgZGVtby12YXVsdC5uby1hcHAuaW50ZWdyYXRpb24udGVzdC50c2A7IGl0IHJlZ2lzdGVycyBvbmUgdGVzdCBwZXIgY2hlY2ssXG4gKiBkZWxlZ2F0aW5nIHRvIHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJ9LlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgZGVjbGFyYXRpdmUgY292ZXJhZ2Ugc3BlY2lmaWNhdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyRGVtb1ZhdWx0Q292ZXJhZ2VTdWl0ZShwYXJhbXM6IFJlZ2lzdGVyRGVtb1ZhdWx0Q292ZXJhZ2VTdWl0ZVBhcmFtcyk6IHZvaWQge1xuICBjb25zdCBjaGVja2VyID0gbmV3IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlcih7IHJvb3RGb2xkZXI6IHBhcmFtcy5yb290Rm9sZGVyIH0pO1xuXG4gIGRlc2NyaWJlKCdkZW1vLXZhdWx0IGNvdmVyYWdlJywgKCkgPT4ge1xuICAgIGZvciAoY29uc3Qgc3BlYyBvZiBwYXJhbXMuaW50ZXJmYWNlcykge1xuICAgICAgaXQoYGRlbW9uc3RyYXRlcyBldmVyeSAke3NwZWMuaW50ZXJmYWNlTmFtZX0gJHtzcGVjLmtpbmR9YCwgKCkgPT4ge1xuICAgICAgICBjb25zdCBtZW1iZXJzID0gY2hlY2tlci5nZXRJbnRlcmZhY2VNZW1iZXJzKHNwZWMpO1xuICAgICAgICBjb25zdCBkZW1vbnN0cmF0ZWQgPSBtZW1iZXJzW3NwZWMua2luZF07XG4gICAgICAgIGV4cGVjdChkZW1vbnN0cmF0ZWQubGVuZ3RoKS50b0JlR3JlYXRlclRoYW4oMCk7XG4gICAgICAgIGV4cGVjdChjaGVja2VyLmZpbmRVbmRlbW9uc3RyYXRlZE1lbWJlcnMoeyBtZW1iZXJzOiBkZW1vbnN0cmF0ZWQsIHJlY2VpdmVyOiBzcGVjLnJlY2VpdmVyIH0pKS50b0VxdWFsKFtdKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdChgcmVmZXJlbmNlcyBubyAke3NwZWMuaW50ZXJmYWNlTmFtZX0gbWVtYmVyIHRoYXQgbm8gbG9uZ2VyIGV4aXN0c2AsICgpID0+IHtcbiAgICAgICAgY29uc3QgbWVtYmVycyA9IGNoZWNrZXIuZ2V0SW50ZXJmYWNlTWVtYmVycyhzcGVjKTtcbiAgICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZFN0YWxlUmVmZXJlbmNlcyh7IHJlY2VpdmVyOiBzcGVjLnJlY2VpdmVyLCB2YWxpZE1lbWJlcnM6IG1lbWJlcnMuYWxsIH0pKS50b0VxdWFsKFtdKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgc3BlYyBvZiBwYXJhbXMuY29uZmlnSW50ZXJmYWNlcykge1xuICAgICAgaXQoYGRlbW9uc3RyYXRlcyBldmVyeSAke3NwZWMuaW50ZXJmYWNlTmFtZX0gb3B0aW9uYCwgKCkgPT4ge1xuICAgICAgICBjb25zdCBtZW1iZXJzID0gY2hlY2tlci5nZXRJbnRlcmZhY2VNZW1iZXJzKHNwZWMpO1xuICAgICAgICBleHBlY3QobWVtYmVycy5wcm9wZXJ0aWVzLmxlbmd0aCkudG9CZUdyZWF0ZXJUaGFuKDApO1xuICAgICAgICBleHBlY3QoY2hlY2tlci5maW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzKHsgbWVtYmVyczogbWVtYmVycy5wcm9wZXJ0aWVzIH0pKS50b0VxdWFsKFtdKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgc3BlYyBvZiBwYXJhbXMuZnVuY3Rpb25Nb2R1bGVzID8/IFtdKSB7XG4gICAgICBpdChgZGVtb25zdHJhdGVzIGV2ZXJ5IGV4cG9ydGVkIGZ1bmN0aW9uIGluICR7c3BlYy5zb3VyY2VQYXRofWAsICgpID0+IHtcbiAgICAgICAgY29uc3QgZnVuY3Rpb25OYW1lcyA9IGNoZWNrZXIuZ2V0RXhwb3J0ZWRGdW5jdGlvbk5hbWVzKHNwZWMpO1xuICAgICAgICBleHBlY3QoZnVuY3Rpb25OYW1lcy5sZW5ndGgpLnRvQmVHcmVhdGVyVGhhbigwKTtcbiAgICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZFVuZGVtb25zdHJhdGVkTWVtYmVycyh7IG1lbWJlcnM6IGZ1bmN0aW9uTmFtZXMgfSkpLnRvRXF1YWwoW10pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgZG9jcyA9IHBhcmFtcy5kb2NzO1xuICAgIGlmIChkb2NzKSB7XG4gICAgICBpdCgnbGlua3MgYSBkZW1vIG5vdGUgZm9yIGV2ZXJ5IGZlYXR1cmUgZG9jJywgKCkgPT4ge1xuICAgICAgICBleHBlY3QoY2hlY2tlci5maW5kVW5saW5rZWRGZWF0dXJlRG9jcyh7IGRvY3NGb2xkZXI6IGRvY3MuZm9sZGVyLCBub25GZWF0dXJlRG9jczogZG9jcy5ub25GZWF0dXJlRG9jcyB9KSlcbiAgICAgICAgICAudG9FcXVhbChbXSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpdCgna2VlcHMgdGhlIHJlZmxlY3RlZCBzdXJmYWNlIG5vbi10cml2aWFsJywgKCkgPT4ge1xuICAgICAgY29uc3QgZ3VhcmQgPSBwYXJhbXMubm9uVHJpdmlhbEd1YXJkO1xuICAgICAgY29uc3QgbWVtYmVycyA9IGNoZWNrZXIuZ2V0SW50ZXJmYWNlTWVtYmVycyhndWFyZCk7XG4gICAgICBleHBlY3QobWVtYmVycy5hbGwpLnRvQ29udGFpbihndWFyZC5leHBlY3RNZW1iZXIpO1xuICAgICAgZXhwZWN0KGNoZWNrZXIuY29sbGVjdERlbW9Ob3RlUmVsYXRpdmVQYXRocygpKS50b0NvbnRhaW4oZ3VhcmQuZXhwZWN0RGVtb05vdGUpO1xuICAgIH0pO1xuICB9KTtcbn1cblxuY29uc3QgQ0xBU1NfTUVNQkVSX01PRElGSUVSUyA9IFN0cmluZy5yYXdgKD86KD86cHVibGljfHByaXZhdGV8cHJvdGVjdGVkfHJlYWRvbmx5fHN0YXRpY3xhYnN0cmFjdHxvdmVycmlkZSlcXHMrKSpgO1xuXG5mdW5jdGlvbiBidWlsZE1lbWJlcnMobWV0aG9kczogc3RyaW5nW10sIHByb3BlcnRpZXM6IHN0cmluZ1tdKTogSW50ZXJmYWNlTWVtYmVycyB7XG4gIHJldHVybiB7XG4gICAgYWxsOiBbLi4ubWV0aG9kcywgLi4ucHJvcGVydGllc10sXG4gICAgbWV0aG9kcyxcbiAgICBwcm9wZXJ0aWVzXG4gIH07XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RDbGFzc01ldGhvZE5hbWVzKGNsYXNzQm9keTogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gWy4uLmNsYXNzQm9keS5tYXRjaEFsbChuZXcgUmVnRXhwKFN0cmluZy5yYXdgXiB7Mn0oPzxtb2RpZmllcnM+JHtDTEFTU19NRU1CRVJfTU9ESUZJRVJTfSkoPzxuYW1lPlxcdyspKD86PFtePl0qPik/XFwoYCwgJ2dtJykpXVxuICAgIC5maWx0ZXIoKG1hdGNoKSA9PiAhaXNOb25QdWJsaWNNZW1iZXIoZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ21vZGlmaWVycycpKSlcbiAgICAubWFwKChtYXRjaCkgPT4gZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ25hbWUnKSk7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RDbGFzc1Byb3BlcnR5TmFtZXMoY2xhc3NCb2R5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBbLi4uY2xhc3NCb2R5Lm1hdGNoQWxsKG5ldyBSZWdFeHAoU3RyaW5nLnJhd2BeIHsyfSg/PG1vZGlmaWVycz4ke0NMQVNTX01FTUJFUl9NT0RJRklFUlN9KSg/PG5hbWU+XFx3KylcXHMqXFw/P1xccypbOj1dYCwgJ2dtJykpXVxuICAgIC5maWx0ZXIoKG1hdGNoKSA9PiAhaXNOb25QdWJsaWNNZW1iZXIoZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ21vZGlmaWVycycpKSlcbiAgICAubWFwKChtYXRjaCkgPT4gZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ25hbWUnKSk7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RFbnVtTWVtYmVyTmFtZXMoZW51bUJvZHk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFsuLi5lbnVtQm9keS5tYXRjaEFsbCgvXiB7Mn0oPzxuYW1lPlxcdyspL2dtKV0ubWFwKChtYXRjaCkgPT4gZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ25hbWUnKSk7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RNZXRob2ROYW1lcyhpbnRlcmZhY2VCb2R5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBbLi4uaW50ZXJmYWNlQm9keS5tYXRjaEFsbCgvXiB7Mn0oPzxuYW1lPlxcdyspKD86PFtePl0qPik/XFwoL2dtKV0ubWFwKChtYXRjaCkgPT4gZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ25hbWUnKSk7XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RQcm9wZXJ0eU5hbWVzKGludGVyZmFjZUJvZHk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFsuLi5pbnRlcmZhY2VCb2R5Lm1hdGNoQWxsKC9eIHsyfSg/PG5hbWU+XFx3KylcXD8/Oi9nbSldLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG5mdW5jdGlvbiBpc05vblB1YmxpY01lbWJlcihtb2RpZmllcnM6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gL1xcYig/OnByaXZhdGV8cHJvdGVjdGVkKVxcYi8udGVzdChtb2RpZmllcnMpO1xufVxuXG5mdW5jdGlvbiBwYXJzZU1lbWJlcnMoa2V5d29yZDogc3RyaW5nLCBib2R5OiBzdHJpbmcpOiBJbnRlcmZhY2VNZW1iZXJzIHtcbiAgc3dpdGNoIChrZXl3b3JkKSB7XG4gICAgY2FzZSAnY2xhc3MnOiB7XG4gICAgICByZXR1cm4gYnVpbGRNZW1iZXJzKGV4dHJhY3RDbGFzc01ldGhvZE5hbWVzKGJvZHkpLCBleHRyYWN0Q2xhc3NQcm9wZXJ0eU5hbWVzKGJvZHkpKTtcbiAgICB9XG4gICAgY2FzZSAnZW51bSc6IHtcbiAgICAgIHJldHVybiBidWlsZE1lbWJlcnMoW10sIGV4dHJhY3RFbnVtTWVtYmVyTmFtZXMoYm9keSkpO1xuICAgIH1cbiAgICBkZWZhdWx0OiB7XG4gICAgICByZXR1cm4gYnVpbGRNZW1iZXJzKGV4dHJhY3RNZXRob2ROYW1lcyhib2R5KSwgZXh0cmFjdFByb3BlcnR5TmFtZXMoYm9keSkpO1xuICAgIH1cbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFtQkE7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLE9BQ0s7QUFDUDtBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLE9BQ0s7QUFFUCxTQUFTLCtCQUErQjtBQUN4QztBQUFBLEVBQ0U7QUFBQSxFQUNBO0FBQUEsT0FDSztBQUNQLFNBQVMsOEJBQThCO0FBcVBoQyxNQUFNLHlCQUF5QjtBQUFBLEVBQzVCLGVBQThCO0FBQUEsRUFDckI7QUFBQSxFQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT1YsWUFBWSxRQUFtRDtBQUNwRSxTQUFLLGFBQWEsT0FBTztBQUN6QixTQUFLLGtCQUFrQixLQUFLLEtBQUssWUFBWSx3QkFBd0IsU0FBUztBQUFBLEVBQ2hGO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT08sK0JBQXlDO0FBQzlDLFdBQU8sS0FBSyxxQkFBcUIsS0FBSyxlQUFlLEVBQUUsSUFBSSxDQUFDLFNBQVMsU0FBUyxLQUFLLGlCQUFpQixJQUFJLENBQUM7QUFBQSxFQUMzRztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBUU8s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
415
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vLi4vc3JjL3NjcmlwdC11dGlscy9kZW1vLXZhdWx0LWNvdmVyYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogU3RhdGljIGNvdmVyYWdlL2ZyZXNobmVzcyBjaGVja3MgdGhhdCBrZWVwIGEgcGx1Z2luJ3MgaW4tcmVwbyBgZGVtby12YXVsdC9gIGluIHN5bmMgd2l0aCBpdHMgcHVibGljIHN1cmZhY2UuXG4gKlxuICogQSBwbHVnaW4gY2FuIHNoaXAgYSBjdXJhdGVkIGRlbW8gdmF1bHQgYXQgYGRlbW8tdmF1bHQvYCBpbiBpdHMgcmVwbyByb290LiBUaGVzZSBoZWxwZXJzIHJlZmxlY3QgdGhlIHJlYWxcbiAqIHB1YmxpYyBBUEkvY29uZmlnL2RvY3Mgc3RyYWlnaHQgZnJvbSBzb3VyY2UgYW5kIGFzc2VydCBcdTIwMTQgV0lUSE9VVCBsYXVuY2hpbmcgT2JzaWRpYW4gXHUyMDE0IHRoYXQgZXZlcnkgZmVhdHVyZSBpc1xuICogZGVtb25zdHJhdGVkIGluIHRoZSBub3RlcyBhbmQgdGhhdCB0aGUgbm90ZXMgcmVmZXJlbmNlIG5vIEFQSSBtZW1iZXIgdGhhdCBubyBsb25nZXIgZXhpc3RzIChyZW5hbWUgZHJpZnQpLlxuICogVGhlIHJ1bnRpbWUgYmVoYXZpb3Igb2YgdGhlIHBsdWdpbiBpcyBjb3ZlcmVkIGJ5IGl0cyBvdGhlciBpbnRlZ3JhdGlvbiB0ZXN0cywgbm90IGJ5IHRoZSBkZW1vIHZhdWx0OyB0aGVcbiAqIHZhdWx0IGlzIGEgbGVhcm5pbmcgcmVzb3VyY2UsIGFuZCB0aGVzZSBjaGVja3Mgb25seSBndWFyZCB0aGF0IGl0IHN0YXlzIHRydXRoZnVsLlxuICpcbiAqIFRoZXkgYWxzbyBlbmZvcmNlIHRoZSBkZW1vLXZhdWx0IEFVVEhPUklORyBjb252ZW50aW9uIFx1MjAxNCBldmVyeSBub3RlIG9wZW5zIHdpdGggYW4gYCMgSDFgIGFuZCBhIHBsYWluXG4gKiBwcm9zZSBwYXJhZ3JhcGgsIGV2ZXJ5IG5vdGUgaXMgcmVhY2hhYmxlIGZyb20gdGhlIHN0YXJ0IG5vdGUsIGFuZCBubyBub3RlIHVzZXMgYSBgW1t3aWtpbGlua11dYCBvciBhXG4gKiBgW0RvY3NdKFx1MjAyNilgIGxpbmUuIFRoZXNlIGNoZWNrcyBhcmUgdW5jb25kaXRpb25hbDogdGhlIGRlbW8gdmF1bHQgaXMgdGhlIHB1Ymxpc2hlZCBkb2N1bWVudGF0aW9uLCByZWFkXG4gKiBpbiBPYnNpZGlhbiBBTkQgb24gR2l0SHViICh3aGVyZSBhIHdpa2lsaW5rIGRvZXMgbm90IHJlbmRlciksIHNvIGEgbm90ZSB0aGF0IGJyZWFrcyB0aGUgY29udmVudGlvbiBpc1xuICogYnJva2VuIGZvciByZWFsIHJlYWRlcnMuIGBhdXRob3JpbmdgIG9ubHkgdHVuZXMgdGhlbSAod2hpY2ggbm90ZSBpcyB0aGUgc3RhcnQsIHdoaWNoIG5vdGVzIHNpdCBvdXRzaWRlXG4gKiB0aGUgbGVhcm5pbmcgcGF0aCk7IGl0IGNhbm5vdCBzd2l0Y2ggdGhlbSBvZmYuXG4gKlxuICogVHdvIGxheWVycyBhcmUgZXhwb3NlZDpcbiAqIC0ge0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlcn0gXHUyMDE0IGEgZnJhbWV3b3JrLWFnbm9zdGljIGNvcmUgdGhhdCByZWFkcyB0aGUgY29ycHVzLCBwYXJzZXMgaW50ZXJmYWNlIC9cbiAqICAgY2xhc3MgLyBlbnVtIG1lbWJlcnMgYW5kIGV4cG9ydGVkIGZ1bmN0aW9ucywgYW5kIHJldHVybnMgZGlhZ25vc3RpYyBhcnJheXMgKHdoYXQgaXMgdW5kZW1vbnN0cmF0ZWQgLyBzdGFsZVxuICogICAvIHVubGlua2VkIC8gb2ZmLWNvbnZlbnRpb24pLlxuICogLSB7QGxpbmsgcmVnaXN0ZXJEZW1vVmF1bHRDb3ZlcmFnZVN1aXRlfSBcdTIwMTQgYSB0aGluIHdyYXBwZXIgdGhhdCByZWdpc3RlcnMgYSBgdml0ZXN0YCBzdWl0ZSBvdmVyIHRoZSBjb3JlLCBzb1xuICogICBhIHBsdWdpbidzIGBkZW1vLXZhdWx0Lm5vLWFwcC5pbnRlZ3JhdGlvbi50ZXN0LnRzYCBpcyBhIHNpbmdsZSBkZWNsYXJhdGl2ZSBjYWxsLlxuICovXG5cbmltcG9ydCB7XG4gIHJlYWRkaXJTeW5jLFxuICByZWFkRmlsZVN5bmNcbn0gZnJvbSAnbm9kZTpmcyc7XG5pbXBvcnQge1xuICBkZXNjcmliZSxcbiAgZXhwZWN0LFxuICBpdFxufSBmcm9tICd2aXRlc3QnO1xuXG5pbXBvcnQgeyBub3JtYWxpemVPcHRpb25hbFByb3BlcnRpZXMgfSBmcm9tICcuLi9vYmplY3QtdXRpbHMudHMnO1xuaW1wb3J0IHsgT2JzaWRpYW5QbHVnaW5SZXBvUGF0aHMgfSBmcm9tICcuLi9vYnNpZGlhbi9wbHVnaW4vb2JzaWRpYW4tcGx1Z2luLXJlcG8tcGF0aHMudHMnO1xuaW1wb3J0IHtcbiAgZGlybmFtZSxcbiAgam9pbixcbiAgcmVsYXRpdmVcbn0gZnJvbSAnLi4vcGF0aC50cyc7XG5pbXBvcnQgeyBnZXRNYW5kYXRvcnlOYW1lZEdyb3VwIH0gZnJvbSAnLi4vcmVnLWV4cC50cyc7XG5pbXBvcnQgeyBlbnN1cmVOb25OdWxsYWJsZSB9IGZyb20gJy4uL3R5cGUtZ3VhcmRzLnRzJztcblxuLyoqXG4gKiBUdW5lcyB0aGUgYWx3YXlzLW9uIGF1dGhvcmluZyBjaGVja3MuIEl0IGNhbm5vdCBkaXNhYmxlIHRoZW0gXHUyMDE0IHNlZSB0aGUgZmlsZSBvdmVydmlldy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRBdXRob3JpbmdTcGVjIHtcbiAgLyoqXG4gICAqIFRoZSBub3RlcyAocGF0aHMgcmVsYXRpdmUgdG8gdGhlIGRlbW8gdmF1bHQpIHRoYXQgc2l0IG91dHNpZGUgdGhlIGxlYXJuaW5nIHBhdGggYW5kIGFyZSB0aGVyZWZvcmVcbiAgICogZXhlbXB0IGZyb20gZXZlcnkgYXV0aG9yaW5nIGNoZWNrLiBEZWZhdWx0cyB0byB0aGUgdmF1bHQncyBvd24gYFJFQURNRS5tZGAsIHdoaWNoIGFkZHJlc3NlcyBzb21lb25lXG4gICAqIGJyb3dzaW5nIHRoZSByZXBvIG9uIEdpdEh1YiByYXRoZXIgdGhhbiBhIHJlYWRlciB3b3JraW5nIHRocm91Z2ggdGhlIHZhdWx0LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhjbHVkZWROb3Rlcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgbm90ZSAocGF0aCByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCkgZXZlcnkgb3RoZXIgbm90ZSBtdXN0IGJlIHJlYWNoYWJsZSBmcm9tLiBEZWZhdWx0cyB0b1xuICAgKiBgMDAgU3RhcnQubWRgLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhcnROb3RlPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJlZmxlY3RzIGEgY29uZmlnIGludGVyZmFjZSB3aG9zZSBvcHRpb25zIGFyZSBkZW1vbnN0cmF0ZWQgYnkgdGhlaXIgYmFyZSBuYW1lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvbmZpZ0ludGVyZmFjZUNvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYGV4cG9ydCBpbnRlcmZhY2VgLCBgZXhwb3J0IGNsYXNzYCwgb3IgYGV4cG9ydCBlbnVtYCB3aG9zZSBwcm9wZXJ0aWVzIGFyZSB0aGUgY29uZmlnXG4gICAqIG9wdGlvbnMuXG4gICAqL1xuICByZWFkb25seSBpbnRlcmZhY2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB0aGF0IGRlY2xhcmVzIHRoZSBpbnRlcmZhY2UsIGNsYXNzLCBvciBlbnVtLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUge0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlcn0gY29uc3RydWN0b3IuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyQ29uc3RydWN0b3JQYXJhbXMge1xuICAvKipcbiAgICogVGhlIG5vdGVzIChwYXRocyByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCkgZXhlbXB0IGZyb20gdGhlIGF1dGhvcmluZyBjaGVja3MuIERlZmF1bHRzIHRvIHRoZVxuICAgKiB2YXVsdCdzIG93biBgUkVBRE1FLm1kYC5cbiAgICovXG4gIHJlYWRvbmx5IGV4Y2x1ZGVkTm90ZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIGFic29sdXRlIHBhdGggb2YgdGhlIHBsdWdpbiByZXBvIHJvb3QgXHUyMDE0IHRoZSBmb2xkZXIgY29udGFpbmluZyBgZGVtby12YXVsdC9gIGFuZCB0aGUgc291cmNlIGJlaW5nXG4gICAqIHJlZmxlY3RlZC4gQ2FsbGVycyB0eXBpY2FsbHkgcGFzcyBgZ2V0Um9vdEZvbGRlcigpID8/IHByb2Nlc3MuY3dkKClgLlxuICAgKi9cbiAgcmVhZG9ubHkgcm9vdEZvbGRlcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmZpbmRTdGFsZVJlZmVyZW5jZXN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRTdGFsZVJlZmVyZW5jZXNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIHJlY2VpdmVyIHdob3NlIGBgIGAke3JlY2VpdmVyfS48bWVtYmVyPmAgYGAgcmVmZXJlbmNlcyBhcmUgc2Nhbm5lZCBmb3IgaW4gdGhlIGRlbW8gY29ycHVzLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVjZWl2ZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG1lbWJlcnMgdGhhdCBjdXJyZW50bHkgZXhpc3Qgb24gdGhlIHJlY2VpdmVyOyBhbnkgcmVmZXJlbmNlZCBtZW1iZXIgbm90IGluIHRoaXMgc2V0IGlzIHN0YWxlLlxuICAgKi9cbiAgcmVhZG9ubHkgdmFsaWRNZW1iZXJzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBUaGUgcGFyYW1ldGVycyBmb3Ige0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlci5maW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJGaW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBtZW1iZXIgbmFtZXMgdGhhdCBtdXN0IGVhY2ggYXBwZWFyIGluIHRoZSBkZW1vIGNvcnB1cy5cbiAgICovXG4gIHJlYWRvbmx5IG1lbWJlcnM6IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBXaGVuIHNldCwgYSBtZW1iZXIgaXMgZGVtb25zdHJhdGVkIG9ubHkgaWYgYGAgYCR7cmVjZWl2ZXJ9LiR7bWVtYmVyfWAgYGAgYXBwZWFycyAoZS5nLiBhIGNvbnRleHQgb2JqZWN0J3NcbiAgICogbWV0aG9kcyk7IHdoZW4gYWJzZW50LCB0aGUgYmFyZSBtZW1iZXIgbmFtZSBpcyBsb29rZWQgdXAgKGUuZy4gYSBjb25maWcgb3B0aW9uKS5cbiAgICovXG4gIHJlYWRvbmx5IHJlY2VpdmVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmZpbmRVbmxpbmtlZEZlYXR1cmVEb2NzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJGaW5kVW5saW5rZWRGZWF0dXJlRG9jc1BhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgZG9jcyBmb2xkZXIgKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIHRvcC1sZXZlbCBgKi5tZGAgZmlsZXMgYXJlIHRoZSBmZWF0dXJlIGRvY3MuXG4gICAqL1xuICByZWFkb25seSBkb2NzRm9sZGVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBkb2MgYmFzZW5hbWVzICh3aXRob3V0IGAubWRgKSB0aGF0IGFyZSBOT1QgcGVyLWZlYXR1cmUgcGFnZXMgYW5kIHNvIG5lZWQgbm8gbGlua2luZyBkZW1vIG5vdGUuXG4gICAqL1xuICByZWFkb25seSBub25GZWF0dXJlRG9jczogc3RyaW5nW107XG59XG5cbi8qKlxuICogVGhlIHBhcmFtZXRlcnMgZm9yIHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXIuZmluZFVucmVhY2hhYmxlTm90ZXN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRVbnJlYWNoYWJsZU5vdGVzUGFyYW1zIHtcbiAgLyoqXG4gICAqIFRoZSBub3RlIChwYXRoIHJlbGF0aXZlIHRvIHRoZSBkZW1vIHZhdWx0KSB0aGUgd2FsayBzdGFydHMgZnJvbSwgZS5nLiBgMDAgU3RhcnQubWRgLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhcnROb3RlOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIHBhcmFtZXRlcnMgZm9yIHtAbGluayBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXIuZ2V0RXhwb3J0ZWRGdW5jdGlvbk5hbWVzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJHZXRFeHBvcnRlZEZ1bmN0aW9uTmFtZXNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIHNvdXJjZSBmaWxlIHBhdGggKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIGBleHBvcnQgZnVuY3Rpb25gcyBhcmUgcGFyc2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJhbWV0ZXJzIGZvciB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLmdldEludGVyZmFjZU1lbWJlcnN9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckdldEludGVyZmFjZU1lbWJlcnNQYXJhbXMge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGBleHBvcnQgaW50ZXJmYWNlYCwgYGV4cG9ydCBjbGFzc2AsIG9yIGBleHBvcnQgZW51bWAgdG8gcGFyc2UuXG4gICAqL1xuICByZWFkb25seSBpbnRlcmZhY2VOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB0aGF0IGRlY2xhcmVzIHRoZSBpbnRlcmZhY2UsIGNsYXNzLCBvciBlbnVtLlxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyZXMgdGhlIGZlYXR1cmUtZG9jIGxpbmtpbmcgY2hlY2suXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0RG9jc0NvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgZG9jcyBmb2xkZXIgKHJlbGF0aXZlIHRvIHRoZSByZXBvIHJvb3QpIHdob3NlIHRvcC1sZXZlbCBgKi5tZGAgZmlsZXMgYXJlIHRoZSBmZWF0dXJlIGRvY3MuXG4gICAqL1xuICByZWFkb25seSBmb2xkZXI6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRvYyBiYXNlbmFtZXMgKHdpdGhvdXQgYC5tZGApIHRoYXQgYXJlIE5PVCBwZXItZmVhdHVyZSBwYWdlcyBhbmQgc28gbmVlZCBubyBsaW5raW5nIGRlbW8gbm90ZS5cbiAgICovXG4gIHJlYWRvbmx5IG5vbkZlYXR1cmVEb2NzOiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBSZWZsZWN0cyBhIG1vZHVsZSdzIGV4cG9ydGVkIGZ1bmN0aW9ucywgZWFjaCBkZW1vbnN0cmF0ZWQgYnkgaXRzIGJhcmUgbmFtZSBpbiB0aGUgZGVtbyBjb3JwdXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGVtb1ZhdWx0RnVuY3Rpb25zQ292ZXJhZ2VTcGVjIHtcbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgZmlsZSBwYXRoIChyZWxhdGl2ZSB0byB0aGUgcmVwbyByb290KSB3aG9zZSBgZXhwb3J0IGZ1bmN0aW9uYHMgbXVzdCBlYWNoIGJlIGRlbW9uc3RyYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZWZsZWN0cyBhIHNpbmdsZSBpbnRlcmZhY2UncyBtZW1iZXJzIGFuZCBkZW1vbnN0cmF0ZXMgdGhlbSB2aWEgYGAgYCR7cmVjZWl2ZXJ9LjxtZW1iZXI+YCBgYCByZWZlcmVuY2VzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdEludGVyZmFjZUNvdmVyYWdlU3BlYyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgYGV4cG9ydCBpbnRlcmZhY2VgLCBgZXhwb3J0IGNsYXNzYCwgb3IgYGV4cG9ydCBlbnVtYCB0byByZWZsZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJmYWNlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoZSBkZW1vbnN0cmF0ZWQgbWVtYmVycyBhcmUgdGhlIHJlZmxlY3RlZCB0eXBlJ3MgbWV0aG9kcyBvciBpdHMgcHJvcGVydGllcyAoZW51bSBtZW1iZXJzIGNvdW50IGFzXG4gICAqIHByb3BlcnRpZXMpLlxuICAgKi9cbiAgcmVhZG9ubHkga2luZDogRGVtb1ZhdWx0SW50ZXJmYWNlTWVtYmVyS2luZDtcblxuICAvKipcbiAgICogVGhlIGlkZW50aWZpZXIgdGhlIG5vdGVzIGNhbGwgdGhlIG1lbWJlcnMgb24gKGUuZy4gYGNvZGVCdXR0b25Db250ZXh0YCkuXG4gICAqL1xuICByZWFkb25seSByZWNlaXZlcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc291cmNlIGZpbGUgcGF0aCAocmVsYXRpdmUgdG8gdGhlIHJlcG8gcm9vdCkgdGhhdCBkZWNsYXJlcyB0aGUgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bS5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBXaGV0aGVyIGFuIGludGVyZmFjZSdzIGRlbW9uc3RyYXRlZCBtZW1iZXJzIGFyZSBpdHMgbWV0aG9kcyBvciBpdHMgcHJvcGVydGllcy5cbiAqL1xuZXhwb3J0IHR5cGUgRGVtb1ZhdWx0SW50ZXJmYWNlTWVtYmVyS2luZCA9ICdtZXRob2RzJyB8ICdwcm9wZXJ0aWVzJztcblxuLyoqXG4gKiBDb25maWd1cmVzIHRoZSBndWFyZCB0aGF0IHRoZSByZWZsZWN0ZWQgc3VyZmFjZSBpcyBub24tdHJpdmlhbCAocHJvdGVjdHMgYWdhaW5zdCBhIHBhcnNpbmcgcmVncmVzc2lvblxuICogc2lsZW50bHkgZW1wdHlpbmcgZXZlcnkgb3RoZXIgY2hlY2spLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIERlbW9WYXVsdE5vblRyaXZpYWxHdWFyZFNwZWMge1xuICAvKipcbiAgICogQSBkZW1vIG5vdGUgKHBhdGggcmVsYXRpdmUgdG8gdGhlIGRlbW8gdmF1bHQpIHRoYXQgbXVzdCBiZSBwcmVzZW50LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhwZWN0RGVtb05vdGU6IHN0cmluZztcblxuICAvKipcbiAgICogQSBtZW1iZXIgdGhhdCBtdXN0IGJlIHJlZmxlY3RlZCBmcm9tIHtAbGluayBEZW1vVmF1bHROb25Ucml2aWFsR3VhcmRTcGVjLmludGVyZmFjZU5hbWV9LlxuICAgKi9cbiAgcmVhZG9ubHkgZXhwZWN0TWVtYmVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBgZXhwb3J0IGludGVyZmFjZWAsIGBleHBvcnQgY2xhc3NgLCBvciBgZXhwb3J0IGVudW1gIHdob3NlIG1lbWJlcnMgYXJlIHJlLXBhcnNlZCBmb3IgdGhlXG4gICAqIGd1YXJkLlxuICAgKi9cbiAgcmVhZG9ubHkgaW50ZXJmYWNlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc291cmNlIGZpbGUgcGF0aCAocmVsYXRpdmUgdG8gdGhlIHJlcG8gcm9vdCkgdGhhdCBkZWNsYXJlcyB0aGUgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bS5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVBhdGg6IHN0cmluZztcbn1cblxuLyoqXG4gKiBBIHNpbmdsZSBkZW1vIG5vdGUsIGFzIHJlYWQgZnJvbSB0aGUgZGVtbyB2YXVsdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZW1vVmF1bHROb3RlIHtcbiAgLyoqXG4gICAqIFRoZSBub3RlJ3MgcmF3IE1hcmtkb3duIGNvbnRlbnQuXG4gICAqL1xuICByZWFkb25seSBjb250ZW50OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBub3RlJ3MgcGF0aCByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCBmb2xkZXIsIGUuZy4gYDAwIFN0YXJ0Lm1kYC5cbiAgICovXG4gIHJlYWRvbmx5IHJlbGF0aXZlUGF0aDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwYXJzZWQgbWVtYmVycyBvZiBhIHNvdXJjZSBpbnRlcmZhY2UsIGNsYXNzLCBvciBlbnVtLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEludGVyZmFjZU1lbWJlcnMge1xuICAvKipcbiAgICogRXZlcnkgbWVtYmVyIFx1MjAxNCB7QGxpbmsgSW50ZXJmYWNlTWVtYmVycy5tZXRob2RzfSBmb2xsb3dlZCBieSB7QGxpbmsgSW50ZXJmYWNlTWVtYmVycy5wcm9wZXJ0aWVzfS5cbiAgICovXG4gIHJlYWRvbmx5IGFsbDogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBtZXRob2QgbWVtYmVycyAoZGVjbGFyZWQgYXMgYG5hbWUoLi4uKWApLlxuICAgKi9cbiAgcmVhZG9ubHkgbWV0aG9kczogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBwcm9wZXJ0eSBtZW1iZXJzIChkZWNsYXJlZCBhcyBgbmFtZT86IC4uLmApLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvcGVydGllczogc3RyaW5nW107XG59XG5cbi8qKlxuICogVGhlIHBhcmFtZXRlcnMgZm9yIHtAbGluayByZWdpc3RlckRlbW9WYXVsdENvdmVyYWdlU3VpdGV9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZ2lzdGVyRGVtb1ZhdWx0Q292ZXJhZ2VTdWl0ZVBhcmFtcyB7XG4gIC8qKlxuICAgKiBUdW5lcyB0aGUgYWx3YXlzLW9uIGF1dGhvcmluZyBjaGVja3MsIG9yIGB1bmRlZmluZWRgIHRvIHRha2UgdGhlaXIgZGVmYXVsdHMuIEl0IGNhbm5vdCBkaXNhYmxlIHRoZW0uXG4gICAqL1xuICByZWFkb25seSBhdXRob3Jpbmc/OiBEZW1vVmF1bHRBdXRob3JpbmdTcGVjO1xuXG4gIC8qKlxuICAgKiBUaGUgY29uZmlnIGludGVyZmFjZXMgd2hvc2Ugb3B0aW9ucyBtdXN0IGVhY2ggYmUgZGVtb25zdHJhdGVkIGJ5IHRoZWlyIGJhcmUgbmFtZS5cbiAgICovXG4gIHJlYWRvbmx5IGNvbmZpZ0ludGVyZmFjZXM6IERlbW9WYXVsdENvbmZpZ0ludGVyZmFjZUNvdmVyYWdlU3BlY1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgZmVhdHVyZS1kb2MgbGlua2luZyBjaGVjaywgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGUgcGx1Z2luIHNoaXBzIG5vIGBkb2NzL2AgZm9sZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgZG9jcz86IERlbW9WYXVsdERvY3NDb3ZlcmFnZVNwZWM7XG5cbiAgLyoqXG4gICAqIFRoZSBtb2R1bGVzIHdob3NlIGBleHBvcnQgZnVuY3Rpb25gcyBtdXN0IGVhY2ggYmUgZGVtb25zdHJhdGVkIGJ5IHRoZWlyIGJhcmUgbmFtZSwgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGVcbiAgICogcGx1Z2luIGV4cG9zZXMgbm8gc3VjaCBtb2R1bGUgdG8gY2hlY2suXG4gICAqL1xuICByZWFkb25seSBmdW5jdGlvbk1vZHVsZXM/OiBEZW1vVmF1bHRGdW5jdGlvbnNDb3ZlcmFnZVNwZWNbXTtcblxuICAvKipcbiAgICogVGhlIGludGVyZmFjZXMgd2hvc2UgbWVtYmVycyBtdXN0IGVhY2ggYmUgZGVtb25zdHJhdGVkIChhbmQgcmVmZXJlbmNlZCB3aXRob3V0IGRyaWZ0KS5cbiAgICovXG4gIHJlYWRvbmx5IGludGVyZmFjZXM6IERlbW9WYXVsdEludGVyZmFjZUNvdmVyYWdlU3BlY1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgZ3VhcmQgdGhhdCBrZWVwcyB0aGUgcmVmbGVjdGVkIHN1cmZhY2Ugbm9uLXRyaXZpYWwuXG4gICAqL1xuICByZWFkb25seSBub25Ucml2aWFsR3VhcmQ6IERlbW9WYXVsdE5vblRyaXZpYWxHdWFyZFNwZWM7XG5cbiAgLyoqXG4gICAqIFRoZSBhYnNvbHV0ZSBwYXRoIG9mIHRoZSBwbHVnaW4gcmVwbyByb290LiBDYWxsZXJzIHR5cGljYWxseSBwYXNzIGBnZXRSb290Rm9sZGVyKCkgPz8gcHJvY2Vzcy5jd2QoKWAuXG4gICAqL1xuICByZWFkb25seSByb290Rm9sZGVyOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVmbGVjdHMgYSBwbHVnaW4ncyBwdWJsaWMgc3VyZmFjZSBmcm9tIHNvdXJjZSBhbmQgY2hlY2tzIGl0cyBpbi1yZXBvIGBkZW1vLXZhdWx0L2Agc3RheXMgaW4gc3luYyB3aXRoIGl0LlxuICpcbiAqIEV2ZXJ5IG1ldGhvZCBpcyBhIHB1cmUgcXVlcnkgb3ZlciBmaWxlcyB1bmRlciB0aGUgcmVwbyByb290ICh0aGUgZGVtbyBjb3JwdXMgaXMgcmVhZCBvbmNlIGFuZCBjYWNoZWQpLCBzb1xuICogdGhlIGNoZWNrZXIgaXMgdHJpdmlhbGx5IHVuaXQtdGVzdGFibGUgYWdhaW5zdCBhIGZpeHR1cmUgcmVwbyBhbmQgY2FycmllcyBubyB0ZXN0LWZyYW1ld29yayBkZXBlbmRlbmN5LlxuICovXG5leHBvcnQgY2xhc3MgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyIHtcbiAgcHJpdmF0ZSBjYWNoZWRDb3JwdXM6IG51bGwgfCBzdHJpbmcgPSBudWxsO1xuICBwcml2YXRlIGNhY2hlZE5vdGVzOiBEZW1vVmF1bHROb3RlW10gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSBkZW1vVmF1bHRGb2xkZXI6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBleGNsdWRlZE5vdGVzOiBTZXQ8c3RyaW5nPjtcbiAgcHJpdmF0ZSByZWFkb25seSByb290Rm9sZGVyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBjaGVja2VyIHJvb3RlZCBhdCBhIHBsdWdpbiByZXBvLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBjb25zdHJ1Y3Rvci5cbiAgICovXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJhbXM6IERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckNvbnN0cnVjdG9yUGFyYW1zKSB7XG4gICAgdGhpcy5yb290Rm9sZGVyID0gcGFyYW1zLnJvb3RGb2xkZXI7XG4gICAgdGhpcy5kZW1vVmF1bHRGb2xkZXIgPSBqb2luKHRoaXMucm9vdEZvbGRlciwgT2JzaWRpYW5QbHVnaW5SZXBvUGF0aHMuRGVtb1ZhdWx0KTtcbiAgICB0aGlzLmV4Y2x1ZGVkTm90ZXMgPSBuZXcgU2V0KHBhcmFtcy5leGNsdWRlZE5vdGVzID8/IERFRkFVTFRfRVhDTFVERURfTk9URVMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbGxlY3RzIHRoZSBkZW1vIG5vdGVzIGFzIHBhdGhzIHJlbGF0aXZlIHRvIHRoZSBkZW1vIHZhdWx0IGZvbGRlciAoZm9yIGEgbm9uLXRyaXZpYWwtc3VyZmFjZSBndWFyZCkuXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSByZWxhdGl2ZSBwYXRocyBvZiBldmVyeSBgKi5tZGAgbm90ZSBpbiB0aGUgZGVtbyB2YXVsdC5cbiAgICovXG4gIHB1YmxpYyBjb2xsZWN0RGVtb05vdGVSZWxhdGl2ZVBhdGhzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Tm90ZXMoKS5tYXAoKG5vdGUpID0+IG5vdGUucmVsYXRpdmVQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkcyBhbmQgY2FjaGVzIGV2ZXJ5IGRlbW8gbm90ZSBpbmRpdmlkdWFsbHkgXHUyMDE0IHRoZSBwZXItbm90ZSB2aWV3IHRoZSBhdXRob3JpbmcgY2hlY2tzIHdvcmsgb24sIGFzXG4gICAqIG9wcG9zZWQgdG8gdGhlIGNvbmNhdGVuYXRlZCB7QGxpbmsgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyLnJlYWRDb3JwdXN9LlxuICAgKlxuICAgKiBAcmV0dXJucyBFdmVyeSBgKi5tZGAgbm90ZSBpbiB0aGUgZGVtbyB2YXVsdCwgZXhjbHVkZWQgb25lcyBpbmNsdWRlZC5cbiAgICovXG4gIHB1YmxpYyBjb2xsZWN0Tm90ZXMoKTogRGVtb1ZhdWx0Tm90ZVtdIHtcbiAgICB0aGlzLmNhY2hlZE5vdGVzID8/PSB0aGlzLmNvbGxlY3RNYXJrZG93bkZpbGVzKHRoaXMuZGVtb1ZhdWx0Rm9sZGVyKS5tYXAoKGZpbGUpID0+ICh7XG4gICAgICBjb250ZW50OiByZWFkRmlsZVN5bmMoZmlsZSwgJ3V0Zi04JyksXG4gICAgICByZWxhdGl2ZVBhdGg6IHJlbGF0aXZlKHRoaXMuZGVtb1ZhdWx0Rm9sZGVyLCBmaWxlKVxuICAgIH0pKTtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWROb3RlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBub3RlcyBjYXJyeWluZyBhIGBbRG9jc10oXHUyMDI2KWAgbGluayBsaW5lLiBUaGUgbm90ZSBJUyB0aGUgZG9jdW1lbnRhdGlvbiwgc28gYSBsaW5lIHBvaW50aW5nXG4gICAqIGVsc2V3aGVyZSBmb3IgdGhlIHJlYWwgZXhwbGFuYXRpb24gaXMgdGhlIHNoYXBlIHRoaXMgY29udmVudGlvbiBleGlzdHMgdG8gcmVtb3ZlLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgcmVsYXRpdmUgcGF0aHMgb2YgdGhlIG9mZmVuZGluZyBub3Rlcy5cbiAgICovXG4gIHB1YmxpYyBmaW5kTm90ZXNXaXRoRG9jc0xpbmtzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Q2hlY2thYmxlTm90ZXMoKVxuICAgICAgLmZpbHRlcigobm90ZSkgPT4gZ2V0TGluZXNPdXRzaWRlRmVuY2VzKG5vdGUuY29udGVudCkuc29tZSgobGluZSkgPT4gRE9DU19MSU5LX1JFR19FWFAudGVzdChsaW5lKSkpXG4gICAgICAubWFwKChub3RlKSA9PiBub3RlLnJlbGF0aXZlUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgbm90ZXMgdGhhdCBkbyBub3Qgb3BlbiB3aXRoIGFuIGAjIEgxYCAoZnJvbnRtYXR0ZXIgYXNpZGUpLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgcmVsYXRpdmUgcGF0aHMgb2YgdGhlIG9mZmVuZGluZyBub3Rlcy5cbiAgICovXG4gIHB1YmxpYyBmaW5kTm90ZXNXaXRob3V0SDEoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0aGlzLmNvbGxlY3RDaGVja2FibGVOb3RlcygpXG4gICAgICAuZmlsdGVyKChub3RlKSA9PiAhaGFzSDEobm90ZS5jb250ZW50KSlcbiAgICAgIC5tYXAoKG5vdGUpID0+IG5vdGUucmVsYXRpdmVQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBub3RlcyB3aXRoIG5vIHByb3NlIHBhcmFncmFwaCBiZWZvcmUgdGhlaXIgZmlyc3QgY29kZSBmZW5jZSBcdTIwMTQgdGhlIDEtMyBzZW50ZW5jZXMgc2F5aW5nIHdoYXQgdGhlXG4gICAqIGZlYXR1cmUgZG9lcyBhbmQgd2h5IGEgcmVhZGVyIHdvdWxkIHdhbnQgaXQsIHdpdGhvdXQgd2hpY2ggdGhlIG5vdGUgaXMgYSBidXR0b24gd2l0aCBubyBsZXNzb24uXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSByZWxhdGl2ZSBwYXRocyBvZiB0aGUgb2ZmZW5kaW5nIG5vdGVzLlxuICAgKi9cbiAgcHVibGljIGZpbmROb3Rlc1dpdGhvdXRJbnRyb1Byb3NlKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Q2hlY2thYmxlTm90ZXMoKVxuICAgICAgLmZpbHRlcigobm90ZSkgPT4gIWhhc0ludHJvUHJvc2Uobm90ZS5jb250ZW50KSlcbiAgICAgIC5tYXAoKG5vdGUpID0+IG5vdGUucmVsYXRpdmVQYXRoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBub3RlcyB1c2luZyBhbiBPYnNpZGlhbiBgW1t3aWtpbGlua11dYCBvdXRzaWRlIGEgY29kZSBmZW5jZS4gVGhlIGRlbW8gdmF1bHQgaXMgYWxzbyByZWFkIG9uXG4gICAqIEdpdEh1Yiwgd2hlcmUgYSB3aWtpbGluayByZW5kZXJzIGFzIGxpdGVyYWwgYnJhY2tldHMgYW5kIGxlYWRzIG5vd2hlcmUuIEEgd2lraWxpbmsgc2hvd24gSU5TSURFIGFcbiAgICogZmVuY2UgaXMgc2FtcGxlIHRleHQsIG5vdCBuYXZpZ2F0aW9uLCBzbyBmZW5jZWQgYmxvY2tzIGFyZSBza2lwcGVkLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgcmVsYXRpdmUgcGF0aHMgb2YgdGhlIG9mZmVuZGluZyBub3Rlcy5cbiAgICovXG4gIHB1YmxpYyBmaW5kTm90ZXNXaXRoV2lraWxpbmtzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Q2hlY2thYmxlTm90ZXMoKVxuICAgICAgLmZpbHRlcigobm90ZSkgPT4gZ2V0TGluZXNPdXRzaWRlRmVuY2VzKG5vdGUuY29udGVudCkuc29tZSgobGluZSkgPT4gV0lLSUxJTktfUkVHX0VYUC50ZXN0KHN0cmlwSW5saW5lQ29kZShsaW5lKSkpKVxuICAgICAgLm1hcCgobm90ZSkgPT4gbm90ZS5yZWxhdGl2ZVBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmRzIG1lbWJlcnMgdGhhdCB0aGUgZGVtbyBub3RlcyByZWZlcmVuY2Ugb24gYSByZWNlaXZlciBidXQgdGhhdCBubyBsb25nZXIgZXhpc3Qgb24gaXQgKHJlbmFtZSBkcmlmdCkuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGxvb2t1cC5cbiAgICogQHJldHVybnMgVGhlIGRpc3RpbmN0IHN0YWxlIG1lbWJlciBuYW1lcyByZWZlcmVuY2VkIGluIHRoZSBkZW1vIGNvcnB1cy5cbiAgICovXG4gIHB1YmxpYyBmaW5kU3RhbGVSZWZlcmVuY2VzKHBhcmFtczogRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyRmluZFN0YWxlUmVmZXJlbmNlc1BhcmFtcyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB2YWxpZE1lbWJlcnMgPSBuZXcgU2V0KHBhcmFtcy52YWxpZE1lbWJlcnMpO1xuICAgIGNvbnN0IHJlZmVyZW5jZWQgPSBbLi4udGhpcy5yZWFkQ29ycHVzKCkubWF0Y2hBbGwobmV3IFJlZ0V4cChTdHJpbmcucmF3YCR7cGFyYW1zLnJlY2VpdmVyfVxcLig/PG1lbWJlcj5cXHcrKWAsICdnJykpXVxuICAgICAgLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdtZW1iZXInKSk7XG4gICAgcmV0dXJuIFsuLi5uZXcgU2V0KHJlZmVyZW5jZWQpXS5maWx0ZXIoKG1lbWJlcikgPT4gIXZhbGlkTWVtYmVycy5oYXMobWVtYmVyKSk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgbWVtYmVycyB0aGF0IGFyZSBub3QgZGVtb25zdHJhdGVkIGFueXdoZXJlIGluIHRoZSBkZW1vIGNvcnB1cy5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyAtIFRoZSBwYXJhbWV0ZXJzIGZvciB0aGUgbG9va3VwLlxuICAgKiBAcmV0dXJucyBUaGUgbWVtYmVyIG5hbWVzIHdpdGggbm8gZGVtb25zdHJhdGlvbi5cbiAgICovXG4gIHB1YmxpYyBmaW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzKHBhcmFtczogRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyRmluZFVuZGVtb25zdHJhdGVkTWVtYmVyc1BhcmFtcyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBjb3JwdXMgPSB0aGlzLnJlYWRDb3JwdXMoKTtcbiAgICByZXR1cm4gcGFyYW1zLm1lbWJlcnMuZmlsdGVyKChtZW1iZXIpID0+IHtcbiAgICAgIGNvbnN0IG5lZWRsZSA9IHBhcmFtcy5yZWNlaXZlciA9PT0gdW5kZWZpbmVkID8gbWVtYmVyIDogYCR7cGFyYW1zLnJlY2VpdmVyfS4ke21lbWJlcn1gO1xuICAgICAgcmV0dXJuICFjb3JwdXMuaW5jbHVkZXMobmVlZGxlKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5kcyBmZWF0dXJlIGRvY3MgdGhhdCBubyBkZW1vIG5vdGUgbGlua3MgdG8uXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGxvb2t1cC5cbiAgICogQHJldHVybnMgVGhlIGZlYXR1cmUtZG9jIGJhc2VuYW1lcyAod2l0aG91dCBgLm1kYCkgbm90IGxpbmtlZCBmcm9tIGFueSBkZW1vIG5vdGUuXG4gICAqL1xuICBwdWJsaWMgZmluZFVubGlua2VkRmVhdHVyZURvY3MocGFyYW1zOiBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJGaW5kVW5saW5rZWRGZWF0dXJlRG9jc1BhcmFtcyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBub25GZWF0dXJlRG9jcyA9IG5ldyBTZXQocGFyYW1zLm5vbkZlYXR1cmVEb2NzKTtcbiAgICBjb25zdCBmZWF0dXJlRG9jcyA9IHJlYWRkaXJTeW5jKGpvaW4odGhpcy5yb290Rm9sZGVyLCBwYXJhbXMuZG9jc0ZvbGRlcikpXG4gICAgICAuZmlsdGVyKChmaWxlKSA9PiBmaWxlLmVuZHNXaXRoKCcubWQnKSlcbiAgICAgIC5tYXAoKGZpbGUpID0+IGZpbGUucmVwbGFjZSgvXFwubWQkLywgJycpKVxuICAgICAgLmZpbHRlcigobmFtZSkgPT4gIW5vbkZlYXR1cmVEb2NzLmhhcyhuYW1lKSk7XG4gICAgY29uc3QgbGlua2VkRG9jcyA9IG5ldyBTZXQoXG4gICAgICBbLi4udGhpcy5yZWFkQ29ycHVzKCkubWF0Y2hBbGwoL2RvY3NcXC8oPzxkb2M+W1xcdy1dKylcXC5tZC9nKV0ubWFwKChtYXRjaCkgPT4gZ2V0TWFuZGF0b3J5TmFtZWRHcm91cChtYXRjaCwgJ2RvYycpKVxuICAgICk7XG4gICAgcmV0dXJuIGZlYXR1cmVEb2NzLmZpbHRlcigoZG9jKSA9PiAhbGlua2VkRG9jcy5oYXMoZG9jKSk7XG4gIH1cblxuICAvKipcbiAgICogRmluZHMgbm90ZXMgdGhhdCBjYW5ub3QgYmUgcmVhY2hlZCBmcm9tIHRoZSBzdGFydCBub3RlIGJ5IGZvbGxvd2luZyBNYXJrZG93biBsaW5rcyBiZXR3ZWVuIG5vdGVzLlxuICAgKlxuICAgKiBUaGUgd2FsayBzdGFydHMgYXQge0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlckZpbmRVbnJlYWNoYWJsZU5vdGVzUGFyYW1zLnN0YXJ0Tm90ZX0gYW5kIGZvbGxvd3NcbiAgICogZXZlcnkgYFtUZXh0XSg8Li9OTiBOYW1lLm1kPilgIGxpbmsgb3V0c2lkZSBhIGNvZGUgZmVuY2UsIHRyYW5zaXRpdmVseS4gQSBub3RlIG5vdGhpbmcgbGlua3MgdG8gaXNcbiAgICogb25lIGEgcmVhZGVyIGNhbiBvbmx5IGZpbmQgYnkgYnJvd3NpbmcgdGhlIGZpbGUgbGlzdCBcdTIwMTQgd2hpY2ggaXMgZXhhY3RseSB3aGF0IHRoZSBncm91cGVkIGluZGV4IGluIHRoZVxuICAgKiBzdGFydCBub3RlIGlzIG1lYW50IHRvIHJlcGxhY2UuIFdoZW4gdGhlIHN0YXJ0IG5vdGUgaXRzZWxmIGlzIG1pc3NpbmcsIEVWRVJZIG5vdGUgaXMgdW5yZWFjaGFibGUsXG4gICAqIGJlY2F1c2UgdGhlcmUgaXMgbm93aGVyZSB0byBzdGFydCBmcm9tLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSB3YWxrLlxuICAgKiBAcmV0dXJucyBUaGUgcmVsYXRpdmUgcGF0aHMgb2YgdGhlIHVucmVhY2hhYmxlIG5vdGVzLlxuICAgKi9cbiAgcHVibGljIGZpbmRVbnJlYWNoYWJsZU5vdGVzKHBhcmFtczogRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyRmluZFVucmVhY2hhYmxlTm90ZXNQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3Qgbm90ZXNCeVJlbGF0aXZlUGF0aCA9IG5ldyBNYXAodGhpcy5jb2xsZWN0Tm90ZXMoKS5tYXAoKG5vdGUpID0+IFtub3RlLnJlbGF0aXZlUGF0aCwgbm90ZV0pKTtcbiAgICBjb25zdCByZWFjaGVkTm90ZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBjb25zdCBwZW5kaW5nTm90ZXMgPSBbcGFyYW1zLnN0YXJ0Tm90ZV07XG5cbiAgICB3aGlsZSAocGVuZGluZ05vdGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5vdGVQYXRoID0gZW5zdXJlTm9uTnVsbGFibGUocGVuZGluZ05vdGVzLnBvcCgpKTtcbiAgICAgIGNvbnN0IG5vdGUgPSBub3Rlc0J5UmVsYXRpdmVQYXRoLmdldChub3RlUGF0aCk7XG4gICAgICBpZiAoIW5vdGUgfHwgcmVhY2hlZE5vdGVzLmhhcyhub3RlUGF0aCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICByZWFjaGVkTm90ZXMuYWRkKG5vdGVQYXRoKTtcbiAgICAgIHBlbmRpbmdOb3Rlcy5wdXNoKC4uLmNvbGxlY3ROb3RlTGlua1RhcmdldHMobm90ZSkpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNvbGxlY3RDaGVja2FibGVOb3RlcygpXG4gICAgICAubWFwKChub3RlKSA9PiBub3RlLnJlbGF0aXZlUGF0aClcbiAgICAgIC5maWx0ZXIoKG5vdGVQYXRoKSA9PiAhcmVhY2hlZE5vdGVzLmhhcyhub3RlUGF0aCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyB0aGUgbmFtZXMgb2YgdGhlIGBleHBvcnQgZnVuY3Rpb25gcyAoaW5jbHVkaW5nIGBhc3luY2AgYW5kIGdlbmVyYXRvciBkZWNsYXJhdGlvbnMpIGluIGEgc291cmNlIGZpbGUuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGxvb2t1cC5cbiAgICogQHJldHVybnMgVGhlIGV4cG9ydGVkIGZ1bmN0aW9uIG5hbWVzIGluIHNvdXJjZSBvcmRlci5cbiAgICovXG4gIHB1YmxpYyBnZXRFeHBvcnRlZEZ1bmN0aW9uTmFtZXMocGFyYW1zOiBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJHZXRFeHBvcnRlZEZ1bmN0aW9uTmFtZXNQYXJhbXMpOiBzdHJpbmdbXSB7XG4gICAgY29uc3Qgc291cmNlID0gcmVhZEZpbGVTeW5jKGpvaW4odGhpcy5yb290Rm9sZGVyLCBwYXJhbXMuc291cmNlUGF0aCksICd1dGYtOCcpO1xuICAgIHJldHVybiBbLi4uc291cmNlLm1hdGNoQWxsKC9eZXhwb3J0ICg/OmFzeW5jICk/ZnVuY3Rpb25cXCo/ICg/PG5hbWU+XFx3KykvZ20pXVxuICAgICAgLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlcyB0aGUgbWVtYmVycyBvZiBhbiBgZXhwb3J0IGludGVyZmFjZWAsIGBleHBvcnQgY2xhc3NgLCBvciBgZXhwb3J0IGVudW1gIGRlY2xhcmVkIGluIGEgc291cmNlIGZpbGUuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgcGFyYW1ldGVycyBmb3IgdGhlIGxvb2t1cC5cbiAgICogQHJldHVybnMgVGhlIHBhcnNlZCB7QGxpbmsgSW50ZXJmYWNlTWVtYmVyc30uXG4gICAqIEB0aHJvd3MgV2hlbiB0aGUgaW50ZXJmYWNlLCBjbGFzcywgb3IgZW51bSBjYW5ub3QgYmUgZm91bmQgaW4gdGhlIHNvdXJjZSBmaWxlLlxuICAgKi9cbiAgcHVibGljIGdldEludGVyZmFjZU1lbWJlcnMocGFyYW1zOiBEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJHZXRJbnRlcmZhY2VNZW1iZXJzUGFyYW1zKTogSW50ZXJmYWNlTWVtYmVycyB7XG4gICAgY29uc3Qgc291cmNlID0gcmVhZEZpbGVTeW5jKGpvaW4odGhpcy5yb290Rm9sZGVyLCBwYXJhbXMuc291cmNlUGF0aCksICd1dGYtOCcpO1xuICAgIGNvbnN0IG1hdGNoID0gbmV3IFJlZ0V4cChTdHJpbmcucmF3YGV4cG9ydCAoPzxrZXl3b3JkPmludGVyZmFjZXxjbGFzc3xlbnVtKSAke3BhcmFtcy5pbnRlcmZhY2VOYW1lfVxcYltee10qXFx7KD88Ym9keT5bXFxzXFxTXSo/KVxcblxcfWApLmV4ZWMoc291cmNlKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENvdWxkIG5vdCBmaW5kIGludGVyZmFjZSAke3BhcmFtcy5pbnRlcmZhY2VOYW1lfWApO1xuICAgIH1cbiAgICByZXR1cm4gcGFyc2VNZW1iZXJzKGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdrZXl3b3JkJyksIGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdib2R5JykpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlYWRzIGFuZCBjYWNoZXMgdGhlIGRlbW8gY29ycHVzIFx1MjAxNCBldmVyeSBgKi5tZGAgbm90ZSBpbiB0aGUgZGVtbyB2YXVsdCBqb2luZWQgaW50byBvbmUgc3RyaW5nLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgY29uY2F0ZW5hdGVkIGRlbW8tbm90ZSBjb250ZW50cy5cbiAgICovXG4gIHB1YmxpYyByZWFkQ29ycHVzKCk6IHN0cmluZyB7XG4gICAgdGhpcy5jYWNoZWRDb3JwdXMgPz89IHRoaXMuY29sbGVjdE5vdGVzKClcbiAgICAgIC5tYXAoKG5vdGUpID0+IG5vdGUuY29udGVudClcbiAgICAgIC5qb2luKCdcXG4nKTtcbiAgICByZXR1cm4gdGhpcy5jYWNoZWRDb3JwdXM7XG4gIH1cblxuICAvLyBUaGUgbm90ZXMgdGhlIGF1dGhvcmluZyBjaGVja3MgYXBwbHkgdG86IGV2ZXJ5IG5vdGUgZXhjZXB0IHRoZSBvbmVzIGRlY2xhcmVkIG91dHNpZGUgdGhlIGxlYXJuaW5nXG4gIC8vIFBhdGggKHRoZSB2YXVsdCdzIG93biBgUkVBRE1FLm1kYCBieSBkZWZhdWx0KS5cbiAgcHJpdmF0ZSBjb2xsZWN0Q2hlY2thYmxlTm90ZXMoKTogRGVtb1ZhdWx0Tm90ZVtdIHtcbiAgICByZXR1cm4gdGhpcy5jb2xsZWN0Tm90ZXMoKS5maWx0ZXIoKG5vdGUpID0+ICF0aGlzLmV4Y2x1ZGVkTm90ZXMuaGFzKG5vdGUucmVsYXRpdmVQYXRoKSk7XG4gIH1cblxuICBwcml2YXRlIGNvbGxlY3RNYXJrZG93bkZpbGVzKGZvbGRlcjogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHJlc3VsdDogc3RyaW5nW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHJlYWRkaXJTeW5jKGZvbGRlciwgeyB3aXRoRmlsZVR5cGVzOiB0cnVlIH0pKSB7XG4gICAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgICBpZiAoZW50cnkubmFtZSA9PT0gT2JzaWRpYW5QbHVnaW5SZXBvUGF0aHMuTm9kZU1vZHVsZXMgYXMgc3RyaW5nKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0LnB1c2goLi4udGhpcy5jb2xsZWN0TWFya2Rvd25GaWxlcyhqb2luKGZvbGRlciwgZW50cnkubmFtZSkpKTtcbiAgICAgIH0gZWxzZSBpZiAoZW50cnkubmFtZS5lbmRzV2l0aCgnLm1kJykpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goam9pbihmb2xkZXIsIGVudHJ5Lm5hbWUpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhIGB2aXRlc3RgIHN1aXRlIHRoYXQga2VlcHMgYSBwbHVnaW4ncyBpbi1yZXBvIGBkZW1vLXZhdWx0L2AgaW4gc3luYyB3aXRoIGl0cyBwdWJsaWMgc3VyZmFjZS5cbiAqXG4gKiBDYWxsIGl0IG9uY2UgZnJvbSBhIHBsdWdpbidzIGBkZW1vLXZhdWx0Lm5vLWFwcC5pbnRlZ3JhdGlvbi50ZXN0LnRzYDsgaXQgcmVnaXN0ZXJzIG9uZSB0ZXN0IHBlciBjaGVjayxcbiAqIGRlbGVnYXRpbmcgdG8ge0BsaW5rIERlbW9WYXVsdENvdmVyYWdlQ2hlY2tlcn0uXG4gKlxuICogQHBhcmFtIHBhcmFtcyAtIFRoZSBkZWNsYXJhdGl2ZSBjb3ZlcmFnZSBzcGVjaWZpY2F0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJEZW1vVmF1bHRDb3ZlcmFnZVN1aXRlKHBhcmFtczogUmVnaXN0ZXJEZW1vVmF1bHRDb3ZlcmFnZVN1aXRlUGFyYW1zKTogdm9pZCB7XG4gIGNvbnN0IGNoZWNrZXIgPSBuZXcgRGVtb1ZhdWx0Q292ZXJhZ2VDaGVja2VyKG5vcm1hbGl6ZU9wdGlvbmFsUHJvcGVydGllczxEZW1vVmF1bHRDb3ZlcmFnZUNoZWNrZXJDb25zdHJ1Y3RvclBhcmFtcz4oe1xuICAgIGV4Y2x1ZGVkTm90ZXM6IHBhcmFtcy5hdXRob3Jpbmc/LmV4Y2x1ZGVkTm90ZXMsXG4gICAgcm9vdEZvbGRlcjogcGFyYW1zLnJvb3RGb2xkZXJcbiAgfSkpO1xuICBjb25zdCBzdGFydE5vdGUgPSBwYXJhbXMuYXV0aG9yaW5nPy5zdGFydE5vdGUgPz8gREVGQVVMVF9TVEFSVF9OT1RFO1xuXG4gIGRlc2NyaWJlKCdkZW1vLXZhdWx0IGNvdmVyYWdlJywgKCkgPT4ge1xuICAgIGZvciAoY29uc3Qgc3BlYyBvZiBwYXJhbXMuaW50ZXJmYWNlcykge1xuICAgICAgaXQoYGRlbW9uc3RyYXRlcyBldmVyeSAke3NwZWMuaW50ZXJmYWNlTmFtZX0gJHtzcGVjLmtpbmR9YCwgKCkgPT4ge1xuICAgICAgICBjb25zdCBtZW1iZXJzID0gY2hlY2tlci5nZXRJbnRlcmZhY2VNZW1iZXJzKHNwZWMpO1xuICAgICAgICBjb25zdCBkZW1vbnN0cmF0ZWQgPSBtZW1iZXJzW3NwZWMua2luZF07XG4gICAgICAgIGV4cGVjdChkZW1vbnN0cmF0ZWQubGVuZ3RoKS50b0JlR3JlYXRlclRoYW4oMCk7XG4gICAgICAgIGV4cGVjdChjaGVja2VyLmZpbmRVbmRlbW9uc3RyYXRlZE1lbWJlcnMoeyBtZW1iZXJzOiBkZW1vbnN0cmF0ZWQsIHJlY2VpdmVyOiBzcGVjLnJlY2VpdmVyIH0pKS50b0VxdWFsKFtdKTtcbiAgICAgIH0pO1xuXG4gICAgICBpdChgcmVmZXJlbmNlcyBubyAke3NwZWMuaW50ZXJmYWNlTmFtZX0gbWVtYmVyIHRoYXQgbm8gbG9uZ2VyIGV4aXN0c2AsICgpID0+IHtcbiAgICAgICAgY29uc3QgbWVtYmVycyA9IGNoZWNrZXIuZ2V0SW50ZXJmYWNlTWVtYmVycyhzcGVjKTtcbiAgICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZFN0YWxlUmVmZXJlbmNlcyh7IHJlY2VpdmVyOiBzcGVjLnJlY2VpdmVyLCB2YWxpZE1lbWJlcnM6IG1lbWJlcnMuYWxsIH0pKS50b0VxdWFsKFtdKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgc3BlYyBvZiBwYXJhbXMuY29uZmlnSW50ZXJmYWNlcykge1xuICAgICAgaXQoYGRlbW9uc3RyYXRlcyBldmVyeSAke3NwZWMuaW50ZXJmYWNlTmFtZX0gb3B0aW9uYCwgKCkgPT4ge1xuICAgICAgICBjb25zdCBtZW1iZXJzID0gY2hlY2tlci5nZXRJbnRlcmZhY2VNZW1iZXJzKHNwZWMpO1xuICAgICAgICBleHBlY3QobWVtYmVycy5wcm9wZXJ0aWVzLmxlbmd0aCkudG9CZUdyZWF0ZXJUaGFuKDApO1xuICAgICAgICBleHBlY3QoY2hlY2tlci5maW5kVW5kZW1vbnN0cmF0ZWRNZW1iZXJzKHsgbWVtYmVyczogbWVtYmVycy5wcm9wZXJ0aWVzIH0pKS50b0VxdWFsKFtdKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgc3BlYyBvZiBwYXJhbXMuZnVuY3Rpb25Nb2R1bGVzID8/IFtdKSB7XG4gICAgICBpdChgZGVtb25zdHJhdGVzIGV2ZXJ5IGV4cG9ydGVkIGZ1bmN0aW9uIGluICR7c3BlYy5zb3VyY2VQYXRofWAsICgpID0+IHtcbiAgICAgICAgY29uc3QgZnVuY3Rpb25OYW1lcyA9IGNoZWNrZXIuZ2V0RXhwb3J0ZWRGdW5jdGlvbk5hbWVzKHNwZWMpO1xuICAgICAgICBleHBlY3QoZnVuY3Rpb25OYW1lcy5sZW5ndGgpLnRvQmVHcmVhdGVyVGhhbigwKTtcbiAgICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZFVuZGVtb25zdHJhdGVkTWVtYmVycyh7IG1lbWJlcnM6IGZ1bmN0aW9uTmFtZXMgfSkpLnRvRXF1YWwoW10pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgZG9jcyA9IHBhcmFtcy5kb2NzO1xuICAgIGlmIChkb2NzKSB7XG4gICAgICBpdCgnbGlua3MgYSBkZW1vIG5vdGUgZm9yIGV2ZXJ5IGZlYXR1cmUgZG9jJywgKCkgPT4ge1xuICAgICAgICBleHBlY3QoY2hlY2tlci5maW5kVW5saW5rZWRGZWF0dXJlRG9jcyh7IGRvY3NGb2xkZXI6IGRvY3MuZm9sZGVyLCBub25GZWF0dXJlRG9jczogZG9jcy5ub25GZWF0dXJlRG9jcyB9KSlcbiAgICAgICAgICAudG9FcXVhbChbXSk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpdCgnb3BlbnMgZXZlcnkgbm90ZSB3aXRoIGFuIEgxJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZE5vdGVzV2l0aG91dEgxKCkpLnRvRXF1YWwoW10pO1xuICAgIH0pO1xuXG4gICAgaXQoJ29wZW5zIGV2ZXJ5IG5vdGUgd2l0aCBhIHByb3NlIHBhcmFncmFwaCBiZWZvcmUgaXRzIGZpcnN0IGNvZGUgYmxvY2snLCAoKSA9PiB7XG4gICAgICBleHBlY3QoY2hlY2tlci5maW5kTm90ZXNXaXRob3V0SW50cm9Qcm9zZSgpKS50b0VxdWFsKFtdKTtcbiAgICB9KTtcblxuICAgIGl0KGByZWFjaGVzIGV2ZXJ5IG5vdGUgZnJvbSAke3N0YXJ0Tm90ZX1gLCAoKSA9PiB7XG4gICAgICBleHBlY3QoY2hlY2tlci5maW5kVW5yZWFjaGFibGVOb3Rlcyh7IHN0YXJ0Tm90ZSB9KSkudG9FcXVhbChbXSk7XG4gICAgfSk7XG5cbiAgICBpdCgndXNlcyBubyB3aWtpbGlua3MsIHdoaWNoIGRvIG5vdCByZW5kZXIgb24gR2l0SHViJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZE5vdGVzV2l0aFdpa2lsaW5rcygpKS50b0VxdWFsKFtdKTtcbiAgICB9KTtcblxuICAgIGl0KCdjYXJyaWVzIG5vIERvY3MgbGluayBsaW5lLCBiZWNhdXNlIHRoZSBub3RlIGlzIHRoZSBkb2NzJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KGNoZWNrZXIuZmluZE5vdGVzV2l0aERvY3NMaW5rcygpKS50b0VxdWFsKFtdKTtcbiAgICB9KTtcblxuICAgIGl0KCdrZWVwcyB0aGUgcmVmbGVjdGVkIHN1cmZhY2Ugbm9uLXRyaXZpYWwnLCAoKSA9PiB7XG4gICAgICBjb25zdCBndWFyZCA9IHBhcmFtcy5ub25Ucml2aWFsR3VhcmQ7XG4gICAgICBjb25zdCBtZW1iZXJzID0gY2hlY2tlci5nZXRJbnRlcmZhY2VNZW1iZXJzKGd1YXJkKTtcbiAgICAgIGV4cGVjdChtZW1iZXJzLmFsbCkudG9Db250YWluKGd1YXJkLmV4cGVjdE1lbWJlcik7XG4gICAgICBleHBlY3QoY2hlY2tlci5jb2xsZWN0RGVtb05vdGVSZWxhdGl2ZVBhdGhzKCkpLnRvQ29udGFpbihndWFyZC5leHBlY3REZW1vTm90ZSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5jb25zdCBDTEFTU19NRU1CRVJfTU9ESUZJRVJTID0gU3RyaW5nLnJhd2AoPzooPzpwdWJsaWN8cHJpdmF0ZXxwcm90ZWN0ZWR8cmVhZG9ubHl8c3RhdGljfGFic3RyYWN0fG92ZXJyaWRlKVxccyspKmA7XG5jb25zdCBBQlNPTFVURV9VUkxfUkVHX0VYUCA9IC9eW2Etel1bXFx3Ky4tXSo6L2k7XG5jb25zdCBBTkdMRV9CUkFDS0VUU19SRUdfRVhQID0gL148fD4kL2c7XG5jb25zdCBDT0RFX0ZFTkNFX1JFR19FWFAgPSAvXlxccyooPzpgYGB8fn5+KS87XG5jb25zdCBERUZBVUxUX0VYQ0xVREVEX05PVEVTID0gWydSRUFETUUubWQnXTtcbmNvbnN0IERFRkFVTFRfU1RBUlRfTk9URSA9ICcwMCBTdGFydC5tZCc7XG5jb25zdCBET0NTX0xJTktfUkVHX0VYUCA9IC9eXFxzKlxcW0RvY3NdXFwoLztcbmNvbnN0IEZST05UTUFUVEVSX1JFR19FWFAgPSAvXi0tLVxccj9cXG5bXFxzXFxTXSo/XFxyP1xcbi0tLVteXFxTXFxuXSpcXHI/XFxuPy87XG5jb25zdCBIMV9SRUdfRVhQID0gL14jIFxcUy87XG5jb25zdCBIRUFESU5HX1JFR19FWFAgPSAvXiN7MSw2fSAvO1xuY29uc3QgSU5MSU5FX0NPREVfUkVHX0VYUCA9IC9gW15gXFxuXSpgL2c7XG5jb25zdCBNQVJLRE9XTl9MSU5LX1JFR19FWFAgPSAvXFxbW15cXF1dKl1cXCgoPzx0YXJnZXQ+W14pXSspXFwpL2c7XG5jb25zdCBXSUtJTElOS19SRUdfRVhQID0gL1xcW1xcW1teXFxdXStdXS87XG5cbmZ1bmN0aW9uIGJ1aWxkTWVtYmVycyhtZXRob2RzOiBzdHJpbmdbXSwgcHJvcGVydGllczogc3RyaW5nW10pOiBJbnRlcmZhY2VNZW1iZXJzIHtcbiAgcmV0dXJuIHtcbiAgICBhbGw6IFsuLi5tZXRob2RzLCAuLi5wcm9wZXJ0aWVzXSxcbiAgICBtZXRob2RzLFxuICAgIHByb3BlcnRpZXNcbiAgfTtcbn1cblxuLy8gUmVzb2x2ZXMgdGhlIG5vdGVzIGEgbm90ZSBsaW5rcyB0bzogZXZlcnkgTWFya2Rvd24gbGluayBvdXRzaWRlIGEgY29kZSBmZW5jZSB3aG9zZSB0YXJnZXQgaXMgYSBgLm1kYFxuLy8gRmlsZSwgbWFkZSByZWxhdGl2ZSB0byB0aGUgZGVtbyB2YXVsdCBzbyBpdCBjYW4gYmUgbG9va2VkIHVwIGluIHRoZSBub3RlIG1hcC4gRXh0ZXJuYWwgVVJMcyBhbmRcbi8vIE5vbi1ub3RlIHRhcmdldHMgKGltYWdlcywgc2NyaXB0cykgYXJlIG5vdCBwYXJ0IG9mIHRoZSBsZWFybmluZyBwYXRoIGFuZCBhcmUgc2tpcHBlZDsgYSBgI2FuY2hvcmAgaXNcbi8vIERyb3BwZWQsIHNpbmNlIGl0IGFkZHJlc3NlcyBhIHBsYWNlIGluc2lkZSBhbiBhbHJlYWR5LXJlc29sdmVkIG5vdGUuXG5mdW5jdGlvbiBjb2xsZWN0Tm90ZUxpbmtUYXJnZXRzKG5vdGU6IERlbW9WYXVsdE5vdGUpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHRhcmdldHM6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3QgbGluZSBvZiBnZXRMaW5lc091dHNpZGVGZW5jZXMobm90ZS5jb250ZW50KSkge1xuICAgIGZvciAoY29uc3QgbWF0Y2ggb2Ygc3RyaXBJbmxpbmVDb2RlKGxpbmUpLm1hdGNoQWxsKE1BUktET1dOX0xJTktfUkVHX0VYUCkpIHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICd0YXJnZXQnKS5yZXBsYWNlQWxsKEFOR0xFX0JSQUNLRVRTX1JFR19FWFAsICcnKTtcbiAgICAgIGNvbnN0IFtub3RlUGF0aCA9ICcnXSA9IHRhcmdldC5zcGxpdCgnIycsIDEpO1xuICAgICAgaWYgKEFCU09MVVRFX1VSTF9SRUdfRVhQLnRlc3Qobm90ZVBhdGgpIHx8ICFub3RlUGF0aC50b0xvd2VyQ2FzZSgpLmVuZHNXaXRoKCcubWQnKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIHRhcmdldHMucHVzaChqb2luKGRpcm5hbWUobm90ZS5yZWxhdGl2ZVBhdGgpLCB0cnlEZWNvZGVVcmlDb21wb25lbnQobm90ZVBhdGgpKSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB0YXJnZXRzO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0Q2xhc3NNZXRob2ROYW1lcyhjbGFzc0JvZHk6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgcmV0dXJuIFsuLi5jbGFzc0JvZHkubWF0Y2hBbGwobmV3IFJlZ0V4cChTdHJpbmcucmF3YF4gezJ9KD88bW9kaWZpZXJzPiR7Q0xBU1NfTUVNQkVSX01PRElGSUVSU30pKD88bmFtZT5cXHcrKSg/OjxbXj5dKj4pP1xcKGAsICdnbScpKV1cbiAgICAuZmlsdGVyKChtYXRjaCkgPT4gIWlzTm9uUHVibGljTWVtYmVyKGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdtb2RpZmllcnMnKSkpXG4gICAgLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0Q2xhc3NQcm9wZXJ0eU5hbWVzKGNsYXNzQm9keTogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gWy4uLmNsYXNzQm9keS5tYXRjaEFsbChuZXcgUmVnRXhwKFN0cmluZy5yYXdgXiB7Mn0oPzxtb2RpZmllcnM+JHtDTEFTU19NRU1CRVJfTU9ESUZJRVJTfSkoPzxuYW1lPlxcdyspXFxzKlxcPz9cXHMqWzo9XWAsICdnbScpKV1cbiAgICAuZmlsdGVyKChtYXRjaCkgPT4gIWlzTm9uUHVibGljTWVtYmVyKGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICdtb2RpZmllcnMnKSkpXG4gICAgLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0RW51bU1lbWJlck5hbWVzKGVudW1Cb2R5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBbLi4uZW51bUJvZHkubWF0Y2hBbGwoL14gezJ9KD88bmFtZT5cXHcrKS9nbSldLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0TWV0aG9kTmFtZXMoaW50ZXJmYWNlQm9keTogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gWy4uLmludGVyZmFjZUJvZHkubWF0Y2hBbGwoL14gezJ9KD88bmFtZT5cXHcrKSg/OjxbXj5dKj4pP1xcKC9nbSldLm1hcCgobWF0Y2gpID0+IGdldE1hbmRhdG9yeU5hbWVkR3JvdXAobWF0Y2gsICduYW1lJykpO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0UHJvcGVydHlOYW1lcyhpbnRlcmZhY2VCb2R5OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBbLi4uaW50ZXJmYWNlQm9keS5tYXRjaEFsbCgvXiB7Mn0oPzxuYW1lPlxcdyspXFw/PzovZ20pXS5tYXAoKG1hdGNoKSA9PiBnZXRNYW5kYXRvcnlOYW1lZEdyb3VwKG1hdGNoLCAnbmFtZScpKTtcbn1cblxuLy8gUmV0dXJucyB0aGUgbm90ZSdzIGxpbmVzIHdpdGggZmVuY2VkIGNvZGUgYmxvY2tzIHJlbW92ZWQgKHRoZSBmZW5jZSBsaW5lcyBpbmNsdWRlZCksIHNvIGEgY2hlY2sgbmV2ZXJcbi8vIE1pc3Rha2VzIHNhbXBsZSBjb2RlIGZvciBwcm9zZSBcdTIwMTQgYSBgW1t3aWtpbGlua11dYCBkZW1vbnN0cmF0ZWQgaW5zaWRlIGEgZmVuY2UgaXMgdGV4dCwgbm90IG5hdmlnYXRpb24uXG5mdW5jdGlvbiBnZXRMaW5lc091dHNpZGVGZW5jZXMoY29udGVudDogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXTtcbiAgbGV0IGlzSW5zaWRlRmVuY2UgPSBmYWxzZTtcbiAgZm9yIChjb25zdCBsaW5lIG9mIGNvbnRlbnQuc3BsaXQoJ1xcbicpKSB7XG4gICAgaWYgKENPREVfRkVOQ0VfUkVHX0VYUC50ZXN0KGxpbmUpKSB7XG4gICAgICBpc0luc2lkZUZlbmNlID0gIWlzSW5zaWRlRmVuY2U7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKCFpc0luc2lkZUZlbmNlKSB7XG4gICAgICBsaW5lcy5wdXNoKGxpbmUpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbGluZXM7XG59XG5cbi8vIFdoZXRoZXIgdGhlIG5vdGUncyBmaXJzdCBjb250ZW50IGxpbmUgKGZyb250bWF0dGVyIGFuZCBibGFuayBsaW5lcyBhc2lkZSkgaXMgYW4gYCMgSDFgLlxuZnVuY3Rpb24gaGFzSDEoY29udGVudDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGZvciAoY29uc3QgbGluZSBvZiBzdHJpcEZyb250bWF0dGVyKGNvbnRlbnQpLnNwbGl0KCdcXG4nKSkge1xuICAgIGNvbnN0IHRyaW1tZWRMaW5lID0gbGluZS50cmltKCk7XG4gICAgaWYgKHRyaW1tZWRMaW5lID09PSAnJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHJldHVybiBIMV9SRUdfRVhQLnRlc3QodHJpbW1lZExpbmUpO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLy8gV2hldGhlciBhIHBsYWluIHByb3NlIGxpbmUgYXBwZWFycyBiZWZvcmUgdGhlIG5vdGUncyBmaXJzdCBjb2RlIGZlbmNlLiBIZWFkaW5ncyBhcmUgbm90IHByb3NlIFx1MjAxNCBhIG5vdGVcbi8vIFRoYXQgZ29lcyBzdHJhaWdodCBmcm9tIGl0cyB0aXRsZSB0byBhIGJ1dHRvbiBpcyBleGFjdGx5IHRoZSBzaGFwZSB0aGlzIGNoZWNrIHJlamVjdHMuXG5mdW5jdGlvbiBoYXNJbnRyb1Byb3NlKGNvbnRlbnQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBmb3IgKGNvbnN0IGxpbmUgb2Ygc3RyaXBGcm9udG1hdHRlcihjb250ZW50KS5zcGxpdCgnXFxuJykpIHtcbiAgICBpZiAoQ09ERV9GRU5DRV9SRUdfRVhQLnRlc3QobGluZSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3QgdHJpbW1lZExpbmUgPSBsaW5lLnRyaW0oKTtcbiAgICBpZiAodHJpbW1lZExpbmUgPT09ICcnIHx8IEhFQURJTkdfUkVHX0VYUC50ZXN0KHRyaW1tZWRMaW5lKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNOb25QdWJsaWNNZW1iZXIobW9kaWZpZXJzOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIC9cXGIoPzpwcml2YXRlfHByb3RlY3RlZClcXGIvLnRlc3QobW9kaWZpZXJzKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VNZW1iZXJzKGtleXdvcmQ6IHN0cmluZywgYm9keTogc3RyaW5nKTogSW50ZXJmYWNlTWVtYmVycyB7XG4gIHN3aXRjaCAoa2V5d29yZCkge1xuICAgIGNhc2UgJ2NsYXNzJzoge1xuICAgICAgcmV0dXJuIGJ1aWxkTWVtYmVycyhleHRyYWN0Q2xhc3NNZXRob2ROYW1lcyhib2R5KSwgZXh0cmFjdENsYXNzUHJvcGVydHlOYW1lcyhib2R5KSk7XG4gICAgfVxuICAgIGNhc2UgJ2VudW0nOiB7XG4gICAgICByZXR1cm4gYnVpbGRNZW1iZXJzKFtdLCBleHRyYWN0RW51bU1lbWJlck5hbWVzKGJvZHkpKTtcbiAgICB9XG4gICAgZGVmYXVsdDoge1xuICAgICAgcmV0dXJuIGJ1aWxkTWVtYmVycyhleHRyYWN0TWV0aG9kTmFtZXMoYm9keSksIGV4dHJhY3RQcm9wZXJ0eU5hbWVzKGJvZHkpKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gc3RyaXBGcm9udG1hdHRlcihjb250ZW50OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gY29udGVudC5yZXBsYWNlKEZST05UTUFUVEVSX1JFR19FWFAsICcnKTtcbn1cblxuZnVuY3Rpb24gc3RyaXBJbmxpbmVDb2RlKGxpbmU6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBsaW5lLnJlcGxhY2VBbGwoSU5MSU5FX0NPREVfUkVHX0VYUCwgJycpO1xufVxuXG4vLyBBIGhhbmQtd3JpdHRlbiBsaW5rIG1heSBjb250YWluIGEgYmFyZSBgJWAgKG9yIGFueSBvdGhlciBpbnZhbGlkIHBlcmNlbnQtZXNjYXBlKSwgd2hpY2ggbWFrZXNcbi8vIGBkZWNvZGVVUklDb21wb25lbnRgIHRocm93LiBTdWNoIGEgdGFyZ2V0IGlzIG1lYW50IGxpdGVyYWxseSwgc28gaXQgaXMgdXNlZCBhcyB3cml0dGVuLlxuZnVuY3Rpb24gdHJ5RGVjb2RlVXJpQ29tcG9uZW50KHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICB0cnkge1xuICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQodmFs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