@dbx-tools/core 0.9.5 → 0.9.6
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/README.md +13 -13
- package/index.ts +9 -9
- package/lib/index.d.ts +9 -9
- package/lib/index.js +7 -7
- package/lib/src/bin.js +3 -3
- package/lib/src/{brand.d.ts → brand-files.d.ts} +6 -6
- package/lib/src/brand-files.js +66 -0
- package/lib/src/bundle.js +6 -6
- package/lib/src/{config.d.ts → config-utils.d.ts} +1 -1
- package/lib/src/config-utils.js +583 -0
- package/lib/src/file-lock.js +7 -7
- package/lib/src/process-lock.js +3 -3
- package/lib/src/{project.d.ts → project-utils.d.ts} +1 -0
- package/lib/src/project-utils.js +296 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -2
- package/src/bin.ts +2 -2
- package/src/{brand.ts → brand-files.ts} +11 -11
- package/src/bundle.ts +5 -5
- package/src/{config.ts → config-utils.ts} +27 -44
- package/src/file-lock.ts +6 -6
- package/src/process-lock.ts +2 -2
- package/src/{project.ts → project-utils.ts} +5 -4
- package/lib/src/brand.js +0 -66
- package/lib/src/config.js +0 -595
- package/lib/src/project.js +0 -295
package/lib/src/project.js
DELETED
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
3
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
-
import { json, net, string } from "@dbx-tools/shared-core";
|
|
5
|
-
import { statSync as fileStatSync } from "./file.js";
|
|
6
|
-
const ROOT_MARKERS = [
|
|
7
|
-
".projenrc.ts",
|
|
8
|
-
".projenrc.js",
|
|
9
|
-
".projenrc.mjs",
|
|
10
|
-
".projenrc.cjs",
|
|
11
|
-
"package.json",
|
|
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
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* because this is crucial do not use exec.spawnSync
|
|
19
|
-
*
|
|
20
|
-
* Run `command args` in `cwd` and classify its stdout: `path` + `pathStats` when
|
|
21
|
-
* the output names something on disk, `url` (a {@link net.UrlBuilder}) when it
|
|
22
|
-
* parses as a real network URL. Empty {@link ProjectContext} on a non-zero exit
|
|
23
|
-
* or empty output.
|
|
24
|
-
*/
|
|
25
|
-
function projectContextCommandOutput(command, args, cwd) {
|
|
26
|
-
const result = spawnSync(command, args, { cwd, stdio: ["ignore", "pipe", "ignore"] });
|
|
27
|
-
const output = result?.stdout?.toString()?.trim();
|
|
28
|
-
if (result.status === 0 && output) {
|
|
29
|
-
const pathStats = fileStatSync(output);
|
|
30
|
-
// Only an EXPLICIT `scheme://...` counts as a URL. `urlBuilder` otherwise
|
|
31
|
-
// synthesizes one (a bare `example.com` -> `https://…`, an absolute path ->
|
|
32
|
-
// `http://localhost/…`), which would mislabel directory outputs and bare
|
|
33
|
-
// tokens - so gate on the raw output already carrying a scheme + authority.
|
|
34
|
-
const url = /^[a-z][a-z0-9+.-]*:\/\//i.test(output) ? net.urlBuilder(output) : undefined;
|
|
35
|
-
return { output, path: pathStats ? output : undefined, pathStats, url };
|
|
36
|
-
}
|
|
37
|
-
return { output };
|
|
38
|
-
}
|
|
39
|
-
const projectCommandCache = new Map();
|
|
40
|
-
function projectContextCommand(command, args, cwd) {
|
|
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;
|
|
52
|
-
}
|
|
53
|
-
function commandRoot(command, args, cwd) {
|
|
54
|
-
const parsed = projectContextCommand(command, args, cwd);
|
|
55
|
-
return parsed.pathStats?.isDirectory() ? parsed.path : undefined;
|
|
56
|
-
}
|
|
57
|
-
function npmRoot(cwd) {
|
|
58
|
-
const resolved = resolveWorkingDirectory(cwd);
|
|
59
|
-
return commandRoot("npm", ["prefix"], resolved);
|
|
60
|
-
}
|
|
61
|
-
function gitRoot(cwd) {
|
|
62
|
-
const resolved = resolveWorkingDirectory(cwd);
|
|
63
|
-
return commandRoot("git", ["rev-parse", "--show-toplevel"], resolved);
|
|
64
|
-
}
|
|
65
|
-
export function root(cwd) {
|
|
66
|
-
const resolved = resolveWorkingDirectory(cwd);
|
|
67
|
-
let current = resolved;
|
|
68
|
-
if (!fileStatSync(current)?.isDirectory()) {
|
|
69
|
-
current = dirname(current);
|
|
70
|
-
}
|
|
71
|
-
const boundaries = new Set([npmRoot(resolved), gitRoot(resolved)]
|
|
72
|
-
.filter((path) => path !== undefined)
|
|
73
|
-
.map((path) => resolve(path)));
|
|
74
|
-
const hasBoundary = boundaries.size > 0;
|
|
75
|
-
let best;
|
|
76
|
-
while (true) {
|
|
77
|
-
for (const [priority, marker] of ROOT_MARKERS.entries()) {
|
|
78
|
-
if (fileStatSync(join(current, marker))?.isFile()) {
|
|
79
|
-
if (best === undefined ||
|
|
80
|
-
priority < best.priority ||
|
|
81
|
-
(priority === best.priority && current.length < best.dir.length)) {
|
|
82
|
-
best = { dir: current, priority };
|
|
83
|
-
}
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
if (!hasBoundary && best) {
|
|
88
|
-
return best.dir;
|
|
89
|
-
}
|
|
90
|
-
if (boundaries.has(current)) {
|
|
91
|
-
return best?.dir;
|
|
92
|
-
}
|
|
93
|
-
const parent = dirname(current);
|
|
94
|
-
if (parent === current) {
|
|
95
|
-
return best?.dir;
|
|
96
|
-
}
|
|
97
|
-
current = parent;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Parse a git remote URL (`https://...`, `git@host:owner/repo.git`, etc.) and
|
|
102
|
-
* return the repo segment, stripping any `.git` suffix. Returns `undefined` for
|
|
103
|
-
* empty or unparsable input.
|
|
104
|
-
*/
|
|
105
|
-
export function parseGitRemote(url) {
|
|
106
|
-
const trimmed = url.trim();
|
|
107
|
-
if (!trimmed)
|
|
108
|
-
return undefined;
|
|
109
|
-
const scp = /^[^@]+@[^:]+:(.+)$/i.exec(trimmed);
|
|
110
|
-
if (scp)
|
|
111
|
-
return lastPathSegment(scp[1] ?? "");
|
|
112
|
-
try {
|
|
113
|
-
const normalized = trimmed.replace(/\.git$/i, "");
|
|
114
|
-
const pathname = new URL(normalized).pathname;
|
|
115
|
-
const segment = pathname.split("/").filter(Boolean).at(-1);
|
|
116
|
-
return segment ? lastPathSegment(segment) : undefined;
|
|
117
|
-
}
|
|
118
|
-
catch {
|
|
119
|
-
return undefined;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
function lastPathSegment(path) {
|
|
123
|
-
const segment = path.split("/").filter(Boolean).at(-1) ?? path;
|
|
124
|
-
return segment.replace(/\.git$/i, "");
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Yield candidate project-root directories for `cwd`, in priority order: the
|
|
128
|
-
* `npm prefix`, the git top-level, then `cwd` itself. Duplicates are skipped;
|
|
129
|
-
* only existing directories are yielded (except the final `cwd` fallback).
|
|
130
|
-
*/
|
|
131
|
-
export function* resolveProjectRoots(cwd) {
|
|
132
|
-
const base = resolveWorkingDirectory(cwd);
|
|
133
|
-
const seen = new Set();
|
|
134
|
-
for (const candidate of [npmRoot(base), gitRoot(base)]) {
|
|
135
|
-
if (!candidate)
|
|
136
|
-
continue;
|
|
137
|
-
const dir = resolve(candidate);
|
|
138
|
-
if (seen.has(dir))
|
|
139
|
-
continue;
|
|
140
|
-
seen.add(dir);
|
|
141
|
-
if (fileStatSync(dir)?.isDirectory())
|
|
142
|
-
yield dir;
|
|
143
|
-
}
|
|
144
|
-
if (!seen.has(base))
|
|
145
|
-
yield base;
|
|
146
|
-
}
|
|
147
|
-
/** The nearest ancestor of `cwd` (from {@link resolveProjectRoots}) with a `package.json`. */
|
|
148
|
-
function workspaceRoot(cwd) {
|
|
149
|
-
let last;
|
|
150
|
-
for (const dir of resolveProjectRoots(cwd)) {
|
|
151
|
-
if (fileStatSync(resolve(dir, "package.json"))?.isFile())
|
|
152
|
-
return dir;
|
|
153
|
-
last = dir;
|
|
154
|
-
}
|
|
155
|
-
return last ?? resolveWorkingDirectory(cwd);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Resolve a human-friendly project name for the repo rooted at `cwd`:
|
|
159
|
-
* `package.json` `name`, then the git remote's repo name, then the root
|
|
160
|
-
* directory's basename.
|
|
161
|
-
*/
|
|
162
|
-
export function name(cwd) {
|
|
163
|
-
const resolved = resolveWorkingDirectory(cwd);
|
|
164
|
-
const rootDir = workspaceRoot(resolved);
|
|
165
|
-
const fromPackage = readPackageName(resolve(rootDir, "package.json"));
|
|
166
|
-
if (fromPackage)
|
|
167
|
-
return fromPackage;
|
|
168
|
-
const remote = projectContextCommand("git", ["-C", rootDir, "remote", "get-url", "origin"], rootDir).output;
|
|
169
|
-
const fromGit = remote ? parseGitRemote(remote) : undefined;
|
|
170
|
-
if (fromGit)
|
|
171
|
-
return fromGit;
|
|
172
|
-
return basename(rootDir);
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* The GitHub CLI's canonical repo URL - the easy path. `gh` already resolves the
|
|
176
|
-
* true host (no ssh-alias parsing) and prints a clean `https://host/owner/repo`.
|
|
177
|
-
* `undefined` when `gh` is absent, unauthenticated, or the dir isn't a GH repo.
|
|
178
|
-
*/
|
|
179
|
-
function repositoryUrlFromGh(cwd) {
|
|
180
|
-
const out = projectContextCommand("gh", ["repo", "view", "--json", "url"], cwd).output;
|
|
181
|
-
return string.trimToNull(json.parseRecord(out)?.url) ?? undefined;
|
|
182
|
-
}
|
|
183
|
-
/** Resolve an ssh host alias (`~/.ssh/config`) to its effective `hostname` via `ssh -G`. */
|
|
184
|
-
function resolveSshHostName(host, cwd) {
|
|
185
|
-
const line = projectContextCommand("ssh", ["-G", host], cwd)
|
|
186
|
-
.output?.split("\n")
|
|
187
|
-
.find((l) => /^hostname\s/i.test(l.trim()));
|
|
188
|
-
const name = line?.trim().split(/\s+/)[1];
|
|
189
|
-
return name && name !== host ? name : undefined;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Fallback: normalize `git remote get-url origin` to a plain
|
|
193
|
-
* `https://host/owner/repo` URL. scp-like / `ssh://` / `git://` /
|
|
194
|
-
* embedded-credential forms are rewritten to https, and an ssh host alias is
|
|
195
|
-
* followed to its real hostname.
|
|
196
|
-
*/
|
|
197
|
-
function repositoryUrlFromGit(cwd) {
|
|
198
|
-
const raw = projectContextCommand("git", ["remote", "get-url", "origin"], cwd).output;
|
|
199
|
-
if (!raw)
|
|
200
|
-
return undefined;
|
|
201
|
-
// Normalize the scheme to https at the string level first: the WHATWG `URL`
|
|
202
|
-
// parser can't convert a non-special scheme (`ssh`/`git`) to `https` (the
|
|
203
|
-
// `protocol` setter no-ops), and scp-like `git@host:owner/repo` isn't a URL at
|
|
204
|
-
// all. Rewrite both into an `https://` string, then let {@link net.urlBuilder}
|
|
205
|
-
// own the structured edits (strip credentials, swap the host).
|
|
206
|
-
let https = raw.replace(/^git\+/, "");
|
|
207
|
-
const scp = /^[^@]+@([^:]+):(.+)$/.exec(https);
|
|
208
|
-
if (scp)
|
|
209
|
-
https = `https://${scp[1]}/${scp[2]}`;
|
|
210
|
-
https = https.replace(/^(ssh|git):\/\//, "https://");
|
|
211
|
-
let builder = net.urlBuilder(https);
|
|
212
|
-
if (!builder)
|
|
213
|
-
return undefined;
|
|
214
|
-
// Drop any embedded `user[:pass]@` credentials.
|
|
215
|
-
if (builder.username || builder.password) {
|
|
216
|
-
builder = builder.with("username", "").with("password", "");
|
|
217
|
-
}
|
|
218
|
-
// Follow an ssh host alias to the true host (so `github-reggie-db` -> `github.com`).
|
|
219
|
-
const realHost = resolveSshHostName(builder.hostname, cwd);
|
|
220
|
-
if (realHost)
|
|
221
|
-
builder = builder.with("hostname", realHost);
|
|
222
|
-
return `${builder.origin}${builder.pathname.replace(/\.git$/, "")}`;
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* The repo's canonical remote URL, or `undefined` when there is no git remote.
|
|
226
|
-
* Tries `gh repo view` first (host-accurate, no parsing), then normalizes
|
|
227
|
-
* `git remote get-url origin`. A blank, omitted, or explicitly current `cwd`
|
|
228
|
-
* reuses cached command probes; another resolved directory executes directly.
|
|
229
|
-
*
|
|
230
|
-
* @param cwd - directory to resolve from (defaults to `process.cwd()`).
|
|
231
|
-
* @param format - `"https"` (default) yields `https://host/owner/repo`;
|
|
232
|
-
* `"npm"` yields npm's `git+https://host/owner/repo.git` form (for a
|
|
233
|
-
* `package.json` `repository.url` that passes npm provenance).
|
|
234
|
-
*/
|
|
235
|
-
export function repositoryUrl(cwd, format = "https") {
|
|
236
|
-
const resolved = resolveWorkingDirectory(cwd);
|
|
237
|
-
const https = repositoryUrlFromGh(resolved) ?? repositoryUrlFromGit(resolved);
|
|
238
|
-
if (!https)
|
|
239
|
-
return undefined;
|
|
240
|
-
return format === "npm" ? `git+${https.replace(/\.git$/, "")}.git` : https;
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* The active npm registry (`npm config get registry`) as a chainable
|
|
244
|
-
* {@link net.UrlBuilder}, or `undefined` when npm is absent or prints no URL.
|
|
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.
|
|
248
|
-
*/
|
|
249
|
-
export function npmRegistry(cwd, options) {
|
|
250
|
-
const resolved = resolveWorkingDirectory(cwd);
|
|
251
|
-
return resolveNpmRegistry(resolved, options);
|
|
252
|
-
}
|
|
253
|
-
function resolveNpmRegistry(cwd, options) {
|
|
254
|
-
const candidates = (function* () {
|
|
255
|
-
yield projectContextCommand("npm", ["config", "get", "registry"], cwd ?? undefined).output?.trim();
|
|
256
|
-
if (typeof process !== "undefined" && process?.env) {
|
|
257
|
-
const envKey = "npm_config_registry";
|
|
258
|
-
if (options?.envVars) {
|
|
259
|
-
yield process.env[envKey];
|
|
260
|
-
yield process.env[envKey.toUpperCase()];
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
})();
|
|
264
|
-
for (const candidate of candidates) {
|
|
265
|
-
if (candidate) {
|
|
266
|
-
const url = net.urlBuilder(candidate);
|
|
267
|
-
if (!url) {
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
else if (options?.overrideOnly) {
|
|
271
|
-
const npmjsRegistryUrl = "https://registry.npmjs.org";
|
|
272
|
-
const registryUrl = url.toString();
|
|
273
|
-
if (registryUrl === npmjsRegistryUrl || registryUrl.startsWith(npmjsRegistryUrl + "/")) {
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return url;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
return undefined;
|
|
281
|
-
}
|
|
282
|
-
function readPackageName(pkgPath) {
|
|
283
|
-
if (!fileStatSync(pkgPath)?.isFile())
|
|
284
|
-
return undefined;
|
|
285
|
-
return string.trimToNull(json.parseRecord(readFileSync(pkgPath, "utf8"))?.name) ?? undefined;
|
|
286
|
-
}
|
|
287
|
-
if (import.meta.main) {
|
|
288
|
-
console.log("npm root:", npmRoot());
|
|
289
|
-
console.log("repo root:", gitRoot());
|
|
290
|
-
console.log("package root:", root());
|
|
291
|
-
console.log("project name:", name());
|
|
292
|
-
console.log("repository url:", repositoryUrl());
|
|
293
|
-
console.log("repository url (npm):", repositoryUrl(undefined, "npm"));
|
|
294
|
-
}
|
|
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=
|