@dbx-tools/core 0.6.89 → 0.6.91

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.
package/lib/src/file.d.ts CHANGED
@@ -10,3 +10,11 @@ import { Stats } from "node:fs";
10
10
  * "not there" and "not accessible" the same and never handle an exception.
11
11
  */
12
12
  export declare function statSync(path: string): Stats | undefined;
13
+ /**
14
+ * Load and cache a parsed record by caller-defined source identity.
15
+ *
16
+ * Every result is cached, including empty records and `undefined`. Include every
17
+ * input that affects parsing in `key`, such as a file path plus a Databricks
18
+ * profile.
19
+ */
20
+ export declare function cachedRecord<T extends Record<string, unknown>>(key: string, loader: () => T | undefined): T | undefined;
package/lib/src/file.js CHANGED
@@ -4,6 +4,7 @@
4
4
  * @module
5
5
  */
6
6
  import { statSync as nodeStatSync } from "node:fs";
7
+ const recordCache = new Map();
7
8
  /**
8
9
  * Best-effort `fs.stat` (sync). Returns `undefined` for a blank path or when the
9
10
  * path can't be stat'd (missing, permission denied, ...), so callers can treat
@@ -18,4 +19,18 @@ export function statSync(path) {
18
19
  }
19
20
  return undefined;
20
21
  }
21
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9maWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEVBQVMsUUFBUSxJQUFJLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUUxRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxJQUFZO0lBQ25DLElBQUksSUFBSSxFQUFFLENBQUM7UUFDVCxJQUFJLENBQUM7WUFDSCxPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QixDQUFDO1FBQUMsTUFBTSxDQUFDLENBQUEsQ0FBQztJQUNaLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGaWxlc3lzdGVtIHV0aWxpdGllczogYmVzdC1lZmZvcnQgYGZzLnN0YXRgIGhlbHBlcnMgdGhhdCBuZXZlciB0aHJvdy5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IFN0YXRzLCBzdGF0U3luYyBhcyBub2RlU3RhdFN5bmMgfSBmcm9tIFwibm9kZTpmc1wiO1xuXG4vKipcbiAqIEJlc3QtZWZmb3J0IGBmcy5zdGF0YCAoc3luYykuIFJldHVybnMgYHVuZGVmaW5lZGAgZm9yIGEgYmxhbmsgcGF0aCBvciB3aGVuIHRoZVxuICogcGF0aCBjYW4ndCBiZSBzdGF0J2QgKG1pc3NpbmcsIHBlcm1pc3Npb24gZGVuaWVkLCAuLi4pLCBzbyBjYWxsZXJzIGNhbiB0cmVhdFxuICogXCJub3QgdGhlcmVcIiBhbmQgXCJub3QgYWNjZXNzaWJsZVwiIHRoZSBzYW1lIGFuZCBuZXZlciBoYW5kbGUgYW4gZXhjZXB0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3RhdFN5bmMocGF0aDogc3RyaW5nKTogU3RhdHMgfCB1bmRlZmluZWQge1xuICBpZiAocGF0aCkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gbm9kZVN0YXRTeW5jKHBhdGgpO1xuICAgIH0gY2F0Y2gge31cbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuIl19
22
+ /**
23
+ * Load and cache a parsed record by caller-defined source identity.
24
+ *
25
+ * Every result is cached, including empty records and `undefined`. Include every
26
+ * input that affects parsing in `key`, such as a file path plus a Databricks
27
+ * profile.
28
+ */
29
+ export function cachedRecord(key, loader) {
30
+ if (recordCache.has(key))
31
+ return recordCache.get(key);
32
+ const value = loader();
33
+ recordCache.set(key, value);
34
+ return value;
35
+ }
36
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9maWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFDSCxPQUFPLEVBQVMsUUFBUSxJQUFJLFlBQVksRUFBRSxNQUFNLFNBQVMsQ0FBQztBQUUxRCxNQUFNLFdBQVcsR0FBRyxJQUFJLEdBQUcsRUFBK0MsQ0FBQztBQUUzRTs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxJQUFZO0lBQ25DLElBQUksSUFBSSxFQUFFLENBQUM7UUFDVCxJQUFJLENBQUM7WUFDSCxPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QixDQUFDO1FBQUMsTUFBTSxDQUFDLENBQUEsQ0FBQztJQUNaLENBQUM7SUFDRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FDMUIsR0FBVyxFQUNYLE1BQTJCO0lBRTNCLElBQUksV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUM7UUFBRSxPQUFPLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFrQixDQUFDO0lBQ3ZFLE1BQU0sS0FBSyxHQUFHLE1BQU0sRUFBRSxDQUFDO0lBQ3ZCLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzVCLE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRmlsZXN5c3RlbSB1dGlsaXRpZXM6IGJlc3QtZWZmb3J0IGBmcy5zdGF0YCBoZWxwZXJzIHRoYXQgbmV2ZXIgdGhyb3cuXG4gKlxuICogQG1vZHVsZVxuICovXG5pbXBvcnQgeyBTdGF0cywgc3RhdFN5bmMgYXMgbm9kZVN0YXRTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcblxuY29uc3QgcmVjb3JkQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfCB1bmRlZmluZWQ+KCk7XG5cbi8qKlxuICogQmVzdC1lZmZvcnQgYGZzLnN0YXRgIChzeW5jKS4gUmV0dXJucyBgdW5kZWZpbmVkYCBmb3IgYSBibGFuayBwYXRoIG9yIHdoZW4gdGhlXG4gKiBwYXRoIGNhbid0IGJlIHN0YXQnZCAobWlzc2luZywgcGVybWlzc2lvbiBkZW5pZWQsIC4uLiksIHNvIGNhbGxlcnMgY2FuIHRyZWF0XG4gKiBcIm5vdCB0aGVyZVwiIGFuZCBcIm5vdCBhY2Nlc3NpYmxlXCIgdGhlIHNhbWUgYW5kIG5ldmVyIGhhbmRsZSBhbiBleGNlcHRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdGF0U3luYyhwYXRoOiBzdHJpbmcpOiBTdGF0cyB8IHVuZGVmaW5lZCB7XG4gIGlmIChwYXRoKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBub2RlU3RhdFN5bmMocGF0aCk7XG4gICAgfSBjYXRjaCB7fVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogTG9hZCBhbmQgY2FjaGUgYSBwYXJzZWQgcmVjb3JkIGJ5IGNhbGxlci1kZWZpbmVkIHNvdXJjZSBpZGVudGl0eS5cbiAqXG4gKiBFdmVyeSByZXN1bHQgaXMgY2FjaGVkLCBpbmNsdWRpbmcgZW1wdHkgcmVjb3JkcyBhbmQgYHVuZGVmaW5lZGAuIEluY2x1ZGUgZXZlcnlcbiAqIGlucHV0IHRoYXQgYWZmZWN0cyBwYXJzaW5nIGluIGBrZXlgLCBzdWNoIGFzIGEgZmlsZSBwYXRoIHBsdXMgYSBEYXRhYnJpY2tzXG4gKiBwcm9maWxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FjaGVkUmVjb3JkPFQgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4oXG4gIGtleTogc3RyaW5nLFxuICBsb2FkZXI6ICgpID0+IFQgfCB1bmRlZmluZWQsXG4pOiBUIHwgdW5kZWZpbmVkIHtcbiAgaWYgKHJlY29yZENhY2hlLmhhcyhrZXkpKSByZXR1cm4gcmVjb3JkQ2FjaGUuZ2V0KGtleSkgYXMgVCB8IHVuZGVmaW5lZDtcbiAgY29uc3QgdmFsdWUgPSBsb2FkZXIoKTtcbiAgcmVjb3JkQ2FjaGUuc2V0KGtleSwgdmFsdWUpO1xuICByZXR1cm4gdmFsdWU7XG59XG4iXX0=
@@ -1,8 +1,9 @@
1
1
  import { Stats } from "node:fs";
2
2
  import { net } from "@dbx-tools/shared-core";
3
+ /** Resolve a blank, null, omitted, relative, or absolute cwd to an absolute path. */
4
+ export declare function resolveWorkingDirectory(cwd?: string | null): string;
3
5
  /** A command's stdout, classified as a filesystem path and/or a URL. */
