@dbx-tools/appkit-mastra 0.3.44 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/lib/index.d.ts +71 -0
  2. package/lib/index.js +56 -0
  3. package/lib/src/agents.d.ts +347 -0
  4. package/lib/src/agents.js +554 -0
  5. package/lib/src/chart.d.ts +192 -0
  6. package/lib/src/chart.js +638 -0
  7. package/lib/src/config.d.ts +479 -0
  8. package/lib/src/config.js +190 -0
  9. package/lib/src/defaults.d.ts +68 -0
  10. package/lib/src/defaults.js +107 -0
  11. package/lib/src/filesystems.d.ts +208 -0
  12. package/lib/src/filesystems.js +958 -0
  13. package/lib/src/genie.d.ts +166 -0
  14. package/lib/src/genie.js +969 -0
  15. package/lib/src/history.d.ts +97 -0
  16. package/lib/src/history.js +264 -0
  17. package/lib/src/mcp.d.ts +66 -0
  18. package/lib/src/mcp.js +65 -0
  19. package/lib/src/memory.d.ts +111 -0
  20. package/lib/src/memory.js +275 -0
  21. package/lib/src/mlflow.d.ts +63 -0
  22. package/lib/src/mlflow.js +117 -0
  23. package/lib/src/model.d.ts +62 -0
  24. package/lib/src/model.js +168 -0
  25. package/lib/src/observability.d.ts +81 -0
  26. package/lib/src/observability.js +98 -0
  27. package/lib/src/pagination.d.ts +23 -0
  28. package/lib/src/pagination.js +31 -0
  29. package/lib/src/plugin.d.ts +352 -0
  30. package/lib/src/plugin.js +1015 -0
  31. package/lib/src/processors.d.ts +62 -0
  32. package/lib/src/processors.js +162 -0
  33. package/lib/src/rest.d.ts +36 -0
  34. package/lib/src/rest.js +46 -0
  35. package/lib/src/server.d.ts +155 -0
  36. package/lib/src/server.js +336 -0
  37. package/lib/src/serving-sanitize.d.ts +104 -0
  38. package/lib/src/serving-sanitize.js +228 -0
  39. package/lib/src/serving.d.ts +61 -0
  40. package/lib/src/serving.js +78 -0
  41. package/lib/src/statement.d.ts +51 -0
  42. package/lib/src/statement.js +83 -0
  43. package/lib/src/storage-schema.d.ts +14 -0
  44. package/lib/src/storage-schema.js +34 -0
  45. package/lib/src/summarize.d.ts +70 -0
  46. package/lib/src/summarize.js +142 -0
  47. package/lib/src/threads.d.ts +109 -0
  48. package/lib/src/threads.js +301 -0
  49. package/lib/src/validation.d.ts +19 -0
  50. package/lib/src/validation.js +17 -0
  51. package/lib/src/workspaces.d.ts +68 -0
  52. package/lib/src/workspaces.js +246 -0
  53. package/lib/src/writer.d.ts +25 -0
  54. package/lib/src/writer.js +40 -0
  55. package/lib/tsconfig.tsbuildinfo +1 -0
  56. package/package.json +17 -13
@@ -0,0 +1,958 @@
1
+ /**
2
+ * Mastra {@link WorkspaceFilesystem} implementations for Databricks Apps.
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.
12
+ *
13
+ * @module
14
+ */
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";
18
+ 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
+ /**
64
+ * Resolve a workspace-relative path to an absolute Databricks path under
65
+ * `basePath`.
66
+ */
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));
77
+ }
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
+ /**
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.
162
+ */
163
+ export class DatabricksWorkspaceFilesystem extends MastraFilesystem {
164
+ id;
165
+ name = "DatabricksWorkspaceFilesystem";
166
+ provider = "databricks";
167
+ basePath;
168
+ 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;
188
+ }
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;
197
+ }
198
+ /** Map a Databricks absolute path back to the workspace namespace. */
199
+ workspacePath(absolutePath) {
200
+ return toDatabricksWorkspacePath(this.basePath, absolutePath);
201
+ }
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
+ });
227
+ }
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
+ }
247
+ }
248
+ /** Delegate to {@link emptyFilesystem} when the base path is missing. */
249
+ async emptyFallback() {
250
+ await this.resolveBasePathStatus();
251
+ return this._basePathMissing ? emptyFilesystem() : undefined;
252
+ }
253
+ 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;
304
+ }
305
+ 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
+ });
442
+ }
443
+ /* --- MastraFilesystem API --- */
444
+ getInfo() {
445
+ return {
446
+ id: this.id,
447
+ name: this.name,
448
+ provider: this.provider,
449
+ status: this.status,
450
+ readOnly: this.readOnly,
451
+ metadata: { basePath: this.basePath },
452
+ };
453
+ }
454
+ getInstructions() {
455
+ 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.",
460
+ ].join(" ");
461
+ }
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
+ 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
+ }
480
+ }
481
+ /** Write file contents into the workspace namespace. */
482
+ 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);
494
+ }
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
+ }
502
+ }
503
+ /** Append to an existing file, creating it when missing. */
504
+ 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 });
518
+ }
519
+ /** Delete a file in the workspace namespace. */
520
+ 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
+ }
544
+ }
545
+ /** Copy a file within the workspace namespace. */
546
+ 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 });
558
+ }
559
+ /** Move or rename a file within the workspace namespace. */
560
+ 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
+ }
589
+ }
590
+ /** Create a directory in the workspace namespace. */
591
+ 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
+ }
607
+ }
608
+ /** Remove a directory from the workspace namespace. */
609
+ 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 });
654
+ }
655
+ /* --- directory listing --- */
656
+ /** List entries in a workspace directory. */
657
+ 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
+ });
737
+ }
738
+ /* --- metadata --- */
739
+ /** Return whether `inputPath` exists in the workspace namespace. */
740
+ async exists(inputPath) {
741
+ 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
+ }
754
+ }
755
+ /** Return file or directory metadata for `inputPath`. */
756
+ async stat(inputPath) {
757
+ 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
+ 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
+ });
789
+ }
790
+ catch (err) {
791
+ this.rethrow(err, inputPath);
792
+ }
793
+ }
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
+ };
828
+ }
829
+ }
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;
841
+ }
842
+ /**
843
+ * Read-only in-memory {@link WorkspaceFilesystem} with a single empty root.
844
+ * Use {@link emptyFilesystem} rather than constructing directly.
845
+ */
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
+ }
955
+ }
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