@dbx-tools/appkit-mastra 0.6.8 → 0.6.10

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.
@@ -1,446 +1,73 @@
1
1
  /**
2
- * Mastra {@link WorkspaceFilesystem} implementations for Databricks Apps.
2
+ * Mastra workspace filesystem adapters.
3
3
  *
4
- * {@link DatabricksWorkspaceFilesystem} maps a Mastra workspace namespace onto
5
- * an absolute Databricks path (Unity Catalog volume, workspace object tree, or
6
- * DBFS). {@link emptyFilesystem} is a read-only no-op mount used when no
7
- * dynamic mounts resolve for a request.
8
- *
9
- * Path helpers ({@link normalizeDatabricksBasePath}, {@link isDbfsPath}, …)
10
- * are exported for tests and callers that need to reason about Databricks
11
- * paths without constructing a filesystem.
4
+ * {@link filesystems} wraps any portable `@dbx-tools/shared-fs` {@link FileSystem}
5
+ * (local disk, Databricks, memory, …) as a Mastra {@link MastraFilesystem}.
6
+ * {@link scratchFilesystem} always returns a fresh {@link localFS.tmpFS} mount
7
+ * (random id root) when Mastra needs a filesystem and no other mount resolved.
12
8
  *
13
9
  * @module
14
10
  */
15
- import { posix as path } from "node:path";
16
- import { ExecutionError, getExecutionContext, ValidationError } from "@databricks/appkit";
17
- import { error, functionModule, hash, log } from "@dbx-tools/shared-core";
11
+ import { localFS } from "@dbx-tools/fs";
12
+ import { FileSystemError, posixPath } from "@dbx-tools/shared-fs";
18
13
  import { DirectoryNotEmptyError, DirectoryNotFoundError, FileExistsError, FileNotFoundError, IsDirectoryError, MastraFilesystem, NotDirectoryError, PermissionError, WorkspaceReadOnlyError, } from "@mastra/core/workspace";
19
- /* ------------------------------ constants ------------------------------ */
20
- const DBFS_READ_CHUNK_BYTES = 1024 * 1024;
21
- const DBFS_PUT_MAX_BYTES = 1024 * 1024;
22
- const EMPTY_FILESYSTEM_EPOCH = new Date(0);
23
- /** Mastra error constructor for a known SDK filesystem failure, if any. */
24
- function filesystemSdkErrorType(err) {
25
- if (err) {
26
- const ctx = error.errorContext(err);
27
- if (ctx.notAccessible) {
28
- return FileNotFoundError;
29
- }
30
- else if (ctx.hasMessage("already", "exists")) {
31
- return FileExistsError;
32
- }
33
- else if (ctx.hasMessage("not", "directory")) {
34
- return NotDirectoryError;
35
- }
36
- else if (ctx.hasMessage("not", "file")) {
37
- return IsDirectoryError;
38
- }
39
- }
40
- return undefined;
41
- }
42
- const logger = log.logger("mastra/filesystems");
43
- /* ------------------------- exported path helpers ------------------------- */
44
- /** Normalize a Databricks base path (POSIX, no trailing slash). */
45
- export function normalizeDatabricksBasePath(basePath) {
46
- const trimmed = basePath.trim();
47
- if (!trimmed.startsWith("/")) {
48
- throw ValidationError.invalidValue("basePath", basePath, "an absolute Databricks path, e.g. /Volumes/catalog/schema/volume");
49
- }
50
- return trimmed.replace(/\/+$/, "") || "/";
51
- }
52
- /** True when `absolutePath` is served by DBFS rather than the UC Files API. */
53
- export function isDbfsPath(absolutePath) {
54
- return absolutePath === "/dbfs" || absolutePath.startsWith("/dbfs/");
55
- }
56
- /** True when `absolutePath` is a Databricks workspace object path. */
57
- export function isWorkspaceFilesPath(absolutePath) {
58
- return (absolutePath === "/Workspace" ||
59
- absolutePath.startsWith("/Workspace/") ||
60
- absolutePath.startsWith("/Users/") ||
61
- absolutePath.startsWith("/Repos/"));
62
- }
63
14
  /**
64
- * Resolve a workspace-relative path to an absolute Databricks path under
65
- * `basePath`.
15
+ * Wrap a portable {@link FileSystem} as a Mastra {@link MastraFilesystem}.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { filesystems } from "@dbx-tools/appkit-mastra";
20
+ * import { DatabricksFileSystem } from "@dbx-tools/databricks";
21
+ * import { localFS } from "@dbx-tools/fs";
22
+ *
23
+ * const volume = filesystems.filesystems(
24
+ * new DatabricksFileSystem({ root: "/Volumes/main/default/assets" }),
25
+ * );
26
+ * const scratch = filesystems.filesystems(localFS.tmpFS("agent-job"));
27
+ * ```
66
28
  */