4
6
  export interface ProjectContext {
5
- readonly cwd: string;
6
7
  readonly output: string;
7
8
  /** `output` when it names something on disk. */
8
9
  readonly path?: string;
@@ -37,8 +38,8 @@ export declare function name(cwd?: string): string;
37
38
  /**
38
39
  * The repo's canonical remote URL, or `undefined` when there is no git remote.
39
40
  * Tries `gh repo view` first (host-accurate, no parsing), then normalizes
40
- * `git remote get-url origin`. Both underlying commands are cached per `cwd` via
41
- * {@link projectContextCommand}.
41
+ * `git remote get-url origin`. A blank, omitted, or explicitly current `cwd`
42
+ * reuses cached command probes; another resolved directory executes directly.
42
43
  *
43
44
  * @param cwd - directory to resolve from (defaults to `process.cwd()`).
44
45
  * @param format - `"https"` (default) yields `https://host/owner/repo`;
@@ -49,7 +50,9 @@ export declare function repositoryUrl(cwd?: string, format?: "https" | "npm"): s
49
50
  /**
50
51
  * The active npm registry (`npm config get registry`) as a chainable
51
52
  * {@link net.UrlBuilder}, or `undefined` when npm is absent or prints no URL.
52
- * Cached per `cwd` via {@link projectContextCommand}.
53
+ * A blank, null, omitted, or explicitly current `cwd` reuses the cached npm
54
+ * command; another resolved directory executes it directly. Environment options
55
+ * are evaluated on every call.
53
56
  */
54
57
  export declare function npmRegistry(cwd?: string | null, options?: {
55
58
  overrideOnly?: boolean;
@@ -1,7 +1,7 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { readFileSync } from "node:fs";
3
3
  import { basename, dirname, join, resolve } from "node:path";
4
- import { context, json, net, string } from "@dbx-tools/shared-core";
4
+ import { json, net, string } from "@dbx-tools/shared-core";
5
5
  import { statSync as fileStatSync } from "./file.js";
6
6
  const ROOT_MARKERS = [
7
7
  ".projenrc.ts",
@@ -10,6 +10,10 @@ const ROOT_MARKERS = [
10
10
  ".projenrc.cjs",
11
11
  "package.json",
12
12
  ];
13
+ /** Resolve a blank, null, omitted, relative, or absolute cwd to an absolute path. */
14
+ export function resolveWorkingDirectory(cwd) {
15
+ return resolve(string.trimToNull(cwd) ?? process.cwd());
16
+ }
13
17
  /**
14
18
  * because this is crucial do not use exec.spawnSync
15
19
  *
@@ -28,38 +32,43 @@ function projectContextCommandOutput(command, args, cwd) {
28
32
  // `http://localhost/…`), which would mislabel directory outputs and bare
29
33
  // tokens - so gate on the raw output already carrying a scheme + authority.
30
34
  const url = /^[a-z][a-z0-9+.-]*:\/\//i.test(output) ? net.urlBuilder(output) : undefined;
31
- return { cwd, output, path: pathStats ? output : undefined, pathStats, url };
35
+ return { output, path: pathStats ? output : undefined, pathStats, url };
32
36
  }
33
- return { cwd, output };
37
+ return { output };
34
38
  }
35
- /**
36
- * {@link projectContextCommandOutput} through the process-context cache.
37
- *
38
- * These commands (`npm prefix`, `git rev-parse`, `gh repo view`) are pure
39
- * functions of the directory they run in, so their output is worth keeping - but
40
- * only while the process is still IN that directory. {@link context.cached}
41
- * owns that rule: the slot remembers the `cwd` it was loaded under and misses
42
- * once the process moves, and a lookup for some OTHER directory runs the command
43
- * without caching, so it can't evict the hot entry. The slot name carries the
44
- * command and its arguments (order-sensitive), so two commands never share one.
45
- */
39
+ const projectCommandCache = new Map();
46
40
  function projectContextCommand(command, args, cwd) {
47
- return context.cached(["project", command, ...args], (resolved) => projectContextCommandOutput(command, args, resolved ?? resolve(cwd ?? ".")), cwd ? resolve(cwd) : undefined);
41
+ const resolved = resolveWorkingDirectory(cwd);
42
+ const key = resolved === resolveWorkingDirectory() ? JSON.stringify([command, ...args]) : undefined;
43
+ if (key !== undefined) {
44
+ const cached = projectCommandCache.get(key);
45
+ if (cached !== undefined)
46
+ return cached;
47
+ }
48
+ const value = projectContextCommandOutput(command, args, resolved);
49
+ if (key !== undefined)
50
+ projectCommandCache.set(key, value);
51
+ return value;
48
52
  }
49
- function npmRoot(cwd) {
50
- const parsed = projectContextCommand("npm", ["prefix"], cwd);
53
+ function commandRoot(command, args, cwd) {
54
+ const parsed = projectContextCommand(command, args, cwd);
51
55
  return parsed.pathStats?.isDirectory() ? parsed.path : undefined;
52
56
  }
57
+ function npmRoot(cwd) {
58
+ const resolved = resolveWorkingDirectory(cwd);
59
+ return commandRoot("npm", ["prefix"], resolved);
60
+ }
53
61
  function gitRoot(cwd) {
54
- const parsed = projectContextCommand("git", ["rev-parse", "--show-toplevel"], cwd);
55
- return parsed.pathStats?.isDirectory() ? parsed.path : undefined;
62
+ const resolved = resolveWorkingDirectory(cwd);
63
+ return commandRoot("git", ["rev-parse", "--show-toplevel"], resolved);
56
64
  }
57
- export function root(cwd = process.cwd()) {
58
- let current = resolve(cwd);
65
+ export function root(cwd) {
66
+ const resolved = resolveWorkingDirectory(cwd);
67
+ let current = resolved;
59
68
  if (!fileStatSync(current)?.isDirectory()) {
60
69
  current = dirname(current);
61
70
  }
62
- const boundaries = new Set([npmRoot(cwd), gitRoot(cwd)]
71
+ const boundaries = new Set([npmRoot(resolved), gitRoot(resolved)]
63
72
  .filter((path) => path !== undefined)
64
73
  .map((path) => resolve(path)));
65
74
  const hasBoundary = boundaries.size > 0;
@@ -119,8 +128,8 @@ function lastPathSegment(path) {
119
128
  * `npm prefix`, the git top-level, then `cwd` itself. Duplicates are skipped;
120
129
  * only existing directories are yielded (except the final `cwd` fallback).
121
130
  */
122
- export function* resolveProjectRoots(cwd = process.cwd()) {
123
- const base = resolve(cwd);
131
+ export function* resolveProjectRoots(cwd) {
132
+ const base = resolveWorkingDirectory(cwd);
124
133
  const seen = new Set();
125
134
  for (const candidate of [npmRoot(base), gitRoot(base)]) {
126
135
  if (!candidate)
@@ -136,22 +145,23 @@ export function* resolveProjectRoots(cwd = process.cwd()) {
136
145
  yield base;
137
146
  }
138
147
  /** The nearest ancestor of `cwd` (from {@link resolveProjectRoots}) with a `package.json`. */
139
- function workspaceRoot(cwd = process.cwd()) {
148
+ function workspaceRoot(cwd) {
140
149
  let last;
141
150
  for (const dir of resolveProjectRoots(cwd)) {
142
151
  if (fileStatSync(resolve(dir, "package.json"))?.isFile())
143
152
  return dir;
144
153
  last = dir;
145
154
  }
146
- return last ?? resolve(cwd);
155
+ return last ?? resolveWorkingDirectory(cwd);
147
156
  }
148
157
  /**
149
158
  * Resolve a human-friendly project name for the repo rooted at `cwd`:
150
159
  * `package.json` `name`, then the git remote's repo name, then the root
151
160
  * directory's basename.
152
161
  */
153
- export function name(cwd = process.cwd()) {
154
- const rootDir = workspaceRoot(cwd);
162
+ export function name(cwd) {
163
+ const resolved = resolveWorkingDirectory(cwd);
164
+ const rootDir = workspaceRoot(resolved);
155
165
  const fromPackage = readPackageName(resolve(rootDir, "package.json"));
156
166
  if (fromPackage)
157
167
  return fromPackage;
@@ -214,16 +224,17 @@ function repositoryUrlFromGit(cwd) {
214
224
  /**
215
225
  * The repo's canonical remote URL, or `undefined` when there is no git remote.
216
226
  * Tries `gh repo view` first (host-accurate, no parsing), then normalizes
217
- * `git remote get-url origin`. Both underlying commands are cached per `cwd` via
218
- * {@link projectContextCommand}.
227
+ * `git remote get-url origin`. A blank, omitted, or explicitly current `cwd`
228
+ * reuses cached command probes; another resolved directory executes directly.
219
229
  *
220
230
  * @param cwd - directory to resolve from (defaults to `process.cwd()`).
221
231
  * @param format - `"https"` (default) yields `https://host/owner/repo`;
222
232
  * `"npm"` yields npm's `git+https://host/owner/repo.git` form (for a
223
233
  * `package.json` `repository.url` that passes npm provenance).
224
234
  */
225
- export function repositoryUrl(cwd = process.cwd(), format = "https") {
226
- const https = repositoryUrlFromGh(cwd) ?? repositoryUrlFromGit(cwd);
235
+ export function repositoryUrl(cwd, format = "https") {
236
+ const resolved = resolveWorkingDirectory(cwd);
237
+ const https = repositoryUrlFromGh(resolved) ?? repositoryUrlFromGit(resolved);
227
238
  if (!https)
228
239
  return undefined;
229
240
  return format === "npm" ? `git+${https.replace(/\.git$/, "")}.git` : https;
@@ -231,9 +242,15 @@ export function repositoryUrl(cwd = process.cwd(), format = "https") {
231
242
  /**
232
243
  * The active npm registry (`npm config get registry`) as a chainable
233
244
  * {@link net.UrlBuilder}, or `undefined` when npm is absent or prints no URL.
234
- * Cached per `cwd` via {@link projectContextCommand}.
245
+ * A blank, null, omitted, or explicitly current `cwd` reuses the cached npm
246
+ * command; another resolved directory executes it directly. Environment options
247
+ * are evaluated on every call.
235
248
  */
236
249
  export function npmRegistry(cwd, options) {
250
+ const resolved = resolveWorkingDirectory(cwd);
251
+ return resolveNpmRegistry(resolved, options);
252
+ }
253
+ function resolveNpmRegistry(cwd, options) {
237
254
  const candidates = (function* () {
238
255
  yield projectContextCommand("npm", ["config", "get", "registry"], cwd ?? undefined).output?.trim();
239
256
  if (typeof process !== "undefined" && process?.env) {
@@ -273,6 +290,6 @@ if (import.meta.main) {
273
290
  console.log("package root:", root());
274
291
  console.log("project name:", name());
275
292
  console.log("repository url:", repositoryUrl());
276
- console.log("repository url (npm):", repositoryUrl(process.cwd(), "npm"));
293
+ console.log("repository url (npm):", repositoryUrl(undefined, "npm"));
277
294
  }
278
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvamVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9qZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEVBQVMsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDN0QsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxRQUFRLElBQUksWUFBWSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBRXJELE1BQU0sWUFBWSxHQUFHO0lBQ25CLGNBQWM7SUFDZCxjQUFjO0lBQ2QsZUFBZTtJQUNmLGVBQWU7SUFDZixjQUFjO0NBQ04sQ0FBQztBQWtCWDs7Ozs7OztHQU9HO0FBQ0gsU0FBUywyQkFBMkIsQ0FBQyxPQUFlLEVBQUUsSUFBYyxFQUFFLEdBQVc7SUFDL0UsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdEYsTUFBTSxNQUFNLEdBQUcsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUNsRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLE1BQU0sRUFBRSxDQUFDO1FBQ2xDLE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN2QywwRUFBMEU7UUFDMUUsNEVBQTRFO1FBQzVFLHlFQUF5RTtRQUN6RSw0RUFBNEU7UUFDNUUsTUFBTSxHQUFHLEdB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SUFDckMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxlQUFlLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUNyQyxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3JDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQztJQUNoRCxPQUFPLENBQUMsR0FBRyxDQUFDLHVCQUF1QixFQUFFLGFBQWEsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUM1RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgc3Bhd25TeW5jIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiO1xuaW1wb3J0IHsgU3RhdHMsIHJlYWRGaWxlU3luYyB9IGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgeyBiYXNlbmFtZSwgZGlybmFtZSwgam9pbiwgcmVzb2x2ZSB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IGNvbnRleHQsIGpzb24sIG5ldCwgc3RyaW5nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IHN0YXRTeW5jIGFzIGZpbGVTdGF0U3luYyB9IGZyb20gXCIuL2ZpbGUudHNcIjtcblxuY29uc3QgUk9PVF9NQVJLRVJTID0gW1xuICBcIi5wcm9qZW5yYy50c1wiLFxuICBcIi5wcm9qZW5yYy5qc1wiLFxuICBcIi5wcm9qZW5yYy5tanNcIixcbiAgXCIucHJvamVucmMuY2pzXCIsXG4gIFwicGFja2FnZS5qc29uXCIsXG5dIGFzIGNvbnN0O1xuXG4vKiogQSBjb21tYW5kJ3Mgc3Rkb3V0LCBjbGFzc2lmaWVkIGFzIGEgZmlsZXN5c3RlbSBwYXRoIGFuZC9vciBhIFVSTC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvamVjdENvbnRleHQge1xuICByZWFkb25seSBjd2Q6IHN0cmluZztcbiAgcmVhZG9ubHkgb3V0cHV0OiBzdHJpbmc7XG4gIC8qKiBgb3V0cHV0YCB3aGVuIGl0IG5hbWVzIHNvbWV0aGluZyBvbiBkaXNrLiAqL1xuICByZWFkb25seSBwYXRoPzogc3RyaW5nO1xuICAvKiogYGZpbGUuc3RhdFN5bmNgIG9mIHtAbGluayBwYXRofSwgd2hlbiBpdCBleGlzdHMuICovXG4gIHJlYWRvbmx5IHBhdGhTdGF0cz86IFN0YXRzO1xuICAvKipcbiAgICogYG91dHB1dGAgcGFyc2VkIGludG8gYSBjaGFpbmFibGUge0BsaW5rIG5ldC5VcmxCdWlsZGVyfSwgd2hlbiBpdCBpcyBhIHJlYWxcbiAgICogbmV0d29yayBVUkwgLSBhIG5vbi1ibGFuayBzY2hlbWUgKG5vdCBgZmlsZTpgKSBBTkQgYSBub24tYmxhbmsgaG9zdG5hbWUuXG4gICAqIEJhcmUgcGF0aHMsIHNjcC1saWtlIGBnaXRAaG9zdDouLi5gIHJlbW90ZXMsIGFuZCBgZmlsZTpgIFVSTHMgc3RheSB1bnNldC5cbiAgICovXG4gIHJlYWRvbmx5IHVybD86IG5ldC5VcmxCdWlsZGVyO1xufVxuXG4vKipcbiAqIGJlY2F1c2UgdGhpcyBpcyBjcnVjaWFsIGRvIG5vdCB1c2UgZXhlYy5zcGF3blN5bmNcbiAqXG4gKiBSdW4gYGNvbW1hbmQgYXJnc2AgaW4gYGN3ZGAgYW5kIGNsYXNzaWZ5IGl0cyBzdGRvdXQ6IGBwYXRoYCArIGBwYXRoU3RhdHNgIHdoZW5cbiAqIHRoZSBvdXRwdXQgbmFtZXMgc29tZXRoaW5nIG9uIGRpc2ssIGB1cmxgIChhIHtAbGluayBuZXQuVXJsQnVpbGRlcn0pIHdoZW4gaXRcbiAqIHBhcnNlcyBhcyBhIHJlYWwgbmV0d29yayBVUkwuIEVtcHR5IHtAbGluayBQcm9qZWN0Q29udGV4dH0gb24gYSBub24temVybyBleGl0XG4gKiBvciBlbXB0eSBvdXRwdXQuXG4gKi9cbmZ1bmN0aW9uIHByb2plY3RDb250ZXh0Q29tbWFuZE91dHB1dChjb21tYW5kOiBzdHJpbmcsIGFyZ3M6IHN0cmluZ1tdLCBjd2Q6IHN0cmluZyk6IFByb2plY3RDb250ZXh0IHtcbiAgY29uc3QgcmVzdWx0ID0gc3Bhd25TeW5jKGNvbW1hbmQsIGFyZ3MsIHsgY3dkLCBzdGRpbzogW1wiaWdub3JlXCIsIFwicGlwZVwiLCBcImlnbm9yZVwiXSB9KTtcbiAgY29uc3Qgb3V0cHV0ID0gcmVzdWx0Py5zdGRvdXQ/LnRvU3RyaW5nKCk/LnRyaW0oKTtcbiAgaWYgKHJlc3VsdC5zdGF0dXMgPT09IDAgJiYgb3V0cHV0KSB7XG4gICAgY29uc3QgcGF0aFN0YXRzID0gZmlsZVN0YXRTeW5jKG91dHB1dCk7XG4gICAgLy8gT25seSBhbiBFWFBMSUNJVCBgc2NoZW1lOi8vLi4uYCBjb3VudHMgYXMgYSBVUkwuIGB1cmxCdWlsZGVyYCBvdGhlcndpc2VcbiAgICAvLyBzeW50aGVzaXplcyBvbmUgKGEgYmFyZSBgZXhhbXBsZS5jb21gIC0+IGBodHRwczovL+KApmAsIGFuIGFic29sdXRlIHBhdGggLT5cbiAgICAvLyBgaHR0cDovL2xvY2FsaG9zdC/igKZgKSwgd2hpY2ggd291bGQgbWlzbGFiZWwgZGlyZWN0b3J5IG91dHB1dHMgYW5kIGJhcmVcbiAgICAvLyB0b2tlbnMgLSBzbyBnYXRlIG9uIHRoZSByYXcgb3V0cHV0IGFscmVhZHkgY2FycnlpbmcgYSBzY2hlbWUgKyBhdXRob3JpdHkuXG4gICAgY29uc3QgdXJsID0gL15bYS16XVthLXowLTkrLi1dKjpcXC9cXC8vaS50ZXN0KG91dHB1dCkgPyBuZXQudXJsQnVpbGRlcihvdXRwdXQpIDogdW5kZWZpbmVkO1xuICAgIHJldHVybiB7IGN3ZCwgb3V0cHV0LCBwYXRoOiBwYXRoU3RhdHMgPyBvdXRwdXQgOiB1bmRlZmluZWQsIHBhdGhTdGF0cywgdXJsIH07XG4gIH1cbiAgcmV0dXJuIHsgY3dkLCBvdXRwdXQgfTtcbn1cblxuLyoqXG4gKiB7QGxpbmsgcHJvamVjdENvbnRleHRDb21tYW5kT3V0cHV0fSB0aHJvdWdoIHRoZSBwcm9jZXNzLWNvbnRleHQgY2FjaGUuXG4gKlxuICogVGhlc2UgY29tbWFuZHMgKGBucG0gcHJlZml4YCwgYGdpdCByZXYtcGFyc2VgLCBgZ2ggcmVwbyB2aWV3YCkgYXJlIHB1cmVcbiAqIGZ1bmN0aW9ucyBvZiB0aGUgZGlyZWN0b3J5IHRoZXkgcnVuIGluLCBzbyB0aGVpciBvdXRwdXQgaXMgd29ydGgga2VlcGluZyAtIGJ1dFxuICogb25seSB3aGlsZSB0aGUgcHJvY2VzcyBpcyBzdGlsbCBJTiB0aGF0IGRpcmVjdG9yeS4ge0BsaW5rIGNvbnRleHQuY2FjaGVkfVxuICogb3ducyB0aGF0IHJ1bGU6IHRoZSBzbG90IHJlbWVtYmVycyB0aGUgYGN3ZGAgaXQgd2FzIGxvYWRlZCB1bmRlciBhbmQgbWlzc2VzXG4gKiBvbmNlIHRoZSBwcm9jZXNzIG1vdmVzLCBhbmQgYSBsb29rdXAgZm9yIHNvbWUgT1RIRVIgZGlyZWN0b3J5IHJ1bnMgdGhlIGNvbW1hbmRcbiAqIHdpdGhvdXQgY2FjaGluZywgc28gaXQgY2FuJ3QgZXZpY3QgdGhlIGhvdCBlbnRyeS4gVGhlIHNsb3QgbmFtZSBjYXJyaWVzIHRoZVxuICogY29tbWFuZCBhbmQgaXRzIGFyZ3VtZW50cyAob3JkZXItc2Vuc2l0aXZlKSwgc28gdHdvIGNvbW1hbmRzIG5ldmVyIHNoYXJlIG9uZS5cbiAqL1xuZnVuY3Rpb24gcHJvamVjdENvbnRleHRDb21tYW5kKGNvbW1hbmQ6IHN0cmluZywgYXJnczogc3RyaW5nW10sIGN3ZD86IHN0cmluZyk6IFByb2plY3RDb250ZXh0IHtcbiAgcmV0dXJuIGNvbnRleHQuY2FjaGVkKFxuICAgIFtcInByb2plY3RcIiwgY29tbWFuZCwgLi4uYXJnc10sXG4gICAgKHJlc29sdmVkKSA9PiBwcm9qZWN0Q29udGV4dENvbW1hbmRPdXRwdXQoY29tbWFuZCwgYXJncywgcmVzb2x2ZWQgPz8gcmVzb2x2ZShjd2QgPz8gXCIuXCIpKSxcbiAgICBjd2QgPyByZXNvbHZlKGN3ZCkgOiB1bmRlZmluZWQsXG4gICk7XG59XG5cbmZ1bmN0aW9uIG5wbVJvb3QoY3dkPzogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcGFyc2VkID0gcHJvamVjdENvbnRleHRDb21tYW5kKFwibnBtXCIsIFtcInByZWZpeFwiXSwgY3dkKTtcbiAgcmV0dXJuIHBhcnNlZC5wYXRoU3RhdHM/LmlzRGlyZWN0b3J5KCkgPyBwYXJzZWQucGF0aCA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gZ2l0Um9vdChjd2Q/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBwYXJzZWQgPSBwcm9qZWN0Q29udGV4dENvbW1hbmQoXCJnaXRcIiwgW1wicmV2LXBhcnNlXCIsIFwiLS1zaG93LXRvcGxldmVsXCJdLCBjd2QpO1xuICByZXR1cm4gcGFyc2VkLnBhdGhTdGF0cz8uaXNEaXJlY3RvcnkoKSA/IHBhcnNlZC5wYXRoIDogdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcm9vdChjd2Q6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCkpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBsZXQgY3VycmVudCA9IHJlc29sdmUoY3dkKTtcblxuICBpZiAoIWZpbGVTdGF0U3luYyhjdXJyZW50KT8uaXNEaXJlY3RvcnkoKSkge1xuICAgIGN1cnJlbnQgPSBkaXJuYW1lKGN1cnJlbnQpO1xuICB9XG4gIGNvbnN0IGJvdW5kYXJpZXMgPSBuZXcgU2V0KFxuICAgIFtucG1Sb290KGN3ZCksIGdpdFJvb3QoY3dkKV1cbiAgICAgIC5maWx0ZXIoKHBhdGgpOiBwYXRoIGlzIHN0cmluZyA9PiBwYXRoICE9PSB1bmRlZmluZWQpXG4gICAgICAubWFwKChwYXRoKSA9PiByZXNvbHZlKHBhdGgpKSxcbiAgKTtcbiAgY29uc3QgaGFzQm91bmRhcnkgPSBib3VuZGFyaWVzLnNpemUgPiAwO1xuICBsZXQgYmVzdDogeyBkaXI6IHN0cmluZzsgcHJpb3JpdHk6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIGZvciAoY29uc3QgW3ByaW9yaXR5LCBtYXJrZXJdIG9mIFJPT1RfTUFSS0VSUy5lbnRyaWVzKCkpIHtcbiAgICAgIGlmIChmaWxlU3RhdFN5bmMoam9pbihjdXJyZW50LCBtYXJrZXIpKT8uaXNGaWxlKCkpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGJlc3QgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgIHByaW9yaXR5IDwgYmVzdC5wcmlvcml0eSB8fFxuICAgICAgICAgIChwcmlvcml0eSA9PT0gYmVzdC5wcmlvcml0eSAmJiBjdXJyZW50Lmxlbmd0aCA8IGJlc3QuZGlyLmxlbmd0aClcbiAgICAgICAgKSB7XG4gICAgICAgICAgYmVzdCA9IHsgZGlyOiBjdXJyZW50LCBwcmlvcml0eSB9O1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWhhc0JvdW5kYXJ5ICYmIGJlc3QpIHtcbiAgICAgIHJldHVybiBiZXN0LmRpcjtcbiAgICB9XG4gICAgaWYgKGJvdW5kYXJpZXMuaGFzKGN1cnJlbnQpKSB7XG4gICAgICByZXR1cm4gYmVzdD8uZGlyO1xuICAgIH1cbiAgICBjb25zdCBwYXJlbnQgPSBkaXJuYW1lKGN1cnJlbnQpO1xuICAgIGlmIChwYXJlbnQgPT09IGN1cnJlbnQpIHtcbiAgICAgIHJldHVybiBiZXN0Py5kaXI7XG4gICAgfVxuICAgIGN1cnJlbnQgPSBwYXJlbnQ7XG4gIH1cbn1cblxuLyoqXG4gKiBQYXJzZSBhIGdpdCByZW1vdGUgVVJMIChgaHR0cHM6Ly8uLi5gLCBgZ2l0QGhvc3Q6b3duZXIvcmVwby5naXRgLCBldGMuKSBhbmRcbiAqIHJldHVybiB0aGUgcmVwbyBzZWdtZW50LCBzdHJpcHBpbmcgYW55IGAuZ2l0YCBzdWZmaXguIFJldHVybnMgYHVuZGVmaW5lZGAgZm9yXG4gKiBlbXB0eSBvciB1bnBhcnNhYmxlIGlucHV0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VHaXRSZW1vdGUodXJsOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCB0cmltbWVkID0gdXJsLnRyaW0oKTtcbiAgaWYgKCF0cmltbWVkKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIGNvbnN0IHNjcCA9IC9eW15AXStAW146XSs6KC4rKSQvaS5leGVjKHRyaW1tZWQpO1xuICBpZiAoc2NwKSByZXR1cm4gbGFzdFBhdGhTZWdtZW50KHNjcFsxXSA/PyBcIlwiKTtcblxuICB0cnkge1xuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSB0cmltbWVkLnJlcGxhY2UoL1xcLmdpdCQvaSwgXCJcIik7XG4gICAgY29uc3QgcGF0aG5hbWUgPSBuZXcgVVJMKG5vcm1hbGl6ZWQpLnBhdGhuYW1lO1xuICAgIGNvbnN0IHNlZ21lbnQgPSBwYXRobmFtZS5zcGxpdChcIi9cIikuZmlsdGVyKEJvb2xlYW4pLmF0KC0xKTtcbiAgICByZXR1cm4gc2VnbWVudCA/IGxhc3RQYXRoU2VnbWVudChzZWdtZW50KSA6IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBsYXN0UGF0aFNlZ21lbnQocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc2VnbWVudCA9IHBhdGguc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKS5hdCgtMSkgPz8gcGF0aDtcbiAgcmV0dXJuIHNlZ21lbnQucmVwbGFjZSgvXFwuZ2l0JC9pLCBcIlwiKTtcbn1cblxuLyoqXG4gKiBZaWVsZCBjYW5kaWRhdGUgcHJvamVjdC1yb290IGRpcmVjdG9yaWVzIGZvciBgY3dkYCwgaW4gcHJpb3JpdHkgb3JkZXI6IHRoZVxuICogYG5wbSBwcmVmaXhgLCB0aGUgZ2l0IHRvcC1sZXZlbCwgdGhlbiBgY3dkYCBpdHNlbGYuIER1cGxpY2F0ZXMgYXJlIHNraXBwZWQ7XG4gKiBvbmx5IGV4aXN0aW5nIGRpcmVjdG9yaWVzIGFyZSB5aWVsZGVkIChleGNlcHQgdGhlIGZpbmFsIGBjd2RgIGZhbGxiYWNrKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiByZXNvbHZlUHJvamVjdFJvb3RzKGN3ZDogc3RyaW5nID0gcHJvY2Vzcy5jd2QoKSk6IEdlbmVyYXRvcjxzdHJpbmc+IHtcbiAgY29uc3QgYmFzZSA9IHJlc29sdmUoY3dkKTtcbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiBbbnBtUm9vdChiYXNlKSwgZ2l0Um9vdChiYXNlKV0pIHtcbiAgICBpZiAoIWNhbmRpZGF0ZSkgY29udGludWU7XG4gICAgY29uc3QgZGlyID0gcmVzb2x2ZShjYW5kaWRhdGUpO1xuICAgIGlmIChzZWVuLmhhcyhkaXIpKSBjb250aW51ZTtcbiAgICBzZWVuLmFkZChkaXIpO1xuICAgIGlmIChmaWxlU3RhdFN5bmMoZGlyKT8uaXNEaXJlY3RvcnkoKSkgeWllbGQgZGlyO1xuICB9XG4gIGlmICghc2Vlbi5oYXMoYmFzZSkpIHlpZWxkIGJhc2U7XG59XG5cbi8qKiBUaGUgbmVhcmVzdCBhbmNlc3RvciBvZiBgY3dkYCAoZnJvbSB7QGxpbmsgcmVzb2x2ZVByb2plY3RSb290c30pIHdpdGggYSBgcGFja2FnZS5qc29uYC4gKi9cbmZ1bmN0aW9uIHdvcmtzcGFjZVJvb3QoY3dkOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpKTogc3RyaW5nIHtcbiAgbGV0IGxhc3Q6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgZm9yIChjb25zdCBkaXIgb2YgcmVzb2x2ZVByb2plY3RSb290cyhjd2QpKSB7XG4gICAgaWYgKGZpbGVTdGF0U3luYyhyZXNvbHZlKGRpciwgXCJwYWNrYWdlLmpzb25cIikpPy5pc0ZpbGUoKSkgcmV0dXJuIGRpcjtcbiAgICBsYXN0ID0gZGlyO1xuICB9XG4gIHJldHVybiBsYXN0ID8/IHJlc29sdmUoY3dkKTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIGEgaHVtYW4tZnJpZW5kbHkgcHJvamVjdCBuYW1lIGZvciB0aGUgcmVwbyByb290ZWQgYXQgYGN3ZGA6XG4gKiBgcGFja2FnZS5qc29uYCBgbmFtZWAsIHRoZW4gdGhlIGdpdCByZW1vdGUncyByZXBvIG5hbWUsIHRoZW4gdGhlIHJvb3RcbiAqIGRpcmVjdG9yeSdzIGJhc2VuYW1lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmFtZShjd2Q6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCkpOiBzdHJpbmcge1xuICBjb25zdCByb290RGlyID0gd29ya3NwYWNlUm9vdChjd2QpO1xuXG4gIGNvbnN0IGZyb21QYWNrYWdlID0gcmVhZFBhY2thZ2VOYW1lKHJlc29sdmUocm9vdERpciwgXCJwYWNrYWdlLmpzb25cIikpO1xuICBpZiAoZnJvbVBhY2thZ2UpIHJldHVybiBmcm9tUGFja2FnZTtcblxuICBjb25zdCByZW1vdGUgPSBwcm9qZWN0Q29udGV4dENvbW1hbmQoXG4gICAgXCJnaXRcIixcbiAgICBbXCItQ1wiLCByb290RGlyLCBcInJlbW90ZVwiLCBcImdldC11cmxcIiwgXCJvcmlnaW5cIl0sXG4gICAgcm9vdERpcixcbiAgKS5vdXRwdXQ7XG4gIGNvbnN0IGZyb21HaXQgPSByZW1vdGUgPyBwYXJzZUdpdFJlbW90ZShyZW1vdGUpIDogdW5kZWZpbmVkO1xuICBpZiAoZnJvbUdpdCkgcmV0dXJuIGZyb21HaXQ7XG5cbiAgcmV0dXJuIGJhc2VuYW1lKHJvb3REaXIpO1xufVxuXG4vKipcbiAqIFRoZSBHaXRIdWIgQ0xJJ3MgY2Fub25pY2FsIHJlcG8gVVJMIC0gdGhlIGVhc3kgcGF0aC4gYGdoYCBhbHJlYWR5IHJlc29sdmVzIHRoZVxuICogdHJ1ZSBob3N0IChubyBzc2gtYWxpYXMgcGFyc2luZykgYW5kIHByaW50cyBhIGNsZWFuIGBodHRwczovL2hvc3Qvb3duZXIvcmVwb2AuXG4gKiBgdW5kZWZpbmVkYCB3aGVuIGBnaGAgaXMgYWJzZW50LCB1bmF1dGhlbnRpY2F0ZWQsIG9yIHRoZSBkaXIgaXNuJ3QgYSBHSCByZXBvLlxuICovXG5mdW5jdGlvbiByZXBvc2l0b3J5VXJsRnJvbUdoKGN3ZD86IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IG91dCA9IHByb2plY3RDb250ZXh0Q29tbWFuZChcImdoXCIsIFtcInJlcG9cIiwgXCJ2aWV3XCIsIFwiLS1qc29uXCIsIFwidXJsXCJdLCBjd2QpLm91dHB1dDtcbiAgcmV0dXJuIHN0cmluZy50cmltVG9OdWxsKGpzb24ucGFyc2VSZWNvcmQob3V0KT8udXJsKSA/PyB1bmRlZmluZWQ7XG59XG5cbi8qKiBSZXNvbHZlIGFuIHNzaCBob3N0IGFsaWFzIChgfi8uc3NoL2NvbmZpZ2ApIHRvIGl0cyBlZmZlY3RpdmUgYGhvc3RuYW1lYCB2aWEgYHNzaCAtR2AuICovXG5mdW5jdGlvbiByZXNvbHZlU3NoSG9zdE5hbWUoaG9zdDogc3RyaW5nLCBjd2Q/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBsaW5lID0gcHJvamVjdENvbnRleHRDb21tYW5kKFwic3NoXCIsIFtcIi1HXCIsIGhvc3RdLCBjd2QpXG4gICAgLm91dHB1dD8uc3BsaXQoXCJcXG5cIilcbiAgICAuZmluZCgobCkgPT4gL15ob3N0bmFtZVxccy9pLnRlc3QobC50cmltKCkpKTtcbiAgY29uc3QgbmFtZSA9IGxpbmU/LnRyaW0oKS5zcGxpdCgvXFxzKy8pWzFdO1xuICByZXR1cm4gbmFtZSAmJiBuYW1lICE9PSBob3N0ID8gbmFtZSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBGYWxsYmFjazogbm9ybWFsaXplIGBnaXQgcmVtb3RlIGdldC11cmwgb3JpZ2luYCB0byBhIHBsYWluXG4gKiBgaHR0cHM6Ly9ob3N0L293bmVyL3JlcG9gIFVSTC4gc2NwLWxpa2UgLyBgc3NoOi8vYCAvIGBnaXQ6Ly9gIC9cbiAqIGVtYmVkZGVkLWNyZWRlbnRpYWwgZm9ybXMgYXJlIHJld3JpdHRlbiB0byBodHRwcywgYW5kIGFuIHNzaCBob3N0IGFsaWFzIGlzXG4gKiBmb2xsb3dlZCB0byBpdHMgcmVhbCBob3N0bmFtZS5cbiAqL1xuZnVuY3Rpb24gcmVwb3NpdG9yeVVybEZyb21HaXQoY3dkPzogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcmF3ID0gcHJvamVjdENvbnRleHRDb21tYW5kKFwiZ2l0XCIsIFtcInJlbW90ZVwiLCBcImdldC11cmxcIiwgXCJvcmlnaW5cIl0sIGN3ZCkub3V0cHV0O1xuICBpZiAoIXJhdykgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAvLyBOb3JtYWxpemUgdGhlIHNjaGVtZSB0byBodHRwcyBhdCB0aGUgc3RyaW5nIGxldmVsIGZpcnN0OiB0aGUgV0hBVFdHIGBVUkxgXG4gIC8vIHBhcnNlciBjYW4ndCBjb252ZXJ0IGEgbm9uLXNwZWNpYWwgc2NoZW1lIChgc3NoYC9gZ2l0YCkgdG8gYGh0dHBzYCAodGhlXG4gIC8vIGBwcm90b2NvbGAgc2V0dGVyIG5vLW9wcyksIGFuZCBzY3AtbGlrZSBgZ2l0QGhvc3Q6b3duZXIvcmVwb2AgaXNuJ3QgYSBVUkwgYXRcbiAgLy8gYWxsLiBSZXdyaXRlIGJvdGggaW50byBhbiBgaHR0cHM6Ly9gIHN0cmluZywgdGhlbiBsZXQge0BsaW5rIG5ldC51cmxCdWlsZGVyfVxuICAvLyBvd24gdGhlIHN0cnVjdHVyZWQgZWRpdHMgKHN0cmlwIGNyZWRlbnRpYWxzLCBzd2FwIHRoZSBob3N0KS5cbiAgbGV0IGh0dHBzID0gcmF3LnJlcGxhY2UoL15naXRcXCsvLCBcIlwiKTtcbiAgY29uc3Qgc2NwID0gL15bXkBdK0AoW146XSspOiguKykkLy5leGVjKGh0dHBzKTtcbiAgaWYgKHNjcCkgaHR0cHMgPSBgaHR0cHM6Ly8ke3NjcFsxXX0vJHtzY3BbMl19YDtcbiAgaHR0cHMgPSBodHRwcy5yZXBsYWNlKC9eKHNzaHxnaXQpOlxcL1xcLy8sIFwiaHR0cHM6Ly9cIik7XG5cbiAgbGV0IGJ1aWxkZXIgPSBuZXQudXJsQnVpbGRlcihodHRwcyk7XG4gIGlmICghYnVpbGRlcikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgLy8gRHJvcCBhbnkgZW1iZWRkZWQgYHVzZXJbOnBhc3NdQGAgY3JlZGVudGlhbHMuXG4gIGlmIChidWlsZGVyLnVzZXJuYW1lIHx8IGJ1aWxkZXIucGFzc3dvcmQpIHtcbiAgICBidWlsZGVyID0gYnVpbGRlci53aXRoKFwidXNlcm5hbWVcIiwgXCJcIikud2l0aChcInBhc3N3b3JkXCIsIFwiXCIpO1xuICB9XG4gIC8vIEZvbGxvdyBhbiBzc2ggaG9zdCBhbGlhcyB0byB0aGUgdHJ1ZSBob3N0IChzbyBgZ2l0aHViLXJlZ2dpZS1kYmAgLT4gYGdpdGh1Yi5jb21gKS5cbiAgY29uc3QgcmVhbEhvc3QgPSByZXNvbHZlU3NoSG9zdE5hbWUoYnVpbGRlci5ob3N0bmFtZSwgY3dkKTtcbiAgaWYgKHJlYWxIb3N0KSBidWlsZGVyID0gYnVpbGRlci53aXRoKFwiaG9zdG5hbWVcIiwgcmVhbEhvc3QpO1xuXG4gIHJldHVybiBgJHtidWlsZGVyLm9yaWdpbn0ke2J1aWxkZXIucGF0aG5hbWUucmVwbGFjZSgvXFwuZ2l0JC8sIFwiXCIpfWA7XG59XG5cbi8qKlxuICogVGhlIHJlcG8ncyBjYW5vbmljYWwgcmVtb3RlIFVSTCwgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGVyZSBpcyBubyBnaXQgcmVtb3RlLlxuICogVHJpZXMgYGdoIHJlcG8gdmlld2AgZmlyc3QgKGhvc3QtYWNjdXJhdGUsIG5vIHBhcnNpbmcpLCB0aGVuIG5vcm1hbGl6ZXNcbiAqIGBnaXQgcmVtb3RlIGdldC11cmwgb3JpZ2luYC4gQm90aCB1bmRlcmx5aW5nIGNvbW1hbmRzIGFyZSBjYWNoZWQgcGVyIGBjd2RgIHZpYVxuICoge0BsaW5rIHByb2plY3RDb250ZXh0Q29tbWFuZH0uXG4gKlxuICogQHBhcmFtIGN3ZCAtIGRpcmVjdG9yeSB0byByZXNvbHZlIGZyb20gKGRlZmF1bHRzIHRvIGBwcm9jZXNzLmN3ZCgpYCkuXG4gKiBAcGFyYW0gZm9ybWF0IC0gYFwiaHR0cHNcImAgKGRlZmF1bHQpIHlpZWxkcyBgaHR0cHM6Ly9ob3N0L293bmVyL3JlcG9gO1xuICogICBgXCJucG1cImAgeWllbGRzIG5wbSdzIGBnaXQraHR0cHM6Ly9ob3N0L293bmVyL3JlcG8uZ2l0YCBmb3JtIChmb3IgYVxuICogICBgcGFja2FnZS5qc29uYCBgcmVwb3NpdG9yeS51cmxgIHRoYXQgcGFzc2VzIG5wbSBwcm92ZW5hbmNlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcG9zaXRvcnlVcmwoXG4gIGN3ZDogc3RyaW5nID0gcHJvY2Vzcy5jd2QoKSxcbiAgZm9ybWF0OiBcImh0dHBzXCIgfCBcIm5wbVwiID0gXCJodHRwc1wiLFxuKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgaHR0cHMgPSByZXBvc2l0b3J5VXJsRnJvbUdoKGN3ZCkgPz8gcmVwb3NpdG9yeVVybEZyb21HaXQoY3dkKTtcbiAgaWYgKCFodHRwcykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIGZvcm1hdCA9PT0gXCJucG1cIiA/IGBnaXQrJHtodHRwcy5yZXBsYWNlKC9cXC5naXQkLywgXCJcIil9LmdpdGAgOiBodHRwcztcbn1cblxuLyoqXG4gKiBUaGUgYWN0aXZlIG5wbSByZWdpc3RyeSAoYG5wbSBjb25maWcgZ2V0IHJlZ2lzdHJ5YCkgYXMgYSBjaGFpbmFibGVcbiAqIHtAbGluayBuZXQuVXJsQnVpbGRlcn0sIG9yIGB1bmRlZmluZWRgIHdoZW4gbnBtIGlzIGFic2VudCBvciBwcmludHMgbm8gVVJMLlxuICogQ2FjaGVkIHBlciBgY3dkYCB2aWEge0BsaW5rIHByb2plY3RDb250ZXh0Q29tbWFuZH0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBucG1SZWdpc3RyeShcbiAgY3dkPzogc3RyaW5nIHwgbnVsbCxcbiAgb3B0aW9ucz86IHsgb3ZlcnJpZGVPbmx5PzogYm9vbGVhbjsgZW52VmFycz86IGJvb2xlYW4gfSxcbik6IG5ldC5VcmxCdWlsZGVyIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgY2FuZGlkYXRlcyA9IChmdW5jdGlvbiogKCkge1xuICAgIHlpZWxkIHByb2plY3RDb250ZXh0Q29tbWFuZChcbiAgICAgIFwibnBtXCIsXG4gICAgICBbXCJjb25maWdcIiwgXCJnZXRcIiwgXCJyZWdpc3RyeVwiXSxcbiAgICAgIGN3ZCA/PyB1bmRlZmluZWQsXG4gICAgKS5vdXRwdXQ/LnRyaW0oKTtcbiAgICBpZiAodHlwZW9mIHByb2Nlc3MgIT09IFwidW5kZWZpbmVkXCIgJiYgcHJvY2Vzcz8uZW52KSB7XG4gICAgICBjb25zdCBlbnZLZXkgPSBcIm5wbV9jb25maWdfcmVnaXN0cnlcIjtcbiAgICAgIGlmIChvcHRpb25zPy5lbnZWYXJzKSB7XG4gICAgICAgIHlpZWxkIHByb2Nlc3MuZW52W2VudktleV07XG4gICAgICAgIHlpZWxkIHByb2Nlc3MuZW52W2VudktleS50b1VwcGVyQ2FzZSgpXTtcbiAgICAgIH1cbiAgICB9XG4gIH0pKCk7XG4gIGZvciAoY29uc3QgY2FuZGlkYXRlIG9mIGNhbmRpZGF0ZXMpIHtcbiAgICBpZiAoY2FuZGlkYXRlKSB7XG4gICAgICBjb25zdCB1cmwgPSBuZXQudXJsQnVpbGRlcihjYW5kaWRhdGUpO1xuICAgICAgaWYgKCF1cmwpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnM/Lm92ZXJyaWRlT25seSkge1xuICAgICAgICBjb25zdCBucG1qc1JlZ2lzdHJ5VXJsID0gXCJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZ1wiO1xuICAgICAgICBjb25zdCByZWdpc3RyeVVybCA9IHVybC50b1N0cmluZygpO1xuICAgICAgICBpZiAocmVnaXN0cnlVcmwgPT09IG5wbWpzUmVnaXN0cnlVcmwgfHwgcmVnaXN0cnlVcmwuc3RhcnRzV2l0aChucG1qc1JlZ2lzdHJ5VXJsICsgXCIvXCIpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB1cmw7XG4gICAgfVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlYWRQYWNrYWdlTmFtZShwa2dQYXRoOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIWZpbGVTdGF0U3luYyhwa2dQYXRoKT8uaXNGaWxlKCkpIHJldHVybiB1bmRlZmluZWQ7XG4gIHJldHVybiBzdHJpbmcudHJpbVRvTnVsbChqc29uLnBhcnNlUmVjb3JkKHJlYWRGaWxlU3luYyhwa2dQYXRoLCBcInV0ZjhcIikpPy5uYW1lKSA/PyB1bmRlZmluZWQ7XG59XG5cbmlmIChpbXBvcnQubWV0YS5tYWluKSB7XG4gIGNvbnNvbGUubG9nKFwibnBtIHJvb3Q6XCIsIG5wbVJvb3QoKSk7XG4gIGNvbnNvbGUubG9nKFwicmVwbyByb290OlwiLCBnaXRSb290KCkpO1xuICBjb25zb2xlLmxvZyhcInBhY2thZ2Ugcm9vdDpcIiwgcm9vdCgpKTtcbiAgY29uc29sZS5sb2coXCJwcm9qZWN0IG5hbWU6XCIsIG5hbWUoKSk7XG4gIGNvbnNvbGUubG9nKFwicmVwb3NpdG9yeSB1cmw6XCIsIHJlcG9zaXRvcnlVcmwoKSk7XG4gIGNvbnNvbGUubG9nKFwicmVwb3NpdG9yeSB1cmwgKG5wbSk6XCIsIHJlcG9zaXRvcnlVcmwocHJvY2Vzcy5jd2QoKSwgXCJucG1cIikpO1xufVxuIl19
295
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvamVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcm9qZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEVBQVMsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDN0QsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDM0QsT0FBTyxFQUFFLFFBQVEsSUFBSSxZQUFZLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFckQsTUFBTSxZQUFZLEdBQUc7SUFDbkIsY0FBYztJQUNkLGNBQWM7SUFDZCxlQUFlO0lBQ2YsZUFBZTtJQUNmLGNBQWM7Q0FDTixDQUFDO0FBRVgscUZBQXFGO0FBQ3JGLE1BQU0sVUFBVSx1QkFBdUIsQ0FBQyxHQUFtQjtJQUN6RCxPQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFpQkQ7Ozs7Ozs7R0FPRztBQUNILFNBQVMsMkJBQTJCLENBQUMsT0FBZSxFQUFFLElBQWMsRUFBRSxHQUFXO0lBQy9FLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RGLE1BQU0sTUFBTSxHQUFHLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUM7SUFDbEQsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsSUFB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QUMsQ0FBQyxDQUFDO0FBQ3hFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyBTdGF0cywgcmVhZEZpbGVTeW5jIH0gZnJvbSBcIm5vZGU6ZnNcIjtcbmltcG9ydCB7IGJhc2VuYW1lLCBkaXJuYW1lLCBqb2luLCByZXNvbHZlIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuaW1wb3J0IHsganNvbiwgbmV0LCBzdHJpbmcgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgc3RhdFN5bmMgYXMgZmlsZVN0YXRTeW5jIH0gZnJvbSBcIi4vZmlsZS50c1wiO1xuXG5jb25zdCBST09UX01BUktFUlMgPSBbXG4gIFwiLnByb2plbnJjLnRzXCIsXG4gIFwiLnByb2plbnJjLmpzXCIsXG4gIFwiLnByb2plbnJjLm1qc1wiLFxuICBcIi5wcm9qZW5yYy5janNcIixcbiAgXCJwYWNrYWdlLmpzb25cIixcbl0gYXMgY29uc3Q7XG5cbi8qKiBSZXNvbHZlIGEgYmxhbmssIG51bGwsIG9taXR0ZWQsIHJlbGF0aXZlLCBvciBhYnNvbHV0ZSBjd2QgdG8gYW4gYWJzb2x1dGUgcGF0aC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlV29ya2luZ0RpcmVjdG9yeShjd2Q/OiBzdHJpbmcgfCBudWxsKTogc3RyaW5nIHtcbiAgcmV0dXJuIHJlc29sdmUoc3RyaW5nLnRyaW1Ub051bGwoY3dkKSA/PyBwcm9jZXNzLmN3ZCgpKTtcbn1cblxuLyoqIEEgY29tbWFuZCdzIHN0ZG91dCwgY2xhc3NpZmllZCBhcyBhIGZpbGVzeXN0ZW0gcGF0aCBhbmQvb3IgYSBVUkwuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb2plY3RDb250ZXh0IHtcbiAgcmVhZG9ubHkgb3V0cHV0OiBzdHJpbmc7XG4gIC8qKiBgb3V0cHV0YCB3aGVuIGl0IG5hbWVzIHNvbWV0aGluZyBvbiBkaXNrLiAqL1xuICByZWFkb25seSBwYXRoPzogc3RyaW5nO1xuICAvKiogYGZpbGUuc3RhdFN5bmNgIG9mIHtAbGluayBwYXRofSwgd2hlbiBpdCBleGlzdHMuICovXG4gIHJlYWRvbmx5IHBhdGhTdGF0cz86IFN0YXRzO1xuICAvKipcbiAgICogYG91dHB1dGAgcGFyc2VkIGludG8gYSBjaGFpbmFibGUge0BsaW5rIG5ldC5VcmxCdWlsZGVyfSwgd2hlbiBpdCBpcyBhIHJlYWxcbiAgICogbmV0d29yayBVUkwgLSBhIG5vbi1ibGFuayBzY2hlbWUgKG5vdCBgZmlsZTpgKSBBTkQgYSBub24tYmxhbmsgaG9zdG5hbWUuXG4gICAqIEJhcmUgcGF0aHMsIHNjcC1saWtlIGBnaXRAaG9zdDouLi5gIHJlbW90ZXMsIGFuZCBgZmlsZTpgIFVSTHMgc3RheSB1bnNldC5cbiAgICovXG4gIHJlYWRvbmx5IHVybD86IG5ldC5VcmxCdWlsZGVyO1xufVxuXG4vKipcbiAqIGJlY2F1c2UgdGhpcyBpcyBjcnVjaWFsIGRvIG5vdCB1c2UgZXhlYy5zcGF3blN5bmNcbiAqXG4gKiBSdW4gYGNvbW1hbmQgYXJnc2AgaW4gYGN3ZGAgYW5kIGNsYXNzaWZ5IGl0cyBzdGRvdXQ6IGBwYXRoYCArIGBwYXRoU3RhdHNgIHdoZW5cbiAqIHRoZSBvdXRwdXQgbmFtZXMgc29tZXRoaW5nIG9uIGRpc2ssIGB1cmxgIChhIHtAbGluayBuZXQuVXJsQnVpbGRlcn0pIHdoZW4gaXRcbiAqIHBhcnNlcyBhcyBhIHJlYWwgbmV0d29yayBVUkwuIEVtcHR5IHtAbGluayBQcm9qZWN0Q29udGV4dH0gb24gYSBub24temVybyBleGl0XG4gKiBvciBlbXB0eSBvdXRwdXQuXG4gKi9cbmZ1bmN0aW9uIHByb2plY3RDb250ZXh0Q29tbWFuZE91dHB1dChjb21tYW5kOiBzdHJpbmcsIGFyZ3M6IHN0cmluZ1tdLCBjd2Q6IHN0cmluZyk6IFByb2plY3RDb250ZXh0IHtcbiAgY29uc3QgcmVzdWx0ID0gc3Bhd25TeW5jKGNvbW1hbmQsIGFyZ3MsIHsgY3dkLCBzdGRpbzogW1wiaWdub3JlXCIsIFwicGlwZVwiLCBcImlnbm9yZVwiXSB9KTtcbiAgY29uc3Qgb3V0cHV0ID0gcmVzdWx0Py5zdGRvdXQ/LnRvU3RyaW5nKCk/LnRyaW0oKTtcbiAgaWYgKHJlc3VsdC5zdGF0dXMgPT09IDAgJiYgb3V0cHV0KSB7XG4gICAgY29uc3QgcGF0aFN0YXRzID0gZmlsZVN0YXRTeW5jKG91dHB1dCk7XG4gICAgLy8gT25seSBhbiBFWFBMSUNJVCBgc2NoZW1lOi8vLi4uYCBjb3VudHMgYXMgYSBVUkwuIGB1cmxCdWlsZGVyYCBvdGhlcndpc2VcbiAgICAvLyBzeW50aGVzaXplcyBvbmUgKGEgYmFyZSBgZXhhbXBsZS5jb21gIC0+IGBodHRwczovL+KApmAsIGFuIGFic29sdXRlIHBhdGggLT5cbiAgICAvLyBgaHR0cDovL2xvY2FsaG9zdC/igKZgKSwgd2hpY2ggd291bGQgbWlzbGFiZWwgZGlyZWN0b3J5IG91dHB1dHMgYW5kIGJhcmVcbiAgICAvLyB0b2tlbnMgLSBzbyBnYXRlIG9uIHRoZSByYXcgb3V0cHV0IGFscmVhZHkgY2FycnlpbmcgYSBzY2hlbWUgKyBhdXRob3JpdHkuXG4gICAgY29uc3QgdXJsID0gL15bYS16XVthLXowLTkrLi1dKjpcXC9cXC8vaS50ZXN0KG91dHB1dCkgPyBuZXQudXJsQnVpbGRlcihvdXRwdXQpIDogdW5kZWZpbmVkO1xuICAgIHJldHVybiB7IG91dHB1dCwgcGF0aDogcGF0aFN0YXRzID8gb3V0cHV0IDogdW5kZWZpbmVkLCBwYXRoU3RhdHMsIHVybCB9O1xuICB9XG4gIHJldHVybiB7IG91dHB1dCB9O1xufVxuXG5jb25zdCBwcm9qZWN0Q29tbWFuZENhY2hlID0gbmV3IE1hcDxzdHJpbmcsIFByb2plY3RDb250ZXh0PigpO1xuXG5mdW5jdGlvbiBwcm9qZWN0Q29udGV4dENvbW1hbmQoY29tbWFuZDogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSwgY3dkPzogc3RyaW5nKTogUHJvamVjdENvbnRleHQge1xuICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVXb3JraW5nRGlyZWN0b3J5KGN3ZCk7XG4gIGNvbnN0IGtleSA9XG4gICAgcmVzb2x2ZWQgPT09IHJlc29sdmVXb3JraW5nRGlyZWN0b3J5KCkgPyBKU09OLnN0cmluZ2lmeShbY29tbWFuZCwgLi4uYXJnc10pIDogdW5kZWZpbmVkO1xuICBpZiAoa2V5ICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zdCBjYWNoZWQgPSBwcm9qZWN0Q29tbWFuZENhY2hlLmdldChrZXkpO1xuICAgIGlmIChjYWNoZWQgIT09IHVuZGVmaW5lZCkgcmV0dXJuIGNhY2hlZDtcbiAgfVxuICBjb25zdCB2YWx1ZSA9IHByb2plY3RDb250ZXh0Q29tbWFuZE91dHB1dChjb21tYW5kLCBhcmdzLCByZXNvbHZlZCk7XG4gIGlmIChrZXkgIT09IHVuZGVmaW5lZCkgcHJvamVjdENvbW1hbmRDYWNoZS5zZXQoa2V5LCB2YWx1ZSk7XG4gIHJldHVybiB2YWx1ZTtcbn1cblxuZnVuY3Rpb24gY29tbWFuZFJvb3QoY29tbWFuZDogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSwgY3dkOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBwYXJzZWQgPSBwcm9qZWN0Q29udGV4dENvbW1hbmQoY29tbWFuZCwgYXJncywgY3dkKTtcbiAgcmV0dXJuIHBhcnNlZC5wYXRoU3RhdHM/LmlzRGlyZWN0b3J5KCkgPyBwYXJzZWQucGF0aCA6IHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gbnBtUm9vdChjd2Q/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVXb3JraW5nRGlyZWN0b3J5KGN3ZCk7XG4gIHJldHVybiBjb21tYW5kUm9vdChcIm5wbVwiLCBbXCJwcmVmaXhcIl0sIHJlc29sdmVkKTtcbn1cblxuZnVuY3Rpb24gZ2l0Um9vdChjd2Q/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCByZXNvbHZlZCA9IHJlc29sdmVXb3JraW5nRGlyZWN0b3J5KGN3ZCk7XG4gIHJldHVybiBjb21tYW5kUm9vdChcImdpdFwiLCBbXCJyZXYtcGFyc2VcIiwgXCItLXNob3ctdG9wbGV2ZWxcIl0sIHJlc29sdmVkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJvb3QoY3dkPzogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlV29ya2luZ0RpcmVjdG9yeShjd2QpO1xuICBsZXQgY3VycmVudCA9IHJlc29sdmVkO1xuXG4gIGlmICghZmlsZVN0YXRTeW5jKGN1cnJlbnQpPy5pc0RpcmVjdG9yeSgpKSB7XG4gICAgY3VycmVudCA9IGRpcm5hbWUoY3VycmVudCk7XG4gIH1cbiAgY29uc3QgYm91bmRhcmllcyA9IG5ldyBTZXQoXG4gICAgW25wbVJvb3QocmVzb2x2ZWQpLCBnaXRSb290KHJlc29sdmVkKV1cbiAgICAgIC5maWx0ZXIoKHBhdGgpOiBwYXRoIGlzIHN0cmluZyA9PiBwYXRoICE9PSB1bmRlZmluZWQpXG4gICAgICAubWFwKChwYXRoKSA9PiByZXNvbHZlKHBhdGgpKSxcbiAgKTtcbiAgY29uc3QgaGFzQm91bmRhcnkgPSBib3VuZGFyaWVzLnNpemUgPiAwO1xuICBsZXQgYmVzdDogeyBkaXI6IHN0cmluZzsgcHJpb3JpdHk6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIGZvciAoY29uc3QgW3ByaW9yaXR5LCBtYXJrZXJdIG9mIFJPT1RfTUFSS0VSUy5lbnRyaWVzKCkpIHtcbiAgICAgIGlmIChmaWxlU3RhdFN5bmMoam9pbihjdXJyZW50LCBtYXJrZXIpKT8uaXNGaWxlKCkpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgIGJlc3QgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgIHByaW9yaXR5IDwgYmVzdC5wcmlvcml0eSB8fFxuICAgICAgICAgIChwcmlvcml0eSA9PT0gYmVzdC5wcmlvcml0eSAmJiBjdXJyZW50Lmxlbmd0aCA8IGJlc3QuZGlyLmxlbmd0aClcbiAgICAgICAgKSB7XG4gICAgICAgICAgYmVzdCA9IHsgZGlyOiBjdXJyZW50LCBwcmlvcml0eSB9O1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWhhc0JvdW5kYXJ5ICYmIGJlc3QpIHtcbiAgICAgIHJldHVybiBiZXN0LmRpcjtcbiAgICB9XG4gICAgaWYgKGJvdW5kYXJpZXMuaGFzKGN1cnJlbnQpKSB7XG4gICAgICByZXR1cm4gYmVzdD8uZGlyO1xuICAgIH1cbiAgICBjb25zdCBwYXJlbnQgPSBkaXJuYW1lKGN1cnJlbnQpO1xuICAgIGlmIChwYXJlbnQgPT09IGN1cnJlbnQpIHtcbiAgICAgIHJldHVybiBiZXN0Py5kaXI7XG4gICAgfVxuICAgIGN1cnJlbnQgPSBwYXJlbnQ7XG4gIH1cbn1cblxuLyoqXG4gKiBQYXJzZSBhIGdpdCByZW1vdGUgVVJMIChgaHR0cHM6Ly8uLi5gLCBgZ2l0QGhvc3Q6b3duZXIvcmVwby5naXRgLCBldGMuKSBhbmRcbiAqIHJldHVybiB0aGUgcmVwbyBzZWdtZW50LCBzdHJpcHBpbmcgYW55IGAuZ2l0YCBzdWZmaXguIFJldHVybnMgYHVuZGVmaW5lZGAgZm9yXG4gKiBlbXB0eSBvciB1bnBhcnNhYmxlIGlucHV0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VHaXRSZW1vdGUodXJsOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCB0cmltbWVkID0gdXJsLnRyaW0oKTtcbiAgaWYgKCF0cmltbWVkKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIGNvbnN0IHNjcCA9IC9eW15AXStAW146XSs6KC4rKSQvaS5leGVjKHRyaW1tZWQpO1xuICBpZiAoc2NwKSByZXR1cm4gbGFzdFBhdGhTZWdtZW50KHNjcFsxXSA/PyBcIlwiKTtcblxuICB0cnkge1xuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSB0cmltbWVkLnJlcGxhY2UoL1xcLmdpdCQvaSwgXCJcIik7XG4gICAgY29uc3QgcGF0aG5hbWUgPSBuZXcgVVJMKG5vcm1hbGl6ZWQpLnBhdGhuYW1lO1xuICAgIGNvbnN0IHNlZ21lbnQgPSBwYXRobmFtZS5zcGxpdChcIi9cIikuZmlsdGVyKEJvb2xlYW4pLmF0KC0xKTtcbiAgICByZXR1cm4gc2VnbWVudCA/IGxhc3RQYXRoU2VnbWVudChzZWdtZW50KSA6IHVuZGVmaW5lZDtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBsYXN0UGF0aFNlZ21lbnQocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc2VnbWVudCA9IHBhdGguc3BsaXQoXCIvXCIpLmZpbHRlcihCb29sZWFuKS5hdCgtMSkgPz8gcGF0aDtcbiAgcmV0dXJuIHNlZ21lbnQucmVwbGFjZSgvXFwuZ2l0JC9pLCBcIlwiKTtcbn1cblxuLyoqXG4gKiBZaWVsZCBjYW5kaWRhdGUgcHJvamVjdC1yb290IGRpcmVjdG9yaWVzIGZvciBgY3dkYCwgaW4gcHJpb3JpdHkgb3JkZXI6IHRoZVxuICogYG5wbSBwcmVmaXhgLCB0aGUgZ2l0IHRvcC1sZXZlbCwgdGhlbiBgY3dkYCBpdHNlbGYuIER1cGxpY2F0ZXMgYXJlIHNraXBwZWQ7XG4gKiBvbmx5IGV4aXN0aW5nIGRpcmVjdG9yaWVzIGFyZSB5aWVsZGVkIChleGNlcHQgdGhlIGZpbmFsIGBjd2RgIGZhbGxiYWNrKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiByZXNvbHZlUHJvamVjdFJvb3RzKGN3ZD86IHN0cmluZyk6IEdlbmVyYXRvcjxzdHJpbmc+IHtcbiAgY29uc3QgYmFzZSA9IHJlc29sdmVXb3JraW5nRGlyZWN0b3J5KGN3ZCk7XG4gIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgZm9yIChjb25zdCBjYW5kaWRhdGUgb2YgW25wbVJvb3QoYmFzZSksIGdpdFJvb3QoYmFzZSldKSB7XG4gICAgaWYgKCFjYW5kaWRhdGUpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGRpciA9IHJlc29sdmUoY2FuZGlkYXRlKTtcbiAgICBpZiAoc2Vlbi5oYXMoZGlyKSkgY29udGludWU7XG4gICAgc2Vlbi5hZGQoZGlyKTtcbiAgICBpZiAoZmlsZVN0YXRTeW5jKGRpcik/LmlzRGlyZWN0b3J5KCkpIHlpZWxkIGRpcjtcbiAgfVxuICBpZiAoIXNlZW4uaGFzKGJhc2UpKSB5aWVsZCBiYXNlO1xufVxuXG4vKiogVGhlIG5lYXJlc3QgYW5jZXN0b3Igb2YgYGN3ZGAgKGZyb20ge0BsaW5rIHJlc29sdmVQcm9qZWN0Um9vdHN9KSB3aXRoIGEgYHBhY2thZ2UuanNvbmAuICovXG5mdW5jdGlvbiB3b3Jrc3BhY2VSb290KGN3ZD86IHN0cmluZyk6IHN0cmluZyB7XG4gIGxldCBsYXN0OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gIGZvciAoY29uc3QgZGlyIG9mIHJlc29sdmVQcm9qZWN0Um9vdHMoY3dkKSkge1xuICAgIGlmIChmaWxlU3RhdFN5bmMocmVzb2x2ZShkaXIsIFwicGFja2FnZS5qc29uXCIpKT8uaXNGaWxlKCkpIHJldHVybiBkaXI7XG4gICAgbGFzdCA9IGRpcjtcbiAgfVxuICByZXR1cm4gbGFzdCA/PyByZXNvbHZlV29ya2luZ0RpcmVjdG9yeShjd2QpO1xufVxuXG4vKipcbiAqIFJlc29sdmUgYSBodW1hbi1mcmllbmRseSBwcm9qZWN0IG5hbWUgZm9yIHRoZSByZXBvIHJvb3RlZCBhdCBgY3dkYDpcbiAqIGBwYWNrYWdlLmpzb25gIGBuYW1lYCwgdGhlbiB0aGUgZ2l0IHJlbW90ZSdzIHJlcG8gbmFtZSwgdGhlbiB0aGUgcm9vdFxuICogZGlyZWN0b3J5J3MgYmFzZW5hbWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuYW1lKGN3ZD86IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZVdvcmtpbmdEaXJlY3RvcnkoY3dkKTtcbiAgY29uc3Qgcm9vdERpciA9IHdvcmtzcGFjZVJvb3QocmVzb2x2ZWQpO1xuXG4gIGNvbnN0IGZyb21QYWNrYWdlID0gcmVhZFBhY2thZ2VOYW1lKHJlc29sdmUocm9vdERpciwgXCJwYWNrYWdlLmpzb25cIikpO1xuICBpZiAoZnJvbVBhY2thZ2UpIHJldHVybiBmcm9tUGFja2FnZTtcblxuICBjb25zdCByZW1vdGUgPSBwcm9qZWN0Q29udGV4dENvbW1hbmQoXG4gICAgXCJnaXRcIixcbiAgICBbXCItQ1wiLCByb290RGlyLCBcInJlbW90ZVwiLCBcImdldC11cmxcIiwgXCJvcmlnaW5cIl0sXG4gICAgcm9vdERpcixcbiAgKS5vdXRwdXQ7XG4gIGNvbnN0IGZyb21HaXQgPSByZW1vdGUgPyBwYXJzZUdpdFJlbW90ZShyZW1vdGUpIDogdW5kZWZpbmVkO1xuICBpZiAoZnJvbUdpdCkgcmV0dXJuIGZyb21HaXQ7XG5cbiAgcmV0dXJuIGJhc2VuYW1lKHJvb3REaXIpO1xufVxuXG4vKipcbiAqIFRoZSBHaXRIdWIgQ0xJJ3MgY2Fub25pY2FsIHJlcG8gVVJMIC0gdGhlIGVhc3kgcGF0aC4gYGdoYCBhbHJlYWR5IHJlc29sdmVzIHRoZVxuICogdHJ1ZSBob3N0IChubyBzc2gtYWxpYXMgcGFyc2luZykgYW5kIHByaW50cyBhIGNsZWFuIGBodHRwczovL2hvc3Qvb3duZXIvcmVwb2AuXG4gKiBgdW5kZWZpbmVkYCB3aGVuIGBnaGAgaXMgYWJzZW50LCB1bmF1dGhlbnRpY2F0ZWQsIG9yIHRoZSBkaXIgaXNuJ3QgYSBHSCByZXBvLlxuICovXG5mdW5jdGlvbiByZXBvc2l0b3J5VXJsRnJvbUdoKGN3ZD86IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IG91dCA9IHByb2plY3RDb250ZXh0Q29tbWFuZChcImdoXCIsIFtcInJlcG9cIiwgXCJ2aWV3XCIsIFwiLS1qc29uXCIsIFwidXJsXCJdLCBjd2QpLm91dHB1dDtcbiAgcmV0dXJuIHN0cmluZy50cmltVG9OdWxsKGpzb24ucGFyc2VSZWNvcmQob3V0KT8udXJsKSA/PyB1bmRlZmluZWQ7XG59XG5cbi8qKiBSZXNvbHZlIGFuIHNzaCBob3N0IGFsaWFzIChgfi8uc3NoL2NvbmZpZ2ApIHRvIGl0cyBlZmZlY3RpdmUgYGhvc3RuYW1lYCB2aWEgYHNzaCAtR2AuICovXG5mdW5jdGlvbiByZXNvbHZlU3NoSG9zdE5hbWUoaG9zdDogc3RyaW5nLCBjd2Q/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBsaW5lID0gcHJvamVjdENvbnRleHRDb21tYW5kKFwic3NoXCIsIFtcIi1HXCIsIGhvc3RdLCBjd2QpXG4gICAgLm91dHB1dD8uc3BsaXQoXCJcXG5cIilcbiAgICAuZmluZCgobCkgPT4gL15ob3N0bmFtZVxccy9pLnRlc3QobC50cmltKCkpKTtcbiAgY29uc3QgbmFtZSA9IGxpbmU/LnRyaW0oKS5zcGxpdCgvXFxzKy8pWzFdO1xuICByZXR1cm4gbmFtZSAmJiBuYW1lICE9PSBob3N0ID8gbmFtZSA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBGYWxsYmFjazogbm9ybWFsaXplIGBnaXQgcmVtb3RlIGdldC11cmwgb3JpZ2luYCB0byBhIHBsYWluXG4gKiBgaHR0cHM6Ly9ob3N0L293bmVyL3JlcG9gIFVSTC4gc2NwLWxpa2UgLyBgc3NoOi8vYCAvIGBnaXQ6Ly9gIC9cbiAqIGVtYmVkZGVkLWNyZWRlbnRpYWwgZm9ybXMgYXJlIHJld3JpdHRlbiB0byBodHRwcywgYW5kIGFuIHNzaCBob3N0IGFsaWFzIGlzXG4gKiBmb2xsb3dlZCB0byBpdHMgcmVhbCBob3N0bmFtZS5cbiAqL1xuZnVuY3Rpb24gcmVwb3NpdG9yeVVybEZyb21HaXQoY3dkPzogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcmF3ID0gcHJvamVjdENvbnRleHRDb21tYW5kKFwiZ2l0XCIsIFtcInJlbW90ZVwiLCBcImdldC11cmxcIiwgXCJvcmlnaW5cIl0sIGN3ZCkub3V0cHV0O1xuICBpZiAoIXJhdykgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAvLyBOb3JtYWxpemUgdGhlIHNjaGVtZSB0byBodHRwcyBhdCB0aGUgc3RyaW5nIGxldmVsIGZpcnN0OiB0aGUgV0hBVFdHIGBVUkxgXG4gIC8vIHBhcnNlciBjYW4ndCBjb252ZXJ0IGEgbm9uLXNwZWNpYWwgc2NoZW1lIChgc3NoYC9gZ2l0YCkgdG8gYGh0dHBzYCAodGhlXG4gIC8vIGBwcm90b2NvbGAgc2V0dGVyIG5vLW9wcyksIGFuZCBzY3AtbGlrZSBgZ2l0QGhvc3Q6b3duZXIvcmVwb2AgaXNuJ3QgYSBVUkwgYXRcbiAgLy8gYWxsLiBSZXdyaXRlIGJvdGggaW50byBhbiBgaHR0cHM6Ly9gIHN0cmluZywgdGhlbiBsZXQge0BsaW5rIG5ldC51cmxCdWlsZGVyfVxuICAvLyBvd24gdGhlIHN0cnVjdHVyZWQgZWRpdHMgKHN0cmlwIGNyZWRlbnRpYWxzLCBzd2FwIHRoZSBob3N0KS5cbiAgbGV0IGh0dHBzID0gcmF3LnJlcGxhY2UoL15naXRcXCsvLCBcIlwiKTtcbiAgY29uc3Qgc2NwID0gL15bXkBdK0AoW146XSspOiguKykkLy5leGVjKGh0dHBzKTtcbiAgaWYgKHNjcCkgaHR0cHMgPSBgaHR0cHM6Ly8ke3NjcFsxXX0vJHtzY3BbMl19YDtcbiAgaHR0cHMgPSBodHRwcy5yZXBsYWNlKC9eKHNzaHxnaXQpOlxcL1xcLy8sIFwiaHR0cHM6Ly9cIik7XG5cbiAgbGV0IGJ1aWxkZXIgPSBuZXQudXJsQnVpbGRlcihodHRwcyk7XG4gIGlmICghYnVpbGRlcikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgLy8gRHJvcCBhbnkgZW1iZWRkZWQgYHVzZXJbOnBhc3NdQGAgY3JlZGVudGlhbHMuXG4gIGlmIChidWlsZGVyLnVzZXJuYW1lIHx8IGJ1aWxkZXIucGFzc3dvcmQpIHtcbiAgICBidWlsZGVyID0gYnVpbGRlci53aXRoKFwidXNlcm5hbWVcIiwgXCJcIikud2l0aChcInBhc3N3b3JkXCIsIFwiXCIpO1xuICB9XG4gIC8vIEZvbGxvdyBhbiBzc2ggaG9zdCBhbGlhcyB0byB0aGUgdHJ1ZSBob3N0IChzbyBgZ2l0aHViLXJlZ2dpZS1kYmAgLT4gYGdpdGh1Yi5jb21gKS5cbiAgY29uc3QgcmVhbEhvc3QgPSByZXNvbHZlU3NoSG9zdE5hbWUoYnVpbGRlci5ob3N0bmFtZSwgY3dkKTtcbiAgaWYgKHJlYWxIb3N0KSBidWlsZGVyID0gYnVpbGRlci53aXRoKFwiaG9zdG5hbWVcIiwgcmVhbEhvc3QpO1xuXG4gIHJldHVybiBgJHtidWlsZGVyLm9yaWdpbn0ke2J1aWxkZXIucGF0aG5hbWUucmVwbGFjZSgvXFwuZ2l0JC8sIFwiXCIpfWA7XG59XG5cbi8qKlxuICogVGhlIHJlcG8ncyBjYW5vbmljYWwgcmVtb3RlIFVSTCwgb3IgYHVuZGVmaW5lZGAgd2hlbiB0aGVyZSBpcyBubyBnaXQgcmVtb3RlLlxuICogVHJpZXMgYGdoIHJlcG8gdmlld2AgZmlyc3QgKGhvc3QtYWNjdXJhdGUsIG5vIHBhcnNpbmcpLCB0aGVuIG5vcm1hbGl6ZXNcbiAqIGBnaXQgcmVtb3RlIGdldC11cmwgb3JpZ2luYC4gQSBibGFuaywgb21pdHRlZCwgb3IgZXhwbGljaXRseSBjdXJyZW50IGBjd2RgXG4gKiByZXVzZXMgY2FjaGVkIGNvbW1hbmQgcHJvYmVzOyBhbm90aGVyIHJlc29sdmVkIGRpcmVjdG9yeSBleGVjdXRlcyBkaXJlY3RseS5cbiAqXG4gKiBAcGFyYW0gY3dkIC0gZGlyZWN0b3J5IHRvIHJlc29sdmUgZnJvbSAoZGVmYXVsdHMgdG8gYHByb2Nlc3MuY3dkKClgKS5cbiAqIEBwYXJhbSBmb3JtYXQgLSBgXCJodHRwc1wiYCAoZGVmYXVsdCkgeWllbGRzIGBodHRwczovL2hvc3Qvb3duZXIvcmVwb2A7XG4gKiAgIGBcIm5wbVwiYCB5aWVsZHMgbnBtJ3MgYGdpdCtodHRwczovL2hvc3Qvb3duZXIvcmVwby5naXRgIGZvcm0gKGZvciBhXG4gKiAgIGBwYWNrYWdlLmpzb25gIGByZXBvc2l0b3J5LnVybGAgdGhhdCBwYXNzZXMgbnBtIHByb3ZlbmFuY2UpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVwb3NpdG9yeVVybChjd2Q/OiBzdHJpbmcsIGZvcm1hdDogXCJodHRwc1wiIHwgXCJucG1cIiA9IFwiaHR0cHNcIik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZVdvcmtpbmdEaXJlY3RvcnkoY3dkKTtcbiAgY29uc3QgaHR0cHMgPSByZXBvc2l0b3J5VXJsRnJvbUdoKHJlc29sdmVkKSA/PyByZXBvc2l0b3J5VXJsRnJvbUdpdChyZXNvbHZlZCk7XG4gIGlmICghaHR0cHMpIHJldHVybiB1bmRlZmluZWQ7XG4gIHJldHVybiBmb3JtYXQgPT09IFwibnBtXCIgPyBgZ2l0KyR7aHR0cHMucmVwbGFjZSgvXFwuZ2l0JC8sIFwiXCIpfS5naXRgIDogaHR0cHM7XG59XG5cbi8qKlxuICogVGhlIGFjdGl2ZSBucG0gcmVnaXN0cnkgKGBucG0gY29uZmlnIGdldCByZWdpc3RyeWApIGFzIGEgY2hhaW5hYmxlXG4gKiB7QGxpbmsgbmV0LlVybEJ1aWxkZXJ9LCBvciBgdW5kZWZpbmVkYCB3aGVuIG5wbSBpcyBhYnNlbnQgb3IgcHJpbnRzIG5vIFVSTC5cbiAqIEEgYmxhbmssIG51bGwsIG9taXR0ZWQsIG9yIGV4cGxpY2l0bHkgY3VycmVudCBgY3dkYCByZXVzZXMgdGhlIGNhY2hlZCBucG1cbiAqIGNvbW1hbmQ7IGFub3RoZXIgcmVzb2x2ZWQgZGlyZWN0b3J5IGV4ZWN1dGVzIGl0IGRpcmVjdGx5LiBFbnZpcm9ubWVudCBvcHRpb25zXG4gKiBhcmUgZXZhbHVhdGVkIG9uIGV2ZXJ5IGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBucG1SZWdpc3RyeShcbiAgY3dkPzogc3RyaW5nIHwgbnVsbCxcbiAgb3B0aW9ucz86IHsgb3ZlcnJpZGVPbmx5PzogYm9vbGVhbjsgZW52VmFycz86IGJvb2xlYW4gfSxcbik6IG5ldC5VcmxCdWlsZGVyIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgcmVzb2x2ZWQgPSByZXNvbHZlV29ya2luZ0RpcmVjdG9yeShjd2QpO1xuICByZXR1cm4gcmVzb2x2ZU5wbVJlZ2lzdHJ5KHJlc29sdmVkLCBvcHRpb25zKTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5wbVJlZ2lzdHJ5KFxuICBjd2Q6IHN0cmluZyB8IG51bGwgfCB1bmRlZmluZWQsXG4gIG9wdGlvbnM6IHsgb3ZlcnJpZGVPbmx5PzogYm9vbGVhbjsgZW52VmFycz86IGJvb2xlYW4gfSB8IHVuZGVmaW5lZCxcbik6IG5ldC5VcmxCdWlsZGVyIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgY2FuZGlkYXRlcyA9IChmdW5jdGlvbiogKCkge1xuICAgIHlpZWxkIHByb2plY3RDb250ZXh0Q29tbWFuZChcbiAgICAgIFwibnBtXCIsXG4gICAgICBbXCJjb25maWdcIiwgXCJnZXRcIiwgXCJyZWdpc3RyeVwiXSxcbiAgICAgIGN3ZCA/PyB1bmRlZmluZWQsXG4gICAgKS5vdXRwdXQ/LnRyaW0oKTtcbiAgICBpZiAodHlwZW9mIHByb2Nlc3MgIT09IFwidW5kZWZpbmVkXCIgJiYgcHJvY2Vzcz8uZW52KSB7XG4gICAgICBjb25zdCBlbnZLZXkgPSBcIm5wbV9jb25maWdfcmVnaXN0cnlcIjtcbiAgICAgIGlmIChvcHRpb25zPy5lbnZWYXJzKSB7XG4gICAgICAgIHlpZWxkIHByb2Nlc3MuZW52W2VudktleV07XG4gICAgICAgIHlpZWxkIHByb2Nlc3MuZW52W2VudktleS50b1VwcGVyQ2FzZSgpXTtcbiAgICAgIH1cbiAgICB9XG4gIH0pKCk7XG4gIGZvciAoY29uc3QgY2FuZGlkYXRlIG9mIGNhbmRpZGF0ZXMpIHtcbiAgICBpZiAoY2FuZGlkYXRlKSB7XG4gICAgICBjb25zdCB1cmwgPSBuZXQudXJsQnVpbGRlcihjYW5kaWRhdGUpO1xuICAgICAgaWYgKCF1cmwpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9IGVsc2UgaWYgKG9wdGlvbnM/Lm92ZXJyaWRlT25seSkge1xuICAgICAgICBjb25zdCBucG1qc1JlZ2lzdHJ5VXJsID0gXCJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZ1wiO1xuICAgICAgICBjb25zdCByZWdpc3RyeVVybCA9IHVybC50b1N0cmluZygpO1xuICAgICAgICBpZiAocmVnaXN0cnlVcmwgPT09IG5wbWpzUmVnaXN0cnlVcmwgfHwgcmVnaXN0cnlVcmwuc3RhcnRzV2l0aChucG1qc1JlZ2lzdHJ5VXJsICsgXCIvXCIpKSB7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiB1cmw7XG4gICAgfVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIHJlYWRQYWNrYWdlTmFtZShwa2dQYXRoOiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAoIWZpbGVTdGF0U3luYyhwa2dQYXRoKT8uaXNGaWxlKCkpIHJldHVybiB1bmRlZmluZWQ7XG4gIHJldHVybiBzdHJpbmcudHJpbVRvTnVsbChqc29uLnBhcnNlUmVjb3JkKHJlYWRGaWxlU3luYyhwa2dQYXRoLCBcInV0ZjhcIikpPy5uYW1lKSA/PyB1bmRlZmluZWQ7XG59XG5cbmlmIChpbXBvcnQubWV0YS5tYWluKSB7XG4gIGNvbnNvbGUubG9nKFwibnBtIHJvb3Q6XCIsIG5wbVJvb3QoKSk7XG4gIGNvbnNvbGUubG9nKFwicmVwbyByb290OlwiLCBnaXRSb290KCkpO1xuICBjb25zb2xlLmxvZyhcInBhY2thZ2Ugcm9vdDpcIiwgcm9vdCgpKTtcbiAgY29uc29sZS5sb2coXCJwcm9qZWN0IG5hbWU6XCIsIG5hbWUoKSk7XG4gIGNvbnNvbGUubG9nKFwicmVwb3NpdG9yeSB1cmw6XCIsIHJlcG9zaXRvcnlVcmwoKSk7XG4gIGNvbnNvbGUubG9nKFwicmVwb3NpdG9yeSB1cmwgKG5wbSk6XCIsIHJlcG9zaXRvcnlVcmwodW5kZWZpbmVkLCBcIm5wbVwiKSk7XG59XG4iXX0=
@@ -1 +1 @@
1
- {"root":["../src/bin.ts","../src/brand.ts","../src/config.ts","../src/exec.ts","../src/file-lock.ts","../src/file.ts","../src/process-lock.ts","../src/project.ts","../index.ts"],"version":"5.9.3"}
1
+ {"root":["../src/bin.ts","../src/brand.ts","../src/bundle.ts","../src/config.ts","../src/exec.ts","../src/file-lock.ts","../src/file.ts","../src/process-lock.ts","../src/project.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -23,7 +23,7 @@
23
23
  "typescript": "^5.9.3"
24
24
  },
25
25
  "dependencies": {
26
- "@dbx-tools/shared-core": "0.6.89",
26
+ "@dbx-tools/shared-core": "0.6.91",
27
27
  "extract-zip": "^2.0.1",
28
28
  "tar": "^7.5.22",
29
29
  "yaml": "^2.9.0",
@@ -43,7 +43,7 @@
43
43
  "./package.json": "./package.json"
44
44
  }
45
45
  },
46
- "version": "0.6.89",
46
+ "version": "0.6.91",
47
47
  "types": "./lib/index.d.ts",
48
48
  "type": "module",
49
49
  "exports": {
package/src/bundle.ts ADDED
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Streaming discovery of Databricks bundle App resources.
3
+ *
4
+ * Bundle files are found with native filesystem traversal inside a hard project
5
+ * boundary. Each candidate is resolved through `databricks bundle validate
6
+ * --output json` so includes, targets, variables, and App configuration follow
7
+ * the Databricks CLI's semantics.
8
+ *
9
+ * @module
10
+ */
11
+
12
+ import { opendir, realpath, stat } from "node:fs/promises";
13
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
14
+ import { json, object, string } from "@dbx-tools/shared-core";
15
+ import { spawn } from "./exec.ts";
16
+ import { resolveWorkingDirectory } from "./project.ts";
17
+ import { project } from "../index.ts";
18
+
19
+ const BUNDLE_FILE_NAMES = new Set(["databricks.yml", "databricks.yaml"]);
20
+ const IGNORED_DIRECTORIES = [
21
+ /^\..*/,
22
+ "node_modules",
23
+ "dist",
24
+ "build",
25
+ "out",
26
+ "target",
27
+ "tmp",
28
+ "vendor",
29
+ ] as const;
30
+
31
+ type AppResource = {
32
+ /** Absolute path to the bundle's root configuration file. */
33
+ bundlePath: string;
34
+ /** Resource key under `resources.apps`. */
35
+ key: string;
36
+ /** Absolute source directory resolved from `source_code_path`. */
37
+ sourceCodePath?: string;
38
+ /** App resource returned by `databricks bundle validate`. */
39
+ config: Record<string, unknown>;
40
+ /** Complete resolved bundle returned by `databricks bundle validate`. */
41
+ data: Record<string, unknown>;
42
+ /** Validation failure associated with partial bundle output. */
43
+ bundleFailure?: Error;
44
+ };
45
+
46
+ /**
47
+ * Stream every App resource in bundles under `projectBoundary`.
48
+ *
49
+ * `cwd` defaults to the current directory and may name a file or directory.
50
+ * Bundle files in its ancestor chain are checked before the rest of the project
51
+ * boundary. No App YAML file is required.
52
+ *
53
+ * A missing or invalid boundary/cwd, or a cwd outside the boundary, yields
54
+ * nothing. A non-zero validation with partial JSON attaches
55
+ * `bundleFailure` to each App resource parsed from that bundle. A failed
56
+ * validation with no App resources yields nothing.
57
+ */
58
+ export async function* appResources(
59
+ projectBoundary: string,
60
+ cwd?: string,
61
+ ): AsyncGenerator<AppResource, void, void> {
62
+ const boundary = await resolveDirectory(projectBoundary);
63
+ const startDirectory = await resolveStartDirectory(cwd);
64
+ if (!boundary || !startDirectory || !isWithinOrEqual(startDirectory, boundary)) {
65
+ return;
66
+ }
67
+
68
+ for await (const bundlePath of bundlePaths(boundary, startDirectory)) {
69
+ const validated = await validateBundle(bundlePath);
70
+ for (const [key, config] of Object.entries(bundleApps(validated.data))) {
71
+ if (!object.isRecord(config)) continue;
72
+ yield {
73
+ bundlePath,
74
+ key,
75
+ config,
76
+ data: validated.data,
77
+ ...object.optional(
78
+ "sourceCodePath",
79
+ resolveSourceCodePath(bundlePath, config.source_code_path),
80
+ ),
81
+ ...object.optional("bundleFailure", validated.bundleFailure),
82
+ };
83
+ }
84
+ }
85
+ }
86
+
87
+ async function resolveDirectory(value: string): Promise<string | undefined> {
88
+ try {
89
+ const resolved = await realpath(resolve(value));
90
+ return (await stat(resolved)).isDirectory() ? resolved : undefined;
91
+ } catch {
92
+ return undefined;
93
+ }
94
+ }
95
+
96
+ async function resolveStartDirectory(cwd?: string): Promise<string | undefined> {
97
+ try {
98
+ const resolved = await realpath(resolveWorkingDirectory(cwd));
99
+ const info = await stat(resolved);
100
+ if (info.isDirectory()) return resolved;
101
+ if (info.isFile()) return dirname(resolved);
102
+ return undefined;
103
+ } catch {
104
+ return undefined;
105
+ }
106
+ }
107
+
108
+ function resolveSourceCodePath(bundlePath: string, sourceCodePath: unknown): string | undefined {
109
+ if (typeof sourceCodePath !== "string") return undefined;
110
+ return isAbsolute(sourceCodePath) ? sourceCodePath : resolve(dirname(bundlePath), sourceCodePath);
111
+ }
112
+
113
+ async function* bundlePaths(
114
+ boundary: string,
115
+ startDirectory: string,
116
+ ): AsyncGenerator<string, void, void> {
117
+ const seen = new Set<string>();
118
+ let current = startDirectory;
119
+ while (isWithinOrEqual(current, boundary)) {
120
+ for (const filename of BUNDLE_FILE_NAMES) {
121
+ const candidate = join(current, filename);
122
+ if (!(await isFile(candidate))) continue;
123
+ const resolved = await realpath(candidate);
124
+ if (seen.has(resolved)) continue;
125
+ seen.add(resolved);
126
+ yield resolved;
127
+ }
128
+ if (current === boundary) break;
129
+ current = dirname(current);
130
+ }
131
+
132
+ yield* descendBundlePaths(boundary, seen);
133
+ }
134
+
135
+ async function* descendBundlePaths(
136
+ directory: string,
137
+ seen: Set<string>,
138
+ ): AsyncGenerator<string, void, void> {
139
+ const entries = await opendir(directory);
140
+ for await (const entry of entries) {
141
+ const candidate = join(directory, entry.name);
142
+ if (entry.isDirectory()) {
143
+ const ignored = IGNORED_DIRECTORIES.some((ignore) => {
144
+ if (ignore instanceof RegExp) return ignore.test(entry.name);
145
+ return ignore === entry.name;
146
+ });
147
+ if (!ignored) {
148
+ yield* descendBundlePaths(candidate, seen);
149
+ }
150
+ continue;
151
+ }
152
+ if (!entry.isFile() || !BUNDLE_FILE_NAMES.has(entry.name)) continue;
153
+ const resolved = await realpath(candidate);
154
+ if (seen.has(resolved)) continue;
155
+ seen.add(resolved);
156
+ yield resolved;
157
+ }
158
+ }
159
+
160
+ async function validateBundle(
161
+ bundlePath: string,
162
+ ): Promise<Pick<AppResource, "data" | "bundleFailure">> {
163
+ const result = await spawn("databricks", ["bundle", "validate", "--output", "json"], {
164
+ cwd: dirname(bundlePath),
165
+ stdin: "ignore",
166
+ stdout: "capture",
167
+ stderr: "capture",
168
+ });
169
+ const detail = string.trimToNull(result.stderr) ?? string.trimToNull(result.stdout);
170
+ const bundleFailure =
171
+ result.exitCode === 0
172
+ ? undefined
173
+ : new Error(
174
+ `databricks bundle validate failed for ${bundlePath} (exit ${result.exitCode})${
175
+ detail ? `: ${detail}` : ""
176
+ }`,
177
+ );
178
+
179
+ const parsed = json.parseRecord(result.stdout);
180
+ if (!parsed) {
181
+ if (bundleFailure) return { data: {}, bundleFailure };
182
+ throw new Error(`Databricks CLI returned invalid bundle JSON for ${bundlePath}`);
183
+ }
184
+ return { data: parsed, ...object.optional("bundleFailure", bundleFailure) };
185
+ }
186
+
187
+ function bundleApps(bundle: Record<string, unknown>): Record<string, unknown> {
188
+ const resources = object.isRecord(bundle.resources) ? bundle.resources : undefined;
189
+ return object.isRecord(resources?.apps) ? resources.apps : {};
190
+ }
191
+
192
+ async function isFile(path: string): Promise<boolean> {
193
+ try {
194
+ return (await stat(path)).isFile();
195
+ } catch {
196
+ return false;
197
+ }
198
+ }
199
+
200
+ function isWithinOrEqual(candidate: string, parent: string): boolean {
201
+ const path = relative(parent, candidate);
202
+ return path === "" || (path !== ".." && !path.startsWith(`..${sep}`) && !isAbsolute(path));
203
+ }
204
+
205
+ if (import.meta.main) {
206
+ const path = process.argv[2];
207
+ if (!path) throw new Error("Usage: bun bundle.ts <path>");
208
+ for await (const resource of appResources(project.root()!, path)) {
209
+ console.dir(resource, { depth: null });
210
+ }
211
+ }