67
- export function resolveDatabricksAbsolutePath(basePath, inputPath) {
68
- const root = normalizeDatabricksBasePath(basePath);
69
- const trimmed = inputPath.trim();
70
- if (!trimmed || trimmed === "/")
71
- return root;
72
- const normalized = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
73
- if (normalized === root || normalized.startsWith(`${root}/`)) {
74
- return path.normalize(normalized);
75
- }
76
- return path.normalize(path.join(root, normalized));
29
+ export function filesystems(fs, options = {}) {
30
+ return new MastraFileSystemAdapter(fs, options);
77
31
  }
78
- /** Map an absolute Databricks path back to the workspace namespace. */
79
- export function toDatabricksWorkspacePath(basePath, absolutePath) {
80
- const root = normalizeDatabricksBasePath(basePath);
81
- const normalized = path.normalize(absolutePath);
82
- if (normalized === root)
83
- return "/";
84
- if (normalized.startsWith(`${root}/`)) {
85
- return normalized.slice(root.length) || "/";
86
- }
87
- return normalized;
88
- }
89
- /* ---------------------------- private helpers ---------------------------- */
90
- /** Pick the Databricks Files API backend for an absolute path. */
91
- function resolveFilesBackend(absolutePath) {
92
- if (isDbfsPath(absolutePath))
93
- return "dbfs";
94
- if (isWorkspaceFilesPath(absolutePath))
95
- return "workspace";
96
- return "uc-files";
97
- }
98
- /** Run the handler that matches `absolutePath`'s Databricks backend. */
99
- async function dispatchFilesBackend(absolutePath, handlers) {
100
- const backend = resolveFilesBackend(absolutePath);
101
- if (backend === "dbfs")
102
- return handlers.dbfs();
103
- if (backend === "workspace")
104
- return handlers.workspace();
105
- return handlers.ucFiles();
106
- }
107
- /** Return `buffer` as a string when `encoding` is set, otherwise unchanged. */
108
- function formatReadResult(buffer, encoding) {
109
- return encoding ? buffer.toString(encoding) : buffer;
110
- }
111
- /** Drain a fetch `ReadableStream` into a single `Buffer`. */
112
- async function readResponseBody(contents) {
113
- if (!contents)
114
- return Buffer.alloc(0);
115
- const reader = contents.getReader();
116
- const chunks = [];
117
- while (true) {
118
- const { done, value } = await reader.read();
119
- if (done)
120
- break;
121
- if (value)
122
- chunks.push(value);
123
- }
124
- return Buffer.concat(chunks.map((chunk) => Buffer.from(chunk)));
125
- }
126
- /** Coerce Mastra {@link FileContent} to a `Buffer`. */
127
- function toBuffer(content) {
128
- if (typeof content === "string")
129
- return Buffer.from(content, "utf8");
130
- return Buffer.from(content);
131
- }
132
- /** Decode a DBFS read payload from base64. */
133
- function decodeDbfsPayload(data) {
134
- if (!data)
135
- return Buffer.alloc(0);
136
- return Buffer.from(data, "base64");
137
- }
138
- /** Wrap a `Buffer` as a one-shot `ReadableStream` for UC file uploads. */
139
- function bufferToReadableStream(buffer) {
140
- return new ReadableStream({
141
- start(controller) {
142
- controller.enqueue(new Uint8Array(buffer));
143
- controller.close();
144
- },
145
- });
146
- }
147
- /** Parse an HTTP date header; returns epoch when missing or invalid. */
148
- function parseHttpDate(value) {
149
- if (!value)
150
- return new Date(0);
151
- const parsed = Date.parse(value);
152
- return Number.isFinite(parsed) ? new Date(parsed) : new Date(0);
153
- }
154
- /* ---------------- DatabricksWorkspaceFilesystem ---------------- */
155
32
  /**
156
- * Mastra filesystem provider that reads and writes through a Databricks
157
- * {@link WorkspaceClient}.
158
- *
159
- * Workspace paths are absolute within the namespace (`/notes.md` maps to
160
- * `<basePath>/notes.md`). Unity Catalog volumes use the Files API;
161
- * `/dbfs/...` paths use DBFS.
33
+ * Thin Mastra {@link MastraFilesystem} adapter over a `@dbx-tools/shared-fs`
34
+ * {@link FileSystem}. Identity fields are getters that read the source on
35
+ * access; construction does not snapshot them.
162
36
  */
163
- export class DatabricksWorkspaceFilesystem extends MastraFilesystem {
164
- id;
165
- name = "DatabricksWorkspaceFilesystem";
166
- provider = "databricks";
167
- basePath;
37
+ export class MastraFileSystemAdapter extends MastraFilesystem {
168
38
  status = "pending";
169
- client;
170
- mkdirs;
171
- _readOnly;
172
- _basePathMissing;
173
- get readOnly() {
174
- return this._readOnly;
175
- }
176
- /**
177
- * @param options.client - Defaults to the AppKit execution-context client.
178
- * @param options.mkdirs - Default `"try"`; see {@link DatabricksMkdirsMode}.
179
- * @param options.readOnly - When omitted, {@link init} probes write access.
180
- */
181
- constructor(options) {
182
- super({ name: "DatabricksWorkspaceFilesystem", ...options });
183
- this.id = options.id ?? `databricks-fs-${hash.fnvHash(options.basePath)}`;
184
- this.client = options.client ?? getExecutionContext().client;
185
- this.basePath = normalizeDatabricksBasePath(options.basePath);
186
- this.mkdirs = options.mkdirs ?? "try";
187
- this._readOnly = options.readOnly;
39
+ fs;
40
+ options;
41
+ constructor(fs, options = {}) {
42
+ super({
43
+ name: options.name ?? "MastraFileSystemAdapter",
44
+ onInit: options.onInit,
45
+ onDestroy: options.onDestroy,
46
+ });
47
+ this.fs = fs;
48
+ this.options = options;
188
49
  }
189
- /* --- path resolution --- */
190
- /** Resolve and sandbox a workspace-relative path under {@link basePath}. */
191
- resolvePath(inputPath) {
192
- const resolved = resolveDatabricksAbsolutePath(this.basePath, inputPath);
193
- if (resolved !== this.basePath && !resolved.startsWith(`${this.basePath}/`)) {
194
- throw new PermissionError(inputPath, "access");
195
- }
196
- return resolved;
50
+ get id() {
51
+ return this.options.id ?? this.fs.id;
197
52
  }
198
- /** Map a Databricks absolute path back to the workspace namespace. */
199
- workspacePath(absolutePath) {
200
- return toDatabricksWorkspacePath(this.basePath, absolutePath);
53
+ get name() {
54
+ return this.options.name ?? "MastraFileSystemAdapter";
201
55
  }
202
- /** Throw when the filesystem is read-only. */
203
- assertWritable(operation) {
204
- if (this.readOnly) {
205
- throw new WorkspaceReadOnlyError(operation);
206
- }
207
- }
208
- /** Map SDK / HTTP errors to Mastra workspace filesystem errors. */
209
- rethrow(err, inputPath) {
210
- const workspacePath = inputPath.startsWith("/")
211
- ? inputPath
212
- : this.workspacePath(this.resolvePath(inputPath));
213
- const ErrorType = filesystemSdkErrorType(err);
214
- if (ErrorType) {
215
- throw new ErrorType(workspacePath);
216
- }
217
- // The upstream message is logged rather than raised: it reaches the model
218
- // (and from there the chat transcript) as the tool's failure text.
219
- logger.warn("operation-failed", {
220
- path: workspacePath,
221
- error: error.errorMessage(err),
222
- });
223
- throw new ExecutionError(`Databricks filesystem operation failed for ${workspacePath}`, {
224
- cause: error.toError(err),
225
- context: { path: workspacePath },
226
- });
56
+ get provider() {
57
+ return this.options.provider ?? this.fs.backend;
227
58
  }
228
- /* --- lifecycle --- */
229
- /**
230
- * Probe whether {@link basePath} exists and cache the result on
231
- * {@link _basePathMissing}.
232
- */
233
- async resolveBasePathStatus() {
234
- if (this._basePathMissing !== undefined)
235
- return;
236
- try {
237
- await this.assertAbsoluteReadable(this.basePath);
238
- this._basePathMissing = false;
239
- }
240
- catch (err) {
241
- if (error.errorContext(err).notAccessible) {
242
- this._basePathMissing = true;
243
- return;
244
- }
245
- this.rethrow(err, "/");
246
- }
59
+ get readOnly() {
60
+ return this.options.readOnly === true || this.fs.readOnly;
247
61
  }
248
- /** Delegate to {@link emptyFilesystem} when the base path is missing. */
249
- async emptyFallback() {
250
- await this.resolveBasePathStatus();
251
- return this._basePathMissing ? emptyFilesystem() : undefined;
62
+ get basePath() {
63
+ return this.fs.root;
252
64
  }
253
65
  async init() {
254
- await this.resolveBasePathStatus();
255
- if (this._basePathMissing) {
256
- if (this.mkdirs === false) {
257
- return;
258
- }
259
- try {
260
- await this.mkdirAbsolute(this.basePath);
261
- this._basePathMissing = false;
262
- if (this._readOnly === undefined) {
263
- this._readOnly = false;
264
- }
265
- }
266
- catch (err) {
267
- if (this.mkdirs === true) {
268
- this.rethrow(err, "/");
269
- }
270
- logger.debug("mkdirs:try-failed", {
271
- basePath: this.basePath,
272
- error: error.errorMessage(err),
273
- });
274
- }
275
- return;
276
- }
277
- if (this._readOnly === undefined) {
278
- await this.probeReadOnly();
279
- }
280
- }
281
- /**
282
- * Write and delete a ephemeral probe file to detect read-only access when
283
- * {@link DatabricksWorkspaceFilesystemOptions.readOnly} was not set.
284
- *
285
- * @returns `true` when the probe write (and cleanup) succeeded.
286
- */
287
- async probeReadOnly() {
288
- const absolutePath = this.resolvePath(`/.__dbx_fs_probe_${hash.id()}`);
289
- try {
290
- await this.writeAbsolute(absolutePath, Buffer.from("probe\n"), true);
291
- this._readOnly = false;
292
- }
293
- catch {
294
- this._readOnly = true;
295
- return false;
296
- }
297
- try {
298
- await this.deleteAbsoluteFile(absolutePath);
299
- }
300
- catch {
301
- // Writable; leave a hidden probe file rather than failing init.
302
- }
303
- return true;
66
+ await this.fs.init();
304
67
  }
305
68
  async destroy() {
306
- // Remote filesystem; nothing to tear down locally.
307
- }
308
- /* --- backend I/O --- */
309
- /** Probe that `absolutePath` exists (file or directory metadata). */
310
- async assertAbsoluteReadable(absolutePath) {
311
- await dispatchFilesBackend(absolutePath, {
312
- dbfs: () => this.client.dbfs.getStatus({ path: absolutePath }),
313
- workspace: () => this.client.workspace.getStatus({ path: absolutePath }),
314
- ucFiles: () => this.client.files.getDirectoryMetadata({ directory_path: absolutePath }),
315
- });
316
- }
317
- /** Read the full contents of `absolutePath` from the matching backend. */
318
- async readAbsolute(absolutePath) {
319
- return dispatchFilesBackend(absolutePath, {
320
- dbfs: () => this.readDbfsFile(absolutePath),
321
- workspace: () => this.readWorkspaceFile(absolutePath),
322
- ucFiles: async () => {
323
- const response = await this.client.files.download({ file_path: absolutePath });
324
- return readResponseBody(response.contents);
325
- },
326
- });
327
- }
328
- /** Write `buffer` to `absolutePath` on the matching backend. */
329
- async writeAbsolute(absolutePath, buffer, overwrite) {
330
- await dispatchFilesBackend(absolutePath, {
331
- dbfs: () => this.writeDbfsFile(absolutePath, buffer, overwrite),
332
- workspace: () => this.writeWorkspaceFile(absolutePath, buffer, overwrite),
333
- ucFiles: () => this.uploadUcFile(absolutePath, buffer, overwrite),
334
- });
335
- }
336
- /** Upload a buffer to a Unity Catalog Files API path. */
337
- uploadUcFile(absolutePath, buffer, overwrite) {
338
- return this.client.files.upload({
339
- file_path: absolutePath,
340
- contents: bufferToReadableStream(buffer),
341
- overwrite,
342
- });
343
- }
344
- /** Delete a single file at `absolutePath` (non-recursive). */
345
- async deleteAbsoluteFile(absolutePath) {
346
- await dispatchFilesBackend(absolutePath, {
347
- dbfs: () => this.client.dbfs.delete({ path: absolutePath, recursive: false }),
348
- workspace: () => this.client.workspace.delete({ path: absolutePath, recursive: false }),
349
- ucFiles: () => this.client.files.delete({ file_path: absolutePath }),
350
- });
351
- }
352
- /**
353
- * Delete a file or directory at `absolutePath`.
354
- *
355
- * DBFS and workspace APIs accept `recursive`; UC volumes recurse manually.
356
- */
357
- async deleteAbsolutePath(absolutePath, recursive) {
358
- await dispatchFilesBackend(absolutePath, {
359
- dbfs: async () => {
360
- await this.client.dbfs.delete({ path: absolutePath, recursive });
361
- },
362
- workspace: async () => {
363
- await this.client.workspace.delete({ path: absolutePath, recursive });
364
- },
365
- ucFiles: async () => {
366
- if (recursive) {
367
- await this.deleteUcDirectoryRecursive(absolutePath);
368
- return;
369
- }
370
- const children = await this.listAbsoluteDirectory(absolutePath);
371
- if (children.length > 0) {
372
- throw new DirectoryNotEmptyError(this.workspacePath(absolutePath));
373
- }
374
- await this.client.files.deleteDirectory({ directory_path: absolutePath });
375
- },
376
- });
377
- }
378
- /** Create `absolutePath` and any missing parents on the matching backend. */
379
- async mkdirAbsolute(absolutePath) {
380
- await dispatchFilesBackend(absolutePath, {
381
- dbfs: () => this.client.dbfs.mkdirs({ path: absolutePath }),
382
- workspace: () => this.client.workspace.mkdirs({ path: absolutePath }),
383
- ucFiles: () => this.client.files.createDirectory({ directory_path: absolutePath }),
384
- });
385
- }
386
- async readDbfsFile(absolutePath) {
387
- const chunks = [];
388
- let offset = 0;
389
- while (true) {
390
- const response = await this.client.dbfs.read({
391
- path: absolutePath,
392
- offset,
393
- length: DBFS_READ_CHUNK_BYTES,
394
- });
395
- const chunk = decodeDbfsPayload(response.data);
396
- if (chunk.length === 0)
397
- break;
398
- chunks.push(chunk);
399
- offset += chunk.length;
400
- if (chunk.length < DBFS_READ_CHUNK_BYTES)
401
- break;
402
- }
403
- return Buffer.concat(chunks);
404
- }
405
- async readWorkspaceFile(absolutePath) {
406
- const response = await this.client.workspace.export({
407
- path: absolutePath,
408
- format: "AUTO",
409
- });
410
- return decodeDbfsPayload(response.content);
411
- }
412
- async writeDbfsFile(absolutePath, buffer, overwrite) {
413
- if (buffer.length <= DBFS_PUT_MAX_BYTES) {
414
- await this.client.dbfs.put({
415
- path: absolutePath,
416
- contents: buffer.toString("base64"),
417
- overwrite,
418
- });
419
- return;
420
- }
421
- const created = await this.client.dbfs.create({ path: absolutePath, overwrite });
422
- const handle = created.handle;
423
- if (handle === undefined) {
424
- throw ExecutionError.missingData("DBFS upload handle");
425
- }
426
- for (let offset = 0; offset < buffer.length; offset += DBFS_PUT_MAX_BYTES) {
427
- const slice = buffer.subarray(offset, offset + DBFS_PUT_MAX_BYTES);
428
- await this.client.dbfs.addBlock({
429
- handle,
430
- data: slice.toString("base64"),
431
- });
432
- }
433
- await this.client.dbfs.close({ handle });
434
- }
435
- async writeWorkspaceFile(absolutePath, buffer, overwrite) {
436
- await this.client.workspace.import({
437
- path: absolutePath,
438
- format: "AUTO",
439
- content: buffer.toString("base64"),
440
- overwrite,
441
- });
69
+ await this.fs.close();
442
70
  }
443
- /* --- MastraFilesystem API --- */
444
71
  getInfo() {
445
72
  return {
446
73
  id: this.id,
@@ -448,511 +75,164 @@ export class DatabricksWorkspaceFilesystem extends MastraFilesystem {
448
75
  provider: this.provider,
449
76
  status: this.status,
450
77
  readOnly: this.readOnly,
451
- metadata: { basePath: this.basePath },
78
+ metadata: { root: this.fs.root, backend: this.fs.backend },
452
79
  };
453
80
  }
454
81
  getInstructions() {
455
82
  return [
456
- `Files live in Databricks under ${this.basePath}.`,
457
- "Workspace paths are absolute within this root (for example `/notes/report.md`).",
458
- "Workspace paths use `/Workspace/...`, `/Users/...`, or `/Repos/...` base paths.",
459
- "Unity Catalog volumes use `/Volumes/<catalog>/<schema>/<volume>/...` base paths.",
83
+ `Files are served by a ${this.fs.backend} filesystem rooted at ${this.fs.root}.`,
84
+ "Workspace paths are absolute within this mount (for example `/notes/report.md`).",
460
85
  ].join(" ");
461
86
  }
462
- /** Map a workspace-relative path to the backing Databricks absolute path. */
463
- resolveAbsolutePath(inputPath) {
464
- return this.resolvePath(inputPath);
465
- }
466
- /** Read file contents from the workspace namespace. */
467
87
  async readFile(inputPath, options) {
468
- await this.ensureReady();
469
- const empty = await this.emptyFallback();
470
- if (empty)
471
- return empty.readFile(inputPath, options);
472
- const absolutePath = this.resolvePath(inputPath);
473
- try {
474
- const buffer = await this.readAbsolute(absolutePath);
475
- return formatReadResult(buffer, options?.encoding);
476
- }
477
- catch (err) {
478
- this.rethrow(err, inputPath);
479
- }
88
+ return this.delegate(inputPath, async () => {
89
+ if (options?.encoding) {
90
+ return this.fs.readFile(inputPath, { encoding: options.encoding });
91
+ }
92
+ return Buffer.from(await this.fs.readFile(inputPath));
93
+ });
480
94
  }
481
- /** Write file contents into the workspace namespace. */
482
95
  async writeFile(inputPath, content, options) {
483
- await this.ensureReady();
484
- const empty = await this.emptyFallback();
485
- if (empty)
486
- return empty.writeFile(inputPath, content, options);
487
- this.assertWritable("writeFile");
488
- const absolutePath = this.resolvePath(inputPath);
489
- const buffer = toBuffer(content);
490
- const overwrite = options?.overwrite ?? true;
491
- try {
492
- if (!overwrite && (await this.exists(inputPath))) {
493
- throw new FileExistsError(inputPath);
96
+ return this.delegateWrite("writeFile", inputPath, async () => {
97
+ if (options?.recursive === false) {
98
+ await this.assertParentExists(inputPath);
494
99
  }
495
- await this.writeAbsolute(absolutePath, buffer, overwrite);
496
- }
497
- catch (err) {
498
- if (err instanceof FileExistsError)
499
- throw err;
500
- this.rethrow(err, inputPath);
501
- }
100
+ await this.fs.writeFile(inputPath, content, {
101
+ overwrite: options?.overwrite ?? true,
102
+ });
103
+ });
502
104
  }
503
- /** Append to an existing file, creating it when missing. */
504
105
  async appendFile(inputPath, content) {
505
- await this.ensureReady();
506
- const empty = await this.emptyFallback();
507
- if (empty)
508
- return empty.appendFile(inputPath, content);
509
- this.assertWritable("appendFile");
510
- const existing = (await this.exists(inputPath))
511
- ? await this.readFile(inputPath)
512
- : Buffer.alloc(0);
513
- const merged = Buffer.concat([
514
- Buffer.isBuffer(existing) ? existing : Buffer.from(existing, "utf8"),
515
- toBuffer(content),
516
- ]);
517
- await this.writeFile(inputPath, merged, { overwrite: true });
106
+ return this.delegateWrite("appendFile", inputPath, () => this.fs.appendFile(inputPath, content));
518
107
  }
519
- /** Delete a file in the workspace namespace. */
520
108
  async deleteFile(inputPath, options) {
521
- await this.ensureReady();
522
- const empty = await this.emptyFallback();
523
- if (empty)
524
- return empty.deleteFile(inputPath, options);
525
- this.assertWritable("deleteFile");
526
- const absolutePath = this.resolvePath(inputPath);
527
- try {
528
- if (!(await this.exists(inputPath))) {
529
- if (options?.force)
530
- return;
531
- throw new FileNotFoundError(inputPath);
532
- }
533
- const entry = await this.stat(inputPath);
534
- if (entry.type === "directory") {
535
- throw new IsDirectoryError(inputPath);
536
- }
537
- await this.deleteAbsoluteFile(absolutePath);
538
- }
539
- catch (err) {
540
- if (err instanceof FileNotFoundError || err instanceof IsDirectoryError)
541
- throw err;
542
- this.rethrow(err, inputPath);
543
- }
109
+ return this.delegateWrite("deleteFile", inputPath, () => this.fs.deleteFile(inputPath, {
110
+ force: options?.force,
111
+ recursive: options?.recursive,
112
+ }));
544
113
  }
545
- /** Copy a file within the workspace namespace. */
546
114
  async copyFile(src, dest, options) {
547
- await this.ensureReady();
548
- const empty = await this.emptyFallback();
549
- if (empty)
550
- return empty.copyFile(src, dest, options);
551
- this.assertWritable("copyFile");
552
- const overwrite = options?.overwrite ?? true;
553
- if (!overwrite && (await this.exists(dest))) {
554
- throw new FileExistsError(dest);
555
- }
556
- const content = await this.readFile(src);
557
- await this.writeFile(dest, content, { overwrite: true });
115
+ return this.delegateWrite("copyFile", dest, () => this.fs.copyFile(src, dest, { overwrite: options?.overwrite ?? true }));
558
116
  }
559
- /** Move or rename a file within the workspace namespace. */
560
117
  async moveFile(src, dest, options) {
561
- await this.ensureReady();
562
- const empty = await this.emptyFallback();
563
- if (empty)
564
- return empty.moveFile(src, dest, options);
565
- this.assertWritable("moveFile");
566
- const srcAbsolute = this.resolvePath(src);
567
- const destAbsolute = this.resolvePath(dest);
568
- const overwrite = options?.overwrite ?? true;
569
- try {
570
- if (!overwrite && (await this.exists(dest))) {
571
- throw new FileExistsError(dest);
572
- }
573
- if (resolveFilesBackend(srcAbsolute) === "dbfs" &&
574
- resolveFilesBackend(destAbsolute) === "dbfs") {
575
- await this.client.dbfs.move({
576
- source_path: srcAbsolute,
577
- destination_path: destAbsolute,
578
- });
579
- return;
580
- }
581
- await this.copyFile(src, dest, { overwrite: true });
582
- await this.deleteFile(src, { force: true });
583
- }
584
- catch (err) {
585
- if (err instanceof FileExistsError)
586
- throw err;
587
- this.rethrow(err, dest);
588
- }
118
+ return this.delegateWrite("moveFile", dest, () => this.fs.moveFile(src, dest, { overwrite: options?.overwrite ?? true }));
589
119
  }
590
- /** Create a directory in the workspace namespace. */
591
120
  async mkdir(inputPath, options) {
592
- await this.ensureReady();
593
- const empty = await this.emptyFallback();
594
- if (empty)
595
- return empty.mkdir(inputPath, options);
596
- this.assertWritable("mkdir");
597
- const absolutePath = this.resolvePath(inputPath);
598
- try {
599
- await this.mkdirAbsolute(absolutePath);
600
- if (!options?.recursive) {
601
- return;
602
- }
603
- }
604
- catch (err) {
605
- this.rethrow(err, inputPath);
606
- }
121
+ return this.delegateWrite("mkdir", inputPath, () => this.fs.mkdir(inputPath, { recursive: options?.recursive }));
607
122
  }
608
- /** Remove a directory from the workspace namespace. */
609
123
  async rmdir(inputPath, options) {
610
- await this.ensureReady();
611
- const empty = await this.emptyFallback();
612
- if (empty)
613
- return empty.rmdir(inputPath, options);
614
- this.assertWritable("rmdir");
615
- const absolutePath = this.resolvePath(inputPath);
616
- try {
617
- if (!(await this.exists(inputPath))) {
618
- if (options?.force)
619
- return;
620
- throw new DirectoryNotFoundError(inputPath);
621
- }
622
- const entry = await this.stat(inputPath);
623
- if (entry.type !== "directory") {
624
- throw new NotDirectoryError(inputPath);
625
- }
626
- await this.deleteAbsolutePath(absolutePath, options?.recursive ?? false);
627
- }
628
- catch (err) {
629
- if (err instanceof DirectoryNotFoundError ||
630
- err instanceof NotDirectoryError ||
631
- err instanceof DirectoryNotEmptyError) {
632
- throw err;
633
- }
634
- this.rethrow(err, inputPath);
635
- }
636
- }
637
- /**
638
- * Recursively delete a Unity Catalog directory tree.
639
- *
640
- * DBFS and workspace trees use native recursive delete via
641
- * {@link deleteAbsolutePath} instead.
642
- */
643
- async deleteUcDirectoryRecursive(absolutePath) {
644
- for (const child of await this.listAbsoluteDirectory(absolutePath)) {
645
- const childAbsolute = path.join(absolutePath, child.name);
646
- if (child.type === "directory") {
647
- await this.deleteUcDirectoryRecursive(childAbsolute);
648
- }
649
- else {
650
- await this.deleteAbsoluteFile(childAbsolute);
651
- }
652
- }
653
- await this.client.files.deleteDirectory({ directory_path: absolutePath });
124
+ return this.delegateWrite("rmdir", inputPath, () => this.fs.rmdir(inputPath, {
125
+ force: options?.force,
126
+ recursive: options?.recursive,
127
+ }), { preferDirectory: true });
654
128
  }
655
- /* --- directory listing --- */
656
- /** List entries in a workspace directory. */
657
129
  async readdir(inputPath, options) {
658
- await this.ensureReady();
659
- const empty = await this.emptyFallback();
660
- if (empty)
661
- return empty.readdir(inputPath, options);
662
- const absolutePath = this.resolvePath(inputPath);
663
- try {
664
- const entries = await this.listAbsoluteDirectory(absolutePath);
665
- const filtered = this.filterEntries(entries, options);
666
- if (!options?.recursive)
667
- return filtered;
668
- return await this.readDirectoryRecursive(absolutePath, options, 0);
669
- }
670
- catch (err) {
671
- this.rethrow(err, inputPath);
672
- }
673
- }
674
- async readDirectoryRecursive(absolutePath, options, depth, relativePrefix = "") {
675
- const maxDepth = options.maxDepth ?? Number.POSITIVE_INFINITY;
676
- const entries = this.filterEntries(await this.listAbsoluteDirectory(absolutePath), options);
677
- const collected = [];
678
- for (const entry of entries) {
679
- const relativeName = relativePrefix ? path.join(relativePrefix, entry.name) : entry.name;
680
- collected.push({ ...entry, name: relativeName });
681
- if (entry.type !== "directory" || depth >= maxDepth)
682
- continue;
683
- collected.push(...(await this.readDirectoryRecursive(path.join(absolutePath, entry.name), options, depth + 1, relativeName)));
684
- }
685
- return collected;
686
- }
687
- async listAbsoluteDirectory(absolutePath) {
688
- return dispatchFilesBackend(absolutePath, {
689
- dbfs: async () => {
690
- const entries = [];
691
- for await (const info of this.client.dbfs.list({ path: absolutePath })) {
692
- entries.push({
693
- name: path.basename(info.path ?? ""),
694
- type: info.is_dir ? "directory" : "file",
695
- size: info.file_size,
696
- });
697
- }
698
- return entries;
699
- },
700
- workspace: async () => {
701
- const entries = [];
702
- for await (const info of this.client.workspace.list({ path: absolutePath })) {
703
- entries.push({
704
- name: path.basename(info.path ?? ""),
705
- type: info.object_type === "DIRECTORY" ? "directory" : "file",
706
- });
707
- }
708
- return entries;
709
- },
710
- ucFiles: async () => {
711
- const entries = [];
712
- for await (const entry of this.client.files.listDirectoryContents({
713
- directory_path: absolutePath,
714
- })) {
715
- entries.push({
716
- name: entry.name ?? path.basename(entry.path ?? ""),
717
- type: entry.is_directory ? "directory" : "file",
718
- size: entry.file_size,
719
- });
720
- }
721
- return entries;
722
- },
723
- });
724
- }
725
- /** Apply Mastra list filters (`extension`, etc.) to directory entries. */
726
- filterEntries(entries, options) {
727
- if (!options?.extension)
728
- return entries;
729
- const extensions = Array.isArray(options.extension) ? options.extension : [options.extension];
730
- const normalized = extensions.map((ext) => ext.startsWith(".") ? ext.toLowerCase() : `.${ext.toLowerCase()}`);
731
- return entries.filter((entry) => {
732
- if (entry.type !== "file")
733
- return true;
734
- const lower = entry.name.toLowerCase();
735
- return normalized.some((ext) => lower.endsWith(ext));
736
- });
130
+ return this.delegate(inputPath, async () => (await this.fs.readdir(inputPath, {
131
+ recursive: options?.recursive,
132
+ maxDepth: options?.maxDepth,
133
+ extension: options?.extension,
134
+ })).map(toMastraEntry), { preferDirectory: true });
737
135
  }
738
- /* --- metadata --- */
739
- /** Return whether `inputPath` exists in the workspace namespace. */
740
136
  async exists(inputPath) {
741
137
  await this.ensureReady();
742
- const empty = await this.emptyFallback();
743
- if (empty)
744
- return empty.exists(inputPath);
745
- try {
746
- await this.stat(inputPath);
747
- return true;
748
- }
749
- catch (err) {
750
- if (err instanceof FileNotFoundError)
751
- return false;
752
- throw err;
753
- }
138
+ return this.fs.exists(inputPath);
754
139
  }
755
- /** Return file or directory metadata for `inputPath`. */
756
140
  async stat(inputPath) {
141
+ return this.delegate(inputPath, async () => toMastraStat(await this.fs.stat(inputPath), inputPath));
142
+ }
143
+ async delegate(path, op, options) {
757
144
  await this.ensureReady();
758
- const empty = await this.emptyFallback();
759
- if (empty)
760
- return empty.stat(inputPath);
761
- const absolutePath = this.resolvePath(inputPath);
762
- const workspacePath = this.workspacePath(absolutePath);
763
145
  try {
764
- return await dispatchFilesBackend(absolutePath, {
765
- dbfs: async () => {
766
- const info = await this.client.dbfs.getStatus({ path: absolutePath });
767
- return {
768
- name: path.basename(info.path ?? absolutePath),
769
- path: workspacePath,
770
- type: info.is_dir ? "directory" : "file",
771
- size: info.file_size ?? 0,
772
- createdAt: new Date(info.modification_time ?? 0),
773
- modifiedAt: new Date(info.modification_time ?? 0),
774
- };
775
- },
776
- workspace: async () => {
777
- const info = await this.client.workspace.getStatus({ path: absolutePath });
778
- return {
779
- name: path.basename(info.path ?? absolutePath),
780
- path: workspacePath,
781
- type: info.object_type === "DIRECTORY" ? "directory" : "file",
782
- size: 0,
783
- createdAt: new Date(info.created_at ?? 0),
784
- modifiedAt: new Date(info.modified_at ?? 0),
785
- };
786
- },
787
- ucFiles: () => this.statUcAbsolute(absolutePath, workspacePath, inputPath),
788
- });
146
+ return await op();
789
147
  }
790
148
  catch (err) {
791
- this.rethrow(err, inputPath);
149
+ this.rethrow(err, path, options);
792
150
  }
793
151
  }
794
- /**
795
- * Stat a Unity Catalog path by probing file metadata first, then
796
- * directory metadata.
797
- */
798
- async statUcAbsolute(absolutePath, workspacePath, inputPath) {
799
- try {
800
- const metadata = await this.client.files.getMetadata({
801
- file_path: absolutePath,
802
- });
803
- return {
804
- name: path.basename(absolutePath),
805
- path: workspacePath,
806
- type: "file",
807
- size: Number(metadata["content-length"] ?? 0),
808
- createdAt: parseHttpDate(metadata["last-modified"]),
809
- modifiedAt: parseHttpDate(metadata["last-modified"]),
810
- mimeType: metadata["content-type"],
811
- };
812
- }
813
- catch (fileErr) {
814
- if (!error.errorContext(fileErr).notAccessible) {
815
- this.rethrow(fileErr, inputPath);
816
- }
817
- await this.client.files.getDirectoryMetadata({
818
- directory_path: absolutePath,
819
- });
820
- return {
821
- name: path.basename(absolutePath),
822
- path: workspacePath,
823
- type: "directory",
824
- size: 0,
825
- createdAt: new Date(0),
826
- modifiedAt: new Date(0),
827
- };
152
+ /** {@link delegate} for a mutation: refuse a read-only mount before doing any work. */
153
+ delegateWrite(operation, path, op, options) {
154
+ if (this.readOnly) {
155
+ throw new WorkspaceReadOnlyError(operation);
828
156
  }
157
+ return this.delegate(path, op, options);
829
158
  }
830
- }
831
- /* --------------------------- empty filesystem --------------------------- */
832
- /** Normalize paths for the in-memory empty filesystem namespace. */
833
- function normalizeEmptyFilesystemPath(inputPath) {
834
- const trimmed = inputPath.trim();
835
- if (!trimmed || trimmed === ".")
836
- return "/";
837
- const normalized = trimmed.startsWith("/")
838
- ? path.normalize(trimmed)
839
- : path.normalize(`/${trimmed}`);
840
- return normalized === "." ? "/" : normalized;
159
+ /** When Mastra asks for non-recursive writes, require the parent directory. */
160
+ async assertParentExists(inputPath) {
161
+ const parent = posixPath.dirname(normalizeWorkspacePath(inputPath));
162
+ if (parent === "/" || (await this.fs.exists(parent)))
163
+ return;
164
+ throw new DirectoryNotFoundError(parent);
165
+ }
166
+ rethrow(err, inputPath, options) {
167
+ if (err instanceof FileNotFoundError ||
168
+ err instanceof DirectoryNotFoundError ||
169
+ err instanceof FileExistsError ||
170
+ err instanceof IsDirectoryError ||
171
+ err instanceof NotDirectoryError ||
172
+ err instanceof DirectoryNotEmptyError ||
173
+ err instanceof PermissionError ||
174
+ err instanceof WorkspaceReadOnlyError) {
175
+ throw err;
176
+ }
177
+ if (err instanceof FileSystemError) {
178
+ throw mapSharedError(err, inputPath, options?.preferDirectory === true);
179
+ }
180
+ throw err;
181
+ }
182
+ }
183
+ /** Fresh writable local temp mount on a root unique to this call. */
184
+ export function scratchFilesystem() {
185
+ return filesystems(localFS.scratchFS("mastra"));
186
+ }
187
+ /** Map a shared-fs error code onto the matching Mastra filesystem error. */
188
+ function mapSharedError(err, inputPath, preferDirectory) {
189
+ const path = err.path ?? inputPath;
190
+ switch (err.code) {
191
+ case "NOT_FOUND":
192
+ return preferDirectory ? new DirectoryNotFoundError(path) : new FileNotFoundError(path);
193
+ case "ALREADY_EXISTS":
194
+ return new FileExistsError(path);
195
+ case "NOT_DIRECTORY":
196
+ return new NotDirectoryError(path);
197
+ case "IS_DIRECTORY":
198
+ return new IsDirectoryError(path);
199
+ case "DIRECTORY_NOT_EMPTY":
200
+ return new DirectoryNotEmptyError(path);
201
+ case "PERMISSION_DENIED":
202
+ return new PermissionError(path, err.message);
203
+ case "READ_ONLY":
204
+ return new WorkspaceReadOnlyError(err.message);
205
+ default:
206
+ return err;
207
+ }
208
+ }
209
+ function toMastraEntry(entry) {
210
+ return {
211
+ name: entry.name,
212
+ type: entry.type === "directory" ? "directory" : "file",
213
+ size: entry.size,
214
+ isSymlink: entry.type === "symbolic-link",
215
+ };
216
+ }
217
+ function toMastraStat(stat, inputPath) {
218
+ const epoch = new Date(0);
219
+ return {
220
+ name: stat.name,
221
+ path: normalizeWorkspacePath(stat.path || inputPath),
222
+ type: stat.type === "directory" ? "directory" : "file",
223
+ size: stat.size ?? 0,
224
+ createdAt: stat.createdAt ?? epoch,
225
+ modifiedAt: stat.modifiedAt ?? epoch,
226
+ mimeType: stat.mimeType,
227
+ };
841
228
  }
842
229
  /**
843
- * Read-only in-memory {@link WorkspaceFilesystem} with a single empty root.
844
- * Use {@link emptyFilesystem} rather than constructing directly.
230
+ * Mastra namespace path (`/a/b`). A `..` that would escape clamps to the root
231
+ * rather than throwing - the wrapped filesystem enforces containment itself,
232
+ * and a mount should not fail a listing over a stray segment.
845
233
  */
846
- class EmptyFilesystem extends MastraFilesystem {
847
- id = "empty-fs";
848
- name = "EmptyFilesystem";
849
- provider = "empty";
850
- readOnly = true;
851
- status = "pending";
852
- constructor() {
853
- super({ name: "EmptyFilesystem" });
854
- }
855
- async init() {
856
- // No remote or on-disk resources to provision.
857
- }
858
- async destroy() {
859
- // Stateless; nothing to release.
860
- }
861
- getInfo() {
862
- return {
863
- id: this.id,
864
- name: this.name,
865
- provider: this.provider,
866
- status: this.status,
867
- readOnly: this.readOnly,
868
- };
869
- }
870
- getInstructions() {
871
- return "This filesystem is empty and read-only.";
872
- }
873
- rootStat() {
874
- return {
875
- name: "/",
876
- path: "/",
877
- type: "directory",
878
- size: 0,
879
- createdAt: EMPTY_FILESYSTEM_EPOCH,
880
- modifiedAt: EMPTY_FILESYSTEM_EPOCH,
881
- };
882
- }
883
- assertWritable(operation) {
884
- throw new WorkspaceReadOnlyError(operation);
885
- }
886
- async readFile(inputPath, _options) {
887
- await this.ensureReady();
888
- const normalized = normalizeEmptyFilesystemPath(inputPath);
889
- if (normalized === "/") {
890
- throw new IsDirectoryError(normalized);
891
- }
892
- throw new FileNotFoundError(normalized);
893
- }
894
- async writeFile(_inputPath, _content, _options) {
895
- await this.ensureReady();
896
- this.assertWritable("writeFile");
897
- }
898
- async appendFile(_inputPath, _content) {
899
- await this.ensureReady();
900
- this.assertWritable("appendFile");
901
- }
902
- async deleteFile(inputPath, options) {
903
- await this.ensureReady();
904
- const normalized = normalizeEmptyFilesystemPath(inputPath);
905
- if (normalized === "/") {
906
- throw new IsDirectoryError(normalized);
907
- }
908
- if (options?.force)
909
- return;
910
- throw new FileNotFoundError(normalized);
911
- }
912
- async copyFile(src, _dest, _options) {
913
- await this.ensureReady();
914
- const normalizedSrc = normalizeEmptyFilesystemPath(src);
915
- if (normalizedSrc !== "/") {
916
- throw new FileNotFoundError(normalizedSrc);
917
- }
918
- throw new IsDirectoryError(normalizedSrc);
919
- }
920
- async moveFile(src, dest, options) {
921
- await this.copyFile(src, dest, options);
922
- }
923
- async mkdir(_inputPath, _options) {
924
- await this.ensureReady();
925
- this.assertWritable("mkdir");
926
- }
927
- async rmdir(inputPath, options) {
928
- await this.ensureReady();
929
- const normalized = normalizeEmptyFilesystemPath(inputPath);
930
- if (normalized === "/") {
931
- throw new DirectoryNotEmptyError(normalized);
932
- }
933
- if (options?.force)
934
- return;
935
- throw new DirectoryNotFoundError(normalized);
936
- }
937
- async readdir(inputPath, _options) {
938
- await this.ensureReady();
939
- const normalized = normalizeEmptyFilesystemPath(inputPath);
940
- if (normalized === "/")
941
- return [];
942
- throw new DirectoryNotFoundError(normalized);
943
- }
944
- async exists(inputPath) {
945
- await this.ensureReady();
946
- return normalizeEmptyFilesystemPath(inputPath) === "/";
947
- }
948
- async stat(inputPath) {
949
- await this.ensureReady();
950
- const normalized = normalizeEmptyFilesystemPath(inputPath);
951
- if (normalized === "/")
952
- return this.rootStat();
953
- throw new FileNotFoundError(normalized);
954
- }
234
+ function normalizeWorkspacePath(inputPath) {
235
+ const result = posixPath.normalize(inputPath);
236
+ return result.ok ? result.path : "/";
955
237
  }
956
- /** Memoized singleton empty read-only filesystem for no-op mounts. */
957
- export const emptyFilesystem = functionModule.memoize(() => new EmptyFilesystem());
958
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZXN5c3RlbXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZmlsZXN5c3RlbXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUVILE9BQU8sRUFBRSxLQUFLLElBQUksSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxjQUFjLEVBQUUsbUJBQW1CLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFMUYsT0FBTyxFQUFFLEtBQUssRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzFFLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsc0JBQXNCLEVBQ3RCLGVBQWUsRUFDZixpQkFBaUIsRUFDakIsZ0JBQWdCLEVBQ2hCLGdCQUFnQixFQUNoQixpQkFBaUIsRUFDakIsZUFBZSxFQUNmLHNCQUFzQixHQUN2QixNQUFNLHdCQUF3QixDQUFDO0FBZWhDLDZFQUE2RTtBQUU3RSxNQUFNLHFCQUFxQixHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDMUMsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ3ZDLE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFM0MsMkVBQTJFO0FBQzNFLFNBQVMsc0JBQXNCLENBQUMsR0FBWTtJQUMxQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ1IsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNwQyxJQUFJLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN0QixPQUFPLGlCQUFpQixDQUFDO1FBQzNCLENBQUM7YUFBTSxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDL0MsT0FBTyxlQUFlLENBQUM7UUFDekIs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QztRQUMvQyxNQUFNLElBQUksaUJBQWlCLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDMUMsQ0FBQztDQUNGO0FBRUQsc0VBQXNFO0FBQ3RFLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksZUFBZSxFQUFFLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTWFzdHJhIHtAbGluayBXb3Jrc3BhY2VGaWxlc3lzdGVtfSBpbXBsZW1lbnRhdGlvbnMgZm9yIERhdGFicmlja3MgQXBwcy5cbiAqXG4gKiB7QGxpbmsgRGF0YWJyaWNrc1dvcmtzcGFjZUZpbGVzeXN0ZW19IG1hcHMgYSBNYXN0cmEgd29ya3NwYWNlIG5hbWVzcGFjZSBvbnRvXG4gKiBhbiBhYnNvbHV0ZSBEYXRhYnJpY2tzIHBhdGggKFVuaXR5IENhdGFsb2cgdm9sdW1lLCB3b3Jrc3BhY2Ugb2JqZWN0IHRyZWUsIG9yXG4gKiBEQkZTKS4ge0BsaW5rIGVtcHR5RmlsZXN5c3RlbX0gaXMgYSByZWFkLW9ubHkgbm8tb3AgbW91bnQgdXNlZCB3aGVuIG5vXG4gKiBkeW5hbWljIG1vdW50cyByZXNvbHZlIGZvciBhIHJlcXVlc3QuXG4gKlxuICogUGF0aCBoZWxwZXJzICh7QGxpbmsgbm9ybWFsaXplRGF0YWJyaWNrc0Jhc2VQYXRofSwge0BsaW5rIGlzRGJmc1BhdGh9LCDigKYpXG4gKiBhcmUgZXhwb3J0ZWQgZm9yIHRlc3RzIGFuZCBjYWxsZXJzIHRoYXQgbmVlZCB0byByZWFzb24gYWJvdXQgRGF0YWJyaWNrc1xuICogcGF0aHMgd2l0aG91dCBjb25zdHJ1Y3RpbmcgYSBmaWxlc3lzdGVtLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBwb3NpeCBhcyBwYXRoIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsgRXhlY3V0aW9uRXJyb3IsIGdldEV4ZWN1dGlvbkNvbnRleHQsIFZhbGlkYXRpb25FcnJvciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IFdvcmtzcGFjZUNsaWVudCB9IGZyb20gXCJAZGF0YWJyaWNrcy9zZGstZXhwZXJpbWVudGFsXCI7XG5pbXBvcnQgeyBlcnJvciwgZnVuY3Rpb25Nb2R1bGUsIGhhc2gsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQge1xuICBEaXJlY3RvcnlOb3RFbXB0eUVycm9yLFxuICBEaXJlY3RvcnlOb3RGb3VuZEVycm9yLFxuICBGaWxlRXhpc3RzRXJyb3IsXG4gIEZpbGVOb3RGb3VuZEVycm9yLFxuICBJc0RpcmVjdG9yeUVycm9yLFxuICBNYXN0cmFGaWxlc3lzdGVtLFxuICBOb3REaXJlY3RvcnlFcnJvcixcbiAgUGVybWlzc2lvbkVycm9yLFxuICBXb3Jrc3BhY2VSZWFkT25seUVycm9yLFxufSBmcm9tIFwiQG1hc3RyYS9jb3JlL3dvcmtzcGFjZVwiO1xuaW1wb3J0IHR5cGUge1xuICBDb3B5T3B0aW9ucyxcbiAgRmlsZUNvbnRlbnQsXG4gIEZpbGVFbnRyeSxcbiAgRmlsZVN0YXQsXG4gIEZpbGVzeXN0ZW1JbmZvLFxuICBMaXN0T3B0aW9ucyxcbiAgTWFzdHJhRmlsZXN5c3RlbU9wdGlvbnMsXG4gIFByb3ZpZGVyU3RhdHVzLFxuICBSZWFkT3B0aW9ucyxcbiAgUmVtb3ZlT3B0aW9ucyxcbiAgV3JpdGVPcHRpb25zLFxufSBmcm9tIFwiQG1hc3RyYS9jb3JlL3dvcmtzcGFjZVwiO1xuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gY29uc3RhbnRzIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5jb25zdCBEQkZTX1JFQURfQ0hVTktfQllURVMgPSAxMDI0ICogMTAyNDtcbmNvbnN0IERCRlNfUFVUX01BWF9CWVRFUyA9IDEwMjQgKiAxMDI0O1xuY29uc3QgRU1QVFlfRklMRVNZU1RFTV9FUE9DSCA9IG5ldyBEYXRlKDApO1xuXG4vKiogTWFzdHJhIGVycm9yIGNvbnN0cnVjdG9yIGZvciBhIGtub3duIFNESyBmaWxlc3lzdGVtIGZhaWx1cmUsIGlmIGFueS4gKi9cbmZ1bmN0aW9uIGZpbGVzeXN0ZW1TZGtFcnJvclR5cGUoZXJyOiB1bmtub3duKTogKG5ldyAocGF0aDogc3RyaW5nKSA9PiBFcnJvcikgfCB1bmRlZmluZWQge1xuICBpZiAoZXJyKSB7XG4gICAgY29uc3QgY3R4ID0gZXJyb3IuZXJyb3JDb250ZXh0KGVycik7XG4gICAgaWYgKGN0eC5ub3RBY2Nlc3NpYmxlKSB7XG4gICAgICByZXR1cm4gRmlsZU5vdEZvdW5kRXJyb3I7XG4gICAgfSBlbHNlIGlmIChjdHguaGFzTWVzc2FnZShcImFscmVhZHlcIiwgXCJleGlzdHNcIikpIHtcbiAgICAgIHJldHVybiBGaWxlRXhpc3RzRXJyb3I7XG4gICAgfSBlbHNlIGlmIChjdHguaGFzTWVzc2FnZShcIm5vdFwiLCBcImRpcmVjdG9yeVwiKSkge1xuICAgICAgcmV0dXJuIE5vdERpcmVjdG9yeUVycm9yO1xuICAgIH0gZWxzZSBpZiAoY3R4Lmhhc01lc3NhZ2UoXCJub3RcIiwgXCJmaWxlXCIpKSB7XG4gICAgICByZXR1cm4gSXNEaXJlY3RvcnlFcnJvcjtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcIm1hc3RyYS9maWxlc3lzdGVtc1wiKTtcblxuLyoqIEhvdyB7QGxpbmsgRGF0YWJyaWNrc1dvcmtzcGFjZUZpbGVzeXN0ZW0uaW5pdH0gaGFuZGxlcyBhIG1pc3Npbmcge0BsaW5rIGJhc2VQYXRofS4gKi9cbmV4cG9ydCB0eXBlIERhdGFicmlja3NNa2RpcnNNb2RlID0gYm9vbGVhbiB8IFwidHJ5XCI7XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgRGF0YWJyaWNrc1dvcmtzcGFjZUZpbGVzeXN0ZW19LiAqL1xuZXhwb3J0IGludGVyZmFjZSBEYXRhYnJpY2tzV29ya3NwYWNlRmlsZXN5c3RlbU9wdGlvbnMgZXh0ZW5kcyBNYXN0cmFGaWxlc3lzdGVtT3B0aW9ucyB7XG4gIC8qKiBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhpcyBmaWxlc3lzdGVtIGluc3RhbmNlLiAqL1xuICBpZD86IHN0cmluZztcbiAgLyoqIEF1dGgtc2NvcGVkIERhdGFicmlja3Mgd29ya3NwYWNlIGNsaWVudC4gKi9cbiAgY2xpZW50PzogV29ya3NwYWNlQ2xpZW50O1xuICAvKipcbiAgICogQWJzb2x1dGUgRGF0YWJyaWNrcyBwYXRoIHRoYXQgcm9vdHMgdGhlIHdvcmtzcGFjZSBuYW1lc3BhY2UsIGUuZy5cbiAgICogYC9Wb2x1bWVzL2NhdGFsb2cvc2NoZW1hL3ZvbHVtZWAgb3IgYC9kYmZzL0ZpbGVTdG9yZS9zaGFyZWRgLlxuICAgKi9cbiAgYmFzZVBhdGg6IHN0cmluZztcbiAgLyoqXG4gICAqIFdoZW4gdGhlIHtAbGluayBiYXNlUGF0aH0gaXMgbWlzc2luZyBhdCB7QGxpbmsgaW5pdH0sIGNyZWF0ZSBpdCB3aXRoIHRoZVxuICAgKiBtYXRjaGluZyBEYXRhYnJpY2tzIGBta2RpcnNgIEFQSS4gYFwidHJ5XCJgIChkZWZhdWx0KSBsb2dzIGF0IGRlYnVnIGFuZFxuICAgKiBmYWxscyBiYWNrIHRvIGFuIGVtcHR5IHJlYWQtb25seSBuYW1lc3BhY2Ugb24gZmFpbHVyZTsgYHRydWVgIGZhaWxzIGluaXQ7XG4gICAqIGBmYWxzZWAgc2tpcHMgY3JlYXRpb24gYW5kIHVzZXMgdGhlIGVtcHR5IG5hbWVzcGFjZS5cbiAgICpcbiAgICogQSBzdWNjZXNzZnVsIG1rZGlyIGFsc28gc2F0aXNmaWVzIHRoZSB3cml0ZS1hY2Nlc3MgcHJvYmUgd2hlblxuICAgKiB7QGxpbmsgcmVhZE9ubHl9IGlzIG9taXR0ZWQuXG4gICAqL1xuICBta2RpcnM/OiBEYXRhYnJpY2tzTWtkaXJzTW9kZTtcbiAgLyoqIEJsb2NrIHdyaXRlcyB3aGlsZSBzdGlsbCBhbGxvd2luZyByZWFkcy4gV2hlbiBvbWl0dGVkLCB7QGxpbmsgaW5pdH0gcHJvYmVzIHdyaXRlIGFjY2Vzcy4gKi9cbiAgcmVhZE9ubHk/OiBib29sZWFuO1xufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGV4cG9ydGVkIHBhdGggaGVscGVycyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbi8qKiBOb3JtYWxpemUgYSBEYXRhYnJpY2tzIGJhc2UgcGF0aCAoUE9TSVgsIG5vIHRyYWlsaW5nIHNsYXNoKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVEYXRhYnJpY2tzQmFzZVBhdGgoYmFzZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHRyaW1tZWQgPSBiYXNlUGF0aC50cmltKCk7XG4gIGlmICghdHJpbW1lZC5zdGFydHNXaXRoKFwiL1wiKSkge1xuICAgIHRocm93IFZhbGlkYXRpb25FcnJvci5pbnZhbGlkVmFsdWUoXG4gICAgICBcImJhc2VQYXRoXCIsXG4gICAgICBiYXNlUGF0aCxcbiAgICAgIFwiYW4gYWJzb2x1dGUgRGF0YWJyaWNrcyBwYXRoLCBlLmcuIC9Wb2x1bWVzL2NhdGFsb2cvc2NoZW1hL3ZvbHVtZVwiLFxuICAgICk7XG4gIH1cbiAgcmV0dXJuIHRyaW1tZWQucmVwbGFjZSgvXFwvKyQvLCBcIlwiKSB8fCBcIi9cIjtcbn1cblxuLyoqIFRydWUgd2hlbiBgYWJzb2x1dGVQYXRoYCBpcyBzZXJ2ZWQgYnkgREJGUyByYXRoZXIgdGhhbiB0aGUgVUMgRmlsZXMgQVBJLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRGJmc1BhdGgoYWJzb2x1dGVQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIGFic29sdXRlUGF0aCA9PT0gXCIvZGJmc1wiIHx8IGFic29sdXRlUGF0aC5zdGFydHNXaXRoKFwiL2RiZnMvXCIpO1xufVxuXG4vKiogVHJ1ZSB3aGVuIGBhYnNvbHV0ZVBhdGhgIGlzIGEgRGF0YWJyaWNrcyB3b3Jrc3BhY2Ugb2JqZWN0IHBhdGguICovXG5leHBvcnQgZnVuY3Rpb24gaXNXb3Jrc3BhY2VGaWxlc1BhdGgoYWJzb2x1dGVQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBhYnNvbHV0ZVBhdGggPT09IFwiL1dvcmtzcGFjZVwiIHx8XG4gICAgYWJzb2x1dGVQYXRoLnN0YXJ0c1dpdGgoXCIvV29ya3NwYWNlL1wiKSB8fFxuICAgIGFic29sdXRlUGF0aC5zdGFydHNXaXRoKFwiL1VzZXJzL1wiKSB8fFxuICAgIGFic29sdXRlUGF0aC5zdGFydHNXaXRoKFwiL1JlcG9zL1wiKVxuICApO1xufVxuXG50eXBlIEZpbGVzQmFja2VuZCA9IFwiZGJmc1wiIHwgXCJ3b3Jrc3BhY2VcIiB8IFwidWMtZmlsZXNcIjtcblxuLyoqIFBlci1iYWNrZW5kIGFzeW5jIGhhbmRsZXIgdXNlZCBieSB7QGxpbmsgZGlzcGF0Y2hGaWxlc0JhY2tlbmR9LiAqL1xudHlwZSBGaWxlc0JhY2tlbmRIYW5kbGVyczxUID0gdW5rbm93bj4gPSB7XG4gIGRiZnM6ICgpID0+IFByb21pc2U8VD47XG4gIHdvcmtzcGFjZTogKCkgPT4gUHJvbWlzZTxUPjtcbiAgdWNGaWxlczogKCkgPT4gUHJvbWlzZTxUPjtcbn07XG5cbi8qKlxuICogUmVzb2x2ZSBhIHdvcmtzcGFjZS1yZWxhdGl2ZSBwYXRoIHRvIGFuIGFic29sdXRlIERhdGFicmlja3MgcGF0aCB1bmRlclxuICogYGJhc2VQYXRoYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVEYXRhYnJpY2tzQWJzb2x1dGVQYXRoKGJhc2VQYXRoOiBzdHJpbmcsIGlucHV0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgcm9vdCA9IG5vcm1hbGl6ZURhdGFicmlja3NCYXNlUGF0aChiYXNlUGF0aCk7XG4gIGNvbnN0IHRyaW1tZWQgPSBpbnB1dFBhdGgudHJpbSgpO1xuICBpZiAoIXRyaW1tZWQgfHwgdHJpbW1lZCA9PT0gXCIvXCIpIHJldHVybiByb290O1xuICBjb25zdCBub3JtYWxpemVkID0gdHJpbW1lZC5zdGFydHNXaXRoKFwiL1wiKSA/IHRyaW1tZWQgOiBgLyR7dHJpbW1lZH1gO1xuICBpZiAobm9ybWFsaXplZCA9PT0gcm9vdCB8fCBub3JtYWxpemVkLnN0YXJ0c1dpdGgoYCR7cm9vdH0vYCkpIHtcbiAgICByZXR1cm4gcGF0aC5ub3JtYWxpemUobm9ybWFsaXplZCk7XG4gIH1cbiAgcmV0dXJuIHBhdGgubm9ybWFsaXplKHBhdGguam9pbihyb290LCBub3JtYWxpemVkKSk7XG59XG5cbi8qKiBNYXAgYW4gYWJzb2x1dGUgRGF0YWJyaWNrcyBwYXRoIGJhY2sgdG8gdGhlIHdvcmtzcGFjZSBuYW1lc3BhY2UuICovXG5leHBvcnQgZnVuY3Rpb24gdG9EYXRhYnJpY2tzV29ya3NwYWNlUGF0aChiYXNlUGF0aDogc3RyaW5nLCBhYnNvbHV0ZVBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHJvb3QgPSBub3JtYWxpemVEYXRhYnJpY2tzQmFzZVBhdGgoYmFzZVBhdGgpO1xuICBjb25zdCBub3JtYWxpemVkID0gcGF0aC5ub3JtYWxpemUoYWJzb2x1dGVQYXRoKTtcbiAgaWYgKG5vcm1hbGl6ZWQgPT09IHJvb3QpIHJldHVybiBcIi9cIjtcbiAgaWYgKG5vcm1hbGl6ZWQuc3RhcnRzV2l0aChgJHtyb290fS9gKSkge1xuICAgIHJldHVybiBub3JtYWxpemVkLnNsaWNlKHJvb3QubGVuZ3RoKSB8fCBcIi9cIjtcbiAgfVxuICByZXR1cm4gbm9ybWFsaXplZDtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBwcml2YXRlIGhlbHBlcnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKiogUGljayB0aGUgRGF0YWJyaWNrcyBGaWxlcyBBUEkgYmFja2VuZCBmb3IgYW4gYWJzb2x1dGUgcGF0aC4gKi9cbmZ1bmN0aW9uIHJlc29sdmVGaWxlc0JhY2tlbmQoYWJzb2x1dGVQYXRoOiBzdHJpbmcpOiBGaWxlc0JhY2tlbmQge1xuICBpZiAoaXNEYmZzUGF0aChhYnNvbHV0ZVBhdGgpKSByZXR1cm4gXCJkYmZzXCI7XG4gIGlmIChpc1dvcmtzcGFjZUZpbGVzUGF0aChhYnNvbHV0ZVBhdGgpKSByZXR1cm4gXCJ3b3Jrc3BhY2VcIjtcbiAgcmV0dXJuIFwidWMtZmlsZXNcIjtcbn1cblxuLyoqIFJ1biB0aGUgaGFuZGxlciB0aGF0IG1hdGNoZXMgYGFic29sdXRlUGF0aGAncyBEYXRhYnJpY2tzIGJhY2tlbmQuICovXG5hc3luYyBmdW5jdGlvbiBkaXNwYXRjaEZpbGVzQmFja2VuZDxUPihcbiAgYWJzb2x1dGVQYXRoOiBzdHJpbmcsXG4gIGhhbmRsZXJzOiBGaWxlc0JhY2tlbmRIYW5kbGVyczxUPixcbik6IFByb21pc2U8VD4ge1xuICBjb25zdCBiYWNrZW5kID0gcmVzb2x2ZUZpbGVzQmFja2VuZChhYnNvbHV0ZVBhdGgpO1xuICBpZiAoYmFja2VuZCA9PT0gXCJkYmZzXCIpIHJldHVybiBoYW5kbGVycy5kYmZzKCk7XG4gIGlmIChiYWNrZW5kID09PSBcIndvcmtzcGFjZVwiKSByZXR1cm4gaGFuZGxlcnMud29ya3NwYWNlKCk7XG4gIHJldHVybiBoYW5kbGVycy51Y0ZpbGVzKCk7XG59XG5cbi8qKiBSZXR1cm4gYGJ1ZmZlcmAgYXMgYSBzdHJpbmcgd2hlbiBgZW5jb2RpbmdgIGlzIHNldCwgb3RoZXJ3aXNlIHVuY2hhbmdlZC4gKi9cbmZ1bmN0aW9uIGZvcm1hdFJlYWRSZXN1bHQoYnVmZmVyOiBCdWZmZXIsIGVuY29kaW5nPzogQnVmZmVyRW5jb2RpbmcpOiBzdHJpbmcgfCBCdWZmZXIge1xuICByZXR1cm4gZW5jb2RpbmcgPyBidWZmZXIudG9TdHJpbmcoZW5jb2RpbmcpIDogYnVmZmVyO1xufVxuXG4vKiogRHJhaW4gYSBmZXRjaCBgUmVhZGFibGVTdHJlYW1gIGludG8gYSBzaW5nbGUgYEJ1ZmZlcmAuICovXG5hc3luYyBmdW5jdGlvbiByZWFkUmVzcG9uc2VCb2R5KFxuICBjb250ZW50czogZ2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB8IHVuZGVmaW5lZCxcbik6IFByb21pc2U8QnVmZmVyPiB7XG4gIGlmICghY29udGVudHMpIHJldHVybiBCdWZmZXIuYWxsb2MoMCk7XG4gIGNvbnN0IHJlYWRlciA9IGNvbnRlbnRzLmdldFJlYWRlcigpO1xuICBjb25zdCBjaHVua3M6IFVpbnQ4QXJyYXlbXSA9IFtdO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgaWYgKGRvbmUpIGJyZWFrO1xuICAgIGlmICh2YWx1ZSkgY2h1bmtzLnB1c2godmFsdWUpO1xuICB9XG4gIHJldHVybiBCdWZmZXIuY29uY2F0KGNodW5rcy5tYXAoKGNodW5rKSA9PiBCdWZmZXIuZnJvbShjaHVuaykpKTtcbn1cblxuLyoqIENvZXJjZSBNYXN0cmEge0BsaW5rIEZpbGVDb250ZW50fSB0byBhIGBCdWZmZXJgLiAqL1xuZnVuY3Rpb24gdG9CdWZmZXIoY29udGVudDogRmlsZUNvbnRlbnQpOiBCdWZmZXIge1xuICBpZiAodHlwZW9mIGNvbnRlbnQgPT09IFwic3RyaW5nXCIpIHJldHVybiBCdWZmZXIuZnJvbShjb250ZW50LCBcInV0ZjhcIik7XG4gIHJldHVybiBCdWZmZXIuZnJvbShjb250ZW50KTtcbn1cblxuLyoqIERlY29kZSBhIERCRlMgcmVhZCBwYXlsb2FkIGZyb20gYmFzZTY0LiAqL1xuZnVuY3Rpb24gZGVjb2RlRGJmc1BheWxvYWQoZGF0YTogc3RyaW5nIHwgdW5kZWZpbmVkKTogQnVmZmVyIHtcbiAgaWYgKCFkYXRhKSByZXR1cm4gQnVmZmVyLmFsbG9jKDApO1xuICByZXR1cm4gQnVmZmVyLmZyb20oZGF0YSwgXCJiYXNlNjRcIik7XG59XG5cbi8qKiBXcmFwIGEgYEJ1ZmZlcmAgYXMgYSBvbmUtc2hvdCBgUmVhZGFibGVTdHJlYW1gIGZvciBVQyBmaWxlIHVwbG9hZHMuICovXG5mdW5jdGlvbiBidWZmZXJUb1JlYWRhYmxlU3RyZWFtKGJ1ZmZlcjogQnVmZmVyKTogZ2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB7XG4gIHJldHVybiBuZXcgUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4oe1xuICAgIHN0YXJ0KGNvbnRyb2xsZXIpIHtcbiAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZShuZXcgVWludDhBcnJheShidWZmZXIpKTtcbiAgICAgIGNvbnRyb2xsZXIuY2xvc2UoKTtcbiAgICB9LFxuICB9KTtcbn1cblxuLyoqIFBhcnNlIGFuIEhUVFAgZGF0ZSBoZWFkZXI7IHJldHVybnMgZXBvY2ggd2hlbiBtaXNzaW5nIG9yIGludmFsaWQuICovXG5mdW5jdGlvbiBwYXJzZUh0dHBEYXRlKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBEYXRlIHtcbiAgaWYgKCF2YWx1ZSkgcmV0dXJuIG5ldyBEYXRlKDApO1xuICBjb25zdCBwYXJzZWQgPSBEYXRlLnBhcnNlKHZhbHVlKTtcbiAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShwYXJzZWQpID8gbmV3IERhdGUocGFyc2VkKSA6IG5ldyBEYXRlKDApO1xufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tIERhdGFicmlja3NXb3Jrc3BhY2VGaWxlc3lzdGVtIC0tLS0tLS0tLS0tLS0tLS0gKi9cblxuLyoqXG4gKiBNYXN0cmEgZmlsZXN5c3RlbSBwcm92aWRlciB0aGF0IHJlYWRzIGFuZCB3cml0ZXMgdGhyb3VnaCBhIERhdGFicmlja3NcbiAqIHtAbGluayBXb3Jrc3BhY2VDbGllbnR9LlxuICpcbiAqIFdvcmtzcGFjZSBwYXRocyBhcmUgYWJzb2x1dGUgd2l0aGluIHRoZSBuYW1lc3BhY2UgKGAvbm90ZXMubWRgIG1hcHMgdG9cbiAqIGA8YmFzZVBhdGg+L25vdGVzLm1kYCkuIFVuaXR5IENhdGFsb2cgdm9sdW1lcyB1c2UgdGhlIEZpbGVzIEFQSTtcbiAqIGAvZGJmcy8uLi5gIHBhdGhzIHVzZSBEQkZTLlxuICovXG5leHBvcnQgY2xhc3MgRGF0YWJyaWNrc1dvcmtzcGFjZUZpbGVzeXN0ZW0gZXh0ZW5kcyBNYXN0cmFGaWxlc3lzdGVtIHtcbiAgcmVhZG9ubHkgaWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgbmFtZSA9IFwiRGF0YWJyaWNrc1dvcmtzcGFjZUZpbGVzeXN0ZW1cIjtcbiAgcmVhZG9ubHkgcHJvdmlkZXIgPSBcImRhdGFicmlja3NcIjtcbiAgcmVhZG9ubHkgYmFzZVBhdGg6IHN0cmluZztcbiAgc3RhdHVzOiBQcm92aWRlclN0YXR1cyA9IFwicGVuZGluZ1wiO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWtkaXJzOiBEYXRhYnJpY2tzTWtkaXJzTW9kZTtcbiAgcHJpdmF0ZSBfcmVhZE9ubHk6IGJvb2xlYW4gfCB1bmRlZmluZWQ7XG4gIHByaXZhdGUgX2Jhc2VQYXRoTWlzc2luZzogYm9vbGVhbiB8IHVuZGVmaW5lZDtcblxuICBnZXQgcmVhZE9ubHkoKTogYm9vbGVhbiB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX3JlYWRPbmx5O1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBvcHRpb25zLmNsaWVudCAtIERlZmF1bHRzIHRvIHRoZSBBcHBLaXQgZXhlY3V0aW9uLWNvbnRleHQgY2xpZW50LlxuICAgKiBAcGFyYW0gb3B0aW9ucy5ta2RpcnMgLSBEZWZhdWx0IGBcInRyeVwiYDsgc2VlIHtAbGluayBEYXRhYnJpY2tzTWtkaXJzTW9kZX0uXG4gICAqIEBwYXJhbSBvcHRpb25zLnJlYWRPbmx5IC0gV2hlbiBvbWl0dGVkLCB7QGxpbmsgaW5pdH0gcHJvYmVzIHdyaXRlIGFjY2Vzcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IERhdGFicmlja3NXb3Jrc3BhY2VGaWxlc3lzdGVtT3B0aW9ucykge1xuICAgIHN1cGVyKHsgbmFtZTogXCJEYXRhYnJpY2tzV29ya3NwYWNlRmlsZXN5c3RlbVwiLCAuLi5vcHRpb25zIH0pO1xuICAgIHRoaXMuaWQgPSBvcHRpb25zLmlkID8/IGBkYXRhYnJpY2tzLWZzLSR7aGFzaC5mbnZIYXNoKG9wdGlvbnMuYmFzZVBhdGgpfWA7XG4gICAgdGhpcy5jbGllbnQgPSBvcHRpb25zLmNsaWVudCA/PyBnZXRFeGVjdXRpb25Db250ZXh0KCkuY2xpZW50O1xuICAgIHRoaXMuYmFzZVBhdGggPSBub3JtYWxpemVEYXRhYnJpY2tzQmFzZVBhdGgob3B0aW9ucy5iYXNlUGF0aCk7XG4gICAgdGhpcy5ta2RpcnMgPSBvcHRpb25zLm1rZGlycyA/PyBcInRyeVwiO1xuICAgIHRoaXMuX3JlYWRPbmx5ID0gb3B0aW9ucy5yZWFkT25seTtcbiAgfVxuXG4gIC8qIC0tLSBwYXRoIHJlc29sdXRpb24gLS0tICovXG5cbiAgLyoqIFJlc29sdmUgYW5kIHNhbmRib3ggYSB3b3Jrc3BhY2UtcmVsYXRpdmUgcGF0aCB1bmRlciB7QGxpbmsgYmFzZVBhdGh9LiAqL1xuICBwcml2YXRlIHJlc29sdmVQYXRoKGlucHV0UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVEYXRhYnJpY2tzQWJzb2x1dGVQYXRoKHRoaXMuYmFzZVBhdGgsIGlucHV0UGF0aCk7XG4gICAgaWYgKHJlc29sdmVkICE9PSB0aGlzLmJhc2VQYXRoICYmICFyZXNvbHZlZC5zdGFydHNXaXRoKGAke3RoaXMuYmFzZVBhdGh9L2ApKSB7XG4gICAgICB0aHJvdyBuZXcgUGVybWlzc2lvbkVycm9yKGlucHV0UGF0aCwgXCJhY2Nlc3NcIik7XG4gICAgfVxuICAgIHJldHVybiByZXNvbHZlZDtcbiAgfVxuXG4gIC8qKiBNYXAgYSBEYXRhYnJpY2tzIGFic29sdXRlIHBhdGggYmFjayB0byB0aGUgd29ya3NwYWNlIG5hbWVzcGFjZS4gKi9cbiAgcHJpdmF0ZSB3b3Jrc3BhY2VQYXRoKGFic29sdXRlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdG9EYXRhYnJpY2tzV29ya3NwYWNlUGF0aCh0aGlzLmJhc2VQYXRoLCBhYnNvbHV0ZVBhdGgpO1xuICB9XG5cbiAgLyoqIFRocm93IHdoZW4gdGhlIGZpbGVzeXN0ZW0gaXMgcmVhZC1vbmx5LiAqL1xuICBwcml2YXRlIGFzc2VydFdyaXRhYmxlKG9wZXJhdGlvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucmVhZE9ubHkpIHtcbiAgICAgIHRocm93IG5ldyBXb3Jrc3BhY2VSZWFkT25seUVycm9yKG9wZXJhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgLyoqIE1hcCBTREsgLyBIVFRQIGVycm9ycyB0byBNYXN0cmEgd29ya3NwYWNlIGZpbGVzeXN0ZW0gZXJyb3JzLiAqL1xuICBwcml2YXRlIHJldGhyb3coZXJyOiB1bmtub3duLCBpbnB1dFBhdGg6IHN0cmluZyk6IG5ldmVyIHtcbiAgICBjb25zdCB3b3Jrc3BhY2VQYXRoID0gaW5wdXRQYXRoLnN0YXJ0c1dpdGgoXCIvXCIpXG4gICAgICA/IGlucHV0UGF0aFxuICAgICAgOiB0aGlzLndvcmtzcGFjZVBhdGgodGhpcy5yZXNvbHZlUGF0aChpbnB1dFBhdGgpKTtcbiAgICBjb25zdCBFcnJvclR5cGUgPSBmaWxlc3lzdGVtU2RrRXJyb3JUeXBlKGVycik7XG4gICAgaWYgKEVycm9yVHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yVHlwZSh3b3Jrc3BhY2VQYXRoKTtcbiAgICB9XG4gICAgLy8gVGhlIHVwc3RyZWFtIG1lc3NhZ2UgaXMgbG9nZ2VkIHJhdGhlciB0aGFuIHJhaXNlZDogaXQgcmVhY2hlcyB0aGUgbW9kZWxcbiAgICAvLyAoYW5kIGZyb20gdGhlcmUgdGhlIGNoYXQgdHJhbnNjcmlwdCkgYXMgdGhlIHRvb2wncyBmYWlsdXJlIHRleHQuXG4gICAgbG9nZ2VyLndhcm4oXCJvcGVyYXRpb24tZmFpbGVkXCIsIHtcbiAgICAgIHBhdGg6IHdvcmtzcGFjZVBhdGgsXG4gICAgICBlcnJvcjogZXJyb3IuZXJyb3JNZXNzYWdlKGVyciksXG4gICAgfSk7XG4gICAgdGhyb3cgbmV3IEV4ZWN1dGlvbkVycm9yKGBEYXRhYnJpY2tzIGZpbGVzeXN0ZW0gb3BlcmF0aW9uIGZhaWxlZCBmb3IgJHt3b3Jrc3BhY2VQYXRofWAsIHtcbiAgICAgIGNhdXNlOiBlcnJvci50b0Vycm9yKGVyciksXG4gICAgICBjb250ZXh0OiB7IHBhdGg6IHdvcmtzcGFjZVBhdGggfSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qIC0tLSBsaWZlY3ljbGUgLS0tICovXG5cbiAgLyoqXG4gICAqIFByb2JlIHdoZXRoZXIge0BsaW5rIGJhc2VQYXRofSBleGlzdHMgYW5kIGNhY2hlIHRoZSByZXN1bHQgb25cbiAgICoge0BsaW5rIF9iYXNlUGF0aE1pc3Npbmd9LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyByZXNvbHZlQmFzZVBhdGhTdGF0dXMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuX2Jhc2VQYXRoTWlzc2luZyAhPT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuYXNzZXJ0QWJzb2x1dGVSZWFkYWJsZSh0aGlzLmJhc2VQYXRoKTtcbiAgICAgIHRoaXMuX2Jhc2VQYXRoTWlzc2luZyA9IGZhbHNlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVycm9yLmVycm9yQ29udGV4dChlcnIpLm5vdEFjY2Vzc2libGUpIHtcbiAgICAgICAgdGhpcy5fYmFzZVBhdGhNaXNzaW5nID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5yZXRocm93KGVyciwgXCIvXCIpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBEZWxlZ2F0ZSB0byB7QGxpbmsgZW1wdHlGaWxlc3lzdGVtfSB3aGVuIHRoZSBiYXNlIHBhdGggaXMgbWlzc2luZy4gKi9cbiAgcHJpdmF0ZSBhc3luYyBlbXB0eUZhbGxiYWNrKCk6IFByb21pc2U8UmV0dXJuVHlwZTx0eXBlb2YgZW1wdHlGaWxlc3lzdGVtPiB8IHVuZGVmaW5lZD4ge1xuICAgIGF3YWl0IHRoaXMucmVzb2x2ZUJhc2VQYXRoU3RhdHVzKCk7XG4gICAgcmV0dXJuIHRoaXMuX2Jhc2VQYXRoTWlzc2luZyA/IGVtcHR5RmlsZXN5c3RlbSgpIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgaW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnJlc29sdmVCYXNlUGF0aFN0YXR1cygpO1xuXG4gICAgaWYgKHRoaXMuX2Jhc2VQYXRoTWlzc2luZykge1xuICAgICAgaWYgKHRoaXMubWtkaXJzID09PSBmYWxzZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0aGlzLm1rZGlyQWJzb2x1dGUodGhpcy5iYXNlUGF0aCk7XG4gICAgICAgIHRoaXMuX2Jhc2VQYXRoTWlzc2luZyA9IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5fcmVhZE9ubHkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRoaXMuX3JlYWRPbmx5ID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBpZiAodGhpcy5ta2RpcnMgPT09IHRydWUpIHtcbiAgICAgICAgICB0aGlzLnJldGhyb3coZXJyLCBcIi9cIik7XG4gICAgICAgIH1cbiAgICAgICAgbG9nZ2VyLmRlYnVnKFwibWtkaXJzOnRyeS1mYWlsZWRcIiwge1xuICAgICAgICAgIGJhc2VQYXRoOiB0aGlzLmJhc2VQYXRoLFxuICAgICAgICAgIGVycm9yOiBlcnJvci5lcnJvck1lc3NhZ2UoZXJyKSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3JlYWRPbmx5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGF3YWl0IHRoaXMucHJvYmVSZWFkT25seSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXcml0ZSBhbmQgZGVsZXRlIGEgZXBoZW1lcmFsIHByb2JlIGZpbGUgdG8gZGV0ZWN0IHJlYWQtb25seSBhY2Nlc3Mgd2hlblxuICAgKiB7QGxpbmsgRGF0YWJyaWNrc1dvcmtzcGFjZUZpbGVzeXN0ZW1PcHRpb25zLnJlYWRPbmx5fSB3YXMgbm90IHNldC5cbiAgICpcbiAgICogQHJldHVybnMgYHRydWVgIHdoZW4gdGhlIHByb2JlIHdyaXRlIChhbmQgY2xlYW51cCkgc3VjY2VlZGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9iZVJlYWRPbmx5KCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHRoaXMucmVzb2x2ZVBhdGgoYC8uX19kYnhfZnNfcHJvYmVfJHtoYXNoLmlkKCl9YCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMud3JpdGVBYnNvbHV0ZShhYnNvbHV0ZVBhdGgsIEJ1ZmZlci5mcm9tKFwicHJvYmVcXG5cIiksIHRydWUpO1xuICAgICAgdGhpcy5fcmVhZE9ubHkgPSBmYWxzZTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIHRoaXMuX3JlYWRPbmx5ID0gdHJ1ZTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZGVsZXRlQWJzb2x1dGVGaWxlKGFic29sdXRlUGF0aCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBXcml0YWJsZTsgbGVhdmUgYSBoaWRkZW4gcHJvYmUgZmlsZSByYXRoZXIgdGhhbiBmYWlsaW5nIGluaXQuXG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgZGVzdHJveSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBSZW1vdGUgZmlsZXN5c3RlbTsgbm90aGluZyB0byB0ZWFyIGRvd24gbG9jYWxseS5cbiAgfVxuXG4gIC8qIC0tLSBiYWNrZW5kIEkvTyAtLS0gKi9cblxuICAvKiogUHJvYmUgdGhhdCBgYWJzb2x1dGVQYXRoYCBleGlzdHMgKGZpbGUgb3IgZGlyZWN0b3J5IG1ldGFkYXRhKS4gKi9cbiAgcHJpdmF0ZSBhc3luYyBhc3NlcnRBYnNvbHV0ZVJlYWRhYmxlKGFic29sdXRlUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgZGlzcGF0Y2hGaWxlc0JhY2tlbmQoYWJzb2x1dGVQYXRoLCB7XG4gICAgICBkYmZzOiAoKSA9PiB0aGlzLmNsaWVudC5kYmZzLmdldFN0YXR1cyh7IHBhdGg6IGFic29sdXRlUGF0aCB9KSxcbiAgICAgIHdvcmtzcGFjZTogKCkgPT4gdGhpcy5jbGllbnQud29ya3NwYWNlLmdldFN0YXR1cyh7IHBhdGg6IGFic29sdXRlUGF0aCB9KSxcbiAgICAgIHVjRmlsZXM6ICgpID0+IHRoaXMuY2xpZW50LmZpbGVzLmdldERpcmVjdG9yeU1ldGFkYXRhKHsgZGlyZWN0b3J5X3BhdGg6IGFic29sdXRlUGF0aCB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBSZWFkIHRoZSBmdWxsIGNvbnRlbnRzIG9mIGBhYnNvbHV0ZVBhdGhgIGZyb20gdGhlIG1hdGNoaW5nIGJhY2tlbmQuICovXG4gIHByaXZhdGUgYXN5bmMgcmVhZEFic29sdXRlKGFic29sdXRlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgICByZXR1cm4gZGlzcGF0Y2hGaWxlc0JhY2tlbmQoYWJzb2x1dGVQYXRoLCB7XG4gICAgICBkYmZzOiAoKSA9PiB0aGlzLnJlYWREYmZzRmlsZShhYnNvbHV0ZVBhdGgpLFxuICAgICAgd29ya3NwYWNlOiAoKSA9PiB0aGlzLnJlYWRXb3Jrc3BhY2VGaWxlKGFic29sdXRlUGF0aCksXG4gICAgICB1Y0ZpbGVzOiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jbGllbnQuZmlsZXMuZG93bmxvYWQoeyBmaWxlX3BhdGg6IGFic29sdXRlUGF0aCB9KTtcbiAgICAgICAgcmV0dXJuIHJlYWRSZXNwb25zZUJvZHkoXG4gICAgICAgICAgcmVzcG9uc2UuY29udGVudHMgYXMgZ2xvYmFsVGhpcy5SZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB8IHVuZGVmaW5lZCxcbiAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKiogV3JpdGUgYGJ1ZmZlcmAgdG8gYGFic29sdXRlUGF0aGAgb24gdGhlIG1hdGNoaW5nIGJhY2tlbmQuICovXG4gIHByaXZhdGUgYXN5bmMgd3JpdGVBYnNvbHV0ZShcbiAgICBhYnNvbHV0ZVBhdGg6IHN0cmluZyxcbiAgICBidWZmZXI6IEJ1ZmZlcixcbiAgICBvdmVyd3JpdGU6IGJvb2xlYW4sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGRpc3BhdGNoRmlsZXNCYWNrZW5kKGFic29sdXRlUGF0aCwge1xuICAgICAgZGJmczogKCkgPT4gdGhpcy53cml0ZURiZnNGaWxlKGFic29sdXRlUGF0aCwgYnVmZmVyLCBvdmVyd3JpdGUpLFxuICAgICAgd29ya3NwYWNlOiAoKSA9PiB0aGlzLndyaXRlV29ya3NwYWNlRmlsZShhYnNvbHV0ZVBhdGgsIGJ1ZmZlciwgb3ZlcndyaXRlKSxcbiAgICAgIHVjRmlsZXM6ICgpID0+IHRoaXMudXBsb2FkVWNGaWxlKGFic29sdXRlUGF0aCwgYnVmZmVyLCBvdmVyd3JpdGUpLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIFVwbG9hZCBhIGJ1ZmZlciB0byBhIFVuaXR5IENhdGFsb2cgRmlsZXMgQVBJIHBhdGguICovXG4gIHByaXZhdGUgdXBsb2FkVWNGaWxlKGFic29sdXRlUGF0aDogc3RyaW5nLCBidWZmZXI6IEJ1ZmZlciwgb3ZlcndyaXRlOiBib29sZWFuKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgcmV0dXJuIHRoaXMuY2xpZW50LmZpbGVzLnVwbG9hZCh7XG4gICAgICBmaWxlX3BhdGg6IGFic29sdXRlUGF0aCxcbiAgICAgIGNvbnRlbnRzOiBidWZmZXJUb1JlYWRhYmxlU3RyZWFtKGJ1ZmZlcikgYXMgbmV2ZXIsXG4gICAgICBvdmVyd3JpdGUsXG4gICAgfSk7XG4gIH1cblxuICAvKiogRGVsZXRlIGEgc2luZ2xlIGZpbGUgYXQgYGFic29sdXRlUGF0aGAgKG5vbi1yZWN1cnNpdmUpLiAqL1xuICBwcml2YXRlIGFzeW5jIGRlbGV0ZUFic29sdXRlRmlsZShhYnNvbHV0ZVBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IGRpc3BhdGNoRmlsZXNCYWNrZW5kKGFic29sdXRlUGF0aCwge1xuICAgICAgZGJmczogKCkgPT4gdGhpcy5jbGllbnQuZGJmcy5kZWxldGUoeyBwYXRoOiBhYnNvbHV0ZVBhdGgsIHJlY3Vyc2l2ZTogZmFsc2UgfSksXG4gICAgICB3b3Jrc3BhY2U6ICgpID0+IHRoaXMuY2xpZW50LndvcmtzcGFjZS5kZWxldGUoeyBwYXRoOiBhYnNvbHV0ZVBhdGgsIHJlY3Vyc2l2ZTogZmFsc2UgfSksXG4gICAgICB1Y0ZpbGVzOiAoKSA9PiB0aGlzLmNsaWVudC5maWxlcy5kZWxldGUoeyBmaWxlX3BhdGg6IGFic29sdXRlUGF0aCB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgYSBmaWxlIG9yIGRpcmVjdG9yeSBhdCBgYWJzb2x1dGVQYXRoYC5cbiAgICpcbiAgICogREJGUyBhbmQgd29ya3NwYWNlIEFQSXMgYWNjZXB0IGByZWN1cnNpdmVgOyBVQyB2b2x1bWVzIHJlY3Vyc2UgbWFudWFsbHkuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGRlbGV0ZUFic29sdXRlUGF0aChhYnNvbHV0ZVBhdGg6IHN0cmluZywgcmVjdXJzaXZlOiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgZGlzcGF0Y2hGaWxlc0JhY2tlbmQoYWJzb2x1dGVQYXRoLCB7XG4gICAgICBkYmZzOiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMuY2xpZW50LmRiZnMuZGVsZXRlKHsgcGF0aDogYWJzb2x1dGVQYXRoLCByZWN1cnNpdmUgfSk7XG4gICAgICB9LFxuICAgICAgd29ya3NwYWNlOiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IHRoaXMuY2xpZW50LndvcmtzcGFjZS5kZWxldGUoeyBwYXRoOiBhYnNvbHV0ZVBhdGgsIHJlY3Vyc2l2ZSB9KTtcbiAgICAgIH0sXG4gICAgICB1Y0ZpbGVzOiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGlmIChyZWN1cnNpdmUpIHtcbiAgICAgICAgICBhd2FpdCB0aGlzLmRlbGV0ZVVjRGlyZWN0b3J5UmVjdXJzaXZlKGFic29sdXRlUGF0aCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNoaWxkcmVuID0gYXdhaXQgdGhpcy5saXN0QWJzb2x1dGVEaXJlY3RvcnkoYWJzb2x1dGVQYXRoKTtcbiAgICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRGlyZWN0b3J5Tm90RW1wdHlFcnJvcih0aGlzLndvcmtzcGFjZVBhdGgoYWJzb2x1dGVQYXRoKSk7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgdGhpcy5jbGllbnQuZmlsZXMuZGVsZXRlRGlyZWN0b3J5KHsgZGlyZWN0b3J5X3BhdGg6IGFic29sdXRlUGF0aCB9KTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvKiogQ3JlYXRlIGBhYnNvbHV0ZVBhdGhgIGFuZCBhbnkgbWlzc2luZyBwYXJlbnRzIG9uIHRoZSBtYXRjaGluZyBiYWNrZW5kLiAqL1xuICBwcml2YXRlIGFzeW5jIG1rZGlyQWJzb2x1dGUoYWJzb2x1dGVQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBkaXNwYXRjaEZpbGVzQmFja2VuZChhYnNvbHV0ZVBhdGgsIHtcbiAgICAgIGRiZnM6ICgpID0+IHRoaXMuY2xpZW50LmRiZnMubWtkaXJzKHsgcGF0aDogYWJzb2x1dGVQYXRoIH0pLFxuICAgICAgd29ya3NwYWNlOiAoKSA9PiB0aGlzLmNsaWVudC53b3Jrc3BhY2UubWtkaXJzKHsgcGF0aDogYWJzb2x1dGVQYXRoIH0pLFxuICAgICAgdWNGaWxlczogKCkgPT4gdGhpcy5jbGllbnQuZmlsZXMuY3JlYXRlRGlyZWN0b3J5KHsgZGlyZWN0b3J5X3BhdGg6IGFic29sdXRlUGF0aCB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVhZERiZnNGaWxlKGFic29sdXRlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgICBjb25zdCBjaHVua3M6IEJ1ZmZlcltdID0gW107XG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jbGllbnQuZGJmcy5yZWFkKHtcbiAgICAgICAgcGF0aDogYWJzb2x1dGVQYXRoLFxuICAgICAgICBvZmZzZXQsXG4gICAgICAgIGxlbmd0aDogREJGU19SRUFEX0NIVU5LX0JZVEVTLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBjaHVuayA9IGRlY29kZURiZnNQYXlsb2FkKHJlc3BvbnNlLmRhdGEpO1xuICAgICAgaWYgKGNodW5rLmxlbmd0aCA9PT0gMCkgYnJlYWs7XG4gICAgICBjaHVua3MucHVzaChjaHVuayk7XG4gICAgICBvZmZzZXQgKz0gY2h1bmsubGVuZ3RoO1xuICAgICAgaWYgKGNodW5rLmxlbmd0aCA8IERCRlNfUkVBRF9DSFVOS19CWVRFUykgYnJlYWs7XG4gICAgfVxuICAgIHJldHVybiBCdWZmZXIuY29uY2F0KGNodW5rcyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlYWRXb3Jrc3BhY2VGaWxlKGFic29sdXRlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IHRoaXMuY2xpZW50LndvcmtzcGFjZS5leHBvcnQoe1xuICAgICAgcGF0aDogYWJzb2x1dGVQYXRoLFxuICAgICAgZm9ybWF0OiBcIkFVVE9cIixcbiAgICB9KTtcbiAgICByZXR1cm4gZGVjb2RlRGJmc1BheWxvYWQocmVzcG9uc2UuY29udGVudCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHdyaXRlRGJmc0ZpbGUoXG4gICAgYWJzb2x1dGVQYXRoOiBzdHJpbmcsXG4gICAgYnVmZmVyOiBCdWZmZXIsXG4gICAgb3ZlcndyaXRlOiBib29sZWFuLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoYnVmZmVyLmxlbmd0aCA8PSBEQkZTX1BVVF9NQVhfQllURVMpIHtcbiAgICAgIGF3YWl0IHRoaXMuY2xpZW50LmRiZnMucHV0KHtcbiAgICAgICAgcGF0aDogYWJzb2x1dGVQYXRoLFxuICAgICAgICBjb250ZW50czogYnVmZmVyLnRvU3RyaW5nKFwiYmFzZTY0XCIpLFxuICAgICAgICBvdmVyd3JpdGUsXG4gICAgICB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgY3JlYXRlZCA9IGF3YWl0IHRoaXMuY2xpZW50LmRiZnMuY3JlYXRlKHsgcGF0aDogYWJzb2x1dGVQYXRoLCBvdmVyd3JpdGUgfSk7XG4gICAgY29uc3QgaGFuZGxlID0gY3JlYXRlZC5oYW5kbGU7XG4gICAgaWYgKGhhbmRsZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBFeGVjdXRpb25FcnJvci5taXNzaW5nRGF0YShcIkRCRlMgdXBsb2FkIGhhbmRsZVwiKTtcbiAgICB9XG4gICAgZm9yIChsZXQgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgYnVmZmVyLmxlbmd0aDsgb2Zmc2V0ICs9IERCRlNfUFVUX01BWF9CWVRFUykge1xuICAgICAgY29uc3Qgc2xpY2UgPSBidWZmZXIuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBEQkZTX1BVVF9NQVhfQllURVMpO1xuICAgICAgYXdhaXQgdGhpcy5jbGllbnQuZGJmcy5hZGRCbG9jayh7XG4gICAgICAgIGhhbmRsZSxcbiAgICAgICAgZGF0YTogc2xpY2UudG9TdHJpbmcoXCJiYXNlNjRcIiksXG4gICAgICB9KTtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5jbGllbnQuZGJmcy5jbG9zZSh7IGhhbmRsZSB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgd3JpdGVXb3Jrc3BhY2VGaWxlKFxuICAgIGFic29sdXRlUGF0aDogc3RyaW5nLFxuICAgIGJ1ZmZlcjogQnVmZmVyLFxuICAgIG92ZXJ3cml0ZTogYm9vbGVhbixcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5jbGllbnQud29ya3NwYWNlLmltcG9ydCh7XG4gICAgICBwYXRoOiBhYnNvbHV0ZVBhdGgsXG4gICAgICBmb3JtYXQ6IFwiQVVUT1wiLFxuICAgICAgY29udGVudDogYnVmZmVyLnRvU3RyaW5nKFwiYmFzZTY0XCIpLFxuICAgICAgb3ZlcndyaXRlLFxuICAgIH0pO1xuICB9XG5cbiAgLyogLS0tIE1hc3RyYUZpbGVzeXN0ZW0gQVBJIC0tLSAqL1xuXG4gIGdldEluZm8oKTogRmlsZXN5c3RlbUluZm88eyBiYXNlUGF0aDogc3RyaW5nIH0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICBwcm92aWRlcjogdGhpcy5wcm92aWRlcixcbiAgICAgIHN0YXR1czogdGhpcy5zdGF0dXMsXG4gICAgICByZWFkT25seTogdGhpcy5yZWFkT25seSxcbiAgICAgIG1ldGFkYXRhOiB7IGJhc2VQYXRoOiB0aGlzLmJhc2VQYXRoIH0sXG4gICAgfTtcbiAgfVxuXG4gIGdldEluc3RydWN0aW9ucygpOiBzdHJpbmcge1xuICAgIHJldHVybiBbXG4gICAgICBgRmlsZXMgbGl2ZSBpbiBEYXRhYnJpY2tzIHVuZGVyICR7dGhpcy5iYXNlUGF0aH0uYCxcbiAgICAgIFwiV29ya3NwYWNlIHBhdGhzIGFyZSBhYnNvbHV0ZSB3aXRoaW4gdGhpcyByb290IChmb3IgZXhhbXBsZSBgL25vdGVzL3JlcG9ydC5tZGApLlwiLFxuICAgICAgXCJXb3Jrc3BhY2UgcGF0aHMgdXNlIGAvV29ya3NwYWNlLy4uLmAsIGAvVXNlcnMvLi4uYCwgb3IgYC9SZXBvcy8uLi5gIGJhc2UgcGF0aHMuXCIsXG4gICAgICBcIlVuaXR5IENhdGFsb2cgdm9sdW1lcyB1c2UgYC9Wb2x1bWVzLzxjYXRhbG9nPi88c2NoZW1hPi88dm9sdW1lPi8uLi5gIGJhc2UgcGF0aHMuXCIsXG4gICAgXS5qb2luKFwiIFwiKTtcbiAgfVxuXG4gIC8qKiBNYXAgYSB3b3Jrc3BhY2UtcmVsYXRpdmUgcGF0aCB0byB0aGUgYmFja2luZyBEYXRhYnJpY2tzIGFic29sdXRlIHBhdGguICovXG4gIHJlc29sdmVBYnNvbHV0ZVBhdGgoaW5wdXRQYXRoOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnJlc29sdmVQYXRoKGlucHV0UGF0aCk7XG4gIH1cblxuICAvKiogUmVhZCBmaWxlIGNvbnRlbnRzIGZyb20gdGhlIHdvcmtzcGFjZSBuYW1lc3BhY2UuICovXG4gIGFzeW5jIHJlYWRGaWxlKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogUmVhZE9wdGlvbnMpOiBQcm9taXNlPHN0cmluZyB8IEJ1ZmZlcj4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICBjb25zdCBlbXB0eSA9IGF3YWl0IHRoaXMuZW1wdHlGYWxsYmFjaygpO1xuICAgIGlmIChlbXB0eSkgcmV0dXJuIGVtcHR5LnJlYWRGaWxlKGlucHV0UGF0aCwgb3B0aW9ucyk7XG4gICAgY29uc3QgYWJzb2x1dGVQYXRoID0gdGhpcy5yZXNvbHZlUGF0aChpbnB1dFBhdGgpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBidWZmZXIgPSBhd2FpdCB0aGlzLnJlYWRBYnNvbHV0ZShhYnNvbHV0ZVBhdGgpO1xuICAgICAgcmV0dXJuIGZvcm1hdFJlYWRSZXN1bHQoYnVmZmVyLCBvcHRpb25zPy5lbmNvZGluZyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLnJldGhyb3coZXJyLCBpbnB1dFBhdGgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBXcml0ZSBmaWxlIGNvbnRlbnRzIGludG8gdGhlIHdvcmtzcGFjZSBuYW1lc3BhY2UuICovXG4gIGFzeW5jIHdyaXRlRmlsZShpbnB1dFBhdGg6IHN0cmluZywgY29udGVudDogRmlsZUNvbnRlbnQsIG9wdGlvbnM/OiBXcml0ZU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KCk7XG4gICAgY29uc3QgZW1wdHkgPSBhd2FpdCB0aGlzLmVtcHR5RmFsbGJhY2soKTtcbiAgICBpZiAoZW1wdHkpIHJldHVybiBlbXB0eS53cml0ZUZpbGUoaW5wdXRQYXRoLCBjb250ZW50LCBvcHRpb25zKTtcbiAgICB0aGlzLmFzc2VydFdyaXRhYmxlKFwid3JpdGVGaWxlXCIpO1xuICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHRoaXMucmVzb2x2ZVBhdGgoaW5wdXRQYXRoKTtcbiAgICBjb25zdCBidWZmZXIgPSB0b0J1ZmZlcihjb250ZW50KTtcbiAgICBjb25zdCBvdmVyd3JpdGUgPSBvcHRpb25zPy5vdmVyd3JpdGUgPz8gdHJ1ZTtcbiAgICB0cnkge1xuICAgICAgaWYgKCFvdmVyd3JpdGUgJiYgKGF3YWl0IHRoaXMuZXhpc3RzKGlucHV0UGF0aCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBGaWxlRXhpc3RzRXJyb3IoaW5wdXRQYXRoKTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHRoaXMud3JpdGVBYnNvbHV0ZShhYnNvbHV0ZVBhdGgsIGJ1ZmZlciwgb3ZlcndyaXRlKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBGaWxlRXhpc3RzRXJyb3IpIHRocm93IGVycjtcbiAgICAgIHRoaXMucmV0aHJvdyhlcnIsIGlucHV0UGF0aCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEFwcGVuZCB0byBhbiBleGlzdGluZyBmaWxlLCBjcmVhdGluZyBpdCB3aGVuIG1pc3NpbmcuICovXG4gIGFzeW5jIGFwcGVuZEZpbGUoaW5wdXRQYXRoOiBzdHJpbmcsIGNvbnRlbnQ6IEZpbGVDb250ZW50KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpO1xuICAgIGNvbnN0IGVtcHR5ID0gYXdhaXQgdGhpcy5lbXB0eUZhbGxiYWNrKCk7XG4gICAgaWYgKGVtcHR5KSByZXR1cm4gZW1wdHkuYXBwZW5kRmlsZShpbnB1dFBhdGgsIGNvbnRlbnQpO1xuICAgIHRoaXMuYXNzZXJ0V3JpdGFibGUoXCJhcHBlbmRGaWxlXCIpO1xuICAgIGNvbnN0IGV4aXN0aW5nID0gKGF3YWl0IHRoaXMuZXhpc3RzKGlucHV0UGF0aCkpXG4gICAgICA/IGF3YWl0IHRoaXMucmVhZEZpbGUoaW5wdXRQYXRoKVxuICAgICAgOiBCdWZmZXIuYWxsb2MoMCk7XG4gICAgY29uc3QgbWVyZ2VkID0gQnVmZmVyLmNvbmNhdChbXG4gICAgICBCdWZmZXIuaXNCdWZmZXIoZXhpc3RpbmcpID8gZXhpc3RpbmcgOiBCdWZmZXIuZnJvbShleGlzdGluZywgXCJ1dGY4XCIpLFxuICAgICAgdG9CdWZmZXIoY29udGVudCksXG4gICAgXSk7XG4gICAgYXdhaXQgdGhpcy53cml0ZUZpbGUoaW5wdXRQYXRoLCBtZXJnZWQsIHsgb3ZlcndyaXRlOiB0cnVlIH0pO1xuICB9XG5cbiAgLyoqIERlbGV0ZSBhIGZpbGUgaW4gdGhlIHdvcmtzcGFjZSBuYW1lc3BhY2UuICovXG4gIGFzeW5jIGRlbGV0ZUZpbGUoaW5wdXRQYXRoOiBzdHJpbmcsIG9wdGlvbnM/OiBSZW1vdmVPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpO1xuICAgIGNvbnN0IGVtcHR5ID0gYXdhaXQgdGhpcy5lbXB0eUZhbGxiYWNrKCk7XG4gICAgaWYgKGVtcHR5KSByZXR1cm4gZW1wdHkuZGVsZXRlRmlsZShpbnB1dFBhdGgsIG9wdGlvbnMpO1xuICAgIHRoaXMuYXNzZXJ0V3JpdGFibGUoXCJkZWxldGVGaWxlXCIpO1xuICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHRoaXMucmVzb2x2ZVBhdGgoaW5wdXRQYXRoKTtcbiAgICB0cnkge1xuICAgICAgaWYgKCEoYXdhaXQgdGhpcy5leGlzdHMoaW5wdXRQYXRoKSkpIHtcbiAgICAgICAgaWYgKG9wdGlvbnM/LmZvcmNlKSByZXR1cm47XG4gICAgICAgIHRocm93IG5ldyBGaWxlTm90Rm91bmRFcnJvcihpbnB1dFBhdGgpO1xuICAgICAgfVxuICAgICAgY29uc3QgZW50cnkgPSBhd2FpdCB0aGlzLnN0YXQoaW5wdXRQYXRoKTtcbiAgICAgIGlmIChlbnRyeS50eXBlID09PSBcImRpcmVjdG9yeVwiKSB7XG4gICAgICAgIHRocm93IG5ldyBJc0RpcmVjdG9yeUVycm9yKGlucHV0UGF0aCk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmRlbGV0ZUFic29sdXRlRmlsZShhYnNvbHV0ZVBhdGgpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEZpbGVOb3RGb3VuZEVycm9yIHx8IGVyciBpbnN0YW5jZW9mIElzRGlyZWN0b3J5RXJyb3IpIHRocm93IGVycjtcbiAgICAgIHRoaXMucmV0aHJvdyhlcnIsIGlucHV0UGF0aCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIENvcHkgYSBmaWxlIHdpdGhpbiB0aGUgd29ya3NwYWNlIG5hbWVzcGFjZS4gKi9cbiAgYXN5bmMgY29weUZpbGUoc3JjOiBzdHJpbmcsIGRlc3Q6IHN0cmluZywgb3B0aW9ucz86IENvcHlPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpO1xuICAgIGNvbnN0IGVtcHR5ID0gYXdhaXQgdGhpcy5lbXB0eUZhbGxiYWNrKCk7XG4gICAgaWYgKGVtcHR5KSByZXR1cm4gZW1wdHkuY29weUZpbGUoc3JjLCBkZXN0LCBvcHRpb25zKTtcbiAgICB0aGlzLmFzc2VydFdyaXRhYmxlKFwiY29weUZpbGVcIik7XG4gICAgY29uc3Qgb3ZlcndyaXRlID0gb3B0aW9ucz8ub3ZlcndyaXRlID8/IHRydWU7XG4gICAgaWYgKCFvdmVyd3JpdGUgJiYgKGF3YWl0IHRoaXMuZXhpc3RzKGRlc3QpKSkge1xuICAgICAgdGhyb3cgbmV3IEZpbGVFeGlzdHNFcnJvcihkZXN0KTtcbiAgICB9XG4gICAgY29uc3QgY29udGVudCA9IGF3YWl0IHRoaXMucmVhZEZpbGUoc3JjKTtcbiAgICBhd2FpdCB0aGlzLndyaXRlRmlsZShkZXN0LCBjb250ZW50LCB7IG92ZXJ3cml0ZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIC8qKiBNb3ZlIG9yIHJlbmFtZSBhIGZpbGUgd2l0aGluIHRoZSB3b3Jrc3BhY2UgbmFtZXNwYWNlLiAqL1xuICBhc3luYyBtb3ZlRmlsZShzcmM6IHN0cmluZywgZGVzdDogc3RyaW5nLCBvcHRpb25zPzogQ29weU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KCk7XG4gICAgY29uc3QgZW1wdHkgPSBhd2FpdCB0aGlzLmVtcHR5RmFsbGJhY2soKTtcbiAgICBpZiAoZW1wdHkpIHJldHVybiBlbXB0eS5tb3ZlRmlsZShzcmMsIGRlc3QsIG9wdGlvbnMpO1xuICAgIHRoaXMuYXNzZXJ0V3JpdGFibGUoXCJtb3ZlRmlsZVwiKTtcbiAgICBjb25zdCBzcmNBYnNvbHV0ZSA9IHRoaXMucmVzb2x2ZVBhdGgoc3JjKTtcbiAgICBjb25zdCBkZXN0QWJzb2x1dGUgPSB0aGlzLnJlc29sdmVQYXRoKGRlc3QpO1xuICAgIGNvbnN0IG92ZXJ3cml0ZSA9IG9wdGlvbnM/Lm92ZXJ3cml0ZSA/PyB0cnVlO1xuICAgIHRyeSB7XG4gICAgICBpZiAoIW92ZXJ3cml0ZSAmJiAoYXdhaXQgdGhpcy5leGlzdHMoZGVzdCkpKSB7XG4gICAgICAgIHRocm93IG5ldyBGaWxlRXhpc3RzRXJyb3IoZGVzdCk7XG4gICAgICB9XG4gICAgICBpZiAoXG4gICAgICAgIHJlc29sdmVGaWxlc0JhY2tlbmQoc3JjQWJzb2x1dGUpID09PSBcImRiZnNcIiAmJlxuICAgICAgICByZXNvbHZlRmlsZXNCYWNrZW5kKGRlc3RBYnNvbHV0ZSkgPT09IFwiZGJmc1wiXG4gICAgICApIHtcbiAgICAgICAgYXdhaXQgdGhpcy5jbGllbnQuZGJmcy5tb3ZlKHtcbiAgICAgICAgICBzb3VyY2VfcGF0aDogc3JjQWJzb2x1dGUsXG4gICAgICAgICAgZGVzdGluYXRpb25fcGF0aDogZGVzdEFic29sdXRlLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgYXdhaXQgdGhpcy5jb3B5RmlsZShzcmMsIGRlc3QsIHsgb3ZlcndyaXRlOiB0cnVlIH0pO1xuICAgICAgYXdhaXQgdGhpcy5kZWxldGVGaWxlKHNyYywgeyBmb3JjZTogdHJ1ZSB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBGaWxlRXhpc3RzRXJyb3IpIHRocm93IGVycjtcbiAgICAgIHRoaXMucmV0aHJvdyhlcnIsIGRlc3QpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBDcmVhdGUgYSBkaXJlY3RvcnkgaW4gdGhlIHdvcmtzcGFjZSBuYW1lc3BhY2UuICovXG4gIGFzeW5jIG1rZGlyKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogeyByZWN1cnNpdmU/OiBib29sZWFuIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KCk7XG4gICAgY29uc3QgZW1wdHkgPSBhd2FpdCB0aGlzLmVtcHR5RmFsbGJhY2soKTtcbiAgICBpZiAoZW1wdHkpIHJldHVybiBlbXB0eS5ta2RpcihpbnB1dFBhdGgsIG9wdGlvbnMpO1xuICAgIHRoaXMuYXNzZXJ0V3JpdGFibGUoXCJta2RpclwiKTtcbiAgICBjb25zdCBhYnNvbHV0ZVBhdGggPSB0aGlzLnJlc29sdmVQYXRoKGlucHV0UGF0aCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMubWtkaXJBYnNvbHV0ZShhYnNvbHV0ZVBhdGgpO1xuICAgICAgaWYgKCFvcHRpb25zPy5yZWN1cnNpdmUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5yZXRocm93KGVyciwgaW5wdXRQYXRoKTtcbiAgICB9XG4gIH1cblxuICAvKiogUmVtb3ZlIGEgZGlyZWN0b3J5IGZyb20gdGhlIHdvcmtzcGFjZSBuYW1lc3BhY2UuICovXG4gIGFzeW5jIHJtZGlyKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogUmVtb3ZlT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICBjb25zdCBlbXB0eSA9IGF3YWl0IHRoaXMuZW1wdHlGYWxsYmFjaygpO1xuICAgIGlmIChlbXB0eSkgcmV0dXJuIGVtcHR5LnJtZGlyKGlucHV0UGF0aCwgb3B0aW9ucyk7XG4gICAgdGhpcy5hc3NlcnRXcml0YWJsZShcInJtZGlyXCIpO1xuICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHRoaXMucmVzb2x2ZVBhdGgoaW5wdXRQYXRoKTtcbiAgICB0cnkge1xuICAgICAgaWYgKCEoYXdhaXQgdGhpcy5leGlzdHMoaW5wdXRQYXRoKSkpIHtcbiAgICAgICAgaWYgKG9wdGlvbnM/LmZvcmNlKSByZXR1cm47XG4gICAgICAgIHRocm93IG5ldyBEaXJlY3RvcnlOb3RGb3VuZEVycm9yKGlucHV0UGF0aCk7XG4gICAgICB9XG4gICAgICBjb25zdCBlbnRyeSA9IGF3YWl0IHRoaXMuc3RhdChpbnB1dFBhdGgpO1xuICAgICAgaWYgKGVudHJ5LnR5cGUgIT09IFwiZGlyZWN0b3J5XCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IE5vdERpcmVjdG9yeUVycm9yKGlucHV0UGF0aCk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmRlbGV0ZUFic29sdXRlUGF0aChhYnNvbHV0ZVBhdGgsIG9wdGlvbnM/LnJlY3Vyc2l2ZSA/PyBmYWxzZSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoXG4gICAgICAgIGVyciBpbnN0YW5jZW9mIERpcmVjdG9yeU5vdEZvdW5kRXJyb3IgfHxcbiAgICAgICAgZXJyIGluc3RhbmNlb2YgTm90RGlyZWN0b3J5RXJyb3IgfHxcbiAgICAgICAgZXJyIGluc3RhbmNlb2YgRGlyZWN0b3J5Tm90RW1wdHlFcnJvclxuICAgICAgKSB7XG4gICAgICAgIHRocm93IGVycjtcbiAgICAgIH1cbiAgICAgIHRoaXMucmV0aHJvdyhlcnIsIGlucHV0UGF0aCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlY3Vyc2l2ZWx5IGRlbGV0ZSBhIFVuaXR5IENhdGFsb2cgZGlyZWN0b3J5IHRyZWUuXG4gICAqXG4gICAqIERCRlMgYW5kIHdvcmtzcGFjZSB0cmVlcyB1c2UgbmF0aXZlIHJlY3Vyc2l2ZSBkZWxldGUgdmlhXG4gICAqIHtAbGluayBkZWxldGVBYnNvbHV0ZVBhdGh9IGluc3RlYWQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGRlbGV0ZVVjRGlyZWN0b3J5UmVjdXJzaXZlKGFic29sdXRlUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiBhd2FpdCB0aGlzLmxpc3RBYnNvbHV0ZURpcmVjdG9yeShhYnNvbHV0ZVBhdGgpKSB7XG4gICAgICBjb25zdCBjaGlsZEFic29sdXRlID0gcGF0aC5qb2luKGFic29sdXRlUGF0aCwgY2hpbGQubmFtZSk7XG4gICAgICBpZiAoY2hpbGQudHlwZSA9PT0gXCJkaXJlY3RvcnlcIikge1xuICAgICAgICBhd2FpdCB0aGlzLmRlbGV0ZVVjRGlyZWN0b3J5UmVjdXJzaXZlKGNoaWxkQWJzb2x1dGUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5kZWxldGVBYnNvbHV0ZUZpbGUoY2hpbGRBYnNvbHV0ZSk7XG4gICAgICB9XG4gICAgfVxuICAgIGF3YWl0IHRoaXMuY2xpZW50LmZpbGVzLmRlbGV0ZURpcmVjdG9yeSh7IGRpcmVjdG9yeV9wYXRoOiBhYnNvbHV0ZVBhdGggfSk7XG4gIH1cblxuICAvKiAtLS0gZGlyZWN0b3J5IGxpc3RpbmcgLS0tICovXG5cbiAgLyoqIExpc3QgZW50cmllcyBpbiBhIHdvcmtzcGFjZSBkaXJlY3RvcnkuICovXG4gIGFzeW5jIHJlYWRkaXIoaW5wdXRQYXRoOiBzdHJpbmcsIG9wdGlvbnM/OiBMaXN0T3B0aW9ucyk6IFByb21pc2U8RmlsZUVudHJ5W10+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KCk7XG4gICAgY29uc3QgZW1wdHkgPSBhd2FpdCB0aGlzLmVtcHR5RmFsbGJhY2soKTtcbiAgICBpZiAoZW1wdHkpIHJldHVybiBlbXB0eS5yZWFkZGlyKGlucHV0UGF0aCwgb3B0aW9ucyk7XG4gICAgY29uc3QgYWJzb2x1dGVQYXRoID0gdGhpcy5yZXNvbHZlUGF0aChpbnB1dFBhdGgpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgdGhpcy5saXN0QWJzb2x1dGVEaXJlY3RvcnkoYWJzb2x1dGVQYXRoKTtcbiAgICAgIGNvbnN0IGZpbHRlcmVkID0gdGhpcy5maWx0ZXJFbnRyaWVzKGVudHJpZXMsIG9wdGlvbnMpO1xuICAgICAgaWYgKCFvcHRpb25zPy5yZWN1cnNpdmUpIHJldHVybiBmaWx0ZXJlZDtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJlYWREaXJlY3RvcnlSZWN1cnNpdmUoYWJzb2x1dGVQYXRoLCBvcHRpb25zLCAwKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMucmV0aHJvdyhlcnIsIGlucHV0UGF0aCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWFkRGlyZWN0b3J5UmVjdXJzaXZlKFxuICAgIGFic29sdXRlUGF0aDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IExpc3RPcHRpb25zLFxuICAgIGRlcHRoOiBudW1iZXIsXG4gICAgcmVsYXRpdmVQcmVmaXggPSBcIlwiLFxuICApOiBQcm9taXNlPEZpbGVFbnRyeVtdPiB7XG4gICAgY29uc3QgbWF4RGVwdGggPSBvcHRpb25zLm1heERlcHRoID8/IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICBjb25zdCBlbnRyaWVzID0gdGhpcy5maWx0ZXJFbnRyaWVzKGF3YWl0IHRoaXMubGlzdEFic29sdXRlRGlyZWN0b3J5KGFic29sdXRlUGF0aCksIG9wdGlvbnMpO1xuICAgIGNvbnN0IGNvbGxlY3RlZDogRmlsZUVudHJ5W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMpIHtcbiAgICAgIGNvbnN0IHJlbGF0aXZlTmFtZSA9IHJlbGF0aXZlUHJlZml4ID8gcGF0aC5qb2luKHJlbGF0aXZlUHJlZml4LCBlbnRyeS5uYW1lKSA6IGVudHJ5Lm5hbWU7XG4gICAgICBjb2xsZWN0ZWQucHVzaCh7IC4uLmVudHJ5LCBuYW1lOiByZWxhdGl2ZU5hbWUgfSk7XG4gICAgICBpZiAoZW50cnkudHlwZSAhPT0gXCJkaXJlY3RvcnlcIiB8fCBkZXB0aCA+PSBtYXhEZXB0aCkgY29udGludWU7XG4gICAgICBjb2xsZWN0ZWQucHVzaChcbiAgICAgICAgLi4uKGF3YWl0IHRoaXMucmVhZERpcmVjdG9yeVJlY3Vyc2l2ZShcbiAgICAgICAgICBwYXRoLmpvaW4oYWJzb2x1dGVQYXRoLCBlbnRyeS5uYW1lKSxcbiAgICAgICAgICBvcHRpb25zLFxuICAgICAgICAgIGRlcHRoICsgMSxcbiAgICAgICAgICByZWxhdGl2ZU5hbWUsXG4gICAgICAgICkpLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIGNvbGxlY3RlZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbGlzdEFic29sdXRlRGlyZWN0b3J5KGFic29sdXRlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxGaWxlRW50cnlbXT4ge1xuICAgIHJldHVybiBkaXNwYXRjaEZpbGVzQmFja2VuZChhYnNvbHV0ZVBhdGgsIHtcbiAgICAgIGRiZnM6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgZW50cmllczogRmlsZUVudHJ5W10gPSBbXTtcbiAgICAgICAgZm9yIGF3YWl0IChjb25zdCBpbmZvIG9mIHRoaXMuY2xpZW50LmRiZnMubGlzdCh7IHBhdGg6IGFic29sdXRlUGF0aCB9KSkge1xuICAgICAgICAgIGVudHJpZXMucHVzaCh7XG4gICAgICAgICAgICBuYW1lOiBwYXRoLmJhc2VuYW1lKGluZm8ucGF0aCA/PyBcIlwiKSxcbiAgICAgICAgICAgIHR5cGU6IGluZm8uaXNfZGlyID8gXCJkaXJlY3RvcnlcIiA6IFwiZmlsZVwiLFxuICAgICAgICAgICAgc2l6ZTogaW5mby5maWxlX3NpemUsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVudHJpZXM7XG4gICAgICB9LFxuICAgICAgd29ya3NwYWNlOiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IGVudHJpZXM6IEZpbGVFbnRyeVtdID0gW107XG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgaW5mbyBvZiB0aGlzLmNsaWVudC53b3Jrc3BhY2UubGlzdCh7IHBhdGg6IGFic29sdXRlUGF0aCB9KSkge1xuICAgICAgICAgIGVudHJpZXMucHVzaCh7XG4gICAgICAgICAgICBuYW1lOiBwYXRoLmJhc2VuYW1lKGluZm8ucGF0aCA/PyBcIlwiKSxcbiAgICAgICAgICAgIHR5cGU6IGluZm8ub2JqZWN0X3R5cGUgPT09IFwiRElSRUNUT1JZXCIgPyBcImRpcmVjdG9yeVwiIDogXCJmaWxlXCIsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVudHJpZXM7XG4gICAgICB9LFxuICAgICAgdWNGaWxlczogYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBlbnRyaWVzOiBGaWxlRW50cnlbXSA9IFtdO1xuICAgICAgICBmb3IgYXdhaXQgKGNvbnN0IGVudHJ5IG9mIHRoaXMuY2xpZW50LmZpbGVzLmxpc3REaXJlY3RvcnlDb250ZW50cyh7XG4gICAgICAgICAgZGlyZWN0b3J5X3BhdGg6IGFic29sdXRlUGF0aCxcbiAgICAgICAgfSkpIHtcbiAgICAgICAgICBlbnRyaWVzLnB1c2goe1xuICAgICAgICAgICAgbmFtZTogZW50cnkubmFtZSA/PyBwYXRoLmJhc2VuYW1lKGVudHJ5LnBhdGggPz8gXCJcIiksXG4gICAgICAgICAgICB0eXBlOiBlbnRyeS5pc19kaXJlY3RvcnkgPyBcImRpcmVjdG9yeVwiIDogXCJmaWxlXCIsXG4gICAgICAgICAgICBzaXplOiBlbnRyeS5maWxlX3NpemUsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVudHJpZXM7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIEFwcGx5IE1hc3RyYSBsaXN0IGZpbHRlcnMgKGBleHRlbnNpb25gLCBldGMuKSB0byBkaXJlY3RvcnkgZW50cmllcy4gKi9cbiAgcHJpdmF0ZSBmaWx0ZXJFbnRyaWVzKGVudHJpZXM6IEZpbGVFbnRyeVtdLCBvcHRpb25zPzogTGlzdE9wdGlvbnMpOiBGaWxlRW50cnlbXSB7XG4gICAgaWYgKCFvcHRpb25zPy5leHRlbnNpb24pIHJldHVybiBlbnRyaWVzO1xuICAgIGNvbnN0IGV4dGVuc2lvbnMgPSBBcnJheS5pc0FycmF5KG9wdGlvbnMuZXh0ZW5zaW9uKSA/IG9wdGlvbnMuZXh0ZW5zaW9uIDogW29wdGlvbnMuZXh0ZW5zaW9uXTtcbiAgICBjb25zdCBub3JtYWxpemVkID0gZXh0ZW5zaW9ucy5tYXAoKGV4dCkgPT5cbiAgICAgIGV4dC5zdGFydHNXaXRoKFwiLlwiKSA/IGV4dC50b0xvd2VyQ2FzZSgpIDogYC4ke2V4dC50b0xvd2VyQ2FzZSgpfWAsXG4gICAgKTtcbiAgICByZXR1cm4gZW50cmllcy5maWx0ZXIoKGVudHJ5KSA9PiB7XG4gICAgICBpZiAoZW50cnkudHlwZSAhPT0gXCJmaWxlXCIpIHJldHVybiB0cnVlO1xuICAgICAgY29uc3QgbG93ZXIgPSBlbnRyeS5uYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICByZXR1cm4gbm9ybWFsaXplZC5zb21lKChleHQpID0+IGxvd2VyLmVuZHNXaXRoKGV4dCkpO1xuICAgIH0pO1xuICB9XG5cbiAgLyogLS0tIG1ldGFkYXRhIC0tLSAqL1xuXG4gIC8qKiBSZXR1cm4gd2hldGhlciBgaW5wdXRQYXRoYCBleGlzdHMgaW4gdGhlIHdvcmtzcGFjZSBuYW1lc3BhY2UuICovXG4gIGFzeW5jIGV4aXN0cyhpbnB1dFBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICBjb25zdCBlbXB0eSA9IGF3YWl0IHRoaXMuZW1wdHlGYWxsYmFjaygpO1xuICAgIGlmIChlbXB0eSkgcmV0dXJuIGVtcHR5LmV4aXN0cyhpbnB1dFBhdGgpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLnN0YXQoaW5wdXRQYXRoKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgaWYgKGVyciBpbnN0YW5jZW9mIEZpbGVOb3RGb3VuZEVycm9yKSByZXR1cm4gZmFsc2U7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICB9XG5cbiAgLyoqIFJldHVybiBmaWxlIG9yIGRpcmVjdG9yeSBtZXRhZGF0YSBmb3IgYGlucHV0UGF0aGAuICovXG4gIGFzeW5jIHN0YXQoaW5wdXRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPEZpbGVTdGF0PiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpO1xuICAgIGNvbnN0IGVtcHR5ID0gYXdhaXQgdGhpcy5lbXB0eUZhbGxiYWNrKCk7XG4gICAgaWYgKGVtcHR5KSByZXR1cm4gZW1wdHkuc3RhdChpbnB1dFBhdGgpO1xuICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHRoaXMucmVzb2x2ZVBhdGgoaW5wdXRQYXRoKTtcbiAgICBjb25zdCB3b3Jrc3BhY2VQYXRoID0gdGhpcy53b3Jrc3BhY2VQYXRoKGFic29sdXRlUGF0aCk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBkaXNwYXRjaEZpbGVzQmFja2VuZChhYnNvbHV0ZVBhdGgsIHtcbiAgICAgICAgZGJmczogYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGluZm8gPSBhd2FpdCB0aGlzLmNsaWVudC5kYmZzLmdldFN0YXR1cyh7IHBhdGg6IGFic29sdXRlUGF0aCB9KTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbmFtZTogcGF0aC5iYXNlbmFtZShpbmZvLnBhdGggPz8gYWJzb2x1dGVQYXRoKSxcbiAgICAgICAgICAgIHBhdGg6IHdvcmtzcGFjZVBhdGgsXG4gICAgICAgICAgICB0eXBlOiBpbmZvLmlzX2RpciA/IChcImRpcmVjdG9yeVwiIGFzIGNvbnN0KSA6IChcImZpbGVcIiBhcyBjb25zdCksXG4gICAgICAgICAgICBzaXplOiBpbmZvLmZpbGVfc2l6ZSA/PyAwLFxuICAgICAgICAgICAgY3JlYXRlZEF0OiBuZXcgRGF0ZShpbmZvLm1vZGlmaWNhdGlvbl90aW1lID8/IDApLFxuICAgICAgICAgICAgbW9kaWZpZWRBdDogbmV3IERhdGUoaW5mby5tb2RpZmljYXRpb25fdGltZSA/PyAwKSxcbiAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgICB3b3Jrc3BhY2U6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBpbmZvID0gYXdhaXQgdGhpcy5jbGllbnQud29ya3NwYWNlLmdldFN0YXR1cyh7IHBhdGg6IGFic29sdXRlUGF0aCB9KTtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbmFtZTogcGF0aC5iYXNlbmFtZShpbmZvLnBhdGggPz8gYWJzb2x1dGVQYXRoKSxcbiAgICAgICAgICAgIHBhdGg6IHdvcmtzcGFjZVBhdGgsXG4gICAgICAgICAgICB0eXBlOiBpbmZvLm9iamVjdF90eXBlID09PSBcIkRJUkVDVE9SWVwiID8gKFwiZGlyZWN0b3J5XCIgYXMgY29uc3QpIDogKFwiZmlsZVwiIGFzIGNvbnN0KSxcbiAgICAgICAgICAgIHNpemU6IDAsXG4gICAgICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKGluZm8uY3JlYXRlZF9hdCA/PyAwKSxcbiAgICAgICAgICAgIG1vZGlmaWVkQXQ6IG5ldyBEYXRlKGluZm8ubW9kaWZpZWRfYXQgPz8gMCksXG4gICAgICAgICAgfTtcbiAgICAgICAgfSxcbiAgICAgICAgdWNGaWxlczogKCkgPT4gdGhpcy5zdGF0VWNBYnNvbHV0ZShhYnNvbHV0ZVBhdGgsIHdvcmtzcGFjZVBhdGgsIGlucHV0UGF0aCksXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMucmV0aHJvdyhlcnIsIGlucHV0UGF0aCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFN0YXQgYSBVbml0eSBDYXRhbG9nIHBhdGggYnkgcHJvYmluZyBmaWxlIG1ldGFkYXRhIGZpcnN0LCB0aGVuXG4gICAqIGRpcmVjdG9yeSBtZXRhZGF0YS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgc3RhdFVjQWJzb2x1dGUoXG4gICAgYWJzb2x1dGVQYXRoOiBzdHJpbmcsXG4gICAgd29ya3NwYWNlUGF0aDogc3RyaW5nLFxuICAgIGlucHV0UGF0aDogc3RyaW5nLFxuICApOiBQcm9taXNlPEZpbGVTdGF0PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gYXdhaXQgdGhpcy5jbGllbnQuZmlsZXMuZ2V0TWV0YWRhdGEoe1xuICAgICAgICBmaWxlX3BhdGg6IGFic29sdXRlUGF0aCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogcGF0aC5iYXNlbmFtZShhYnNvbHV0ZVBhdGgpLFxuICAgICAgICBwYXRoOiB3b3Jrc3BhY2VQYXRoLFxuICAgICAgICB0eXBlOiBcImZpbGVcIiBhcyBjb25zdCxcbiAgICAgICAgc2l6ZTogTnVtYmVyKG1ldGFkYXRhW1wiY29udGVudC1sZW5ndGhcIl0gPz8gMCksXG4gICAgICAgIGNyZWF0ZWRBdDogcGFyc2VIdHRwRGF0ZShtZXRhZGF0YVtcImxhc3QtbW9kaWZpZWRcIl0pLFxuICAgICAgICBtb2RpZmllZEF0OiBwYXJzZUh0dHBEYXRlKG1ldGFkYXRhW1wibGFzdC1tb2RpZmllZFwiXSksXG4gICAgICAgIG1pbWVUeXBlOiBtZXRhZGF0YVtcImNvbnRlbnQtdHlwZVwiXSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZmlsZUVycikge1xuICAgICAgaWYgKCFlcnJvci5lcnJvckNvbnRleHQoZmlsZUVycikubm90QWNjZXNzaWJsZSkge1xuICAgICAgICB0aGlzLnJldGhyb3coZmlsZUVyciwgaW5wdXRQYXRoKTtcbiAgICAgIH1cbiAgICAgIGF3YWl0IHRoaXMuY2xpZW50LmZpbGVzLmdldERpcmVjdG9yeU1ldGFkYXRhKHtcbiAgICAgICAgZGlyZWN0b3J5X3BhdGg6IGFic29sdXRlUGF0aCxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogcGF0aC5iYXNlbmFtZShhYnNvbHV0ZVBhdGgpLFxuICAgICAgICBwYXRoOiB3b3Jrc3BhY2VQYXRoLFxuICAgICAgICB0eXBlOiBcImRpcmVjdG9yeVwiIGFzIGNvbnN0LFxuICAgICAgICBzaXplOiAwLFxuICAgICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKDApLFxuICAgICAgICBtb2RpZmllZEF0OiBuZXcgRGF0ZSgwKSxcbiAgICAgIH07XG4gICAgfVxuICB9XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBlbXB0eSBmaWxlc3lzdGVtIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKiogTm9ybWFsaXplIHBhdGhzIGZvciB0aGUgaW4tbWVtb3J5IGVtcHR5IGZpbGVzeXN0ZW0gbmFtZXNwYWNlLiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplRW1wdHlGaWxlc3lzdGVtUGF0aChpbnB1dFBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHRyaW1tZWQgPSBpbnB1dFBhdGgudHJpbSgpO1xuICBpZiAoIXRyaW1tZWQgfHwgdHJpbW1lZCA9PT0gXCIuXCIpIHJldHVybiBcIi9cIjtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IHRyaW1tZWQuc3RhcnRzV2l0aChcIi9cIilcbiAgICA/IHBhdGgubm9ybWFsaXplKHRyaW1tZWQpXG4gICAgOiBwYXRoLm5vcm1hbGl6ZShgLyR7dHJpbW1lZH1gKTtcbiAgcmV0dXJuIG5vcm1hbGl6ZWQgPT09IFwiLlwiID8gXCIvXCIgOiBub3JtYWxpemVkO1xufVxuXG4vKipcbiAqIFJlYWQtb25seSBpbi1tZW1vcnkge0BsaW5rIFdvcmtzcGFjZUZpbGVzeXN0ZW19IHdpdGggYSBzaW5nbGUgZW1wdHkgcm9vdC5cbiAqIFVzZSB7QGxpbmsgZW1wdHlGaWxlc3lzdGVtfSByYXRoZXIgdGhhbiBjb25zdHJ1Y3RpbmcgZGlyZWN0bHkuXG4gKi9cbmNsYXNzIEVtcHR5RmlsZXN5c3RlbSBleHRlbmRzIE1hc3RyYUZpbGVzeXN0ZW0ge1xuICByZWFkb25seSBpZCA9IFwiZW1wdHktZnNcIjtcbiAgcmVhZG9ubHkgbmFtZSA9IFwiRW1wdHlGaWxlc3lzdGVtXCI7XG4gIHJlYWRvbmx5IHByb3ZpZGVyID0gXCJlbXB0eVwiO1xuICByZWFkb25seSByZWFkT25seSA9IHRydWU7XG4gIHN0YXR1czogUHJvdmlkZXJTdGF0dXMgPSBcInBlbmRpbmdcIjtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcih7IG5hbWU6IFwiRW1wdHlGaWxlc3lzdGVtXCIgfSk7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBpbml0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIE5vIHJlbW90ZSBvciBvbi1kaXNrIHJlc291cmNlcyB0byBwcm92aXNpb24uXG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBkZXN0cm95KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIC8vIFN0YXRlbGVzczsgbm90aGluZyB0byByZWxlYXNlLlxuICB9XG5cbiAgZ2V0SW5mbygpOiBGaWxlc3lzdGVtSW5mbyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiB0aGlzLmlkLFxuICAgICAgbmFtZTogdGhpcy5uYW1lLFxuICAgICAgcHJvdmlkZXI6IHRoaXMucHJvdmlkZXIsXG4gICAgICBzdGF0dXM6IHRoaXMuc3RhdHVzLFxuICAgICAgcmVhZE9ubHk6IHRoaXMucmVhZE9ubHksXG4gICAgfTtcbiAgfVxuXG4gIGdldEluc3RydWN0aW9ucygpOiBzdHJpbmcge1xuICAgIHJldHVybiBcIlRoaXMgZmlsZXN5c3RlbSBpcyBlbXB0eSBhbmQgcmVhZC1vbmx5LlwiO1xuICB9XG5cbiAgcHJpdmF0ZSByb290U3RhdCgpOiBGaWxlU3RhdCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IFwiL1wiLFxuICAgICAgcGF0aDogXCIvXCIsXG4gICAgICB0eXBlOiBcImRpcmVjdG9yeVwiLFxuICAgICAgc2l6ZTogMCxcbiAgICAgIGNyZWF0ZWRBdDogRU1QVFlfRklMRVNZU1RFTV9FUE9DSCxcbiAgICAgIG1vZGlmaWVkQXQ6IEVNUFRZX0ZJTEVTWVNURU1fRVBPQ0gsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgYXNzZXJ0V3JpdGFibGUob3BlcmF0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aHJvdyBuZXcgV29ya3NwYWNlUmVhZE9ubHlFcnJvcihvcGVyYXRpb24pO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgcmVhZEZpbGUoaW5wdXRQYXRoOiBzdHJpbmcsIF9vcHRpb25zPzogUmVhZE9wdGlvbnMpOiBQcm9taXNlPHN0cmluZyB8IEJ1ZmZlcj4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplRW1wdHlGaWxlc3lzdGVtUGF0aChpbnB1dFBhdGgpO1xuICAgIGlmIChub3JtYWxpemVkID09PSBcIi9cIikge1xuICAgICAgdGhyb3cgbmV3IElzRGlyZWN0b3J5RXJyb3Iobm9ybWFsaXplZCk7XG4gICAgfVxuICAgIHRocm93IG5ldyBGaWxlTm90Rm91bmRFcnJvcihub3JtYWxpemVkKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHdyaXRlRmlsZShcbiAgICBfaW5wdXRQYXRoOiBzdHJpbmcsXG4gICAgX2NvbnRlbnQ6IEZpbGVDb250ZW50LFxuICAgIF9vcHRpb25zPzogV3JpdGVPcHRpb25zLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KCk7XG4gICAgdGhpcy5hc3NlcnRXcml0YWJsZShcIndyaXRlRmlsZVwiKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGFwcGVuZEZpbGUoX2lucHV0UGF0aDogc3RyaW5nLCBfY29udGVudDogRmlsZUNvbnRlbnQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KCk7XG4gICAgdGhpcy5hc3NlcnRXcml0YWJsZShcImFwcGVuZEZpbGVcIik7XG4gIH1cblxuICBvdmVycmlkZSBhc3luYyBkZWxldGVGaWxlKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogUmVtb3ZlT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplRW1wdHlGaWxlc3lzdGVtUGF0aChpbnB1dFBhdGgpO1xuICAgIGlmIChub3JtYWxpemVkID09PSBcIi9cIikge1xuICAgICAgdGhyb3cgbmV3IElzRGlyZWN0b3J5RXJyb3Iobm9ybWFsaXplZCk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zPy5mb3JjZSkgcmV0dXJuO1xuICAgIHRocm93IG5ldyBGaWxlTm90Rm91bmRFcnJvcihub3JtYWxpemVkKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGNvcHlGaWxlKHNyYzogc3RyaW5nLCBfZGVzdDogc3RyaW5nLCBfb3B0aW9ucz86IENvcHlPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpO1xuICAgIGNvbnN0IG5vcm1hbGl6ZWRTcmMgPSBub3JtYWxpemVFbXB0eUZpbGVzeXN0ZW1QYXRoKHNyYyk7XG4gICAgaWYgKG5vcm1hbGl6ZWRTcmMgIT09IFwiL1wiKSB7XG4gICAgICB0aHJvdyBuZXcgRmlsZU5vdEZvdW5kRXJyb3Iobm9ybWFsaXplZFNyYyk7XG4gICAgfVxuICAgIHRocm93IG5ldyBJc0RpcmVjdG9yeUVycm9yKG5vcm1hbGl6ZWRTcmMpO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgbW92ZUZpbGUoc3JjOiBzdHJpbmcsIGRlc3Q6IHN0cmluZywgb3B0aW9ucz86IENvcHlPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5jb3B5RmlsZShzcmMsIGRlc3QsIG9wdGlvbnMpO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgbWtkaXIoX2lucHV0UGF0aDogc3RyaW5nLCBfb3B0aW9ucz86IHsgcmVjdXJzaXZlPzogYm9vbGVhbiB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpO1xuICAgIHRoaXMuYXNzZXJ0V3JpdGFibGUoXCJta2RpclwiKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHJtZGlyKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogUmVtb3ZlT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICBjb25zdCBub3JtYWxpemVkID0gbm9ybWFsaXplRW1wdHlGaWxlc3lzdGVtUGF0aChpbnB1dFBhdGgpO1xuICAgIGlmIChub3JtYWxpemVkID09PSBcIi9cIikge1xuICAgICAgdGhyb3cgbmV3IERpcmVjdG9yeU5vdEVtcHR5RXJyb3Iobm9ybWFsaXplZCk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zPy5mb3JjZSkgcmV0dXJuO1xuICAgIHRocm93IG5ldyBEaXJlY3RvcnlOb3RGb3VuZEVycm9yKG5vcm1hbGl6ZWQpO1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgcmVhZGRpcihpbnB1dFBhdGg6IHN0cmluZywgX29wdGlvbnM/OiBMaXN0T3B0aW9ucyk6IFByb21pc2U8RmlsZUVudHJ5W10+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlYWR5KCk7XG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZUVtcHR5RmlsZXN5c3RlbVBhdGgoaW5wdXRQYXRoKTtcbiAgICBpZiAobm9ybWFsaXplZCA9PT0gXCIvXCIpIHJldHVybiBbXTtcbiAgICB0aHJvdyBuZXcgRGlyZWN0b3J5Tm90Rm91bmRFcnJvcihub3JtYWxpemVkKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGV4aXN0cyhpbnB1dFBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICByZXR1cm4gbm9ybWFsaXplRW1wdHlGaWxlc3lzdGVtUGF0aChpbnB1dFBhdGgpID09PSBcIi9cIjtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIHN0YXQoaW5wdXRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPEZpbGVTdGF0PiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZWFkeSgpO1xuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVFbXB0eUZpbGVzeXN0ZW1QYXRoKGlucHV0UGF0aCk7XG4gICAgaWYgKG5vcm1hbGl6ZWQgPT09IFwiL1wiKSByZXR1cm4gdGhpcy5yb290U3RhdCgpO1xuICAgIHRocm93IG5ldyBGaWxlTm90Rm91bmRFcnJvcihub3JtYWxpemVkKTtcbiAgfVxufVxuXG4vKiogTWVtb2l6ZWQgc2luZ2xldG9uIGVtcHR5IHJlYWQtb25seSBmaWxlc3lzdGVtIGZvciBuby1vcCBtb3VudHMuICovXG5leHBvcnQgY29uc3QgZW1wdHlGaWxlc3lzdGVtID0gZnVuY3Rpb25Nb2R1bGUubWVtb2l6ZSgoKSA9PiBuZXcgRW1wdHlGaWxlc3lzdGVtKCkpO1xuIl19
238
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZXN5c3RlbXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZmlsZXN5c3RlbXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7OztHQVNHO0FBRUgsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4QyxPQUFPLEVBQUUsZUFBZSxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBTWxFLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsc0JBQXNCLEVBQ3RCLGVBQWUsRUFDZixpQkFBaUIsRUFDakIsZ0JBQWdCLEVBQ2hCLGdCQUFnQixFQUNoQixpQkFBaUIsRUFDakIsZUFBZSxFQUNmLHNCQUFzQixHQUN2QixNQUFNLHdCQUF3QixDQUFDO0FBb0NoQzs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sVUFBVSxXQUFXLENBQ3pCLEVBQWMsRUFDZCxVQUEwQyxFQUFFO0lBRTVDLE9BQU8sSUFBSSx1QkFBdUIsQ0FBQyxFQUFFLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDbEQsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sdUJBQXdCLFNBQVEsZ0JBQWdCO0lBQzNELE1BQU0sR0FBbUIsU0FBUyxDQUFDO0lBRWxCLEVBQUUsQ0FBYTtJQUNmLE9BQU8sQ0FBaUM7SUFFekQsWUFBWSxFQUFjLEVBQUUsVUFBMEMsRUFBRTtRQUN0RSxLQUFLLENBQUM7WUFDSixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksSUFBSSx5QkFBeUI7WUFDL0MsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1lBQ3RCLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztTQUM3QixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztRQUNiLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ3pCLENBQUM7SUFFRCxJQUFJLEVBQUU7UUFDSixPQUFPLElBQUksQ0FBQyxPQUFP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QUksSUFBSSxDQUFDO1FBQ3BCLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxJQUFJLEtBQUs7UUFDbEMsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVLElBQUksS0FBSztRQUNwQyxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7S0FDeEIsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxzQkFBc0IsQ0FBQyxTQUFpQjtJQUMvQyxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzlDLE9BQU8sTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDO0FBQ3ZDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE1hc3RyYSB3b3Jrc3BhY2UgZmlsZXN5c3RlbSBhZGFwdGVycy5cbiAqXG4gKiB7QGxpbmsgZmlsZXN5c3RlbXN9IHdyYXBzIGFueSBwb3J0YWJsZSBgQGRieC10b29scy9zaGFyZWQtZnNgIHtAbGluayBGaWxlU3lzdGVtfVxuICogKGxvY2FsIGRpc2ssIERhdGFicmlja3MsIG1lbW9yeSwg4oCmKSBhcyBhIE1hc3RyYSB7QGxpbmsgTWFzdHJhRmlsZXN5c3RlbX0uXG4gKiB7QGxpbmsgc2NyYXRjaEZpbGVzeXN0ZW19IGFsd2F5cyByZXR1cm5zIGEgZnJlc2gge0BsaW5rIGxvY2FsRlMudG1wRlN9IG1vdW50XG4gKiAocmFuZG9tIGlkIHJvb3QpIHdoZW4gTWFzdHJhIG5lZWRzIGEgZmlsZXN5c3RlbSBhbmQgbm8gb3RoZXIgbW91bnQgcmVzb2x2ZWQuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGxvY2FsRlMgfSBmcm9tIFwiQGRieC10b29scy9mc1wiO1xuaW1wb3J0IHsgRmlsZVN5c3RlbUVycm9yLCBwb3NpeFBhdGggfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtZnNcIjtcbmltcG9ydCB0eXBlIHtcbiAgRmlsZUVudHJ5IGFzIFNoYXJlZEZpbGVFbnRyeSxcbiAgRmlsZVN0YXQgYXMgU2hhcmVkRmlsZVN0YXQsXG4gIEZpbGVTeXN0ZW0sXG59IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1mc1wiO1xuaW1wb3J0IHtcbiAgRGlyZWN0b3J5Tm90RW1wdHlFcnJvcixcbiAgRGlyZWN0b3J5Tm90Rm91bmRFcnJvcixcbiAgRmlsZUV4aXN0c0Vycm9yLFxuICBGaWxlTm90Rm91bmRFcnJvcixcbiAgSXNEaXJlY3RvcnlFcnJvcixcbiAgTWFzdHJhRmlsZXN5c3RlbSxcbiAgTm90RGlyZWN0b3J5RXJyb3IsXG4gIFBlcm1pc3Npb25FcnJvcixcbiAgV29ya3NwYWNlUmVhZE9ubHlFcnJvcixcbn0gZnJvbSBcIkBtYXN0cmEvY29yZS93b3Jrc3BhY2VcIjtcbmltcG9ydCB0eXBlIHtcbiAgQ29weU9wdGlvbnMsXG4gIEZpbGVDb250ZW50LFxuICBGaWxlRW50cnksXG4gIEZpbGVTdGF0LFxuICBGaWxlc3lzdGVtSW5mbyxcbiAgTGlzdE9wdGlvbnMsXG4gIE1hc3RyYUZpbGVzeXN0ZW1PcHRpb25zLFxuICBQcm92aWRlclN0YXR1cyxcbiAgUmVhZE9wdGlvbnMsXG4gIFJlbW92ZU9wdGlvbnMsXG4gIFdyaXRlT3B0aW9ucyxcbn0gZnJvbSBcIkBtYXN0cmEvY29yZS93b3Jrc3BhY2VcIjtcblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayBmaWxlc3lzdGVtc30gLyB7QGxpbmsgTWFzdHJhRmlsZVN5c3RlbUFkYXB0ZXJ9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBNYXN0cmFGaWxlU3lzdGVtQWRhcHRlck9wdGlvbnMgZXh0ZW5kcyBNYXN0cmFGaWxlc3lzdGVtT3B0aW9ucyB7XG4gIC8qKiBPdmVycmlkZSB0aGUgTWFzdHJhIGZpbGVzeXN0ZW0gaWQuIERlZmF1bHRzIHRvIHRoZSBzb3VyY2Uge0BsaW5rIEZpbGVTeXN0ZW0uaWR9LiAqL1xuICBpZD86IHN0cmluZztcblxuICAvKiogT3ZlcnJpZGUgdGhlIE1hc3RyYSBkaXNwbGF5IG5hbWUuIERlZmF1bHRzIHRvIGBNYXN0cmFGaWxlU3lzdGVtQWRhcHRlcmAuICovXG4gIG5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE92ZXJyaWRlIHRoZSBNYXN0cmEgcHJvdmlkZXIgaWQuIERlZmF1bHRzIHRvIHRoZSBzb3VyY2VcbiAgICoge0BsaW5rIEZpbGVTeXN0ZW0uYmFja2VuZH0uXG4gICAqL1xuICBwcm92aWRlcj86IHN0cmluZztcblxuICAvKipcbiAgICogRm9yY2UgcmVhZC1vbmx5IG1vdW50cyBldmVuIHdoZW4gdGhlIHNvdXJjZSBmaWxlc3lzdGVtIGFsbG93cyB3cml0ZXMuXG4gICAqIFRoZSBzb3VyY2Uge0BsaW5rIEZpbGVTeXN0ZW0ucmVhZE9ubHl9IGZsYWcgc3RpbGwgYXBwbGllcyBlaXRoZXIgd2F5LlxuICAgKi9cbiAgcmVhZE9ubHk/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFdyYXAgYSBwb3J0YWJsZSB7QGxpbmsgRmlsZVN5c3RlbX0gYXMgYSBNYXN0cmEge0BsaW5rIE1hc3RyYUZpbGVzeXN0ZW19LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c1xuICogaW1wb3J0IHsgZmlsZXN5c3RlbXMgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXQtbWFzdHJhXCI7XG4gKiBpbXBvcnQgeyBEYXRhYnJpY2tzRmlsZVN5c3RlbSB9IGZyb20gXCJAZGJ4LXRvb2xzL2RhdGFicmlja3NcIjtcbiAqIGltcG9ydCB7IGxvY2FsRlMgfSBmcm9tIFwiQGRieC10b29scy9mc1wiO1xuICpcbiAqIGNvbnN0IHZvbHVtZSA9IGZpbGVzeXN0ZW1zLmZpbGVzeXN0ZW1zKFxuICogICBuZXcgRGF0YWJyaWNrc0ZpbGVTeXN0ZW0oeyByb290OiBcIi9Wb2x1bWVzL21haW4vZGVmYXVsdC9hc3NldHNcIiB9KSxcbiAqICk7XG4gKiBjb25zdCBzY3JhdGNoID0gZmlsZXN5c3RlbXMuZmlsZXN5c3RlbXMobG9jYWxGUy50bXBGUyhcImFnZW50LWpvYlwiKSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbGVzeXN0ZW1zKFxuICBmczogRmlsZVN5c3RlbSxcbiAgb3B0aW9uczogTWFzdHJhRmlsZVN5c3RlbUFkYXB0ZXJPcHRpb25zID0ge30sXG4pOiBNYXN0cmFGaWxlU3lzdGVtQWRhcHRlciB7XG4gIHJldHVybiBuZXcgTWFzdHJhRmlsZVN5c3RlbUFkYXB0ZXIoZnMsIG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIFRoaW4gTWFzdHJhIHtAbGluayBNYXN0cmFGaWxlc3lzdGVtfSBhZGFwdGVyIG92ZXIgYSBgQGRieC10b29scy9zaGFyZWQtZnNgXG4gKiB7QGxpbmsgRmlsZVN5c3RlbX0uIElkZW50aXR5IGZpZWxkcyBhcmUgZ2V0dGVycyB0aGF0IHJlYWQgdGhlIHNvdXJjZSBvblxuICogYWNjZXNzOyBjb25zdHJ1Y3Rpb24gZG9lcyBub3Qgc25hcHNob3QgdGhlbS5cbiAqL1xuZXhwb3J0IGNsYXNzIE1hc3RyYUZpbGVTeXN0ZW1BZGFwdGVyIGV4dGVuZHMgTWFzdHJhRmlsZXN5c3RlbSB7XG4gIHN0YXR1czogUHJvdmlkZXJTdGF0dXMgPSBcInBlbmRpbmdcIjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGZzOiBGaWxlU3lzdGVtO1xuICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnM6IE1hc3RyYUZpbGVTeXN0ZW1BZGFwdGVyT3B0aW9ucztcblxuICBjb25zdHJ1Y3RvcihmczogRmlsZVN5c3RlbSwgb3B0aW9uczogTWFzdHJhRmlsZVN5c3RlbUFkYXB0ZXJPcHRpb25zID0ge30pIHtcbiAgICBzdXBlcih7XG4gICAgICBuYW1lOiBvcHRpb25zLm5hbWUgPz8gXCJNYXN0cmFGaWxlU3lzdGVtQWRhcHRlclwiLFxuICAgICAgb25Jbml0OiBvcHRpb25zLm9uSW5pdCxcbiAgICAgIG9uRGVzdHJveTogb3B0aW9ucy5vbkRlc3Ryb3ksXG4gICAgfSk7XG4gICAgdGhpcy5mcyA9IGZzO1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gIH1cblxuICBnZXQgaWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLmlkID8/IHRoaXMuZnMuaWQ7XG4gIH1cblxuICBnZXQgbmFtZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMubmFtZSA/PyBcIk1hc3RyYUZpbGVTeXN0ZW1BZGFwdGVyXCI7XG4gIH1cblxuICBnZXQgcHJvdmlkZXIoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLnByb3ZpZGVyID8/IHRoaXMuZnMuYmFja2VuZDtcbiAgfVxuXG4gIGdldCByZWFkT25seSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zLnJlYWRPbmx5ID09PSB0cnVlIHx8IHRoaXMuZnMucmVhZE9ubHk7XG4gIH1cblxuICBnZXQgYmFzZVBhdGgoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5mcy5yb290O1xuICB9XG5cbiAgb3ZlcnJpZGUgYXN5bmMgaW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmZzLmluaXQoKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFzeW5jIGRlc3Ryb3koKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5mcy5jbG9zZSgpO1xuICB9XG5cbiAgZ2V0SW5mbygpOiBGaWxlc3lzdGVtSW5mbzx7IHJvb3Q6IHN0cmluZzsgYmFja2VuZDogc3RyaW5nIH0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IHRoaXMuaWQsXG4gICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICBwcm92aWRlcjogdGhpcy5wcm92aWRlcixcbiAgICAgIHN0YXR1czogdGhpcy5zdGF0dXMsXG4gICAgICByZWFkT25seTogdGhpcy5yZWFkT25seSxcbiAgICAgIG1ldGFkYXRhOiB7IHJvb3Q6IHRoaXMuZnMucm9vdCwgYmFja2VuZDogdGhpcy5mcy5iYWNrZW5kIH0sXG4gICAgfTtcbiAgfVxuXG4gIGdldEluc3RydWN0aW9ucygpOiBzdHJpbmcge1xuICAgIHJldHVybiBbXG4gICAgICBgRmlsZXMgYXJlIHNlcnZlZCBieSBhICR7dGhpcy5mcy5iYWNrZW5kfSBmaWxlc3lzdGVtIHJvb3RlZCBhdCAke3RoaXMuZnMucm9vdH0uYCxcbiAgICAgIFwiV29ya3NwYWNlIHBhdGhzIGFyZSBhYnNvbHV0ZSB3aXRoaW4gdGhpcyBtb3VudCAoZm9yIGV4YW1wbGUgYC9ub3Rlcy9yZXBvcnQubWRgKS5cIixcbiAgICBdLmpvaW4oXCIgXCIpO1xuICB9XG5cbiAgYXN5bmMgcmVhZEZpbGUoaW5wdXRQYXRoOiBzdHJpbmcsIG9wdGlvbnM/OiBSZWFkT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nIHwgQnVmZmVyPiB7XG4gICAgcmV0dXJuIHRoaXMuZGVsZWdhdGUoaW5wdXRQYXRoLCBhc3luYyAoKSA9PiB7XG4gICAgICBpZiAob3B0aW9ucz8uZW5jb2RpbmcpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnMucmVhZEZpbGUoaW5wdXRQYXRoLCB7IGVuY29kaW5nOiBvcHRpb25zLmVuY29kaW5nIH0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIEJ1ZmZlci5mcm9tKGF3YWl0IHRoaXMuZnMucmVhZEZpbGUoaW5wdXRQYXRoKSk7XG4gICAgfSk7XG4gIH1cblxuICBhc3luYyB3cml0ZUZpbGUoaW5wdXRQYXRoOiBzdHJpbmcsIGNvbnRlbnQ6IEZpbGVDb250ZW50LCBvcHRpb25zPzogV3JpdGVPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuZGVsZWdhdGVXcml0ZShcIndyaXRlRmlsZVwiLCBpbnB1dFBhdGgsIGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChvcHRpb25zPy5yZWN1cnNpdmUgPT09IGZhbHNlKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuYXNzZXJ0UGFyZW50RXhpc3RzKGlucHV0UGF0aCk7XG4gICAgICB9XG4gICAgICBhd2FpdCB0aGlzLmZzLndyaXRlRmlsZShpbnB1dFBhdGgsIGNvbnRlbnQsIHtcbiAgICAgICAgb3ZlcndyaXRlOiBvcHRpb25zPy5vdmVyd3JpdGUgPz8gdHJ1ZSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgYXBwZW5kRmlsZShpbnB1dFBhdGg6IHN0cmluZywgY29udGVudDogRmlsZUNvbnRlbnQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5kZWxlZ2F0ZVdyaXRlKFwiYXBwZW5kRmlsZVwiLCBpbnB1dFBhdGgsICgpID0+XG4gICAgICB0aGlzLmZzLmFwcGVuZEZpbGUoaW5wdXRQYXRoLCBjb250ZW50KSxcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlRmlsZShpbnB1dFBhdGg6IHN0cmluZywgb3B0aW9ucz86IFJlbW92ZU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5kZWxlZ2F0ZVdyaXRlKFwiZGVsZXRlRmlsZVwiLCBpbnB1dFBhdGgsICgpID0+XG4gICAgICB0aGlzLmZzLmRlbGV0ZUZpbGUoaW5wdXRQYXRoLCB7XG4gICAgICAgIGZvcmNlOiBvcHRpb25zPy5mb3JjZSxcbiAgICAgICAgcmVjdXJzaXZlOiBvcHRpb25zPy5yZWN1cnNpdmUsXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgYXN5bmMgY29weUZpbGUoc3JjOiBzdHJpbmcsIGRlc3Q6IHN0cmluZywgb3B0aW9ucz86IENvcHlPcHRpb25zKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuZGVsZWdhdGVXcml0ZShcImNvcHlGaWxlXCIsIGRlc3QsICgpID0+XG4gICAgICB0aGlzLmZzLmNvcHlGaWxlKHNyYywgZGVzdCwgeyBvdmVyd3JpdGU6IG9wdGlvbnM/Lm92ZXJ3cml0ZSA/PyB0cnVlIH0pLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBtb3ZlRmlsZShzcmM6IHN0cmluZywgZGVzdDogc3RyaW5nLCBvcHRpb25zPzogQ29weU9wdGlvbnMpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5kZWxlZ2F0ZVdyaXRlKFwibW92ZUZpbGVcIiwgZGVzdCwgKCkgPT5cbiAgICAgIHRoaXMuZnMubW92ZUZpbGUoc3JjLCBkZXN0LCB7IG92ZXJ3cml0ZTogb3B0aW9ucz8ub3ZlcndyaXRlID8/IHRydWUgfSksXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIG1rZGlyKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogeyByZWN1cnNpdmU/OiBib29sZWFuIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gdGhpcy5kZWxlZ2F0ZVdyaXRlKFwibWtkaXJcIiwgaW5wdXRQYXRoLCAoKSA9PlxuICAgICAgdGhpcy5mcy5ta2RpcihpbnB1dFBhdGgsIHsgcmVjdXJzaXZlOiBvcHRpb25zPy5yZWN1cnNpdmUgfSksXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIHJtZGlyKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogUmVtb3ZlT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLmRlbGVnYXRlV3JpdGUoXG4gICAgICBcInJtZGlyXCIsXG4gICAgICBpbnB1dFBhdGgsXG4gICAgICAoKSA9PlxuICAgICAgICB0aGlzLmZzLnJtZGlyKGlucHV0UGF0aCwge1xuICAgICAgICAgIGZvcmNlOiBvcHRpb25zPy5mb3JjZSxcbiAgICAgICAgICByZWN1cnNpdmU6IG9wdGlvbnM/LnJlY3Vyc2l2ZSxcbiAgICAgICAgfSksXG4gICAgICB7IHByZWZlckRpcmVjdG9yeTogdHJ1ZSB9LFxuICAgICk7XG4gIH1cblxuICBhc3luYyByZWFkZGlyKGlucHV0UGF0aDogc3RyaW5nLCBvcHRpb25zPzogTGlzdE9wdGlvbnMpOiBQcm9taXNlPEZpbGVFbnRyeVtdPiB7XG4gICAgcmV0dXJuIHRoaXMuZGVsZWdhdGUoXG4gICAgICBpbnB1dFBhdGgsXG4gICAgICBhc3luYyAoKSA9PlxuICAgICAgICAoXG4gICAgICAgICAgYXdhaXQgdGhpcy5mcy5yZWFkZGlyKGlucHV0UGF0aCwge1xuICAgICAgICAgICAgcmVjdXJzaXZlOiBvcHRpb25zPy5yZWN1cnNpdmUsXG4gICAgICAgICAgICBtYXhEZXB0aDogb3B0aW9ucz8ubWF4RGVwdGgsXG4gICAgICAgICAgICBleHRlbnNpb246IG9wdGlvbnM/LmV4dGVuc2lvbixcbiAgICAgICAgICB9KVxuICAgICAgICApLm1hcCh0b01hc3RyYUVudHJ5KSxcbiAgICAgIHsgcHJlZmVyRGlyZWN0b3J5OiB0cnVlIH0sXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGV4aXN0cyhpbnB1dFBhdGg6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICByZXR1cm4gdGhpcy5mcy5leGlzdHMoaW5wdXRQYXRoKTtcbiAgfVxuXG4gIGFzeW5jIHN0YXQoaW5wdXRQYXRoOiBzdHJpbmcpOiBQcm9taXNlPEZpbGVTdGF0PiB7XG4gICAgcmV0dXJuIHRoaXMuZGVsZWdhdGUoaW5wdXRQYXRoLCBhc3luYyAoKSA9PlxuICAgICAgdG9NYXN0cmFTdGF0KGF3YWl0IHRoaXMuZnMuc3RhdChpbnB1dFBhdGgpLCBpbnB1dFBhdGgpLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRlbGVnYXRlPFQ+KFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBvcDogKCkgPT4gUHJvbWlzZTxUPixcbiAgICBvcHRpb25zPzogeyBwcmVmZXJEaXJlY3Rvcnk/OiBib29sZWFuIH0sXG4gICk6IFByb21pc2U8VD4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVhZHkoKTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IG9wKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLnJldGhyb3coZXJyLCBwYXRoLCBvcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvKioge0BsaW5rIGRlbGVnYXRlfSBmb3IgYSBtdXRhdGlvbjogcmVmdXNlIGEgcmVhZC1vbmx5IG1vdW50IGJlZm9yZSBkb2luZyBhbnkgd29yay4gKi9cbiAgcHJpdmF0ZSBkZWxlZ2F0ZVdyaXRlKFxuICAgIG9wZXJhdGlvbjogc3RyaW5nLFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBvcDogKCkgPT4gUHJvbWlzZTx2b2lkPixcbiAgICBvcHRpb25zPzogeyBwcmVmZXJEaXJlY3Rvcnk/OiBib29sZWFuIH0sXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLnJlYWRPbmx5KSB7XG4gICAgICB0aHJvdyBuZXcgV29ya3NwYWNlUmVhZE9ubHlFcnJvcihvcGVyYXRpb24pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5kZWxlZ2F0ZShwYXRoLCBvcCwgb3B0aW9ucyk7XG4gIH1cblxuICAvKiogV2hlbiBNYXN0cmEgYXNrcyBmb3Igbm9uLXJlY3Vyc2l2ZSB3cml0ZXMsIHJlcXVpcmUgdGhlIHBhcmVudCBkaXJlY3RvcnkuICovXG4gIHByaXZhdGUgYXN5bmMgYXNzZXJ0UGFyZW50RXhpc3RzKGlucHV0UGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgcGFyZW50ID0gcG9zaXhQYXRoLmRpcm5hbWUobm9ybWFsaXplV29ya3NwYWNlUGF0aChpbnB1dFBhdGgpKTtcbiAgICBpZiAocGFyZW50ID09PSBcIi9cIiB8fCAoYXdhaXQgdGhpcy5mcy5leGlzdHMocGFyZW50KSkpIHJldHVybjtcbiAgICB0aHJvdyBuZXcgRGlyZWN0b3J5Tm90Rm91bmRFcnJvcihwYXJlbnQpO1xuICB9XG5cbiAgcHJpdmF0ZSByZXRocm93KGVycjogdW5rbm93biwgaW5wdXRQYXRoOiBzdHJpbmcsIG9wdGlvbnM/OiB7IHByZWZlckRpcmVjdG9yeT86IGJvb2xlYW4gfSk6IG5ldmVyIHtcbiAgICBpZiAoXG4gICAgICBlcnIgaW5zdGFuY2VvZiBGaWxlTm90Rm91bmRFcnJvciB8fFxuICAgICAgZXJyIGluc3RhbmNlb2YgRGlyZWN0b3J5Tm90Rm91bmRFcnJvciB8fFxuICAgICAgZXJyIGluc3RhbmNlb2YgRmlsZUV4aXN0c0Vycm9yIHx8XG4gICAgICBlcnIgaW5zdGFuY2VvZiBJc0RpcmVjdG9yeUVycm9yIHx8XG4gICAgICBlcnIgaW5zdGFuY2VvZiBOb3REaXJlY3RvcnlFcnJvciB8fFxuICAgICAgZXJyIGluc3RhbmNlb2YgRGlyZWN0b3J5Tm90RW1wdHlFcnJvciB8fFxuICAgICAgZXJyIGluc3RhbmNlb2YgUGVybWlzc2lvbkVycm9yIHx8XG4gICAgICBlcnIgaW5zdGFuY2VvZiBXb3Jrc3BhY2VSZWFkT25seUVycm9yXG4gICAgKSB7XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuXG4gICAgaWYgKGVyciBpbnN0YW5jZW9mIEZpbGVTeXN0ZW1FcnJvcikge1xuICAgICAgdGhyb3cgbWFwU2hhcmVkRXJyb3IoZXJyLCBpbnB1dFBhdGgsIG9wdGlvbnM/LnByZWZlckRpcmVjdG9yeSA9PT0gdHJ1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgZXJyO1xuICB9XG59XG5cbi8qKiBGcmVzaCB3cml0YWJsZSBsb2NhbCB0ZW1wIG1vdW50IG9uIGEgcm9vdCB1bmlxdWUgdG8gdGhpcyBjYWxsLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjcmF0Y2hGaWxlc3lzdGVtKCk6IE1hc3RyYUZpbGVTeXN0ZW1BZGFwdGVyIHtcbiAgcmV0dXJuIGZpbGVzeXN0ZW1zKGxvY2FsRlMuc2NyYXRjaEZTKFwibWFzdHJhXCIpKTtcbn1cblxuLyoqIE1hcCBhIHNoYXJlZC1mcyBlcnJvciBjb2RlIG9udG8gdGhlIG1hdGNoaW5nIE1hc3RyYSBmaWxlc3lzdGVtIGVycm9yLiAqL1xuZnVuY3Rpb24gbWFwU2hhcmVkRXJyb3IoZXJyOiBGaWxlU3lzdGVtRXJyb3IsIGlucHV0UGF0aDogc3RyaW5nLCBwcmVmZXJEaXJlY3Rvcnk6IGJvb2xlYW4pOiBFcnJvciB7XG4gIGNvbnN0IHBhdGggPSBlcnIucGF0aCA/PyBpbnB1dFBhdGg7XG4gIHN3aXRjaCAoZXJyLmNvZGUpIHtcbiAgICBjYXNlIFwiTk9UX0ZPVU5EXCI6XG4gICAgICByZXR1cm4gcHJlZmVyRGlyZWN0b3J5ID8gbmV3IERpcmVjdG9yeU5vdEZvdW5kRXJyb3IocGF0aCkgOiBuZXcgRmlsZU5vdEZvdW5kRXJyb3IocGF0aCk7XG4gICAgY2FzZSBcIkFMUkVBRFlfRVhJU1RTXCI6XG4gICAgICByZXR1cm4gbmV3IEZpbGVFeGlzdHNFcnJvcihwYXRoKTtcbiAgICBjYXNlIFwiTk9UX0RJUkVDVE9SWVwiOlxuICAgICAgcmV0dXJuIG5ldyBOb3REaXJlY3RvcnlFcnJvcihwYXRoKTtcbiAgICBjYXNlIFwiSVNfRElSRUNUT1JZXCI6XG4gICAgICByZXR1cm4gbmV3IElzRGlyZWN0b3J5RXJyb3IocGF0aCk7XG4gICAgY2FzZSBcIkRJUkVDVE9SWV9OT1RfRU1QVFlcIjpcbiAgICAgIHJldHVybiBuZXcgRGlyZWN0b3J5Tm90RW1wdHlFcnJvcihwYXRoKTtcbiAgICBjYXNlIFwiUEVSTUlTU0lPTl9ERU5JRURcIjpcbiAgICAgIHJldHVybiBuZXcgUGVybWlzc2lvbkVycm9yKHBhdGgsIGVyci5tZXNzYWdlKTtcbiAgICBjYXNlIFwiUkVBRF9PTkxZXCI6XG4gICAgICByZXR1cm4gbmV3IFdvcmtzcGFjZVJlYWRPbmx5RXJyb3IoZXJyLm1lc3NhZ2UpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZXJyO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvTWFzdHJhRW50cnkoZW50cnk6IFNoYXJlZEZpbGVFbnRyeSk6IEZpbGVFbnRyeSB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogZW50cnkubmFtZSxcbiAgICB0eXBlOiBlbnRyeS50eXBlID09PSBcImRpcmVjdG9yeVwiID8gXCJkaXJlY3RvcnlcIiA6IFwiZmlsZVwiLFxuICAgIHNpemU6IGVudHJ5LnNpemUsXG4gICAgaXNTeW1saW5rOiBlbnRyeS50eXBlID09PSBcInN5bWJvbGljLWxpbmtcIixcbiAgfTtcbn1cblxuZnVuY3Rpb24gdG9NYXN0cmFTdGF0KHN0YXQ6IFNoYXJlZEZpbGVTdGF0LCBpbnB1dFBhdGg6IHN0cmluZyk6IEZpbGVTdGF0IHtcbiAgY29uc3QgZXBvY2ggPSBuZXcgRGF0ZSgwKTtcbiAgcmV0dXJuIHtcbiAgICBuYW1lOiBzdGF0Lm5hbWUsXG4gICAgcGF0aDogbm9ybWFsaXplV29ya3NwYWNlUGF0aChzdGF0LnBhdGggfHwgaW5wdXRQYXRoKSxcbiAgICB0eXBlOiBzdGF0LnR5cGUgPT09IFwiZGlyZWN0b3J5XCIgPyBcImRpcmVjdG9yeVwiIDogXCJmaWxlXCIsXG4gICAgc2l6ZTogc3RhdC5zaXplID8/IDAsXG4gICAgY3JlYXRlZEF0OiBzdGF0LmNyZWF0ZWRBdCA/PyBlcG9jaCxcbiAgICBtb2RpZmllZEF0OiBzdGF0Lm1vZGlmaWVkQXQgPz8gZXBvY2gsXG4gICAgbWltZVR5cGU6IHN0YXQubWltZVR5cGUsXG4gIH07XG59XG5cbi8qKlxuICogTWFzdHJhIG5hbWVzcGFjZSBwYXRoIChgL2EvYmApLiBBIGAuLmAgdGhhdCB3b3VsZCBlc2NhcGUgY2xhbXBzIHRvIHRoZSByb290XG4gKiByYXRoZXIgdGhhbiB0aHJvd2luZyAtIHRoZSB3cmFwcGVkIGZpbGVzeXN0ZW0gZW5mb3JjZXMgY29udGFpbm1lbnQgaXRzZWxmLFxuICogYW5kIGEgbW91bnQgc2hvdWxkIG5vdCBmYWlsIGEgbGlzdGluZyBvdmVyIGEgc3RyYXkgc2VnbWVudC5cbiAqL1xuZnVuY3Rpb24gbm9ybWFsaXplV29ya3NwYWNlUGF0aChpbnB1dFBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHJlc3VsdCA9IHBvc2l4UGF0aC5ub3JtYWxpemUoaW5wdXRQYXRoKTtcbiAgcmV0dXJuIHJlc3VsdC5vayA/IHJlc3VsdC5wYXRoIDogXCIvXCI7XG59XG4iXX0=