@tscircuit/cli 0.1.43-dev.3 → 0.1.43

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/dist/main.js ADDED
@@ -0,0 +1,1260 @@
1
+ #!/usr/bin/env node
2
+
3
+ // cli/main.ts
4
+ import { Command } from "commander";
5
+
6
+ // cli/init/register.ts
7
+ import * as fs4 from "node:fs";
8
+ import * as path5 from "node:path";
9
+
10
+ // lib/shared/detect-pkg-manager.ts
11
+ import fs from "fs";
12
+ var detectPackageManager = () => {
13
+ const userAgent = process.env.npm_config_user_agent || "";
14
+ if (userAgent.startsWith("yarn")) return "yarn";
15
+ if (userAgent.startsWith("pnpm")) return "pnpm";
16
+ if (userAgent.startsWith("bun")) return "bun";
17
+ if (fs.existsSync("yarn.lock")) return "yarn";
18
+ if (fs.existsSync("pnpm-lock.yaml")) return "pnpm";
19
+ if (fs.existsSync("bun.lockb")) return "bun";
20
+ return "npm";
21
+ };
22
+
23
+ // lib/shared/setup-tsci-packages.ts
24
+ import fs2 from "node:fs";
25
+ import path from "node:path";
26
+ import { execSync } from "node:child_process";
27
+ function setupTsciProject(directory = process.cwd(), dependencies = ["@types/react", "@tscircuit/core"]) {
28
+ const projectPath = path.resolve(directory);
29
+ if (!fs2.existsSync(projectPath)) {
30
+ fs2.mkdirSync(projectPath, { recursive: true });
31
+ }
32
+ const packageManager = detectPackageManager();
33
+ console.log(`Initializing project in ${projectPath}...`);
34
+ process.chdir(projectPath);
35
+ if (!fs2.existsSync("package.json")) {
36
+ const initCommand = packageManager === "yarn" ? "yarn init -y" : packageManager === "pnpm" ? "pnpm init" : packageManager === "bun" ? "bun init -y" : "npm init -y";
37
+ execSync(initCommand, { stdio: "inherit" });
38
+ console.log("Project initialized successfully.");
39
+ }
40
+ const packageJsonPath = path.join(projectPath, "package.json");
41
+ const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
42
+ fs2.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
43
+ console.log("Updated package.json to remove unnecessary fields.");
44
+ if (dependencies.length > 0) {
45
+ console.log("Installing dependencies...");
46
+ const installCommand = packageManager === "yarn" ? `yarn add -D ${dependencies.join(" ")}` : packageManager === "pnpm" ? `pnpm add -D ${dependencies.join(" ")}` : packageManager === "bun" ? `bun add -D ${dependencies.join(" ")}` : `npm install -D ${dependencies.join(" ")}`;
47
+ execSync(installCommand, { stdio: "inherit" });
48
+ console.log("Dependencies installed successfully.");
49
+ }
50
+ return packageJson.name || "unknown";
51
+ }
52
+
53
+ // lib/shared/generate-ts-config.ts
54
+ import path2 from "node:path";
55
+
56
+ // lib/shared/write-file-if-not-exists.ts
57
+ import fs3 from "fs";
58
+ var writeFileIfNotExists = (filePath, content) => {
59
+ if (!fs3.existsSync(filePath)) {
60
+ fs3.writeFileSync(filePath, content.trimStart(), "utf-8");
61
+ console.info(`Created: ${filePath}`);
62
+ } else {
63
+ console.info(`Skipped: ${filePath} already exists`);
64
+ }
65
+ };
66
+
67
+ // lib/shared/generate-ts-config.ts
68
+ var generateTsConfig = (dir) => {
69
+ const tsconfigPath = path2.join(dir, "tsconfig.json");
70
+ const tsconfigContent = JSON.stringify(
71
+ {
72
+ compilerOptions: {
73
+ target: "ES6",
74
+ module: "ESNext",
75
+ jsx: "react-jsx",
76
+ outDir: "dist",
77
+ strict: true,
78
+ esModuleInterop: true,
79
+ moduleResolution: "node",
80
+ skipLibCheck: true,
81
+ forceConsistentCasingInFileNames: true,
82
+ resolveJsonModule: true,
83
+ sourceMap: true,
84
+ allowSyntheticDefaultImports: true,
85
+ experimentalDecorators: true
86
+ }
87
+ },
88
+ null,
89
+ 2
90
+ );
91
+ writeFileIfNotExists(tsconfigPath, tsconfigContent);
92
+ };
93
+
94
+ // lib/shared/generate-gitignore-file.ts
95
+ import path3 from "node:path";
96
+ var generateGitIgnoreFile = (dir) => {
97
+ const gitignorePath = path3.join(dir, ".gitignore");
98
+ const gitignoreContent = `# Dependencies
99
+ node_modules/
100
+
101
+ # Build output
102
+ dist/
103
+ build/
104
+
105
+ # Environment variables
106
+ .env
107
+ .env.local
108
+ .env.*.local
109
+
110
+ # IDE files
111
+ .vscode/
112
+ .idea/
113
+ *.swp
114
+ *.swo
115
+
116
+ # OS files
117
+ .DS_Store
118
+ Thumbs.db
119
+
120
+ # Debug logs
121
+ npm-debug.log*
122
+ yarn-debug.log*
123
+ yarn-error.log*
124
+ `;
125
+ writeFileIfNotExists(gitignorePath, gitignoreContent);
126
+ };
127
+
128
+ // lib/shared/generate-package-json.ts
129
+ import * as path4 from "node:path";
130
+ var generatePackageJson = (dir) => {
131
+ const packageJsonPath = path4.join(dir, "package.json");
132
+ const packageJsonContent = {
133
+ name: path4.basename(dir),
134
+ version: "1.0.0",
135
+ description: "A TSCircuit project",
136
+ main: "index.tsx",
137
+ keywords: ["tscircuit", "electronics"],
138
+ scripts: {
139
+ dev: "tsci dev",
140
+ build: "tsci build"
141
+ }
142
+ };
143
+ writeFileIfNotExists(
144
+ packageJsonPath,
145
+ JSON.stringify(packageJsonContent, null, 2)
146
+ );
147
+ };
148
+
149
+ // cli/init/register.ts
150
+ var registerInit = (program2) => {
151
+ program2.command("init").description(
152
+ "Initialize a new TSCircuit project in the specified directory (or current directory if none is provided)"
153
+ ).argument(
154
+ "[directory]",
155
+ "Directory name (optional, defaults to current directory)"
156
+ ).action((directory) => {
157
+ const projectDir = directory ? path5.resolve(process.cwd(), directory) : process.cwd();
158
+ fs4.mkdirSync(projectDir, { recursive: true });
159
+ writeFileIfNotExists(
160
+ path5.join(projectDir, "index.tsx"),
161
+ `
162
+ import "@tscircuit/core";
163
+
164
+ export default () => (
165
+ <board width="10mm" height="10mm">
166
+ <resistor resistance="1k" footprint="0402" name="R1" schX={3} pcbX={3} />
167
+ <capacitor capacitance="1000pF" footprint="0402" name="C1" schX={-3} pcbX={-3} />
168
+ <trace from=".R1 > .pin1" to=".C1 > .pin1" />
169
+ </board>
170
+ );
171
+ `
172
+ );
173
+ writeFileIfNotExists(
174
+ path5.join(projectDir, ".npmrc"),
175
+ `
176
+ @tsci:registry=https://npm.tscircuit.com
177
+ `
178
+ );
179
+ generatePackageJson(projectDir);
180
+ generateTsConfig(projectDir);
181
+ generateGitIgnoreFile(projectDir);
182
+ setupTsciProject(projectDir);
183
+ console.info(
184
+ `\u{1F389} Initialization complete! Run ${directory ? `"cd ${directory}" & ` : ""}"tsci dev" to start developing.`
185
+ );
186
+ process.exit(0);
187
+ });
188
+ };
189
+
190
+ // cli/dev/register.ts
191
+ import * as fs11 from "node:fs";
192
+ import * as net from "node:net";
193
+ import * as path11 from "node:path";
194
+
195
+ // lib/dependency-analysis/installNodeModuleTypesForSnippet.ts
196
+ import * as fs5 from "node:fs";
197
+ import * as path6 from "node:path";
198
+ import * as ts from "typescript";
199
+ async function installNodeModuleTypesForSnippet(snippetPath) {
200
+ const content = fs5.readFileSync(snippetPath, "utf-8");
201
+ const sourceFile = ts.createSourceFile(
202
+ snippetPath,
203
+ content,
204
+ ts.ScriptTarget.Latest,
205
+ true
206
+ );
207
+ const imports = [];
208
+ function visit(node) {
209
+ if (ts.isImportDeclaration(node)) {
210
+ const moduleSpecifier = node.moduleSpecifier;
211
+ if (moduleSpecifier && ts.isStringLiteral(moduleSpecifier)) {
212
+ const importPath = moduleSpecifier.text;
213
+ if (importPath.startsWith("@tsci/")) {
214
+ imports.push(importPath);
215
+ }
216
+ }
217
+ }
218
+ ts.forEachChild(node, visit);
219
+ }
220
+ visit(sourceFile);
221
+ let projectRoot = path6.dirname(snippetPath);
222
+ while (projectRoot !== path6.parse(projectRoot).root) {
223
+ if (fs5.existsSync(path6.join(projectRoot, "package.json"))) {
224
+ break;
225
+ }
226
+ projectRoot = path6.dirname(projectRoot);
227
+ }
228
+ for (const importPath of imports) {
229
+ const [owner, name] = importPath.replace("@tsci/", "").split(".");
230
+ try {
231
+ const response = await fetch(
232
+ `https://registry-api.tscircuit.com/snippets/get?owner_name=${owner}&unscoped_name=${name}`
233
+ );
234
+ if (!response.ok) {
235
+ console.warn(`Failed to fetch types for ${importPath}`);
236
+ continue;
237
+ }
238
+ const data = await response.json();
239
+ if (data.snippet.dts) {
240
+ const packageDir = path6.join(
241
+ projectRoot,
242
+ "node_modules",
243
+ "@tsci",
244
+ `${owner}.${name}`
245
+ );
246
+ fs5.mkdirSync(packageDir, { recursive: true });
247
+ fs5.writeFileSync(path6.join(packageDir, "index.d.ts"), data.snippet.dts);
248
+ }
249
+ } catch (error) {
250
+ console.warn(`Error fetching types for ${importPath}:`, error);
251
+ }
252
+ }
253
+ }
254
+
255
+ // cli/dev/DevServer.ts
256
+ import ky2 from "ky";
257
+
258
+ // lib/server/createHttpServer.ts
259
+ import * as http from "node:http";
260
+ import * as fs6 from "node:fs";
261
+ import * as path7 from "node:path";
262
+ import { getNodeHandler } from "winterspec/adapters/node";
263
+
264
+ // package.json
265
+ var package_default = {
266
+ name: "@tscircuit/cli",
267
+ main: "dist/main.js",
268
+ type: "module",
269
+ version: "0.1.42",
270
+ bin: {
271
+ tsci: "./dist/main.js"
272
+ },
273
+ scripts: {
274
+ start: "bun run dev",
275
+ dev: "bun --hot ./cli/main.ts dev ./example-dir/snippet1-basic.tsx",
276
+ build: "tsup-node cli/main.ts --format esm --sourcemap inline",
277
+ format: "biome format --write .",
278
+ "format:check": "biome format .",
279
+ cli: "bun ./cli/main.ts"
280
+ },
281
+ devDependencies: {
282
+ "@biomejs/biome": "^1.9.4",
283
+ "@tscircuit/core": "^0.0.249",
284
+ "@tscircuit/fake-snippets": "^0.0.6",
285
+ "@types/bun": "^1.1.15",
286
+ "@types/configstore": "^6.0.2",
287
+ "@types/react": "^19.0.8",
288
+ "@types/semver": "^7.5.8",
289
+ "get-port": "^7.1.0",
290
+ tempy: "^3.1.0",
291
+ tsup: "^8.3.5",
292
+ "typed-ky": "^0.0.4"
293
+ },
294
+ peerDependencies: {
295
+ typescript: "^5.0.0"
296
+ },
297
+ dependencies: {
298
+ "@tscircuit/eval": "^0.0.96",
299
+ "@tscircuit/file-server": "^0.0.13",
300
+ "@tscircuit/runframe": "^0.0.167",
301
+ "bun-match-svg": "^0.0.9",
302
+ chokidar: "4.0.1",
303
+ "circuit-json-to-readable-netlist": "^0.0.8",
304
+ "circuit-to-svg": "^0.0.101",
305
+ commander: "^12.1.0",
306
+ configstore: "^7.0.0",
307
+ cosmiconfig: "^9.0.0",
308
+ delay: "^6.0.0",
309
+ "dsn-converter": "^0.0.63",
310
+ "jwt-decode": "^4.0.0",
311
+ ky: "^1.7.4",
312
+ "make-vfs": "^1.0.15",
313
+ "perfect-cli": "^1.0.20",
314
+ redaxios: "^0.5.1",
315
+ semver: "^7.6.3"
316
+ }
317
+ };
318
+
319
+ // lib/server/createHttpServer.ts
320
+ import winterspecBundle from "@tscircuit/file-server/dist/bundle.js";
321
+
322
+ // lib/site/getIndex.ts
323
+ var getIndex = async () => {
324
+ return `<html>
325
+ <head>
326
+ </head>
327
+ <body>
328
+ <script src="https://cdn.tailwindcss.com"></script>
329
+ <div id="root">loading...</div>
330
+ <script>
331
+ globalThis.process = { env: { NODE_ENV: "production" } }
332
+ </script>
333
+ <script src="/standalone.min.js"></script>
334
+ </body>
335
+ </html>`;
336
+ };
337
+
338
+ // lib/server/createHttpServer.ts
339
+ var createHttpServer = async (port = 3020) => {
340
+ const fileServerHandler = getNodeHandler(winterspecBundle, {});
341
+ const server = http.createServer(async (req, res) => {
342
+ const url = new URL(req.url, `http://${req.headers.host}`);
343
+ if (url.pathname === "/standalone.min.js") {
344
+ const standaloneFilePath = process.env.RUNFRAME_STANDALONE_FILE_PATH || path7.resolve(
345
+ process.cwd(),
346
+ "node_modules",
347
+ "@tscircuit/runframe/dist/standalone.min.js"
348
+ );
349
+ try {
350
+ const content = fs6.readFileSync(standaloneFilePath, "utf8");
351
+ res.writeHead(200, {
352
+ "Content-Type": "application/javascript; charset=utf-8"
353
+ });
354
+ res.end(content);
355
+ return;
356
+ } catch (error) {
357
+ console.info(
358
+ "Local runframe standalone not found, falling back to the production version."
359
+ );
360
+ }
361
+ res.writeHead(302, {
362
+ Location: `https://cdn.jsdelivr.net/npm/@tscircuit/runframe@${package_default.dependencies["@tscircuit/runframe"].replace(/^[^0-9]+/, "")}/dist/standalone.min.js`
363
+ });
364
+ res.end();
365
+ return;
366
+ }
367
+ if (url.pathname === "/") {
368
+ const html = await getIndex();
369
+ res.writeHead(200, { "Content-Type": "text/html" });
370
+ res.end(html);
371
+ return;
372
+ }
373
+ if (url.pathname.startsWith("/api/")) {
374
+ req.url = req.url.replace("/api/", "/");
375
+ fileServerHandler(req, res);
376
+ return;
377
+ }
378
+ res.writeHead(404);
379
+ res.end("Not found");
380
+ });
381
+ return new Promise((resolve7) => {
382
+ server.listen(port, () => {
383
+ console.log(`Server running at http://localhost:${port}`);
384
+ resolve7({ server });
385
+ });
386
+ });
387
+ };
388
+
389
+ // lib/server/EventsWatcher.ts
390
+ import { EventEmitter } from "events";
391
+ var EventsWatcher = class extends EventEmitter {
392
+ lastPollTime;
393
+ pollInterval;
394
+ baseUrl;
395
+ polling = false;
396
+ timeoutId;
397
+ constructor(baseUrl = "http://localhost:3000", pollInterval = 1e3) {
398
+ super();
399
+ this.baseUrl = baseUrl;
400
+ this.pollInterval = pollInterval;
401
+ this.lastPollTime = (/* @__PURE__ */ new Date()).toISOString();
402
+ }
403
+ async start() {
404
+ if (this.polling) return;
405
+ this.polling = true;
406
+ await this.poll();
407
+ }
408
+ stop() {
409
+ this.polling = false;
410
+ if (this.timeoutId) {
411
+ clearTimeout(this.timeoutId);
412
+ }
413
+ }
414
+ async poll() {
415
+ if (!this.polling) return;
416
+ try {
417
+ const response = await fetch(
418
+ `${this.baseUrl}/api/events/list?since=${encodeURIComponent(this.lastPollTime)}`
419
+ );
420
+ if (!response.ok) {
421
+ throw new Error(`HTTP error! status: ${response.status}`);
422
+ }
423
+ const data = await response.json();
424
+ const latestEvent = data.event_list[data.event_list.length - 1];
425
+ this.lastPollTime = latestEvent ? latestEvent.created_at : (/* @__PURE__ */ new Date()).toISOString();
426
+ data.event_list.forEach((event) => {
427
+ this.emit(event.event_type, event);
428
+ this.emit("*", event);
429
+ });
430
+ } catch (error) {
431
+ this.emit("error", error);
432
+ }
433
+ this.timeoutId = globalThis.setTimeout(
434
+ () => this.poll(),
435
+ this.pollInterval
436
+ );
437
+ }
438
+ };
439
+
440
+ // cli/dev/DevServer.ts
441
+ import path10 from "node:path";
442
+ import fs10 from "node:fs";
443
+ import * as chokidar from "chokidar";
444
+
445
+ // lib/dependency-analysis/FilesystemTypesHandler.ts
446
+ import * as fs8 from "node:fs";
447
+ import * as path8 from "node:path";
448
+
449
+ // lib/dependency-analysis/findImportsInSnippet.ts
450
+ import * as fs7 from "node:fs";
451
+ import * as ts2 from "typescript";
452
+ function findImportsInSnippet(snippetPath) {
453
+ const content = fs7.readFileSync(snippetPath, "utf-8");
454
+ const sourceFile = ts2.createSourceFile(
455
+ snippetPath,
456
+ content,
457
+ ts2.ScriptTarget.Latest,
458
+ true
459
+ );
460
+ const imports = [];
461
+ function visit(node) {
462
+ if (ts2.isImportDeclaration(node)) {
463
+ const moduleSpecifier = node.moduleSpecifier;
464
+ if (moduleSpecifier && ts2.isStringLiteral(moduleSpecifier)) {
465
+ const importPath = moduleSpecifier.text;
466
+ if (importPath.startsWith("@tsci/")) {
467
+ imports.push(importPath);
468
+ }
469
+ }
470
+ }
471
+ ts2.forEachChild(node, visit);
472
+ }
473
+ visit(sourceFile);
474
+ return imports;
475
+ }
476
+
477
+ // lib/dependency-analysis/FilesystemTypesHandler.ts
478
+ var FilesystemTypesHandler = class {
479
+ projectRoot;
480
+ constructor(initialDir) {
481
+ this.projectRoot = this.findProjectRoot(initialDir);
482
+ }
483
+ async handleInitialTypeDependencies(filePath) {
484
+ console.log("Checking initial type dependencies...");
485
+ try {
486
+ if (!this.areTypesInstalled(filePath)) {
487
+ console.log("Installing missing initial types...");
488
+ await installNodeModuleTypesForSnippet(filePath);
489
+ }
490
+ } catch (error) {
491
+ console.warn("Error handling initial type dependencies:", error);
492
+ }
493
+ }
494
+ async handleFileTypeDependencies(filePath) {
495
+ try {
496
+ if (!this.areTypesInstalled(filePath)) {
497
+ console.log("Installing missing file types...");
498
+ await installNodeModuleTypesForSnippet(filePath);
499
+ }
500
+ } catch (error) {
501
+ console.warn("Failed to verify types:", error);
502
+ }
503
+ }
504
+ areTypesInstalled(filePath) {
505
+ const imports = findImportsInSnippet(filePath);
506
+ return imports.every((imp) => this.checkTypeExists(imp));
507
+ }
508
+ checkTypeExists(importPath) {
509
+ if (!importPath.startsWith("@tsci/")) return true;
510
+ const pathWithoutPrefix = importPath.replace("@tsci/", "");
511
+ const [owner, name] = pathWithoutPrefix.split(".");
512
+ const typePath = path8.join(
513
+ this.projectRoot,
514
+ "node_modules",
515
+ "@tsci",
516
+ `${owner}.${name}`,
517
+ "index.d.ts"
518
+ );
519
+ return fs8.existsSync(typePath);
520
+ }
521
+ findProjectRoot(startDir) {
522
+ let root = path8.resolve(startDir);
523
+ while (root !== path8.parse(root).root) {
524
+ if (fs8.existsSync(path8.join(root, "package.json"))) {
525
+ return root;
526
+ }
527
+ root = path8.dirname(root);
528
+ }
529
+ return startDir;
530
+ }
531
+ };
532
+
533
+ // lib/cli-config/index.ts
534
+ import Configstore from "configstore";
535
+ import { jwtDecode } from "jwt-decode";
536
+ var cliConfig = new Configstore(
537
+ "tscircuit"
538
+ );
539
+ var getSessionToken = () => {
540
+ return cliConfig.get("sessionToken");
541
+ };
542
+ var setSessionToken = (token) => {
543
+ cliConfig.set("sessionToken", token);
544
+ const decoded = jwtDecode(token);
545
+ cliConfig.set("githubUsername", decoded.github_username);
546
+ };
547
+ var clearSession = () => {
548
+ cliConfig.delete("sessionToken");
549
+ cliConfig.delete("githubUsername");
550
+ };
551
+ var getRegistryApiUrl = () => {
552
+ return cliConfig.get("registryApiUrl") ?? "https://registry-api.tscircuit.com";
553
+ };
554
+
555
+ // lib/registry-api/get-ky.ts
556
+ import ky from "ky";
557
+ var prettyResponseErrorHook = async (_request, _options, response) => {
558
+ if (!response.ok) {
559
+ try {
560
+ const errorData = await response.json();
561
+ throw new Error(
562
+ `FAIL [${response.status}]: ${_request.method} ${new URL(_request.url).pathname}
563
+
564
+ ${JSON.stringify(errorData, null, 2)}`
565
+ );
566
+ } catch (e) {
567
+ }
568
+ }
569
+ };
570
+ var getKy = () => {
571
+ return ky.create({
572
+ prefixUrl: getRegistryApiUrl(),
573
+ hooks: {
574
+ afterResponse: [prettyResponseErrorHook]
575
+ }
576
+ });
577
+ };
578
+
579
+ // lib/shared/push-snippet.ts
580
+ import * as fs9 from "node:fs";
581
+ import * as path9 from "node:path";
582
+ import semver from "semver";
583
+ var pushSnippet = async ({
584
+ filePath,
585
+ onExit = (code) => process.exit(code),
586
+ onError = (message) => console.error(message),
587
+ onSuccess = (message) => console.log(message)
588
+ }) => {
589
+ const sessionToken = cliConfig.get("sessionToken");
590
+ if (!sessionToken) {
591
+ onError(
592
+ "You need to log in to save snippet. Run 'tsci login' to authenticate."
593
+ );
594
+ return onExit(1);
595
+ }
596
+ let snippetFilePath = null;
597
+ if (filePath) {
598
+ snippetFilePath = path9.resolve(filePath);
599
+ } else {
600
+ const defaultEntrypoint = path9.resolve("index.tsx");
601
+ if (fs9.existsSync(defaultEntrypoint)) {
602
+ snippetFilePath = defaultEntrypoint;
603
+ onSuccess("No file provided. Using 'index.tsx' as the entrypoint.");
604
+ } else {
605
+ onError(
606
+ "No entrypoint found. Run 'tsci init' to bootstrap a basic project."
607
+ );
608
+ return onExit(1);
609
+ }
610
+ }
611
+ const packageJsonPath = path9.resolve(
612
+ path9.join(path9.dirname(snippetFilePath), "package.json")
613
+ );
614
+ let packageJson = {};
615
+ if (fs9.existsSync(packageJsonPath)) {
616
+ try {
617
+ packageJson = JSON.parse(fs9.readFileSync(packageJsonPath).toString());
618
+ } catch {
619
+ onError("Invalid package.json provided");
620
+ return onExit(1);
621
+ }
622
+ }
623
+ if (!fs9.existsSync(snippetFilePath)) {
624
+ onError(`File not found: ${snippetFilePath}`);
625
+ return onExit(1);
626
+ }
627
+ const ky3 = getKy();
628
+ const packageName = (packageJson.name ?? path9.parse(snippetFilePath).name).replace(/^@/, "");
629
+ const packageAuthor = packageJson.author?.split(" ")[0] ?? cliConfig.get("githubUsername");
630
+ const packageIdentifier = `${packageAuthor}/${packageName}`;
631
+ let packageVersion = packageJson.version ?? await ky3.post("package_releases/list", {
632
+ json: { package_name: packageIdentifier }
633
+ }).json().then(
634
+ (response) => response.package_releases?.[response.package_releases.length - 1]?.version
635
+ ).catch((error) => {
636
+ onError(`Failed to retrieve latest package version: ${error}`);
637
+ return onExit(1);
638
+ });
639
+ if (!packageVersion) {
640
+ onError("Failed to retrieve package version.");
641
+ return onExit(1);
642
+ }
643
+ const updatePackageJsonVersion = (newVersion) => {
644
+ if (packageJson.version) {
645
+ try {
646
+ packageJson.version = newVersion ?? `${packageVersion}`;
647
+ fs9.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
648
+ } catch (error) {
649
+ onError(`Failed to update package.json version: ${error}`);
650
+ }
651
+ }
652
+ };
653
+ const doesPackageExist = await ky3.post("packages/get", {
654
+ json: { name: packageIdentifier },
655
+ throwHttpErrors: false
656
+ }).json().then((response) => !(response.error?.error_code === "package_not_found"));
657
+ if (!doesPackageExist) {
658
+ await ky3.post("packages/create", {
659
+ json: { name: packageIdentifier },
660
+ headers: { Authorization: `Bearer ${sessionToken}` }
661
+ }).catch((error) => {
662
+ onError(`Error creating package: ${error}`);
663
+ return onExit(1);
664
+ });
665
+ }
666
+ const doesReleaseExist = await ky3.post("package_releases/get", {
667
+ json: {
668
+ package_name_with_version: `${packageIdentifier}@${packageVersion}`
669
+ },
670
+ throwHttpErrors: false
671
+ }).json().then((response) => {
672
+ if (response.package_release?.version) {
673
+ packageVersion = response.package_release.version;
674
+ updatePackageJsonVersion(response.package_release.version);
675
+ return true;
676
+ }
677
+ return !(response.error?.error_code === "package_release_not_found");
678
+ });
679
+ if (doesReleaseExist) {
680
+ const bumpedVersion = semver.inc(packageVersion, "patch");
681
+ onSuccess(
682
+ `Incrementing Package Version ${packageVersion} -> ${bumpedVersion}`
683
+ );
684
+ packageVersion = bumpedVersion;
685
+ updatePackageJsonVersion(packageVersion);
686
+ }
687
+ await ky3.post("package_releases/create", {
688
+ json: {
689
+ package_name_with_version: `${packageIdentifier}@${packageVersion}`
690
+ },
691
+ throwHttpErrors: false
692
+ }).catch((error) => {
693
+ onError(`Error creating release: ${error}`);
694
+ return onExit(1);
695
+ });
696
+ onSuccess("\n");
697
+ const directoryFiles = fs9.readdirSync(path9.dirname(snippetFilePath));
698
+ for (const file of directoryFiles) {
699
+ const fileExtension = path9.extname(file).replace(".", "");
700
+ if (!["json", "tsx", "ts"].includes(fileExtension)) continue;
701
+ const fileContent = fs9.readFileSync(path9.join(path9.dirname(snippetFilePath), file)).toString() ?? "";
702
+ await ky3.post("package_files/create", {
703
+ json: {
704
+ file_path: file,
705
+ content_text: fileContent,
706
+ package_name_with_version: `${packageIdentifier}@${packageVersion}`
707
+ },
708
+ throwHttpErrors: false
709
+ }).then(() => {
710
+ onSuccess(`Uploaded file ${file} to the registry.`);
711
+ }).catch((error) => {
712
+ onError(`Error uploading file ${file}: ${error}`);
713
+ });
714
+ }
715
+ onSuccess(
716
+ [
717
+ `Successfully pushed package ${packageIdentifier}@${packageVersion} to the registry!`,
718
+ `https://tscircuit.com/${packageIdentifier}`
719
+ ].join(" ")
720
+ );
721
+ };
722
+
723
+ // cli/dev/DevServer.ts
724
+ var DevServer = class {
725
+ port;
726
+ /**
727
+ * The path to a component that exports a <board /> or <group /> component
728
+ */
729
+ componentFilePath;
730
+ projectDir;
731
+ /**
732
+ * The HTTP server that hosts the file server and event bus. You can use
733
+ * fsKy to communicate with the file server/event bus
734
+ */
735
+ httpServer;
736
+ /**
737
+ * Watches for events on the event bus by polling `api/events/list`
738
+ */
739
+ eventsWatcher;
740
+ /**
741
+ * A ky instance that can be used to communicate with the file server and
742
+ * event bus
743
+ */
744
+ fsKy;
745
+ /**
746
+ * A chokidar instance that watches the project directory for file changes
747
+ */
748
+ filesystemWatcher;
749
+ typesHandler;
750
+ constructor({
751
+ port,
752
+ componentFilePath
753
+ }) {
754
+ this.port = port;
755
+ this.componentFilePath = componentFilePath;
756
+ this.projectDir = path10.dirname(componentFilePath);
757
+ this.fsKy = ky2.create({
758
+ prefixUrl: `http://localhost:${port}`
759
+ });
760
+ this.typesHandler = new FilesystemTypesHandler(this.projectDir);
761
+ }
762
+ async start() {
763
+ const { server } = await createHttpServer(this.port);
764
+ this.httpServer = server;
765
+ this.eventsWatcher = new EventsWatcher(`http://localhost:${this.port}`);
766
+ this.eventsWatcher.start();
767
+ this.eventsWatcher.on(
768
+ "FILE_UPDATED",
769
+ this.handleFileUpdatedEventFromServer.bind(this)
770
+ );
771
+ this.eventsWatcher.on(
772
+ "REQUEST_TO_SAVE_SNIPPET",
773
+ this.saveSnippet.bind(this)
774
+ );
775
+ this.filesystemWatcher = chokidar.watch(this.projectDir, {
776
+ persistent: true,
777
+ ignoreInitial: true,
778
+ ignored: ["**/node_modules/**", "**/.git/**"]
779
+ });
780
+ this.filesystemWatcher.on(
781
+ "change",
782
+ (filePath) => this.handleFileChangedOnFilesystem(filePath)
783
+ );
784
+ this.filesystemWatcher.on(
785
+ "add",
786
+ (filePath) => this.handleFileChangedOnFilesystem(filePath)
787
+ );
788
+ this.upsertInitialFiles();
789
+ this.typesHandler?.handleInitialTypeDependencies(this.componentFilePath);
790
+ }
791
+ async addEntrypoint() {
792
+ const relativeComponentFilePath = path10.relative(
793
+ this.projectDir,
794
+ this.componentFilePath
795
+ );
796
+ await this.fsKy.post("api/files/upsert", {
797
+ json: {
798
+ file_path: "entrypoint.tsx",
799
+ text_content: `
800
+ import MyCircuit from "./${relativeComponentFilePath}"
801
+
802
+ circuit.add(<MyCircuit />)
803
+ `
804
+ }
805
+ });
806
+ }
807
+ async handleFileUpdatedEventFromServer(ev) {
808
+ if (ev.initiator === "filesystem_change") return;
809
+ if (ev.file_path === "manual-edits.json") {
810
+ console.log("Manual edits updated, updating on filesystem...");
811
+ const { file } = await this.fsKy.get("api/files/get", {
812
+ searchParams: { file_path: ev.file_path }
813
+ }).json();
814
+ fs10.writeFileSync(
815
+ path10.join(this.projectDir, "manual-edits.json"),
816
+ file.text_content
817
+ );
818
+ }
819
+ }
820
+ async handleFileChangedOnFilesystem(absoluteFilePath) {
821
+ const relativeFilePath = path10.relative(this.projectDir, absoluteFilePath);
822
+ if (relativeFilePath.includes("manual-edits.json")) return;
823
+ await this.typesHandler?.handleFileTypeDependencies(absoluteFilePath);
824
+ console.log(`${relativeFilePath} saved. Applying changes...`);
825
+ await this.fsKy.post("api/files/upsert", {
826
+ json: {
827
+ file_path: relativeFilePath,
828
+ text_content: fs10.readFileSync(absoluteFilePath, "utf-8"),
829
+ initiator: "filesystem_change"
830
+ }
831
+ }).json();
832
+ }
833
+ async upsertInitialFiles() {
834
+ const relevantFiles = /* @__PURE__ */ new Set([
835
+ "entrypoint.tsx",
836
+ "manual-edits.json",
837
+ "snippet.tsx",
838
+ path10.basename(this.componentFilePath)
839
+ // Include the main component file
840
+ ]);
841
+ const fileNames = fs10.readdirSync(this.projectDir);
842
+ for (const fileName of fileNames) {
843
+ if (fs10.statSync(path10.join(this.projectDir, fileName)).isDirectory() || !relevantFiles.has(fileName))
844
+ continue;
845
+ const fileContent = fs10.readFileSync(
846
+ path10.join(this.projectDir, fileName),
847
+ "utf-8"
848
+ );
849
+ await this.fsKy.post("api/files/upsert", {
850
+ json: {
851
+ file_path: fileName,
852
+ text_content: fileContent,
853
+ initiator: "filesystem_change"
854
+ }
855
+ });
856
+ }
857
+ }
858
+ async saveSnippet() {
859
+ const postEvent = async (event) => this.fsKy.post("api/events/create", {
860
+ json: { event_type: event },
861
+ throwHttpErrors: false
862
+ });
863
+ await pushSnippet({
864
+ filePath: this.componentFilePath,
865
+ onExit: (e) => {
866
+ console.error("Failed to save snippet", e);
867
+ postEvent("FAILED_TO_SAVE_SNIPPET");
868
+ },
869
+ onError: (e) => {
870
+ console.error("Failed to save snippet", e);
871
+ postEvent("FAILED_TO_SAVE_SNIPPET");
872
+ },
873
+ onSuccess: () => {
874
+ postEvent("SNIPPET_SAVED");
875
+ }
876
+ });
877
+ }
878
+ async stop() {
879
+ this.httpServer?.close();
880
+ this.eventsWatcher?.stop();
881
+ }
882
+ };
883
+
884
+ // cli/dev/register.ts
885
+ var registerDev = (program2) => {
886
+ program2.command("dev").description("Start development server for a snippet").argument("[file]", "Path to the snippet file").option("-p, --port <number>", "Port to run server on", "3020").action(async (file, options) => {
887
+ let port = parseInt(options.port);
888
+ const isPortAvailable = (port2) => {
889
+ return new Promise((resolve7) => {
890
+ const server2 = net.createServer();
891
+ server2.once("error", () => resolve7(false));
892
+ server2.once("listening", () => {
893
+ server2.close(() => resolve7(true));
894
+ });
895
+ server2.listen(port2);
896
+ });
897
+ };
898
+ while (!await isPortAvailable(port)) {
899
+ console.log(`Port ${port} is in use, trying port ${port + 1}...`);
900
+ port += 1;
901
+ }
902
+ let absolutePath;
903
+ if (file) {
904
+ absolutePath = path11.resolve(file);
905
+ if (!absolutePath.endsWith(".tsx")) {
906
+ console.error("Error: Only .tsx files are supported");
907
+ return;
908
+ }
909
+ } else {
910
+ const entrypointPath = path11.resolve("index.tsx");
911
+ if (fs11.existsSync(entrypointPath)) {
912
+ absolutePath = entrypointPath;
913
+ console.log("Found entrypoint at:", entrypointPath);
914
+ } else {
915
+ console.log(
916
+ "No entrypoint found. Run 'tsci init' to bootstrap a basic project."
917
+ );
918
+ return;
919
+ }
920
+ }
921
+ const fileDir = path11.dirname(absolutePath);
922
+ try {
923
+ console.log("Installing types for imported snippets...");
924
+ await installNodeModuleTypesForSnippet(absolutePath);
925
+ console.log("Types installed successfully");
926
+ } catch (error) {
927
+ console.warn("Failed to install types:", error);
928
+ }
929
+ const server = new DevServer({
930
+ port,
931
+ componentFilePath: absolutePath
932
+ });
933
+ await server.start();
934
+ await server.addEntrypoint();
935
+ });
936
+ };
937
+
938
+ // cli/auth/login/register.ts
939
+ import delay from "delay";
940
+ var registerAuthLogin = (program2) => {
941
+ const loginAction = async () => {
942
+ const sessionToken = getSessionToken();
943
+ if (sessionToken) {
944
+ console.log(
945
+ "Already logged in! Use 'tsci logout' if you need to switch accounts."
946
+ );
947
+ return;
948
+ }
949
+ const ky3 = getKy();
950
+ const { login_page } = await ky3.post(
951
+ "sessions/login_page/create",
952
+ {
953
+ json: {}
954
+ }
955
+ ).json();
956
+ console.log("Please visit the following URL to log in:");
957
+ console.log(login_page.url);
958
+ while (true) {
959
+ const { login_page: new_login_page } = await ky3.post(
960
+ "sessions/login_page/get",
961
+ {
962
+ json: {
963
+ login_page_id: login_page.login_page_id
964
+ },
965
+ headers: {
966
+ Authorization: `Bearer ${login_page.login_page_auth_token}`
967
+ }
968
+ }
969
+ ).json();
970
+ if (new_login_page.was_login_successful) {
971
+ console.log("Logged in! Generating token...");
972
+ break;
973
+ }
974
+ if (new_login_page.is_expired) {
975
+ throw new Error("Login page expired");
976
+ }
977
+ await delay(1e3);
978
+ }
979
+ const { session } = await ky3.post(
980
+ "sessions/login_page/exchange_for_cli_session",
981
+ {
982
+ json: {
983
+ login_page_id: login_page.login_page_id
984
+ },
985
+ headers: {
986
+ Authorization: `Bearer ${login_page.login_page_auth_token}`
987
+ }
988
+ }
989
+ ).json();
990
+ setSessionToken(session.token);
991
+ console.log("\nReady to use!");
992
+ };
993
+ program2.commands.find((c) => c.name() === "auth").command("login").description("Authenticate CLI, login to registry").action(loginAction);
994
+ program2.command("login").description("Login to tscircuit registry").action(loginAction);
995
+ };
996
+
997
+ // cli/auth/logout/register.ts
998
+ var registerAuthLogout = (program2) => {
999
+ const logoutAction = () => {
1000
+ clearSession();
1001
+ console.log("You have been logged out!");
1002
+ };
1003
+ program2.commands.find((c) => c.name() === "auth").command("logout").description("Logout from registry").action(logoutAction);
1004
+ program2.command("logout").description("Logout from tscircuit registry").action(logoutAction);
1005
+ };
1006
+
1007
+ // cli/auth/register.ts
1008
+ var registerAuth = (program2) => {
1009
+ program2.command("auth").description("Login/logout");
1010
+ };
1011
+
1012
+ // cli/config/register.ts
1013
+ var registerConfig = (program2) => {
1014
+ program2.command("config").description("Manage tscircuit CLI configuration");
1015
+ };
1016
+
1017
+ // cli/config/print/register.ts
1018
+ var registerConfigPrint = (program2) => {
1019
+ program2.commands.find((c) => c.name() === "config").command("print").description("Print the current config").action(() => {
1020
+ console.log(JSON.stringify(cliConfig.all, null, 2));
1021
+ });
1022
+ };
1023
+
1024
+ // cli/clone/register.ts
1025
+ import * as fs12 from "node:fs";
1026
+ import * as path12 from "node:path";
1027
+ var registerClone = (program2) => {
1028
+ program2.command("clone").description("Clone a snippet from the registry").argument("<snippet>", "Snippet to clone (e.g. author/snippetName)").action(async (snippetPath) => {
1029
+ const match = snippetPath.match(/^(?:@tsci\/)?([^/.]+)[/.](.+)$/);
1030
+ if (!match) {
1031
+ console.error(
1032
+ "Invalid snippet path. Use format: author/snippetName, author.snippetName, or @tsci/author.snippetName"
1033
+ );
1034
+ process.exit(1);
1035
+ }
1036
+ const [, author, snippetName] = match;
1037
+ console.log(`Cloning ${author}/${snippetName}...`);
1038
+ const ky3 = getKy();
1039
+ let packageFileList;
1040
+ try {
1041
+ packageFileList = await ky3.post(
1042
+ "package_files/list",
1043
+ {
1044
+ json: {
1045
+ package_name: `${author}/${snippetName}`,
1046
+ use_latest_version: true
1047
+ }
1048
+ }
1049
+ ).json();
1050
+ } catch (error) {
1051
+ console.error(
1052
+ "Failed to fetch package files:",
1053
+ error instanceof Error ? error.message : error
1054
+ );
1055
+ process.exit(1);
1056
+ }
1057
+ const dirPath = path12.resolve(`${author}.${snippetName}`);
1058
+ fs12.mkdirSync(dirPath, { recursive: true });
1059
+ for (const fileInfo of packageFileList.package_files) {
1060
+ const filePath = fileInfo.file_path.replace(/^\/|dist\//g, "");
1061
+ if (!filePath) continue;
1062
+ const fullPath = path12.join(dirPath, filePath);
1063
+ fs12.mkdirSync(path12.dirname(fullPath), { recursive: true });
1064
+ try {
1065
+ const fileContent = await ky3.post(
1066
+ "package_files/get",
1067
+ {
1068
+ json: {
1069
+ package_name: `${author}/${snippetName}`,
1070
+ file_path: fileInfo.file_path
1071
+ }
1072
+ }
1073
+ ).json();
1074
+ let fileText = fileContent.package_file.content_text;
1075
+ if (filePath.endsWith(".tsx") && !fileText.includes("@tscircuit/core")) {
1076
+ fileText = `import "@tscircuit/core";
1077
+
1078
+ ${fileText}`;
1079
+ }
1080
+ fs12.writeFileSync(fullPath, fileText);
1081
+ } catch (error) {
1082
+ console.warn(
1083
+ `Skipping ${filePath} due to error:`,
1084
+ error instanceof Error ? error.message : error
1085
+ );
1086
+ }
1087
+ }
1088
+ fs12.writeFileSync(
1089
+ path12.join(dirPath, ".npmrc"),
1090
+ "@tsci:registry=https://npm.tscircuit.com"
1091
+ );
1092
+ generateTsConfig(dirPath);
1093
+ setupTsciProject(dirPath);
1094
+ console.log(`Successfully cloned to ${dirPath}/`);
1095
+ console.log(
1096
+ `Run "cd ${path12.dirname(dirPath)} && tsci dev" to start developing.`
1097
+ );
1098
+ });
1099
+ };
1100
+
1101
+ // cli/main.ts
1102
+ import { perfectCli } from "perfect-cli";
1103
+ import semver2 from "semver";
1104
+
1105
+ // cli/export/register.ts
1106
+ import { createCircuitWebWorker } from "@tscircuit/eval";
1107
+ import webWorkerBundleUrl from "@tscircuit/eval/blob-url";
1108
+ import { getVirtualFileSystemFromDirPath } from "make-vfs";
1109
+ import path13 from "node:path";
1110
+ import fs13 from "node:fs";
1111
+ import {
1112
+ convertCircuitJsonToSchematicSvg,
1113
+ convertCircuitJsonToPcbSvg
1114
+ } from "circuit-to-svg";
1115
+ import { convertCircuitJsonToDsnString } from "dsn-converter";
1116
+ import { convertCircuitJsonToReadableNetlist } from "circuit-json-to-readable-netlist";
1117
+ var ALLOWED_FORMATS = [
1118
+ "json",
1119
+ "circuit-json",
1120
+ "schematic-svg",
1121
+ "pcb-svg",
1122
+ "gerbers",
1123
+ "readable-netlist",
1124
+ "gltf",
1125
+ "specctra-dsn"
1126
+ ];
1127
+ var OUTPUT_EXTENSIONS = {
1128
+ json: ".circuit.json",
1129
+ "circuit-json": ".circuit.json",
1130
+ "schematic-svg": "-schematic.svg",
1131
+ "pcb-svg": "-pcb.svg",
1132
+ gerbers: "-gerbers.zip",
1133
+ "readable-netlist": "-readable.netlist",
1134
+ gltf: ".gltf",
1135
+ "specctra-dsn": ".dsn"
1136
+ };
1137
+ var registerExport = (program2) => {
1138
+ program2.command("export").description("Export tscircuit code to various formats").argument("<file>", "Path to the snippet file").option("-f, --format <format>", "Output format").option("-o, --output <path>", "Output file path").action(async (file, options) => {
1139
+ const { format = "circuit-json" } = options;
1140
+ let { output } = options;
1141
+ if (!ALLOWED_FORMATS.includes(format)) {
1142
+ throw new Error(
1143
+ `Invalid format: ${format}
1144
+ Supported formats: ${ALLOWED_FORMATS.join(",")}`
1145
+ );
1146
+ }
1147
+ if (!output) {
1148
+ output = path13.basename(file).replace(/\.[^.]+$/, "");
1149
+ }
1150
+ const worker = await createCircuitWebWorker({
1151
+ webWorkerUrl: webWorkerBundleUrl
1152
+ });
1153
+ const projectDir = path13.dirname(file);
1154
+ const relativeComponentPath = path13.relative(projectDir, file);
1155
+ await worker.executeWithFsMap({
1156
+ entrypoint: "entrypoint.tsx",
1157
+ fsMap: {
1158
+ ...await getVirtualFileSystemFromDirPath({
1159
+ dirPath: projectDir,
1160
+ contentFormat: "string"
1161
+ }),
1162
+ "entrypoint.tsx": `
1163
+ import MyCircuit from "./${relativeComponentPath}"
1164
+
1165
+ circuit.add(<MyCircuit />)
1166
+ `
1167
+ }
1168
+ });
1169
+ await worker.renderUntilSettled();
1170
+ const circuitJson = await worker.getCircuitJson();
1171
+ const outputPath = path13.join(
1172
+ projectDir,
1173
+ `${output}${OUTPUT_EXTENSIONS[format]}`
1174
+ );
1175
+ let outputContent;
1176
+ switch (format) {
1177
+ case "schematic-svg":
1178
+ outputContent = convertCircuitJsonToSchematicSvg(circuitJson);
1179
+ break;
1180
+ case "pcb-svg":
1181
+ outputContent = convertCircuitJsonToPcbSvg(circuitJson);
1182
+ break;
1183
+ case "specctra-dsn":
1184
+ outputContent = convertCircuitJsonToDsnString(circuitJson);
1185
+ break;
1186
+ case "readable-netlist":
1187
+ outputContent = convertCircuitJsonToReadableNetlist(circuitJson);
1188
+ break;
1189
+ default:
1190
+ outputContent = JSON.stringify(circuitJson);
1191
+ }
1192
+ fs13.writeFileSync(outputPath, outputContent);
1193
+ console.log(`Exported to ${outputPath}`);
1194
+ process.exit(0);
1195
+ });
1196
+ };
1197
+
1198
+ // cli/auth/print-token/register.ts
1199
+ var registerAuthPrintToken = (program2) => {
1200
+ program2.commands.find((c) => c.name() === "auth").command("print-token").description("Prints your auth token").action(() => {
1201
+ const token = cliConfig.get("sessionToken");
1202
+ if (!token) return console.log("You need to log in to access this.");
1203
+ console.log("Your Token:\n", token);
1204
+ });
1205
+ };
1206
+
1207
+ // cli/auth/set-token/register.ts
1208
+ function validateJWTLength(token) {
1209
+ const parts = token.split(".");
1210
+ if (parts.length === 3 && parts.every((part) => part.length > 0)) {
1211
+ return true;
1212
+ } else {
1213
+ return false;
1214
+ }
1215
+ }
1216
+ var registerAuthSetToken = (program2) => {
1217
+ program2.commands.find((c) => c.name() === "auth").command("set-token").description("Explicitly set your auth token").argument("<token>", "New token to manually configure").action((token) => {
1218
+ if (!validateJWTLength(token))
1219
+ return console.log("Invalid token provided");
1220
+ setSessionToken(token);
1221
+ console.log("Token manually updated.");
1222
+ });
1223
+ };
1224
+
1225
+ // cli/push/register.ts
1226
+ var registerPush = (program2) => {
1227
+ program2.command("push").description("Save snippet code to Registry API").argument("[file]", "Path to the snippet file").action(async (filePath) => {
1228
+ await pushSnippet({
1229
+ filePath,
1230
+ onExit: (code) => process.exit(code),
1231
+ onError: (message) => console.error(message),
1232
+ onSuccess: (message) => console.log(message)
1233
+ });
1234
+ });
1235
+ };
1236
+
1237
+ // cli/main.ts
1238
+ var program = new Command();
1239
+ program.name("tsci").description("CLI for developing tscircuit snippets").version(semver2.inc(package_default.version, "patch") ?? package_default.version);
1240
+ registerInit(program);
1241
+ registerDev(program);
1242
+ registerClone(program);
1243
+ registerPush(program);
1244
+ registerAuth(program);
1245
+ registerAuthLogin(program);
1246
+ registerAuthLogout(program);
1247
+ registerAuthPrintToken(program);
1248
+ registerAuthSetToken(program);
1249
+ registerConfig(program);
1250
+ registerConfigPrint(program);
1251
+ registerExport(program);
1252
+ if (process.argv.length === 2) {
1253
+ perfectCli(program, process.argv);
1254
+ } else {
1255
+ program.parse();
1256
+ }
1257
+ export {
1258
+ program
1259
+ };
1260
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vY2xpL21haW4udHMiLCAiLi4vY2xpL2luaXQvcmVnaXN0ZXIudHMiLCAiLi4vbGliL3NoYXJlZC9kZXRlY3QtcGtnLW1hbmFnZXIudHMiLCAiLi4vbGliL3NoYXJlZC9zZXR1cC10c2NpLXBhY2thZ2VzLnRzIiwgIi4uL2xpYi9zaGFyZWQvZ2VuZXJhdGUtdHMtY29uZmlnLnRzIiwgIi4uL2xpYi9zaGFyZWQvd3JpdGUtZmlsZS1pZi1ub3QtZXhpc3RzLnRzIiwgIi4uL2xpYi9zaGFyZWQvZ2VuZXJhdGUtZ2l0aWdub3JlLWZpbGUudHMiLCAiLi4vbGliL3NoYXJlZC9nZW5lcmF0ZS1wYWNrYWdlLWpzb24udHMiLCAiLi4vY2xpL2Rldi9yZWdpc3Rlci50cyIsICIuLi9saWIvZGVwZW5kZW5jeS1hbmFseXNpcy9pbnN0YWxsTm9kZU1vZHVsZVR5cGVzRm9yU25pcHBldC50cyIsICIuLi9jbGkvZGV2L0RldlNlcnZlci50cyIsICIuLi9saWIvc2VydmVyL2NyZWF0ZUh0dHBTZXJ2ZXIudHMiLCAiLi4vcGFja2FnZS5qc29uIiwgIi4uL2xpYi9zaXRlL2dldEluZGV4LnRzIiwgIi4uL2xpYi9zZXJ2ZXIvRXZlbnRzV2F0Y2hlci50cyIsICIuLi9saWIvZGVwZW5kZW5jeS1hbmFseXNpcy9GaWxlc3lzdGVtVHlwZXNIYW5kbGVyLnRzIiwgIi4uL2xpYi9kZXBlbmRlbmN5LWFuYWx5c2lzL2ZpbmRJbXBvcnRzSW5TbmlwcGV0LnRzIiwgIi4uL2xpYi9jbGktY29uZmlnL2luZGV4LnRzIiwgIi4uL2xpYi9yZWdpc3RyeS1hcGkvZ2V0LWt5LnRzIiwgIi4uL2xpYi9zaGFyZWQvcHVzaC1zbmlwcGV0LnRzIiwgIi4uL2NsaS9hdXRoL2xvZ2luL3JlZ2lzdGVyLnRzIiwgIi4uL2NsaS9hdXRoL2xvZ291dC9yZWdpc3Rlci50cyIsICIuLi9jbGkvYXV0aC9yZWdpc3Rlci50cyIsICIuLi9jbGkvY29uZmlnL3JlZ2lzdGVyLnRzIiwgIi4uL2NsaS9jb25maWcvcHJpbnQvcmVnaXN0ZXIudHMiLCAiLi4vY2xpL2Nsb25lL3JlZ2lzdGVyLnRzIiwgIi4uL2NsaS9leHBvcnQvcmVnaXN0ZXIudHMiLCAiLi4vY2xpL2F1dGgvcHJpbnQtdG9rZW4vcmVnaXN0ZXIudHMiLCAiLi4vY2xpL2F1dGgvc2V0LXRva2VuL3JlZ2lzdGVyLnRzIiwgIi4uL2NsaS9wdXNoL3JlZ2lzdGVyLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIjIS91c3IvYmluL2VudiBub2RlXG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiXG5pbXBvcnQgeyByZWdpc3RlckluaXQgfSBmcm9tIFwiLi9pbml0L3JlZ2lzdGVyXCJcbmltcG9ydCB7IHJlZ2lzdGVyRGV2IH0gZnJvbSBcIi4vZGV2L3JlZ2lzdGVyXCJcbmltcG9ydCB7IHJlZ2lzdGVyQXV0aExvZ2luIH0gZnJvbSBcIi4vYXV0aC9sb2dpbi9yZWdpc3RlclwiXG5pbXBvcnQgeyByZWdpc3RlckF1dGhMb2dvdXQgfSBmcm9tIFwiLi9hdXRoL2xvZ291dC9yZWdpc3RlclwiXG5pbXBvcnQgeyByZWdpc3RlckF1dGggfSBmcm9tIFwiLi9hdXRoL3JlZ2lzdGVyXCJcbmltcG9ydCB7IHJlZ2lzdGVyQ29uZmlnIH0gZnJvbSBcIi4vY29uZmlnL3JlZ2lzdGVyXCJcbmltcG9ydCB7IHJlZ2lzdGVyQ29uZmlnUHJpbnQgfSBmcm9tIFwiLi9jb25maWcvcHJpbnQvcmVnaXN0ZXJcIlxuaW1wb3J0IHsgcmVnaXN0ZXJDbG9uZSB9IGZyb20gXCIuL2Nsb25lL3JlZ2lzdGVyXCJcbmltcG9ydCB7IHBlcmZlY3RDbGkgfSBmcm9tIFwicGVyZmVjdC1jbGlcIlxuaW1wb3J0IHBrZyBmcm9tIFwiLi4vcGFja2FnZS5qc29uXCJcbmltcG9ydCBzZW12ZXIgZnJvbSBcInNlbXZlclwiXG5pbXBvcnQgeyByZWdpc3RlckV4cG9ydCB9IGZyb20gXCIuL2V4cG9ydC9yZWdpc3RlclwiXG5pbXBvcnQgeyByZWdpc3RlckF1dGhQcmludFRva2VuIH0gZnJvbSBcIi4vYXV0aC9wcmludC10b2tlbi9yZWdpc3RlclwiXG5pbXBvcnQgeyByZWdpc3RlckF1dGhTZXRUb2tlbiB9IGZyb20gXCIuL2F1dGgvc2V0LXRva2VuL3JlZ2lzdGVyXCJcbmltcG9ydCB7IHJlZ2lzdGVyUHVzaCB9IGZyb20gXCIuL3B1c2gvcmVnaXN0ZXJcIlxuXG5leHBvcnQgY29uc3QgcHJvZ3JhbSA9IG5ldyBDb21tYW5kKClcblxucHJvZ3JhbVxuICAubmFtZShcInRzY2lcIilcbiAgLmRlc2NyaXB0aW9uKFwiQ0xJIGZvciBkZXZlbG9waW5nIHRzY2lyY3VpdCBzbmlwcGV0c1wiKVxuICAvLyBIQUNLOiBhdCBidWlsZCB0aW1lIHRoZSB2ZXJzaW9uIGlzIG9sZCwgd2UgbmVlZCB0b1xuICAvLyBmaXggdGhpcyBhdCBzb21lIHBvaW50Li4uXG4gIC52ZXJzaW9uKHNlbXZlci5pbmMocGtnLnZlcnNpb24sIFwicGF0Y2hcIikgPz8gcGtnLnZlcnNpb24pXG5cbnJlZ2lzdGVySW5pdChwcm9ncmFtKVxuXG5yZWdpc3RlckRldihwcm9ncmFtKVxucmVnaXN0ZXJDbG9uZShwcm9ncmFtKVxucmVnaXN0ZXJQdXNoKHByb2dyYW0pXG5cbnJlZ2lzdGVyQXV0aChwcm9ncmFtKVxucmVnaXN0ZXJBdXRoTG9naW4ocHJvZ3JhbSlcbnJlZ2lzdGVyQXV0aExvZ291dChwcm9ncmFtKVxucmVnaXN0ZXJBdXRoUHJpbnRUb2tlbihwcm9ncmFtKVxucmVnaXN0ZXJBdXRoU2V0VG9rZW4ocHJvZ3JhbSlcblxucmVnaXN0ZXJDb25maWcocHJvZ3JhbSlcbnJlZ2lzdGVyQ29uZmlnUHJpbnQocHJvZ3JhbSlcblxucmVnaXN0ZXJFeHBvcnQocHJvZ3JhbSlcblxuaWYgKHByb2Nlc3MuYXJndi5sZW5ndGggPT09IDIpIHtcbiAgcGVyZmVjdENsaShwcm9ncmFtLCBwcm9jZXNzLmFyZ3YpXG59IGVsc2Uge1xuICBwcm9ncmFtLnBhcnNlKClcbn1cbiIsICJpbXBvcnQgdHlwZSB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCJcbmltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiXG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwibm9kZTpmc1wiXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuaW1wb3J0IHsgc2V0dXBUc2NpUHJvamVjdCB9IGZyb20gXCJsaWIvc2hhcmVkL3NldHVwLXRzY2ktcGFja2FnZXNcIlxuaW1wb3J0IHsgZ2VuZXJhdGVUc0NvbmZpZyB9IGZyb20gXCJsaWIvc2hhcmVkL2dlbmVyYXRlLXRzLWNvbmZpZ1wiXG5pbXBvcnQgeyB3cml0ZUZpbGVJZk5vdEV4aXN0cyB9IGZyb20gXCJsaWIvc2hhcmVkL3dyaXRlLWZpbGUtaWYtbm90LWV4aXN0c1wiXG5pbXBvcnQgeyBnZW5lcmF0ZUdpdElnbm9yZUZpbGUgfSBmcm9tIFwibGliL3NoYXJlZC9nZW5lcmF0ZS1naXRpZ25vcmUtZmlsZVwiXG5pbXBvcnQgeyBnZW5lcmF0ZVBhY2thZ2VKc29uIH0gZnJvbSBcImxpYi9zaGFyZWQvZ2VuZXJhdGUtcGFja2FnZS1qc29uXCJcblxuZXhwb3J0IGNvbnN0IHJlZ2lzdGVySW5pdCA9IChwcm9ncmFtOiBDb21tYW5kKSA9PiB7XG4gIHByb2dyYW1cbiAgICAuY29tbWFuZChcImluaXRcIilcbiAgICAuZGVzY3JpcHRpb24oXG4gICAgICBcIkluaXRpYWxpemUgYSBuZXcgVFNDaXJjdWl0IHByb2plY3QgaW4gdGhlIHNwZWNpZmllZCBkaXJlY3RvcnkgKG9yIGN1cnJlbnQgZGlyZWN0b3J5IGlmIG5vbmUgaXMgcHJvdmlkZWQpXCIsXG4gICAgKVxuICAgIC5hcmd1bWVudChcbiAgICAgIFwiW2RpcmVjdG9yeV1cIixcbiAgICAgIFwiRGlyZWN0b3J5IG5hbWUgKG9wdGlvbmFsLCBkZWZhdWx0cyB0byBjdXJyZW50IGRpcmVjdG9yeSlcIixcbiAgICApXG4gICAgLmFjdGlvbigoZGlyZWN0b3J5Pzogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCBwcm9qZWN0RGlyID0gZGlyZWN0b3J5XG4gICAgICAgID8gcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGRpcmVjdG9yeSlcbiAgICAgICAgOiBwcm9jZXNzLmN3ZCgpXG5cbiAgICAgIC8vIEVuc3VyZSB0aGUgZGlyZWN0b3J5IGV4aXN0c1xuICAgICAgZnMubWtkaXJTeW5jKHByb2plY3REaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cbiAgICAgIC8vIENyZWF0ZSBlc3NlbnRpYWwgcHJvamVjdCBmaWxlc1xuICAgICAgd3JpdGVGaWxlSWZOb3RFeGlzdHMoXG4gICAgICAgIHBhdGguam9pbihwcm9qZWN0RGlyLCBcImluZGV4LnRzeFwiKSxcbiAgICAgICAgYFxuaW1wb3J0IFwiQHRzY2lyY3VpdC9jb3JlXCI7XG5cbmV4cG9ydCBkZWZhdWx0ICgpID0+IChcbiAgPGJvYXJkIHdpZHRoPVwiMTBtbVwiIGhlaWdodD1cIjEwbW1cIj5cbiAgICA8cmVzaXN0b3IgcmVzaXN0YW5jZT1cIjFrXCIgZm9vdHByaW50PVwiMDQwMlwiIG5hbWU9XCJSMVwiIHNjaFg9ezN9IHBjYlg9ezN9IC8+XG4gICAgPGNhcGFjaXRvciBjYXBhY2l0YW5jZT1cIjEwMDBwRlwiIGZvb3RwcmludD1cIjA0MDJcIiBuYW1lPVwiQzFcIiBzY2hYPXstM30gcGNiWD17LTN9IC8+XG4gICAgPHRyYWNlIGZyb209XCIuUjEgPiAucGluMVwiIHRvPVwiLkMxID4gLnBpbjFcIiAvPlxuICA8L2JvYXJkPlxuKTtcbmAsXG4gICAgICApXG5cbiAgICAgIHdyaXRlRmlsZUlmTm90RXhpc3RzKFxuICAgICAgICBwYXRoLmpvaW4ocHJvamVjdERpciwgXCIubnBtcmNcIiksXG4gICAgICAgIGBcbkB0c2NpOnJlZ2lzdHJ5PWh0dHBzOi8vbnBtLnRzY2lyY3VpdC5jb21cbmAsXG4gICAgICApXG5cbiAgICAgIC8vIEdlbmVyYXRlIHBhY2thZ2UuanNvblxuICAgICAgZ2VuZXJhdGVQYWNrYWdlSnNvbihwcm9qZWN0RGlyKVxuICAgICAgLy8gR2VuZXJhdGUgdHNjb25maWcuanNvblxuICAgICAgZ2VuZXJhdGVUc0NvbmZpZyhwcm9qZWN0RGlyKVxuICAgICAgLy8gQ3JlYXRlIC5naXRpZ25vcmUgZmlsZVxuICAgICAgZ2VuZXJhdGVHaXRJZ25vcmVGaWxlKHByb2plY3REaXIpXG4gICAgICAvLyBTZXR1cCBwcm9qZWN0IGRlcGVuZGVuY2llc1xuICAgICAgc2V0dXBUc2NpUHJvamVjdChwcm9qZWN0RGlyKVxuXG4gICAgICBjb25zb2xlLmluZm8oXG4gICAgICAgIGBcdUQ4M0NcdURGODkgSW5pdGlhbGl6YXRpb24gY29tcGxldGUhIFJ1biAke2RpcmVjdG9yeSA/IGBcImNkICR7ZGlyZWN0b3J5fVwiICYgYCA6IFwiXCJ9XCJ0c2NpIGRldlwiIHRvIHN0YXJ0IGRldmVsb3BpbmcuYCxcbiAgICAgIClcbiAgICAgIHByb2Nlc3MuZXhpdCgwKVxuICAgIH0pXG59XG4iLCAiaW1wb3J0IGZzIGZyb20gXCJmc1wiXG5cbi8vIERldGVjdCB0aGUgcGFja2FnZSBtYW5hZ2VyIGJlaW5nIHVzZWQgaW4gdGhlIHByb2plY3RcbmV4cG9ydCBjb25zdCBkZXRlY3RQYWNrYWdlTWFuYWdlciA9ICgpOiBzdHJpbmcgPT4ge1xuICBjb25zdCB1c2VyQWdlbnQgPSBwcm9jZXNzLmVudi5ucG1fY29uZmlnX3VzZXJfYWdlbnQgfHwgXCJcIlxuICBpZiAodXNlckFnZW50LnN0YXJ0c1dpdGgoXCJ5YXJuXCIpKSByZXR1cm4gXCJ5YXJuXCJcbiAgaWYgKHVzZXJBZ2VudC5zdGFydHNXaXRoKFwicG5wbVwiKSkgcmV0dXJuIFwicG5wbVwiXG4gIGlmICh1c2VyQWdlbnQuc3RhcnRzV2l0aChcImJ1blwiKSkgcmV0dXJuIFwiYnVuXCJcblxuICBpZiAoZnMuZXhpc3RzU3luYyhcInlhcm4ubG9ja1wiKSkgcmV0dXJuIFwieWFyblwiXG4gIGlmIChmcy5leGlzdHNTeW5jKFwicG5wbS1sb2NrLnlhbWxcIikpIHJldHVybiBcInBucG1cIlxuICBpZiAoZnMuZXhpc3RzU3luYyhcImJ1bi5sb2NrYlwiKSkgcmV0dXJuIFwiYnVuXCJcblxuICByZXR1cm4gXCJucG1cIiAvLyBEZWZhdWx0IHRvIG5wbVxufVxuIiwgImltcG9ydCB7IGRldGVjdFBhY2thZ2VNYW5hZ2VyIH0gZnJvbSBcIi4vZGV0ZWN0LXBrZy1tYW5hZ2VyXCJcbmltcG9ydCBmcyBmcm9tIFwibm9kZTpmc1wiXG5pbXBvcnQgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCJcbmltcG9ydCB7IGV4ZWNTeW5jIH0gZnJvbSBcIm5vZGU6Y2hpbGRfcHJvY2Vzc1wiXG5cbmV4cG9ydCBmdW5jdGlvbiBzZXR1cFRzY2lQcm9qZWN0KFxuICBkaXJlY3RvcnkgPSBwcm9jZXNzLmN3ZCgpLFxuICBkZXBlbmRlbmNpZXMgPSBbXCJAdHlwZXMvcmVhY3RcIiwgXCJAdHNjaXJjdWl0L2NvcmVcIl0sXG4pIHtcbiAgY29uc3QgcHJvamVjdFBhdGggPSBwYXRoLnJlc29sdmUoZGlyZWN0b3J5KVxuICBpZiAoIWZzLmV4aXN0c1N5bmMocHJvamVjdFBhdGgpKSB7XG4gICAgZnMubWtkaXJTeW5jKHByb2plY3RQYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuICB9XG4gIGNvbnN0IHBhY2thZ2VNYW5hZ2VyID0gZGV0ZWN0UGFja2FnZU1hbmFnZXIoKVxuXG4gIGNvbnNvbGUubG9nKGBJbml0aWFsaXppbmcgcHJvamVjdCBpbiAke3Byb2plY3RQYXRofS4uLmApXG4gIHByb2Nlc3MuY2hkaXIocHJvamVjdFBhdGgpXG5cbiAgaWYgKCFmcy5leGlzdHNTeW5jKFwicGFja2FnZS5qc29uXCIpKSB7XG4gICAgY29uc3QgaW5pdENvbW1hbmQgPVxuICAgICAgcGFja2FnZU1hbmFnZXIgPT09IFwieWFyblwiXG4gICAgICAgID8gXCJ5YXJuIGluaXQgLXlcIlxuICAgICAgICA6IHBhY2thZ2VNYW5hZ2VyID09PSBcInBucG1cIlxuICAgICAgICAgID8gXCJwbnBtIGluaXRcIlxuICAgICAgICAgIDogcGFja2FnZU1hbmFnZXIgPT09IFwiYnVuXCJcbiAgICAgICAgICAgID8gXCJidW4gaW5pdCAteVwiXG4gICAgICAgICAgICA6IFwibnBtIGluaXQgLXlcIlxuXG4gICAgZXhlY1N5bmMoaW5pdENvbW1hbmQsIHsgc3RkaW86IFwiaW5oZXJpdFwiIH0pXG4gICAgY29uc29sZS5sb2coXCJQcm9qZWN0IGluaXRpYWxpemVkIHN1Y2Nlc3NmdWxseS5cIilcbiAgfVxuXG4gIC8vIFJlYWQgYW5kIG1vZGlmeSBwYWNrYWdlLmpzb25cbiAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gcGF0aC5qb2luKHByb2plY3RQYXRoLCBcInBhY2thZ2UuanNvblwiKVxuICBjb25zdCBwYWNrYWdlSnNvbiA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHBhY2thZ2VKc29uUGF0aCwgXCJ1dGYtOFwiKSlcblxuICBmcy53cml0ZUZpbGVTeW5jKHBhY2thZ2VKc29uUGF0aCwgSlNPTi5zdHJpbmdpZnkocGFja2FnZUpzb24sIG51bGwsIDIpKVxuICBjb25zb2xlLmxvZyhcIlVwZGF0ZWQgcGFja2FnZS5qc29uIHRvIHJlbW92ZSB1bm5lY2Vzc2FyeSBmaWVsZHMuXCIpXG5cbiAgaWYgKGRlcGVuZGVuY2llcy5sZW5ndGggPiAwKSB7XG4gICAgY29uc29sZS5sb2coXCJJbnN0YWxsaW5nIGRlcGVuZGVuY2llcy4uLlwiKVxuICAgIGNvbnN0IGluc3RhbGxDb21tYW5kID1cbiAgICAgIHBhY2thZ2VNYW5hZ2VyID09PSBcInlhcm5cIlxuICAgICAgICA/IGB5YXJuIGFkZCAtRCAke2RlcGVuZGVuY2llcy5qb2luKFwiIFwiKX1gXG4gICAgICAgIDogcGFja2FnZU1hbmFnZXIgPT09IFwicG5wbVwiXG4gICAgICAgICAgPyBgcG5wbSBhZGQgLUQgJHtkZXBlbmRlbmNpZXMuam9pbihcIiBcIil9YFxuICAgICAgICAgIDogcGFja2FnZU1hbmFnZXIgPT09IFwiYnVuXCJcbiAgICAgICAgICAgID8gYGJ1biBhZGQgLUQgJHtkZXBlbmRlbmNpZXMuam9pbihcIiBcIil9YFxuICAgICAgICAgICAgOiBgbnBtIGluc3RhbGwgLUQgJHtkZXBlbmRlbmNpZXMuam9pbihcIiBcIil9YFxuXG4gICAgZXhlY1N5bmMoaW5zdGFsbENvbW1hbmQsIHsgc3RkaW86IFwiaW5oZXJpdFwiIH0pXG4gICAgY29uc29sZS5sb2coXCJEZXBlbmRlbmNpZXMgaW5zdGFsbGVkIHN1Y2Nlc3NmdWxseS5cIilcbiAgfVxuXG4gIHJldHVybiBwYWNrYWdlSnNvbi5uYW1lIHx8IFwidW5rbm93blwiXG59XG4iLCAiaW1wb3J0IHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyB3cml0ZUZpbGVJZk5vdEV4aXN0cyB9IGZyb20gXCIuL3dyaXRlLWZpbGUtaWYtbm90LWV4aXN0c1wiXG5cbi8vIEdlbmVyYXRlIGEgUmVhY3QtY29tcGF0aWJsZSB0c2NvbmZpZy5qc29uXG5leHBvcnQgY29uc3QgZ2VuZXJhdGVUc0NvbmZpZyA9IChkaXI6IHN0cmluZykgPT4ge1xuICBjb25zdCB0c2NvbmZpZ1BhdGggPSBwYXRoLmpvaW4oZGlyLCBcInRzY29uZmlnLmpzb25cIilcbiAgY29uc3QgdHNjb25maWdDb250ZW50ID0gSlNPTi5zdHJpbmdpZnkoXG4gICAge1xuICAgICAgY29tcGlsZXJPcHRpb25zOiB7XG4gICAgICAgIHRhcmdldDogXCJFUzZcIixcbiAgICAgICAgbW9kdWxlOiBcIkVTTmV4dFwiLFxuICAgICAgICBqc3g6IFwicmVhY3QtanN4XCIsXG4gICAgICAgIG91dERpcjogXCJkaXN0XCIsXG4gICAgICAgIHN0cmljdDogdHJ1ZSxcbiAgICAgICAgZXNNb2R1bGVJbnRlcm9wOiB0cnVlLFxuICAgICAgICBtb2R1bGVSZXNvbHV0aW9uOiBcIm5vZGVcIixcbiAgICAgICAgc2tpcExpYkNoZWNrOiB0cnVlLFxuICAgICAgICBmb3JjZUNvbnNpc3RlbnRDYXNpbmdJbkZpbGVOYW1lczogdHJ1ZSxcbiAgICAgICAgcmVzb2x2ZUpzb25Nb2R1bGU6IHRydWUsXG4gICAgICAgIHNvdXJjZU1hcDogdHJ1ZSxcbiAgICAgICAgYWxsb3dTeW50aGV0aWNEZWZhdWx0SW1wb3J0czogdHJ1ZSxcbiAgICAgICAgZXhwZXJpbWVudGFsRGVjb3JhdG9yczogdHJ1ZSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBudWxsLFxuICAgIDIsXG4gIClcbiAgd3JpdGVGaWxlSWZOb3RFeGlzdHModHNjb25maWdQYXRoLCB0c2NvbmZpZ0NvbnRlbnQpXG59XG4iLCAiaW1wb3J0IGZzIGZyb20gXCJmc1wiXG5cbmV4cG9ydCBjb25zdCB3cml0ZUZpbGVJZk5vdEV4aXN0cyA9IChmaWxlUGF0aDogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpID0+IHtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGZpbGVQYXRoKSkge1xuICAgIGZzLndyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIGNvbnRlbnQudHJpbVN0YXJ0KCksIFwidXRmLThcIilcbiAgICBjb25zb2xlLmluZm8oYENyZWF0ZWQ6ICR7ZmlsZVBhdGh9YClcbiAgfSBlbHNlIHtcbiAgICBjb25zb2xlLmluZm8oYFNraXBwZWQ6ICR7ZmlsZVBhdGh9IGFscmVhZHkgZXhpc3RzYClcbiAgfVxufVxuIiwgImltcG9ydCB7IHdyaXRlRmlsZUlmTm90RXhpc3RzIH0gZnJvbSBcIi4vd3JpdGUtZmlsZS1pZi1ub3QtZXhpc3RzXCJcbmltcG9ydCBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuXG5leHBvcnQgY29uc3QgZ2VuZXJhdGVHaXRJZ25vcmVGaWxlID0gKGRpcjogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IGdpdGlnbm9yZVBhdGggPSBwYXRoLmpvaW4oZGlyLCBcIi5naXRpZ25vcmVcIilcbiAgY29uc3QgZ2l0aWdub3JlQ29udGVudCA9IGAjIERlcGVuZGVuY2llc1xubm9kZV9tb2R1bGVzL1xuXG4jIEJ1aWxkIG91dHB1dFxuZGlzdC9cbmJ1aWxkL1xuXG4jIEVudmlyb25tZW50IHZhcmlhYmxlc1xuLmVudlxuLmVudi5sb2NhbFxuLmVudi4qLmxvY2FsXG5cbiMgSURFIGZpbGVzXG4udnNjb2RlL1xuLmlkZWEvXG4qLnN3cFxuKi5zd29cblxuIyBPUyBmaWxlc1xuLkRTX1N0b3JlXG5UaHVtYnMuZGJcblxuIyBEZWJ1ZyBsb2dzXG5ucG0tZGVidWcubG9nKlxueWFybi1kZWJ1Zy5sb2cqXG55YXJuLWVycm9yLmxvZypcbmBcblxuICB3cml0ZUZpbGVJZk5vdEV4aXN0cyhnaXRpZ25vcmVQYXRoLCBnaXRpZ25vcmVDb250ZW50KVxufVxuIiwgImltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyB3cml0ZUZpbGVJZk5vdEV4aXN0cyB9IGZyb20gXCIuL3dyaXRlLWZpbGUtaWYtbm90LWV4aXN0c1wiXG5cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZVBhY2thZ2VKc29uID0gKGRpcjogc3RyaW5nKSA9PiB7XG4gIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHBhdGguam9pbihkaXIsIFwicGFja2FnZS5qc29uXCIpXG4gIGNvbnN0IHBhY2thZ2VKc29uQ29udGVudCA9IHtcbiAgICBuYW1lOiBwYXRoLmJhc2VuYW1lKGRpciksXG4gICAgdmVyc2lvbjogXCIxLjAuMFwiLFxuICAgIGRlc2NyaXB0aW9uOiBcIkEgVFNDaXJjdWl0IHByb2plY3RcIixcbiAgICBtYWluOiBcImluZGV4LnRzeFwiLFxuICAgIGtleXdvcmRzOiBbXCJ0c2NpcmN1aXRcIiwgXCJlbGVjdHJvbmljc1wiXSxcbiAgICBzY3JpcHRzOiB7XG4gICAgICBkZXY6IFwidHNjaSBkZXZcIixcbiAgICAgIGJ1aWxkOiBcInRzY2kgYnVpbGRcIixcbiAgICB9LFxuICB9XG5cbiAgd3JpdGVGaWxlSWZOb3RFeGlzdHMoXG4gICAgcGFja2FnZUpzb25QYXRoLFxuICAgIEpTT04uc3RyaW5naWZ5KHBhY2thZ2VKc29uQ29udGVudCwgbnVsbCwgMiksXG4gIClcbn1cbiIsICJpbXBvcnQgdHlwZSB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCJcbmltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCJcbmltcG9ydCAqIGFzIG5ldCBmcm9tIFwibm9kZTpuZXRcIlxuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCJcbmltcG9ydCB7IGluc3RhbGxOb2RlTW9kdWxlVHlwZXNGb3JTbmlwcGV0IH0gZnJvbSBcIi4uLy4uL2xpYi9kZXBlbmRlbmN5LWFuYWx5c2lzL2luc3RhbGxOb2RlTW9kdWxlVHlwZXNGb3JTbmlwcGV0XCJcbmltcG9ydCB7IERldlNlcnZlciB9IGZyb20gXCIuL0RldlNlcnZlclwiXG5cbmV4cG9ydCBjb25zdCByZWdpc3RlckRldiA9IChwcm9ncmFtOiBDb21tYW5kKSA9PiB7XG4gIHByb2dyYW1cbiAgICAuY29tbWFuZChcImRldlwiKVxuICAgIC5kZXNjcmlwdGlvbihcIlN0YXJ0IGRldmVsb3BtZW50IHNlcnZlciBmb3IgYSBzbmlwcGV0XCIpXG4gICAgLmFyZ3VtZW50KFwiW2ZpbGVdXCIsIFwiUGF0aCB0byB0aGUgc25pcHBldCBmaWxlXCIpXG4gICAgLm9wdGlvbihcIi1wLCAtLXBvcnQgPG51bWJlcj5cIiwgXCJQb3J0IHRvIHJ1biBzZXJ2ZXIgb25cIiwgXCIzMDIwXCIpXG4gICAgLmFjdGlvbihhc3luYyAoZmlsZTogc3RyaW5nLCBvcHRpb25zOiB7IHBvcnQ6IHN0cmluZyB9KSA9PiB7XG4gICAgICBsZXQgcG9ydCA9IHBhcnNlSW50KG9wdGlvbnMucG9ydClcblxuICAgICAgY29uc3QgaXNQb3J0QXZhaWxhYmxlID0gKHBvcnQ6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4gPT4ge1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgICAgICBjb25zdCBzZXJ2ZXIgPSBuZXQuY3JlYXRlU2VydmVyKClcbiAgICAgICAgICBzZXJ2ZXIub25jZShcImVycm9yXCIsICgpID0+IHJlc29sdmUoZmFsc2UpKVxuICAgICAgICAgIHNlcnZlci5vbmNlKFwibGlzdGVuaW5nXCIsICgpID0+IHtcbiAgICAgICAgICAgIHNlcnZlci5jbG9zZSgoKSA9PiByZXNvbHZlKHRydWUpKVxuICAgICAgICAgIH0pXG4gICAgICAgICAgc2VydmVyLmxpc3Rlbihwb3J0KVxuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICB3aGlsZSAoIShhd2FpdCBpc1BvcnRBdmFpbGFibGUocG9ydCkpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBQb3J0ICR7cG9ydH0gaXMgaW4gdXNlLCB0cnlpbmcgcG9ydCAke3BvcnQgKyAxfS4uLmApXG4gICAgICAgIHBvcnQgKz0gMVxuICAgICAgfVxuXG4gICAgICBsZXQgYWJzb2x1dGVQYXRoOiBzdHJpbmdcblxuICAgICAgaWYgKGZpbGUpIHtcbiAgICAgICAgYWJzb2x1dGVQYXRoID0gcGF0aC5yZXNvbHZlKGZpbGUpXG4gICAgICAgIGlmICghYWJzb2x1dGVQYXRoLmVuZHNXaXRoKFwiLnRzeFwiKSkge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvcjogT25seSAudHN4IGZpbGVzIGFyZSBzdXBwb3J0ZWRcIilcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgZW50cnlwb2ludFBhdGggPSBwYXRoLnJlc29sdmUoXCJpbmRleC50c3hcIilcbiAgICAgICAgaWYgKGZzLmV4aXN0c1N5bmMoZW50cnlwb2ludFBhdGgpKSB7XG4gICAgICAgICAgYWJzb2x1dGVQYXRoID0gZW50cnlwb2ludFBhdGhcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkZvdW5kIGVudHJ5cG9pbnQgYXQ6XCIsIGVudHJ5cG9pbnRQYXRoKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgXCJObyBlbnRyeXBvaW50IGZvdW5kLiBSdW4gJ3RzY2kgaW5pdCcgdG8gYm9vdHN0cmFwIGEgYmFzaWMgcHJvamVjdC5cIixcbiAgICAgICAgICApXG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgZmlsZURpciA9IHBhdGguZGlybmFtZShhYnNvbHV0ZVBhdGgpXG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiSW5zdGFsbGluZyB0eXBlcyBmb3IgaW1wb3J0ZWQgc25pcHBldHMuLi5cIilcbiAgICAgICAgYXdhaXQgaW5zdGFsbE5vZGVNb2R1bGVUeXBlc0ZvclNuaXBwZXQoYWJzb2x1dGVQYXRoKVxuICAgICAgICBjb25zb2xlLmxvZyhcIlR5cGVzIGluc3RhbGxlZCBzdWNjZXNzZnVsbHlcIilcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcIkZhaWxlZCB0byBpbnN0YWxsIHR5cGVzOlwiLCBlcnJvcilcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2VydmVyID0gbmV3IERldlNlcnZlcih7XG4gICAgICAgIHBvcnQsXG4gICAgICAgIGNvbXBvbmVudEZpbGVQYXRoOiBhYnNvbHV0ZVBhdGgsXG4gICAgICB9KVxuXG4gICAgICBhd2FpdCBzZXJ2ZXIuc3RhcnQoKVxuICAgICAgYXdhaXQgc2VydmVyLmFkZEVudHJ5cG9pbnQoKVxuICAgIH0pXG59XG4iLCAiaW1wb3J0ICogYXMgZnMgZnJvbSBcIm5vZGU6ZnNcIlxuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCJcbmltcG9ydCAqIGFzIHRzIGZyb20gXCJ0eXBlc2NyaXB0XCJcblxuaW50ZXJmYWNlIFNuaXBwZXRBcGlSZXNwb25zZSB7XG4gIHNuaXBwZXQ6IHtcbiAgICBkdHM6IHN0cmluZ1xuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnN0YWxsTm9kZU1vZHVsZVR5cGVzRm9yU25pcHBldChzbmlwcGV0UGF0aDogc3RyaW5nKSB7XG4gIGNvbnN0IGNvbnRlbnQgPSBmcy5yZWFkRmlsZVN5bmMoc25pcHBldFBhdGgsIFwidXRmLThcIilcbiAgY29uc3Qgc291cmNlRmlsZSA9IHRzLmNyZWF0ZVNvdXJjZUZpbGUoXG4gICAgc25pcHBldFBhdGgsXG4gICAgY29udGVudCxcbiAgICB0cy5TY3JpcHRUYXJnZXQuTGF0ZXN0LFxuICAgIHRydWUsXG4gIClcblxuICBjb25zdCBpbXBvcnRzOiBzdHJpbmdbXSA9IFtdXG5cbiAgZnVuY3Rpb24gdmlzaXQobm9kZTogdHMuTm9kZSkge1xuICAgIGlmICh0cy5pc0ltcG9ydERlY2xhcmF0aW9uKG5vZGUpKSB7XG4gICAgICBjb25zdCBtb2R1bGVTcGVjaWZpZXIgPSBub2RlLm1vZHVsZVNwZWNpZmllclxuICAgICAgaWYgKG1vZHVsZVNwZWNpZmllciAmJiB0cy5pc1N0cmluZ0xpdGVyYWwobW9kdWxlU3BlY2lmaWVyKSkge1xuICAgICAgICBjb25zdCBpbXBvcnRQYXRoID0gbW9kdWxlU3BlY2lmaWVyLnRleHRcbiAgICAgICAgaWYgKGltcG9ydFBhdGguc3RhcnRzV2l0aChcIkB0c2NpL1wiKSkge1xuICAgICAgICAgIGltcG9ydHMucHVzaChpbXBvcnRQYXRoKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHRzLmZvckVhY2hDaGlsZChub2RlLCB2aXNpdClcbiAgfVxuXG4gIHZpc2l0KHNvdXJjZUZpbGUpXG5cbiAgbGV0IHByb2plY3RSb290ID0gcGF0aC5kaXJuYW1lKHNuaXBwZXRQYXRoKVxuICB3aGlsZSAocHJvamVjdFJvb3QgIT09IHBhdGgucGFyc2UocHJvamVjdFJvb3QpLnJvb3QpIHtcbiAgICBpZiAoZnMuZXhpc3RzU3luYyhwYXRoLmpvaW4ocHJvamVjdFJvb3QsIFwicGFja2FnZS5qc29uXCIpKSkge1xuICAgICAgYnJlYWtcbiAgICB9XG4gICAgcHJvamVjdFJvb3QgPSBwYXRoLmRpcm5hbWUocHJvamVjdFJvb3QpXG4gIH1cblxuICBmb3IgKGNvbnN0IGltcG9ydFBhdGggb2YgaW1wb3J0cykge1xuICAgIGNvbnN0IFtvd25lciwgbmFtZV0gPSBpbXBvcnRQYXRoLnJlcGxhY2UoXCJAdHNjaS9cIiwgXCJcIikuc3BsaXQoXCIuXCIpXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goXG4gICAgICAgIGBodHRwczovL3JlZ2lzdHJ5LWFwaS50c2NpcmN1aXQuY29tL3NuaXBwZXRzL2dldD9vd25lcl9uYW1lPSR7b3duZXJ9JnVuc2NvcGVkX25hbWU9JHtuYW1lfWAsXG4gICAgICApXG5cbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBGYWlsZWQgdG8gZmV0Y2ggdHlwZXMgZm9yICR7aW1wb3J0UGF0aH1gKVxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBjb25zdCBkYXRhOiBTbmlwcGV0QXBpUmVzcG9uc2UgPSBhd2FpdCByZXNwb25zZS5qc29uKClcblxuICAgICAgaWYgKGRhdGEuc25pcHBldC5kdHMpIHtcbiAgICAgICAgY29uc3QgcGFja2FnZURpciA9IHBhdGguam9pbihcbiAgICAgICAgICBwcm9qZWN0Um9vdCxcbiAgICAgICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgICAgIFwiQHRzY2lcIixcbiAgICAgICAgICBgJHtvd25lcn0uJHtuYW1lfWAsXG4gICAgICAgIClcbiAgICAgICAgZnMubWtkaXJTeW5jKHBhY2thZ2VEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cbiAgICAgICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLmpvaW4ocGFja2FnZURpciwgXCJpbmRleC5kLnRzXCIpLCBkYXRhLnNuaXBwZXQuZHRzKVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLndhcm4oYEVycm9yIGZldGNoaW5nIHR5cGVzIGZvciAke2ltcG9ydFBhdGh9OmAsIGVycm9yKVxuICAgIH1cbiAgfVxufVxuIiwgImltcG9ydCBreSBmcm9tIFwia3lcIlxuaW1wb3J0IHR5cGUgeyBGaWxlU2VydmVyUm91dGVzIH0gZnJvbSBcImxpYi9maWxlLXNlcnZlci9GaWxlU2VydmVyUm91dGVzXCJcbmltcG9ydCB7IGNyZWF0ZUh0dHBTZXJ2ZXIgfSBmcm9tIFwibGliL3NlcnZlci9jcmVhdGVIdHRwU2VydmVyXCJcbmltcG9ydCB7IEV2ZW50c1dhdGNoZXIgfSBmcm9tIFwibGliL3NlcnZlci9FdmVudHNXYXRjaGVyXCJcbmltcG9ydCB0eXBlIGh0dHAgZnJvbSBcIm5vZGU6aHR0cFwiXG5pbXBvcnQgdHlwZSB7IFR5cGVkS3lJbnN0YW5jZSB9IGZyb20gXCJ0eXBlZC1reVwiXG5pbXBvcnQgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCJcbmltcG9ydCBmcyBmcm9tIFwibm9kZTpmc1wiXG5pbXBvcnQgdHlwZSB7IEZpbGVVcGRhdGVkRXZlbnQgfSBmcm9tIFwibGliL2ZpbGUtc2VydmVyL0ZpbGVTZXJ2ZXJFdmVudFwiXG5pbXBvcnQgKiBhcyBjaG9raWRhciBmcm9tIFwiY2hva2lkYXJcIlxuaW1wb3J0IHsgRmlsZXN5c3RlbVR5cGVzSGFuZGxlciB9IGZyb20gXCJsaWIvZGVwZW5kZW5jeS1hbmFseXNpcy9GaWxlc3lzdGVtVHlwZXNIYW5kbGVyXCJcbmltcG9ydCB7IHB1c2hTbmlwcGV0IH0gZnJvbSBcImxpYi9zaGFyZWQvcHVzaC1zbmlwcGV0XCJcblxuZXhwb3J0IGNsYXNzIERldlNlcnZlciB7XG4gIHBvcnQ6IG51bWJlclxuICAvKipcbiAgICogVGhlIHBhdGggdG8gYSBjb21wb25lbnQgdGhhdCBleHBvcnRzIGEgPGJvYXJkIC8+IG9yIDxncm91cCAvPiBjb21wb25lbnRcbiAgICovXG4gIGNvbXBvbmVudEZpbGVQYXRoOiBzdHJpbmdcblxuICBwcm9qZWN0RGlyOiBzdHJpbmdcblxuICAvKipcbiAgICogVGhlIEhUVFAgc2VydmVyIHRoYXQgaG9zdHMgdGhlIGZpbGUgc2VydmVyIGFuZCBldmVudCBidXMuIFlvdSBjYW4gdXNlXG4gICAqIGZzS3kgdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgZmlsZSBzZXJ2ZXIvZXZlbnQgYnVzXG4gICAqL1xuICBodHRwU2VydmVyPzogaHR0cC5TZXJ2ZXJcbiAgLyoqXG4gICAqIFdhdGNoZXMgZm9yIGV2ZW50cyBvbiB0aGUgZXZlbnQgYnVzIGJ5IHBvbGxpbmcgYGFwaS9ldmVudHMvbGlzdGBcbiAgICovXG4gIGV2ZW50c1dhdGNoZXI/OiBFdmVudHNXYXRjaGVyXG4gIC8qKlxuICAgKiBBIGt5IGluc3RhbmNlIHRoYXQgY2FuIGJlIHVzZWQgdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgZmlsZSBzZXJ2ZXIgYW5kXG4gICAqIGV2ZW50IGJ1c1xuICAgKi9cbiAgZnNLeTogVHlwZWRLeUluc3RhbmNlPGtleW9mIEZpbGVTZXJ2ZXJSb3V0ZXMsIEZpbGVTZXJ2ZXJSb3V0ZXM+XG4gIC8qKlxuICAgKiBBIGNob2tpZGFyIGluc3RhbmNlIHRoYXQgd2F0Y2hlcyB0aGUgcHJvamVjdCBkaXJlY3RvcnkgZm9yIGZpbGUgY2hhbmdlc1xuICAgKi9cbiAgZmlsZXN5c3RlbVdhdGNoZXI/OiBjaG9raWRhci5GU1dhdGNoZXJcblxuICBwcml2YXRlIHR5cGVzSGFuZGxlcj86IEZpbGVzeXN0ZW1UeXBlc0hhbmRsZXJcblxuICBjb25zdHJ1Y3Rvcih7XG4gICAgcG9ydCxcbiAgICBjb21wb25lbnRGaWxlUGF0aCxcbiAgfToge1xuICAgIHBvcnQ6IG51bWJlclxuICAgIGNvbXBvbmVudEZpbGVQYXRoOiBzdHJpbmdcbiAgfSkge1xuICAgIHRoaXMucG9ydCA9IHBvcnRcbiAgICB0aGlzLmNvbXBvbmVudEZpbGVQYXRoID0gY29tcG9uZW50RmlsZVBhdGhcbiAgICB0aGlzLnByb2plY3REaXIgPSBwYXRoLmRpcm5hbWUoY29tcG9uZW50RmlsZVBhdGgpXG4gICAgdGhpcy5mc0t5ID0ga3kuY3JlYXRlKHtcbiAgICAgIHByZWZpeFVybDogYGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0fWAsXG4gICAgfSkgYXMgYW55XG4gICAgdGhpcy50eXBlc0hhbmRsZXIgPSBuZXcgRmlsZXN5c3RlbVR5cGVzSGFuZGxlcih0aGlzLnByb2plY3REaXIpXG4gIH1cblxuICBhc3luYyBzdGFydCgpIHtcbiAgICBjb25zdCB7IHNlcnZlciB9ID0gYXdhaXQgY3JlYXRlSHR0cFNlcnZlcih0aGlzLnBvcnQpXG4gICAgdGhpcy5odHRwU2VydmVyID0gc2VydmVyXG5cbiAgICB0aGlzLmV2ZW50c1dhdGNoZXIgPSBuZXcgRXZlbnRzV2F0Y2hlcihgaHR0cDovL2xvY2FsaG9zdDoke3RoaXMucG9ydH1gKVxuICAgIHRoaXMuZXZlbnRzV2F0Y2hlci5zdGFydCgpXG5cbiAgICB0aGlzLmV2ZW50c1dhdGNoZXIub24oXG4gICAgICBcIkZJTEVfVVBEQVRFRFwiLFxuICAgICAgdGhpcy5oYW5kbGVGaWxlVXBkYXRlZEV2ZW50RnJvbVNlcnZlci5iaW5kKHRoaXMpLFxuICAgIClcblxuICAgIHRoaXMuZXZlbnRzV2F0Y2hlci5vbihcbiAgICAgIFwiUkVRVUVTVF9UT19TQVZFX1NOSVBQRVRcIixcbiAgICAgIHRoaXMuc2F2ZVNuaXBwZXQuYmluZCh0aGlzKSxcbiAgICApXG5cbiAgICB0aGlzLmZpbGVzeXN0ZW1XYXRjaGVyID0gY2hva2lkYXIud2F0Y2godGhpcy5wcm9qZWN0RGlyLCB7XG4gICAgICBwZXJzaXN0ZW50OiB0cnVlLFxuICAgICAgaWdub3JlSW5pdGlhbDogdHJ1ZSxcbiAgICAgIGlnbm9yZWQ6IFtcIioqL25vZGVfbW9kdWxlcy8qKlwiLCBcIioqLy5naXQvKipcIl0sXG4gICAgfSlcblxuICAgIHRoaXMuZmlsZXN5c3RlbVdhdGNoZXIub24oXCJjaGFuZ2VcIiwgKGZpbGVQYXRoKSA9PlxuICAgICAgdGhpcy5oYW5kbGVGaWxlQ2hhbmdlZE9uRmlsZXN5c3RlbShmaWxlUGF0aCksXG4gICAgKVxuICAgIHRoaXMuZmlsZXN5c3RlbVdhdGNoZXIub24oXCJhZGRcIiwgKGZpbGVQYXRoKSA9PlxuICAgICAgdGhpcy5oYW5kbGVGaWxlQ2hhbmdlZE9uRmlsZXN5c3RlbShmaWxlUGF0aCksXG4gICAgKVxuXG4gICAgdGhpcy51cHNlcnRJbml0aWFsRmlsZXMoKVxuXG4gICAgdGhpcy50eXBlc0hhbmRsZXI/LmhhbmRsZUluaXRpYWxUeXBlRGVwZW5kZW5jaWVzKHRoaXMuY29tcG9uZW50RmlsZVBhdGgpXG4gIH1cblxuICBhc3luYyBhZGRFbnRyeXBvaW50KCkge1xuICAgIGNvbnN0IHJlbGF0aXZlQ29tcG9uZW50RmlsZVBhdGggPSBwYXRoLnJlbGF0aXZlKFxuICAgICAgdGhpcy5wcm9qZWN0RGlyLFxuICAgICAgdGhpcy5jb21wb25lbnRGaWxlUGF0aCxcbiAgICApXG4gICAgYXdhaXQgdGhpcy5mc0t5LnBvc3QoXCJhcGkvZmlsZXMvdXBzZXJ0XCIsIHtcbiAgICAgIGpzb246IHtcbiAgICAgICAgZmlsZV9wYXRoOiBcImVudHJ5cG9pbnQudHN4XCIsXG4gICAgICAgIHRleHRfY29udGVudDogYFxuaW1wb3J0IE15Q2lyY3VpdCBmcm9tIFwiLi8ke3JlbGF0aXZlQ29tcG9uZW50RmlsZVBhdGh9XCJcblxuY2lyY3VpdC5hZGQoPE15Q2lyY3VpdCAvPilcbmAsXG4gICAgICB9LFxuICAgIH0pXG4gIH1cblxuICBhc3luYyBoYW5kbGVGaWxlVXBkYXRlZEV2ZW50RnJvbVNlcnZlcihldjogRmlsZVVwZGF0ZWRFdmVudCkge1xuICAgIGlmIChldi5pbml0aWF0b3IgPT09IFwiZmlsZXN5c3RlbV9jaGFuZ2VcIikgcmV0dXJuXG5cbiAgICBpZiAoZXYuZmlsZV9wYXRoID09PSBcIm1hbnVhbC1lZGl0cy5qc29uXCIpIHtcbiAgICAgIGNvbnNvbGUubG9nKFwiTWFudWFsIGVkaXRzIHVwZGF0ZWQsIHVwZGF0aW5nIG9uIGZpbGVzeXN0ZW0uLi5cIilcbiAgICAgIGNvbnN0IHsgZmlsZSB9ID0gYXdhaXQgdGhpcy5mc0t5XG4gICAgICAgIC5nZXQoXCJhcGkvZmlsZXMvZ2V0XCIsIHtcbiAgICAgICAgICBzZWFyY2hQYXJhbXM6IHsgZmlsZV9wYXRoOiBldi5maWxlX3BhdGggfSxcbiAgICAgICAgfSlcbiAgICAgICAgLmpzb24oKVxuICAgICAgZnMud3JpdGVGaWxlU3luYyhcbiAgICAgICAgcGF0aC5qb2luKHRoaXMucHJvamVjdERpciwgXCJtYW51YWwtZWRpdHMuanNvblwiKSxcbiAgICAgICAgZmlsZS50ZXh0X2NvbnRlbnQsXG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgaGFuZGxlRmlsZUNoYW5nZWRPbkZpbGVzeXN0ZW0oYWJzb2x1dGVGaWxlUGF0aDogc3RyaW5nKSB7XG4gICAgY29uc3QgcmVsYXRpdmVGaWxlUGF0aCA9IHBhdGgucmVsYXRpdmUodGhpcy5wcm9qZWN0RGlyLCBhYnNvbHV0ZUZpbGVQYXRoKVxuICAgIC8vIFdlJ3ZlIHRlbXBvcmFyaWx5IGRpc2FibGVkIHVwc2VydGluZyBtYW51YWwgZWRpdHMgZnJvbSBmaWxlc3lzdGVtIGNoYW5nZXNcbiAgICAvLyBiZWNhdXNlIGl0IGNhbiBiZSBlZGl0ZWQgYnkgdGhlIGJyb3dzZXJcbiAgICBpZiAocmVsYXRpdmVGaWxlUGF0aC5pbmNsdWRlcyhcIm1hbnVhbC1lZGl0cy5qc29uXCIpKSByZXR1cm5cblxuICAgIGF3YWl0IHRoaXMudHlwZXNIYW5kbGVyPy5oYW5kbGVGaWxlVHlwZURlcGVuZGVuY2llcyhhYnNvbHV0ZUZpbGVQYXRoKVxuXG4gICAgY29uc29sZS5sb2coYCR7cmVsYXRpdmVGaWxlUGF0aH0gc2F2ZWQuIEFwcGx5aW5nIGNoYW5nZXMuLi5gKVxuICAgIGF3YWl0IHRoaXMuZnNLeVxuICAgICAgLnBvc3QoXCJhcGkvZmlsZXMvdXBzZXJ0XCIsIHtcbiAgICAgICAganNvbjoge1xuICAgICAgICAgIGZpbGVfcGF0aDogcmVsYXRpdmVGaWxlUGF0aCxcbiAgICAgICAgICB0ZXh0X2NvbnRlbnQ6IGZzLnJlYWRGaWxlU3luYyhhYnNvbHV0ZUZpbGVQYXRoLCBcInV0Zi04XCIpLFxuICAgICAgICAgIGluaXRpYXRvcjogXCJmaWxlc3lzdGVtX2NoYW5nZVwiLFxuICAgICAgICB9LFxuICAgICAgfSlcbiAgICAgIC5qc29uKClcbiAgfVxuXG4gIGFzeW5jIHVwc2VydEluaXRpYWxGaWxlcygpIHtcbiAgICAvLyBEZWZpbmUgdGhlIGxpc3Qgb2YgZmlsZXMgd2UgY2FyZSBhYm91dFxuICAgIGNvbnN0IHJlbGV2YW50RmlsZXMgPSBuZXcgU2V0KFtcbiAgICAgIFwiZW50cnlwb2ludC50c3hcIixcbiAgICAgIFwibWFudWFsLWVkaXRzLmpzb25cIixcbiAgICAgIFwic25pcHBldC50c3hcIixcbiAgICAgIHBhdGguYmFzZW5hbWUodGhpcy5jb21wb25lbnRGaWxlUGF0aCksIC8vIEluY2x1ZGUgdGhlIG1haW4gY29tcG9uZW50IGZpbGVcbiAgICBdKVxuXG4gICAgLy8gU2NhbiBwcm9qZWN0IGRpcmVjdG9yeSBmb3IgcmVsZXZhbnQgZmlsZXMgYW5kIHVwc2VydCB0aGVtXG4gICAgY29uc3QgZmlsZU5hbWVzID0gZnMucmVhZGRpclN5bmModGhpcy5wcm9qZWN0RGlyKVxuICAgIGZvciAoY29uc3QgZmlsZU5hbWUgb2YgZmlsZU5hbWVzKSB7XG4gICAgICAvLyBTa2lwIGRpcmVjdG9yaWVzIGFuZCBub24tcmVsZXZhbnQgZmlsZXNcbiAgICAgIGlmIChcbiAgICAgICAgZnMuc3RhdFN5bmMocGF0aC5qb2luKHRoaXMucHJvamVjdERpciwgZmlsZU5hbWUpKS5pc0RpcmVjdG9yeSgpIHx8XG4gICAgICAgICFyZWxldmFudEZpbGVzLmhhcyhmaWxlTmFtZSlcbiAgICAgIClcbiAgICAgICAgY29udGludWVcbiAgICAgIGNvbnN0IGZpbGVDb250ZW50ID0gZnMucmVhZEZpbGVTeW5jKFxuICAgICAgICBwYXRoLmpvaW4odGhpcy5wcm9qZWN0RGlyLCBmaWxlTmFtZSksXG4gICAgICAgIFwidXRmLThcIixcbiAgICAgIClcbiAgICAgIGF3YWl0IHRoaXMuZnNLeS5wb3N0KFwiYXBpL2ZpbGVzL3Vwc2VydFwiLCB7XG4gICAgICAgIGpzb246IHtcbiAgICAgICAgICBmaWxlX3BhdGg6IGZpbGVOYW1lLFxuICAgICAgICAgIHRleHRfY29udGVudDogZmlsZUNvbnRlbnQsXG4gICAgICAgICAgaW5pdGlhdG9yOiBcImZpbGVzeXN0ZW1fY2hhbmdlXCIsXG4gICAgICAgIH0sXG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2F2ZVNuaXBwZXQoKSB7XG4gICAgY29uc3QgcG9zdEV2ZW50ID0gYXN5bmMgKFxuICAgICAgZXZlbnQ6IFwiRkFJTEVEX1RPX1NBVkVfU05JUFBFVFwiIHwgXCJTTklQUEVUX1NBVkVEXCIsXG4gICAgKSA9PlxuICAgICAgdGhpcy5mc0t5LnBvc3QoXCJhcGkvZXZlbnRzL2NyZWF0ZVwiLCB7XG4gICAgICAgIGpzb246IHsgZXZlbnRfdHlwZTogZXZlbnQgfSxcbiAgICAgICAgdGhyb3dIdHRwRXJyb3JzOiBmYWxzZSxcbiAgICAgIH0pXG5cbiAgICBhd2FpdCBwdXNoU25pcHBldCh7XG4gICAgICBmaWxlUGF0aDogdGhpcy5jb21wb25lbnRGaWxlUGF0aCxcbiAgICAgIG9uRXhpdDogKGUpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkZhaWxlZCB0byBzYXZlIHNuaXBwZXRcIiwgZSlcbiAgICAgICAgcG9zdEV2ZW50KFwiRkFJTEVEX1RPX1NBVkVfU05JUFBFVFwiKVxuICAgICAgfSxcbiAgICAgIG9uRXJyb3I6IChlKSA9PiB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJGYWlsZWQgdG8gc2F2ZSBzbmlwcGV0XCIsIGUpXG4gICAgICAgIHBvc3RFdmVudChcIkZBSUxFRF9UT19TQVZFX1NOSVBQRVRcIilcbiAgICAgIH0sXG4gICAgICBvblN1Y2Nlc3M6ICgpID0+IHtcbiAgICAgICAgcG9zdEV2ZW50KFwiU05JUFBFVF9TQVZFRFwiKVxuICAgICAgfSxcbiAgICB9KVxuICB9XG5cbiAgYXN5bmMgc3RvcCgpIHtcbiAgICB0aGlzLmh0dHBTZXJ2ZXI/LmNsb3NlKClcbiAgICB0aGlzLmV2ZW50c1dhdGNoZXI/LnN0b3AoKVxuICB9XG59XG4iLCAiaW1wb3J0ICogYXMgaHR0cCBmcm9tIFwibm9kZTpodHRwXCJcbmltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCJcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyBnZXROb2RlSGFuZGxlciB9IGZyb20gXCJ3aW50ZXJzcGVjL2FkYXB0ZXJzL25vZGVcIlxuaW1wb3J0IHBrZyBmcm9tIFwiLi4vLi4vcGFja2FnZS5qc29uXCJcblxuLy8gQHRzLWlnbm9yZVxuaW1wb3J0IHdpbnRlcnNwZWNCdW5kbGUgZnJvbSBcIkB0c2NpcmN1aXQvZmlsZS1zZXJ2ZXIvZGlzdC9idW5kbGUuanNcIlxuaW1wb3J0IHsgZ2V0SW5kZXggfSBmcm9tIFwiLi4vc2l0ZS9nZXRJbmRleFwiXG5cbmV4cG9ydCBjb25zdCBjcmVhdGVIdHRwU2VydmVyID0gYXN5bmMgKHBvcnQgPSAzMDIwKSA9PiB7XG4gIGNvbnN0IGZpbGVTZXJ2ZXJIYW5kbGVyID0gZ2V0Tm9kZUhhbmRsZXIod2ludGVyc3BlY0J1bmRsZSBhcyBhbnksIHt9KVxuXG4gIGNvbnN0IHNlcnZlciA9IGh0dHAuY3JlYXRlU2VydmVyKGFzeW5jIChyZXEsIHJlcykgPT4ge1xuICAgIGNvbnN0IHVybCA9IG5ldyBVUkwocmVxLnVybCEsIGBodHRwOi8vJHtyZXEuaGVhZGVycy5ob3N0fWApXG5cbiAgICBpZiAodXJsLnBhdGhuYW1lID09PSBcIi9zdGFuZGFsb25lLm1pbi5qc1wiKSB7XG4gICAgICBjb25zdCBzdGFuZGFsb25lRmlsZVBhdGggPVxuICAgICAgICBwcm9jZXNzLmVudi5SVU5GUkFNRV9TVEFOREFMT05FX0ZJTEVfUEFUSCB8fFxuICAgICAgICBwYXRoLnJlc29sdmUoXG4gICAgICAgICAgcHJvY2Vzcy5jd2QoKSxcbiAgICAgICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgICAgIFwiQHRzY2lyY3VpdC9ydW5mcmFtZS9kaXN0L3N0YW5kYWxvbmUubWluLmpzXCIsXG4gICAgICAgIClcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhzdGFuZGFsb25lRmlsZVBhdGgsIFwidXRmOFwiKVxuICAgICAgICByZXMud3JpdGVIZWFkKDIwMCwge1xuICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vamF2YXNjcmlwdDsgY2hhcnNldD11dGYtOFwiLFxuICAgICAgICB9KVxuICAgICAgICByZXMuZW5kKGNvbnRlbnQpXG4gICAgICAgIHJldHVyblxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5pbmZvKFxuICAgICAgICAgIFwiTG9jYWwgcnVuZnJhbWUgc3RhbmRhbG9uZSBub3QgZm91bmQsIGZhbGxpbmcgYmFjayB0byB0aGUgcHJvZHVjdGlvbiB2ZXJzaW9uLlwiLFxuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIHJlcy53cml0ZUhlYWQoMzAyLCB7XG4gICAgICAgIExvY2F0aW9uOiBgaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9AdHNjaXJjdWl0L3J1bmZyYW1lQCR7cGtnLmRlcGVuZGVuY2llc1tcIkB0c2NpcmN1aXQvcnVuZnJhbWVcIl0ucmVwbGFjZSgvXlteMC05XSsvLCBcIlwiKX0vZGlzdC9zdGFuZGFsb25lLm1pbi5qc2AsXG4gICAgICB9KVxuICAgICAgcmVzLmVuZCgpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAodXJsLnBhdGhuYW1lID09PSBcIi9cIikge1xuICAgICAgY29uc3QgaHRtbCA9IGF3YWl0IGdldEluZGV4KClcbiAgICAgIHJlcy53cml0ZUhlYWQoMjAwLCB7IFwiQ29udGVudC1UeXBlXCI6IFwidGV4dC9odG1sXCIgfSlcbiAgICAgIHJlcy5lbmQoaHRtbClcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGlmICh1cmwucGF0aG5hbWUuc3RhcnRzV2l0aChcIi9hcGkvXCIpKSB7XG4gICAgICByZXEudXJsID0gcmVxLnVybCEucmVwbGFjZShcIi9hcGkvXCIsIFwiL1wiKVxuICAgICAgZmlsZVNlcnZlckhhbmRsZXIocmVxLCByZXMpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICByZXMud3JpdGVIZWFkKDQwNClcbiAgICByZXMuZW5kKFwiTm90IGZvdW5kXCIpXG4gIH0pXG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlPHsgc2VydmVyOiBodHRwLlNlcnZlciB9PigocmVzb2x2ZSkgPT4ge1xuICAgIHNlcnZlci5saXN0ZW4ocG9ydCwgKCkgPT4ge1xuICAgICAgY29uc29sZS5sb2coYFNlcnZlciBydW5uaW5nIGF0IGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0fWApXG4gICAgICByZXNvbHZlKHsgc2VydmVyIH0pXG4gICAgfSlcbiAgfSlcbn1cbiIsICJ7XG4gIFwibmFtZVwiOiBcIkB0c2NpcmN1aXQvY2xpXCIsXG4gIFwibWFpblwiOiBcImRpc3QvbWFpbi5qc1wiLFxuICBcInR5cGVcIjogXCJtb2R1bGVcIixcbiAgXCJ2ZXJzaW9uXCI6IFwiMC4xLjQyXCIsXG4gIFwiYmluXCI6IHtcbiAgICBcInRzY2lcIjogXCIuL2Rpc3QvbWFpbi5qc1wiXG4gIH0sXG4gIFwic2NyaXB0c1wiOiB7XG4gICAgXCJzdGFydFwiOiBcImJ1biBydW4gZGV2XCIsXG4gICAgXCJkZXZcIjogXCJidW4gLS1ob3QgLi9jbGkvbWFpbi50cyBkZXYgLi9leGFtcGxlLWRpci9zbmlwcGV0MS1iYXNpYy50c3hcIixcbiAgICBcImJ1aWxkXCI6IFwidHN1cC1ub2RlIGNsaS9tYWluLnRzIC0tZm9ybWF0IGVzbSAtLXNvdXJjZW1hcCBpbmxpbmVcIixcbiAgICBcImZvcm1hdFwiOiBcImJpb21lIGZvcm1hdCAtLXdyaXRlIC5cIixcbiAgICBcImZvcm1hdDpjaGVja1wiOiBcImJpb21lIGZvcm1hdCAuXCIsXG4gICAgXCJjbGlcIjogXCJidW4gLi9jbGkvbWFpbi50c1wiXG4gIH0sXG4gIFwiZGV2RGVwZW5kZW5jaWVzXCI6IHtcbiAgICBcIkBiaW9tZWpzL2Jpb21lXCI6IFwiXjEuOS40XCIsXG4gICAgXCJAdHNjaXJjdWl0L2NvcmVcIjogXCJeMC4wLjI0OVwiLFxuICAgIFwiQHRzY2lyY3VpdC9mYWtlLXNuaXBwZXRzXCI6IFwiXjAuMC42XCIsXG4gICAgXCJAdHlwZXMvYnVuXCI6IFwiXjEuMS4xNVwiLFxuICAgIFwiQHR5cGVzL2NvbmZpZ3N0b3JlXCI6IFwiXjYuMC4yXCIsXG4gICAgXCJAdHlwZXMvcmVhY3RcIjogXCJeMTkuMC44XCIsXG4gICAgXCJAdHlwZXMvc2VtdmVyXCI6IFwiXjcuNS44XCIsXG4gICAgXCJnZXQtcG9ydFwiOiBcIl43LjEuMFwiLFxuICAgIFwidGVtcHlcIjogXCJeMy4xLjBcIixcbiAgICBcInRzdXBcIjogXCJeOC4zLjVcIixcbiAgICBcInR5cGVkLWt5XCI6IFwiXjAuMC40XCJcbiAgfSxcbiAgXCJwZWVyRGVwZW5kZW5jaWVzXCI6IHtcbiAgICBcInR5cGVzY3JpcHRcIjogXCJeNS4wLjBcIlxuICB9LFxuICBcImRlcGVuZGVuY2llc1wiOiB7XG4gICAgXCJAdHNjaXJjdWl0L2V2YWxcIjogXCJeMC4wLjk2XCIsXG4gICAgXCJAdHNjaXJjdWl0L2ZpbGUtc2VydmVyXCI6IFwiXjAuMC4xM1wiLFxuICAgIFwiQHRzY2lyY3VpdC9ydW5mcmFtZVwiOiBcIl4wLjAuMTY3XCIsXG4gICAgXCJidW4tbWF0Y2gtc3ZnXCI6IFwiXjAuMC45XCIsXG4gICAgXCJjaG9raWRhclwiOiBcIjQuMC4xXCIsXG4gICAgXCJjaXJjdWl0LWpzb24tdG8tcmVhZGFibGUtbmV0bGlzdFwiOiBcIl4wLjAuOFwiLFxuICAgIFwiY2lyY3VpdC10by1zdmdcIjogXCJeMC4wLjEwMVwiLFxuICAgIFwiY29tbWFuZGVyXCI6IFwiXjEyLjEuMFwiLFxuICAgIFwiY29uZmlnc3RvcmVcIjogXCJeNy4wLjBcIixcbiAgICBcImNvc21pY29uZmlnXCI6IFwiXjkuMC4wXCIsXG4gICAgXCJkZWxheVwiOiBcIl42LjAuMFwiLFxuICAgIFwiZHNuLWNvbnZlcnRlclwiOiBcIl4wLjAuNjNcIixcbiAgICBcImp3dC1kZWNvZGVcIjogXCJeNC4wLjBcIixcbiAgICBcImt5XCI6IFwiXjEuNy40XCIsXG4gICAgXCJtYWtlLXZmc1wiOiBcIl4xLjAuMTVcIixcbiAgICBcInBlcmZlY3QtY2xpXCI6IFwiXjEuMC4yMFwiLFxuICAgIFwicmVkYXhpb3NcIjogXCJeMC41LjFcIixcbiAgICBcInNlbXZlclwiOiBcIl43LjYuM1wiXG4gIH1cbn1cbiIsICJpbXBvcnQgcGtnIGZyb20gXCIuLi8uLi9wYWNrYWdlLmpzb25cIlxuXG5leHBvcnQgY29uc3QgZ2V0SW5kZXggPSBhc3luYyAoKSA9PiB7XG4gIHJldHVybiBgPGh0bWw+XG4gICAgPGhlYWQ+XG4gICAgPC9oZWFkPlxuICAgIDxib2R5PlxuICAgICAgPHNjcmlwdCBzcmM9XCJodHRwczovL2Nkbi50YWlsd2luZGNzcy5jb21cIj48L3NjcmlwdD5cbiAgICAgIDxkaXYgaWQ9XCJyb290XCI+bG9hZGluZy4uLjwvZGl2PlxuICAgICAgPHNjcmlwdD5cbiAgICAgIGdsb2JhbFRoaXMucHJvY2VzcyA9IHsgZW52OiB7IE5PREVfRU5WOiBcInByb2R1Y3Rpb25cIiB9IH1cbiAgICAgIDwvc2NyaXB0PlxuICAgICAgPHNjcmlwdCBzcmM9XCIvc3RhbmRhbG9uZS5taW4uanNcIj48L3NjcmlwdD5cbiAgICA8L2JvZHk+XG4gIDwvaHRtbD5gXG59XG5cbi8vIDxzY3JpcHQgc3JjPVwiaHR0cHM6Ly9jZG4uanNkZWxpdnIubmV0L25wbS9AdHNjaXJjdWl0L3J1bmZyYW1lQCR7cGtnLmRlcGVuZGVuY2llc1tcIkB0c2NpcmN1aXQvcnVuZnJhbWVcIl0ucmVwbGFjZSgvXlteMC05XSsvLCBcIlwiKX0vZGlzdC9zdGFuZGFsb25lLm1pbi5qc1wiPjwvc2NyaXB0PlxuIiwgImltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gXCJldmVudHNcIlxuXG5pbnRlcmZhY2UgRXZlbnQge1xuICBldmVudF9pZDogc3RyaW5nXG4gIGNyZWF0ZWRfYXQ6IHN0cmluZ1xuICBldmVudF90eXBlOiBzdHJpbmdcbiAgW2tleTogc3RyaW5nXTogYW55XG59XG5cbmludGVyZmFjZSBFdmVudHNSZXNwb25zZSB7XG4gIGV2ZW50X2xpc3Q6IEV2ZW50W11cbn1cblxuZXhwb3J0IGNsYXNzIEV2ZW50c1dhdGNoZXIgZXh0ZW5kcyBFdmVudEVtaXR0ZXIge1xuICBwcml2YXRlIGxhc3RQb2xsVGltZTogc3RyaW5nXG4gIHByaXZhdGUgcG9sbEludGVydmFsOiBudW1iZXJcbiAgcHJpdmF0ZSBiYXNlVXJsOiBzdHJpbmdcbiAgcHJpdmF0ZSBwb2xsaW5nID0gZmFsc2VcbiAgcHJpdmF0ZSB0aW1lb3V0SWQ/OiBOb2RlSlMuVGltZW91dFxuXG4gIGNvbnN0cnVjdG9yKGJhc2VVcmwgPSBcImh0dHA6Ly9sb2NhbGhvc3Q6MzAwMFwiLCBwb2xsSW50ZXJ2YWwgPSAxMDAwKSB7XG4gICAgc3VwZXIoKVxuICAgIHRoaXMuYmFzZVVybCA9IGJhc2VVcmxcbiAgICB0aGlzLnBvbGxJbnRlcnZhbCA9IHBvbGxJbnRlcnZhbFxuICAgIHRoaXMubGFzdFBvbGxUaW1lID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpXG4gIH1cblxuICBhc3luYyBzdGFydCgpIHtcbiAgICBpZiAodGhpcy5wb2xsaW5nKSByZXR1cm5cbiAgICB0aGlzLnBvbGxpbmcgPSB0cnVlXG4gICAgYXdhaXQgdGhpcy5wb2xsKClcbiAgfVxuXG4gIHN0b3AoKSB7XG4gICAgdGhpcy5wb2xsaW5nID0gZmFsc2VcbiAgICBpZiAodGhpcy50aW1lb3V0SWQpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLnRpbWVvdXRJZClcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBvbGwoKSB7XG4gICAgaWYgKCF0aGlzLnBvbGxpbmcpIHJldHVyblxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goXG4gICAgICAgIGAke3RoaXMuYmFzZVVybH0vYXBpL2V2ZW50cy9saXN0P3NpbmNlPSR7ZW5jb2RlVVJJQ29tcG9uZW50KHRoaXMubGFzdFBvbGxUaW1lKX1gLFxuICAgICAgKVxuXG4gICAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgSFRUUCBlcnJvciEgc3RhdHVzOiAke3Jlc3BvbnNlLnN0YXR1c31gKVxuICAgICAgfVxuXG4gICAgICBjb25zdCBkYXRhOiBFdmVudHNSZXNwb25zZSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKVxuXG4gICAgICAvLyBVcGRhdGUgbGFzdCBwb2xsIHRpbWUgdG8gbGF0ZXN0IGV2ZW50IG9yIGN1cnJlbnQgdGltZVxuICAgICAgY29uc3QgbGF0ZXN0RXZlbnQgPSBkYXRhLmV2ZW50X2xpc3RbZGF0YS5ldmVudF9saXN0Lmxlbmd0aCAtIDFdXG4gICAgICB0aGlzLmxhc3RQb2xsVGltZSA9IGxhdGVzdEV2ZW50XG4gICAgICAgID8gbGF0ZXN0RXZlbnQuY3JlYXRlZF9hdFxuICAgICAgICA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKVxuXG4gICAgICAvLyBFbWl0IGV2ZW50cyBpbiBjaHJvbm9sb2dpY2FsIG9yZGVyXG4gICAgICBkYXRhLmV2ZW50X2xpc3QuZm9yRWFjaCgoZXZlbnQpID0+IHtcbiAgICAgICAgdGhpcy5lbWl0KGV2ZW50LmV2ZW50X3R5cGUsIGV2ZW50KVxuICAgICAgICB0aGlzLmVtaXQoXCIqXCIsIGV2ZW50KVxuICAgICAgfSlcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5lbWl0KFwiZXJyb3JcIiwgZXJyb3IpXG4gICAgfVxuICAgIC8vIFNjaGVkdWxlIG5leHQgcG9sbFxuICAgIHRoaXMudGltZW91dElkID0gZ2xvYmFsVGhpcy5zZXRUaW1lb3V0KFxuICAgICAgKCkgPT4gdGhpcy5wb2xsKCksXG4gICAgICB0aGlzLnBvbGxJbnRlcnZhbCxcbiAgICApIGFzIHVua25vd24gYXMgTm9kZUpTLlRpbWVvdXRcbiAgfVxufVxuIiwgImltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCJcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyBmaW5kSW1wb3J0c0luU25pcHBldCB9IGZyb20gXCIuL2ZpbmRJbXBvcnRzSW5TbmlwcGV0XCJcbmltcG9ydCB7IGluc3RhbGxOb2RlTW9kdWxlVHlwZXNGb3JTbmlwcGV0IH0gZnJvbSBcIi4vaW5zdGFsbE5vZGVNb2R1bGVUeXBlc0ZvclNuaXBwZXRcIlxuXG5leHBvcnQgY2xhc3MgRmlsZXN5c3RlbVR5cGVzSGFuZGxlciB7XG4gIHByaXZhdGUgcHJvamVjdFJvb3Q6IHN0cmluZ1xuXG4gIGNvbnN0cnVjdG9yKGluaXRpYWxEaXI6IHN0cmluZykge1xuICAgIHRoaXMucHJvamVjdFJvb3QgPSB0aGlzLmZpbmRQcm9qZWN0Um9vdChpbml0aWFsRGlyKVxuICB9XG5cbiAgYXN5bmMgaGFuZGxlSW5pdGlhbFR5cGVEZXBlbmRlbmNpZXMoZmlsZVBhdGg6IHN0cmluZykge1xuICAgIGNvbnNvbGUubG9nKFwiQ2hlY2tpbmcgaW5pdGlhbCB0eXBlIGRlcGVuZGVuY2llcy4uLlwiKVxuICAgIHRyeSB7XG4gICAgICBpZiAoIXRoaXMuYXJlVHlwZXNJbnN0YWxsZWQoZmlsZVBhdGgpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiSW5zdGFsbGluZyBtaXNzaW5nIGluaXRpYWwgdHlwZXMuLi5cIilcbiAgICAgICAgYXdhaXQgaW5zdGFsbE5vZGVNb2R1bGVUeXBlc0ZvclNuaXBwZXQoZmlsZVBhdGgpXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUud2FybihcIkVycm9yIGhhbmRsaW5nIGluaXRpYWwgdHlwZSBkZXBlbmRlbmNpZXM6XCIsIGVycm9yKVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGhhbmRsZUZpbGVUeXBlRGVwZW5kZW5jaWVzKGZpbGVQYXRoOiBzdHJpbmcpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKCF0aGlzLmFyZVR5cGVzSW5zdGFsbGVkKGZpbGVQYXRoKSkge1xuICAgICAgICBjb25zb2xlLmxvZyhcIkluc3RhbGxpbmcgbWlzc2luZyBmaWxlIHR5cGVzLi4uXCIpXG4gICAgICAgIGF3YWl0IGluc3RhbGxOb2RlTW9kdWxlVHlwZXNGb3JTbmlwcGV0KGZpbGVQYXRoKVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJGYWlsZWQgdG8gdmVyaWZ5IHR5cGVzOlwiLCBlcnJvcilcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFyZVR5cGVzSW5zdGFsbGVkKGZpbGVQYXRoOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBjb25zdCBpbXBvcnRzID0gZmluZEltcG9ydHNJblNuaXBwZXQoZmlsZVBhdGgpXG4gICAgcmV0dXJuIGltcG9ydHMuZXZlcnkoKGltcCkgPT4gdGhpcy5jaGVja1R5cGVFeGlzdHMoaW1wKSlcbiAgfVxuXG4gIHByaXZhdGUgY2hlY2tUeXBlRXhpc3RzKGltcG9ydFBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGlmICghaW1wb3J0UGF0aC5zdGFydHNXaXRoKFwiQHRzY2kvXCIpKSByZXR1cm4gdHJ1ZVxuXG4gICAgY29uc3QgcGF0aFdpdGhvdXRQcmVmaXggPSBpbXBvcnRQYXRoLnJlcGxhY2UoXCJAdHNjaS9cIiwgXCJcIilcbiAgICBjb25zdCBbb3duZXIsIG5hbWVdID0gcGF0aFdpdGhvdXRQcmVmaXguc3BsaXQoXCIuXCIpXG5cbiAgICBjb25zdCB0eXBlUGF0aCA9IHBhdGguam9pbihcbiAgICAgIHRoaXMucHJvamVjdFJvb3QsXG4gICAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgICAgXCJAdHNjaVwiLFxuICAgICAgYCR7b3duZXJ9LiR7bmFtZX1gLFxuICAgICAgXCJpbmRleC5kLnRzXCIsXG4gICAgKVxuXG4gICAgcmV0dXJuIGZzLmV4aXN0c1N5bmModHlwZVBhdGgpXG4gIH1cblxuICBwcml2YXRlIGZpbmRQcm9qZWN0Um9vdChzdGFydERpcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBsZXQgcm9vdCA9IHBhdGgucmVzb2x2ZShzdGFydERpcilcbiAgICB3aGlsZSAocm9vdCAhPT0gcGF0aC5wYXJzZShyb290KS5yb290KSB7XG4gICAgICBpZiAoZnMuZXhpc3RzU3luYyhwYXRoLmpvaW4ocm9vdCwgXCJwYWNrYWdlLmpzb25cIikpKSB7XG4gICAgICAgIHJldHVybiByb290XG4gICAgICB9XG4gICAgICByb290ID0gcGF0aC5kaXJuYW1lKHJvb3QpXG4gICAgfVxuICAgIHJldHVybiBzdGFydERpclxuICB9XG59XG4iLCAiaW1wb3J0ICogYXMgZnMgZnJvbSBcIm5vZGU6ZnNcIlxuaW1wb3J0ICogYXMgdHMgZnJvbSBcInR5cGVzY3JpcHRcIlxuXG5leHBvcnQgZnVuY3Rpb24gZmluZEltcG9ydHNJblNuaXBwZXQoc25pcHBldFBhdGg6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgY29udGVudCA9IGZzLnJlYWRGaWxlU3luYyhzbmlwcGV0UGF0aCwgXCJ1dGYtOFwiKVxuICBjb25zdCBzb3VyY2VGaWxlID0gdHMuY3JlYXRlU291cmNlRmlsZShcbiAgICBzbmlwcGV0UGF0aCxcbiAgICBjb250ZW50LFxuICAgIHRzLlNjcmlwdFRhcmdldC5MYXRlc3QsXG4gICAgdHJ1ZSxcbiAgKVxuXG4gIGNvbnN0IGltcG9ydHM6IHN0cmluZ1tdID0gW11cblxuICBmdW5jdGlvbiB2aXNpdChub2RlOiB0cy5Ob2RlKSB7XG4gICAgaWYgKHRzLmlzSW1wb3J0RGVjbGFyYXRpb24obm9kZSkpIHtcbiAgICAgIGNvbnN0IG1vZHVsZVNwZWNpZmllciA9IG5vZGUubW9kdWxlU3BlY2lmaWVyXG4gICAgICBpZiAobW9kdWxlU3BlY2lmaWVyICYmIHRzLmlzU3RyaW5nTGl0ZXJhbChtb2R1bGVTcGVjaWZpZXIpKSB7XG4gICAgICAgIGNvbnN0IGltcG9ydFBhdGggPSBtb2R1bGVTcGVjaWZpZXIudGV4dFxuICAgICAgICBpZiAoaW1wb3J0UGF0aC5zdGFydHNXaXRoKFwiQHRzY2kvXCIpKSB7XG4gICAgICAgICAgaW1wb3J0cy5wdXNoKGltcG9ydFBhdGgpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgdHMuZm9yRWFjaENoaWxkKG5vZGUsIHZpc2l0KVxuICB9XG5cbiAgdmlzaXQoc291cmNlRmlsZSlcblxuICByZXR1cm4gaW1wb3J0c1xufVxuIiwgImltcG9ydCBDb25maWdzdG9yZSBmcm9tIFwiY29uZmlnc3RvcmVcIlxuaW1wb3J0IHR5cGUgeyBUeXBlZENvbmZpZ3N0b3JlIH0gZnJvbSBcIi4vVHlwZWRDb25maWdTdG9yZVwiXG5pbXBvcnQgeyBqd3REZWNvZGUgfSBmcm9tIFwiand0LWRlY29kZVwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xpQ29uZmlnIHtcbiAgc2Vzc2lvblRva2VuPzogc3RyaW5nXG4gIGdpdGh1YlVzZXJuYW1lPzogc3RyaW5nXG4gIHJlZ2lzdHJ5QXBpVXJsPzogc3RyaW5nXG59XG5cbmV4cG9ydCBjb25zdCBjbGlDb25maWc6IFR5cGVkQ29uZmlnc3RvcmU8Q2xpQ29uZmlnPiA9IG5ldyBDb25maWdzdG9yZShcbiAgXCJ0c2NpcmN1aXRcIixcbilcblxuZXhwb3J0IGNvbnN0IGdldFNlc3Npb25Ub2tlbiA9ICgpOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xuICByZXR1cm4gY2xpQ29uZmlnLmdldChcInNlc3Npb25Ub2tlblwiKVxufVxuXG5leHBvcnQgY29uc3Qgc2V0U2Vzc2lvblRva2VuID0gKHRva2VuOiBzdHJpbmcpID0+IHtcbiAgY2xpQ29uZmlnLnNldChcInNlc3Npb25Ub2tlblwiLCB0b2tlbilcbiAgY29uc3QgZGVjb2RlZCA9IGp3dERlY29kZTx7XG4gICAgZ2l0aHViX3VzZXJuYW1lOiBzdHJpbmdcbiAgfT4odG9rZW4pXG4gIGNsaUNvbmZpZy5zZXQoXCJnaXRodWJVc2VybmFtZVwiLCBkZWNvZGVkLmdpdGh1Yl91c2VybmFtZSlcbn1cblxuZXhwb3J0IGNvbnN0IGNsZWFyU2Vzc2lvbiA9ICgpID0+IHtcbiAgY2xpQ29uZmlnLmRlbGV0ZShcInNlc3Npb25Ub2tlblwiKVxuICBjbGlDb25maWcuZGVsZXRlKFwiZ2l0aHViVXNlcm5hbWVcIilcbn1cblxuZXhwb3J0IGNvbnN0IGdldFJlZ2lzdHJ5QXBpVXJsID0gKCk6IHN0cmluZyA9PiB7XG4gIHJldHVybiBjbGlDb25maWcuZ2V0KFwicmVnaXN0cnlBcGlVcmxcIikgPz8gXCJodHRwczovL3JlZ2lzdHJ5LWFwaS50c2NpcmN1aXQuY29tXCJcbn1cbiIsICJpbXBvcnQgeyBnZXRSZWdpc3RyeUFwaVVybCB9IGZyb20gXCJsaWIvY2xpLWNvbmZpZ1wiXG5pbXBvcnQga3ksIHsgdHlwZSBBZnRlclJlc3BvbnNlSG9vayB9IGZyb20gXCJreVwiXG5cbmV4cG9ydCBjb25zdCBwcmV0dHlSZXNwb25zZUVycm9ySG9vazogQWZ0ZXJSZXNwb25zZUhvb2sgPSBhc3luYyAoXG4gIF9yZXF1ZXN0LFxuICBfb3B0aW9ucyxcbiAgcmVzcG9uc2UsXG4pID0+IHtcbiAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBlcnJvckRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKClcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEZBSUwgWyR7cmVzcG9uc2Uuc3RhdHVzfV06ICR7X3JlcXVlc3QubWV0aG9kfSAke1xuICAgICAgICAgIG5ldyBVUkwoX3JlcXVlc3QudXJsKS5wYXRobmFtZVxuICAgICAgICB9IFxcblxcbiAke0pTT04uc3RyaW5naWZ5KGVycm9yRGF0YSwgbnVsbCwgMil9YCxcbiAgICAgIClcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvL2lnbm9yZSwgYWxsb3cgdGhlIGVycm9yIHRvIGJlIHRocm93blxuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY29uc3QgZ2V0S3kgPSAoKSA9PiB7XG4gIHJldHVybiBreS5jcmVhdGUoe1xuICAgIHByZWZpeFVybDogZ2V0UmVnaXN0cnlBcGlVcmwoKSxcbiAgICBob29rczoge1xuICAgICAgYWZ0ZXJSZXNwb25zZTogW3ByZXR0eVJlc3BvbnNlRXJyb3JIb29rXSxcbiAgICB9LFxuICB9KVxufVxuIiwgImltcG9ydCB7IGNsaUNvbmZpZyB9IGZyb20gXCJsaWIvY2xpLWNvbmZpZ1wiXG5pbXBvcnQgeyBnZXRLeSB9IGZyb20gXCJsaWIvcmVnaXN0cnktYXBpL2dldC1reVwiXG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwibm9kZTpmc1wiXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIlxuaW1wb3J0IHNlbXZlciBmcm9tIFwic2VtdmVyXCJcblxudHlwZSBQdXNoT3B0aW9ucyA9IHtcbiAgZmlsZVBhdGg/OiBzdHJpbmdcbiAgb25FeGl0PzogKGNvZGU6IG51bWJlcikgPT4gdm9pZFxuICBvbkVycm9yPzogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZFxuICBvblN1Y2Nlc3M/OiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkXG59XG5cbmV4cG9ydCBjb25zdCBwdXNoU25pcHBldCA9IGFzeW5jICh7XG4gIGZpbGVQYXRoLFxuICBvbkV4aXQgPSAoY29kZSkgPT4gcHJvY2Vzcy5leGl0KGNvZGUpLFxuICBvbkVycm9yID0gKG1lc3NhZ2UpID0+IGNvbnNvbGUuZXJyb3IobWVzc2FnZSksXG4gIG9uU3VjY2VzcyA9IChtZXNzYWdlKSA9PiBjb25zb2xlLmxvZyhtZXNzYWdlKSxcbn06IFB1c2hPcHRpb25zKSA9PiB7XG4gIGNvbnN0IHNlc3Npb25Ub2tlbiA9IGNsaUNvbmZpZy5nZXQoXCJzZXNzaW9uVG9rZW5cIilcbiAgaWYgKCFzZXNzaW9uVG9rZW4pIHtcbiAgICBvbkVycm9yKFxuICAgICAgXCJZb3UgbmVlZCB0byBsb2cgaW4gdG8gc2F2ZSBzbmlwcGV0LiBSdW4gJ3RzY2kgbG9naW4nIHRvIGF1dGhlbnRpY2F0ZS5cIixcbiAgICApXG4gICAgcmV0dXJuIG9uRXhpdCgxKVxuICB9XG5cbiAgbGV0IHNuaXBwZXRGaWxlUGF0aDogc3RyaW5nIHwgbnVsbCA9IG51bGxcbiAgaWYgKGZpbGVQYXRoKSB7XG4gICAgc25pcHBldEZpbGVQYXRoID0gcGF0aC5yZXNvbHZlKGZpbGVQYXRoKVxuICB9IGVsc2Uge1xuICAgIGNvbnN0IGRlZmF1bHRFbnRyeXBvaW50ID0gcGF0aC5yZXNvbHZlKFwiaW5kZXgudHN4XCIpXG4gICAgaWYgKGZzLmV4aXN0c1N5bmMoZGVmYXVsdEVudHJ5cG9pbnQpKSB7XG4gICAgICBzbmlwcGV0RmlsZVBhdGggPSBkZWZhdWx0RW50cnlwb2ludFxuICAgICAgb25TdWNjZXNzKFwiTm8gZmlsZSBwcm92aWRlZC4gVXNpbmcgJ2luZGV4LnRzeCcgYXMgdGhlIGVudHJ5cG9pbnQuXCIpXG4gICAgfSBlbHNlIHtcbiAgICAgIG9uRXJyb3IoXG4gICAgICAgIFwiTm8gZW50cnlwb2ludCBmb3VuZC4gUnVuICd0c2NpIGluaXQnIHRvIGJvb3RzdHJhcCBhIGJhc2ljIHByb2plY3QuXCIsXG4gICAgICApXG4gICAgICByZXR1cm4gb25FeGl0KDEpXG4gICAgfVxuICB9XG5cbiAgY29uc3QgcGFja2FnZUpzb25QYXRoID0gcGF0aC5yZXNvbHZlKFxuICAgIHBhdGguam9pbihwYXRoLmRpcm5hbWUoc25pcHBldEZpbGVQYXRoKSwgXCJwYWNrYWdlLmpzb25cIiksXG4gIClcbiAgbGV0IHBhY2thZ2VKc29uOiB7IG5hbWU/OiBzdHJpbmc7IGF1dGhvcj86IHN0cmluZzsgdmVyc2lvbj86IHN0cmluZyB9ID0ge31cbiAgaWYgKGZzLmV4aXN0c1N5bmMocGFja2FnZUpzb25QYXRoKSkge1xuICAgIHRyeSB7XG4gICAgICBwYWNrYWdlSnNvbiA9IEpTT04ucGFyc2UoZnMucmVhZEZpbGVTeW5jKHBhY2thZ2VKc29uUGF0aCkudG9TdHJpbmcoKSlcbiAgICB9IGNhdGNoIHtcbiAgICAgIG9uRXJyb3IoXCJJbnZhbGlkIHBhY2thZ2UuanNvbiBwcm92aWRlZFwiKVxuICAgICAgcmV0dXJuIG9uRXhpdCgxKVxuICAgIH1cbiAgfVxuXG4gIGlmICghZnMuZXhpc3RzU3luYyhzbmlwcGV0RmlsZVBhdGgpKSB7XG4gICAgb25FcnJvcihgRmlsZSBub3QgZm91bmQ6ICR7c25pcHBldEZpbGVQYXRofWApXG4gICAgcmV0dXJuIG9uRXhpdCgxKVxuICB9XG5cbiAgY29uc3Qga3kgPSBnZXRLeSgpXG4gIGNvbnN0IHBhY2thZ2VOYW1lID0gKFxuICAgIHBhY2thZ2VKc29uLm5hbWUgPz8gcGF0aC5wYXJzZShzbmlwcGV0RmlsZVBhdGgpLm5hbWVcbiAgKS5yZXBsYWNlKC9eQC8sIFwiXCIpXG4gIGNvbnN0IHBhY2thZ2VBdXRob3IgPVxuICAgIHBhY2thZ2VKc29uLmF1dGhvcj8uc3BsaXQoXCIgXCIpWzBdID8/IGNsaUNvbmZpZy5nZXQoXCJnaXRodWJVc2VybmFtZVwiKVxuICBjb25zdCBwYWNrYWdlSWRlbnRpZmllciA9IGAke3BhY2thZ2VBdXRob3J9LyR7cGFja2FnZU5hbWV9YFxuXG4gIGxldCBwYWNrYWdlVmVyc2lvbiA9XG4gICAgcGFja2FnZUpzb24udmVyc2lvbiA/P1xuICAgIChhd2FpdCBreVxuICAgICAgLnBvc3Q8e1xuICAgICAgICBlcnJvcj86IHsgZXJyb3JfY29kZTogc3RyaW5nIH1cbiAgICAgICAgcGFja2FnZV9yZWxlYXNlcz86IHsgdmVyc2lvbjogc3RyaW5nOyBpc19sYXRlc3Q6IGJvb2xlYW4gfVtdXG4gICAgICB9PihcInBhY2thZ2VfcmVsZWFzZXMvbGlzdFwiLCB7XG4gICAgICAgIGpzb246IHsgcGFja2FnZV9uYW1lOiBwYWNrYWdlSWRlbnRpZmllciB9LFxuICAgICAgfSlcbiAgICAgIC5qc29uKClcbiAgICAgIC50aGVuKFxuICAgICAgICAocmVzcG9uc2UpID0+XG4gICAgICAgICAgcmVzcG9uc2UucGFja2FnZV9yZWxlYXNlcz8uW3Jlc3BvbnNlLnBhY2thZ2VfcmVsZWFzZXMubGVuZ3RoIC0gMV1cbiAgICAgICAgICAgID8udmVyc2lvbixcbiAgICAgIClcbiAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgb25FcnJvcihgRmFpbGVkIHRvIHJldHJpZXZlIGxhdGVzdCBwYWNrYWdlIHZlcnNpb246ICR7ZXJyb3J9YClcbiAgICAgICAgcmV0dXJuIG9uRXhpdCgxKVxuICAgICAgfSkpXG5cbiAgaWYgKCFwYWNrYWdlVmVyc2lvbikge1xuICAgIG9uRXJyb3IoXCJGYWlsZWQgdG8gcmV0cmlldmUgcGFja2FnZSB2ZXJzaW9uLlwiKVxuICAgIHJldHVybiBvbkV4aXQoMSlcbiAgfVxuXG4gIGNvbnN0IHVwZGF0ZVBhY2thZ2VKc29uVmVyc2lvbiA9IChuZXdWZXJzaW9uPzogc3RyaW5nKSA9PiB7XG4gICAgaWYgKHBhY2thZ2VKc29uLnZlcnNpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHBhY2thZ2VKc29uLnZlcnNpb24gPSBuZXdWZXJzaW9uID8/IGAke3BhY2thZ2VWZXJzaW9ufWBcbiAgICAgICAgZnMud3JpdGVGaWxlU3luYyhwYWNrYWdlSnNvblBhdGgsIEpTT04uc3RyaW5naWZ5KHBhY2thZ2VKc29uLCBudWxsLCAyKSlcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIG9uRXJyb3IoYEZhaWxlZCB0byB1cGRhdGUgcGFja2FnZS5qc29uIHZlcnNpb246ICR7ZXJyb3J9YClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBjb25zdCBkb2VzUGFja2FnZUV4aXN0ID0gYXdhaXQga3lcbiAgICAucG9zdDx7IGVycm9yPzogeyBlcnJvcl9jb2RlOiBzdHJpbmcgfSB9PihcInBhY2thZ2VzL2dldFwiLCB7XG4gICAgICBqc29uOiB7IG5hbWU6IHBhY2thZ2VJZGVudGlmaWVyIH0sXG4gICAgICB0aHJvd0h0dHBFcnJvcnM6IGZhbHNlLFxuICAgIH0pXG4gICAgLmpzb24oKVxuICAgIC50aGVuKChyZXNwb25zZSkgPT4gIShyZXNwb25zZS5lcnJvcj8uZXJyb3JfY29kZSA9PT0gXCJwYWNrYWdlX25vdF9mb3VuZFwiKSlcblxuICBpZiAoIWRvZXNQYWNrYWdlRXhpc3QpIHtcbiAgICBhd2FpdCBreVxuICAgICAgLnBvc3QoXCJwYWNrYWdlcy9jcmVhdGVcIiwge1xuICAgICAgICBqc29uOiB7IG5hbWU6IHBhY2thZ2VJZGVudGlmaWVyIH0sXG4gICAgICAgIGhlYWRlcnM6IHsgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke3Nlc3Npb25Ub2tlbn1gIH0sXG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBvbkVycm9yKGBFcnJvciBjcmVhdGluZyBwYWNrYWdlOiAke2Vycm9yfWApXG4gICAgICAgIHJldHVybiBvbkV4aXQoMSlcbiAgICAgIH0pXG4gIH1cblxuICBjb25zdCBkb2VzUmVsZWFzZUV4aXN0ID0gYXdhaXQga3lcbiAgICAucG9zdDx7XG4gICAgICBlcnJvcj86IHsgZXJyb3JfY29kZTogc3RyaW5nIH1cbiAgICAgIHBhY2thZ2VfcmVsZWFzZT86IHsgdmVyc2lvbjogc3RyaW5nIH1cbiAgICB9PihcInBhY2thZ2VfcmVsZWFzZXMvZ2V0XCIsIHtcbiAgICAgIGpzb246IHtcbiAgICAgICAgcGFja2FnZV9uYW1lX3dpdGhfdmVyc2lvbjogYCR7cGFja2FnZUlkZW50aWZpZXJ9QCR7cGFja2FnZVZlcnNpb259YCxcbiAgICAgIH0sXG4gICAgICB0aHJvd0h0dHBFcnJvcnM6IGZhbHNlLFxuICAgIH0pXG4gICAgLmpzb24oKVxuICAgIC50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgaWYgKHJlc3BvbnNlLnBhY2thZ2VfcmVsZWFzZT8udmVyc2lvbikge1xuICAgICAgICBwYWNrYWdlVmVyc2lvbiA9IHJlc3BvbnNlLnBhY2thZ2VfcmVsZWFzZS52ZXJzaW9uXG4gICAgICAgIHVwZGF0ZVBhY2thZ2VKc29uVmVyc2lvbihyZXNwb25zZS5wYWNrYWdlX3JlbGVhc2UudmVyc2lvbilcbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH1cbiAgICAgIHJldHVybiAhKHJlc3BvbnNlLmVycm9yPy5lcnJvcl9jb2RlID09PSBcInBhY2thZ2VfcmVsZWFzZV9ub3RfZm91bmRcIilcbiAgICB9KVxuXG4gIGlmIChkb2VzUmVsZWFzZUV4aXN0KSB7XG4gICAgY29uc3QgYnVtcGVkVmVyc2lvbiA9IHNlbXZlci5pbmMocGFja2FnZVZlcnNpb24sIFwicGF0Y2hcIikhXG4gICAgb25TdWNjZXNzKFxuICAgICAgYEluY3JlbWVudGluZyBQYWNrYWdlIFZlcnNpb24gJHtwYWNrYWdlVmVyc2lvbn0gLT4gJHtidW1wZWRWZXJzaW9ufWAsXG4gICAgKVxuICAgIHBhY2thZ2VWZXJzaW9uID0gYnVtcGVkVmVyc2lvblxuICAgIHVwZGF0ZVBhY2thZ2VKc29uVmVyc2lvbihwYWNrYWdlVmVyc2lvbilcbiAgfVxuXG4gIGF3YWl0IGt5XG4gICAgLnBvc3QoXCJwYWNrYWdlX3JlbGVhc2VzL2NyZWF0ZVwiLCB7XG4gICAgICBqc29uOiB7XG4gICAgICAgIHBhY2thZ2VfbmFtZV93aXRoX3ZlcnNpb246IGAke3BhY2thZ2VJZGVudGlmaWVyfUAke3BhY2thZ2VWZXJzaW9ufWAsXG4gICAgICB9LFxuICAgICAgdGhyb3dIdHRwRXJyb3JzOiBmYWxzZSxcbiAgICB9KVxuICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgIG9uRXJyb3IoYEVycm9yIGNyZWF0aW5nIHJlbGVhc2U6ICR7ZXJyb3J9YClcbiAgICAgIHJldHVybiBvbkV4aXQoMSlcbiAgICB9KVxuXG4gIG9uU3VjY2VzcyhcIlxcblwiKVxuXG4gIGNvbnN0IGRpcmVjdG9yeUZpbGVzID0gZnMucmVhZGRpclN5bmMocGF0aC5kaXJuYW1lKHNuaXBwZXRGaWxlUGF0aCkpXG4gIGZvciAoY29uc3QgZmlsZSBvZiBkaXJlY3RvcnlGaWxlcykge1xuICAgIGNvbnN0IGZpbGVFeHRlbnNpb24gPSBwYXRoLmV4dG5hbWUoZmlsZSkucmVwbGFjZShcIi5cIiwgXCJcIilcbiAgICBpZiAoIVtcImpzb25cIiwgXCJ0c3hcIiwgXCJ0c1wiXS5pbmNsdWRlcyhmaWxlRXh0ZW5zaW9uKSkgY29udGludWVcbiAgICBjb25zdCBmaWxlQ29udGVudCA9XG4gICAgICBmc1xuICAgICAgICAucmVhZEZpbGVTeW5jKHBhdGguam9pbihwYXRoLmRpcm5hbWUoc25pcHBldEZpbGVQYXRoKSwgZmlsZSkpXG4gICAgICAgIC50b1N0cmluZygpID8/IFwiXCJcbiAgICBhd2FpdCBreVxuICAgICAgLnBvc3QoXCJwYWNrYWdlX2ZpbGVzL2NyZWF0ZVwiLCB7XG4gICAgICAgIGpzb246IHtcbiAgICAgICAgICBmaWxlX3BhdGg6IGZpbGUsXG4gICAgICAgICAgY29udGVudF90ZXh0OiBmaWxlQ29udGVudCxcbiAgICAgICAgICBwYWNrYWdlX25hbWVfd2l0aF92ZXJzaW9uOiBgJHtwYWNrYWdlSWRlbnRpZmllcn1AJHtwYWNrYWdlVmVyc2lvbn1gLFxuICAgICAgICB9LFxuICAgICAgICB0aHJvd0h0dHBFcnJvcnM6IGZhbHNlLFxuICAgICAgfSlcbiAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgb25TdWNjZXNzKGBVcGxvYWRlZCBmaWxlICR7ZmlsZX0gdG8gdGhlIHJlZ2lzdHJ5LmApXG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBvbkVycm9yKGBFcnJvciB1cGxvYWRpbmcgZmlsZSAke2ZpbGV9OiAke2Vycm9yfWApXG4gICAgICB9KVxuICB9XG5cbiAgb25TdWNjZXNzKFxuICAgIFtcbiAgICAgIGBTdWNjZXNzZnVsbHkgcHVzaGVkIHBhY2thZ2UgJHtwYWNrYWdlSWRlbnRpZmllcn1AJHtwYWNrYWdlVmVyc2lvbn0gdG8gdGhlIHJlZ2lzdHJ5IWAsXG4gICAgICBgaHR0cHM6Ly90c2NpcmN1aXQuY29tLyR7cGFja2FnZUlkZW50aWZpZXJ9YCxcbiAgICBdLmpvaW4oXCIgXCIpLFxuICApXG59XG4iLCAiaW1wb3J0IHR5cGUgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiXG5pbXBvcnQgeyBzZXRTZXNzaW9uVG9rZW4sIGdldFNlc3Npb25Ub2tlbiB9IGZyb20gXCJsaWIvY2xpLWNvbmZpZ1wiXG5pbXBvcnQgZGVsYXkgZnJvbSBcImRlbGF5XCJcbmltcG9ydCB7IGdldEt5IH0gZnJvbSBcImxpYi9yZWdpc3RyeS1hcGkvZ2V0LWt5XCJcbmltcG9ydCB0eXBlIHsgRW5kcG9pbnRSZXNwb25zZSB9IGZyb20gXCJsaWIvcmVnaXN0cnktYXBpL2VuZHBvaW50LXR5cGVzXCJcblxuZXhwb3J0IGNvbnN0IHJlZ2lzdGVyQXV0aExvZ2luID0gKHByb2dyYW06IENvbW1hbmQpID0+IHtcbiAgLy8gRGVmaW5lIHRoZSBsb2dpbiBhY3Rpb24gb25jZSB0byBzaGFyZSBiZXR3ZWVuIGJvdGggY29tbWFuZHNcbiAgY29uc3QgbG9naW5BY3Rpb24gPSBhc3luYyAoKSA9PiB7XG4gICAgY29uc3Qgc2Vzc2lvblRva2VuID0gZ2V0U2Vzc2lvblRva2VuKClcbiAgICBpZiAoc2Vzc2lvblRva2VuKSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgXCJBbHJlYWR5IGxvZ2dlZCBpbiEgVXNlICd0c2NpIGxvZ291dCcgaWYgeW91IG5lZWQgdG8gc3dpdGNoIGFjY291bnRzLlwiLFxuICAgICAgKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgY29uc3Qga3kgPSBnZXRLeSgpXG5cbiAgICBjb25zdCB7IGxvZ2luX3BhZ2UgfSA9IGF3YWl0IGt5XG4gICAgICAucG9zdDxFbmRwb2ludFJlc3BvbnNlW1wic2Vzc2lvbnMvbG9naW5fcGFnZS9jcmVhdGVcIl0+KFxuICAgICAgICBcInNlc3Npb25zL2xvZ2luX3BhZ2UvY3JlYXRlXCIsXG4gICAgICAgIHtcbiAgICAgICAgICBqc29uOiB7fSxcbiAgICAgICAgfSxcbiAgICAgIClcbiAgICAgIC5qc29uKClcblxuICAgIGNvbnNvbGUubG9nKFwiUGxlYXNlIHZpc2l0IHRoZSBmb2xsb3dpbmcgVVJMIHRvIGxvZyBpbjpcIilcbiAgICBjb25zb2xlLmxvZyhsb2dpbl9wYWdlLnVybClcblxuICAgIC8vIFdhaXQgdW50aWwgd2UgcmVjZWl2ZSBjb25maXJtYXRpb25cbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgeyBsb2dpbl9wYWdlOiBuZXdfbG9naW5fcGFnZSB9ID0gYXdhaXQga3lcbiAgICAgICAgLnBvc3Q8RW5kcG9pbnRSZXNwb25zZVtcInNlc3Npb25zL2xvZ2luX3BhZ2UvZ2V0XCJdPihcbiAgICAgICAgICBcInNlc3Npb25zL2xvZ2luX3BhZ2UvZ2V0XCIsXG4gICAgICAgICAge1xuICAgICAgICAgICAganNvbjoge1xuICAgICAgICAgICAgICBsb2dpbl9wYWdlX2lkOiBsb2dpbl9wYWdlLmxvZ2luX3BhZ2VfaWQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7bG9naW5fcGFnZS5sb2dpbl9wYWdlX2F1dGhfdG9rZW59YCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgKVxuICAgICAgICAuanNvbigpXG5cbiAgICAgIGlmIChuZXdfbG9naW5fcGFnZS53YXNfbG9naW5fc3VjY2Vzc2Z1bCkge1xuICAgICAgICBjb25zb2xlLmxvZyhcIkxvZ2dlZCBpbiEgR2VuZXJhdGluZyB0b2tlbi4uLlwiKVxuICAgICAgICBicmVha1xuICAgICAgfVxuXG4gICAgICBpZiAobmV3X2xvZ2luX3BhZ2UuaXNfZXhwaXJlZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJMb2dpbiBwYWdlIGV4cGlyZWRcIilcbiAgICAgIH1cblxuICAgICAgYXdhaXQgZGVsYXkoMTAwMClcbiAgICB9XG5cbiAgICBjb25zdCB7IHNlc3Npb24gfSA9IGF3YWl0IGt5XG4gICAgICAucG9zdDxFbmRwb2ludFJlc3BvbnNlW1wic2Vzc2lvbnMvbG9naW5fcGFnZS9leGNoYW5nZV9mb3JfY2xpX3Nlc3Npb25cIl0+KFxuICAgICAgICBcInNlc3Npb25zL2xvZ2luX3BhZ2UvZXhjaGFuZ2VfZm9yX2NsaV9zZXNzaW9uXCIsXG4gICAgICAgIHtcbiAgICAgICAgICBqc29uOiB7XG4gICAgICAgICAgICBsb2dpbl9wYWdlX2lkOiBsb2dpbl9wYWdlLmxvZ2luX3BhZ2VfaWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7bG9naW5fcGFnZS5sb2dpbl9wYWdlX2F1dGhfdG9rZW59YCxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgKVxuICAgICAgLmpzb24oKVxuXG4gICAgc2V0U2Vzc2lvblRva2VuKHNlc3Npb24udG9rZW4pXG4gICAgY29uc29sZS5sb2coXCJcXG5SZWFkeSB0byB1c2UhXCIpXG4gIH1cblxuICAvLyBSZWdpc3RlciB0aGUgYXV0aCBsb2dpbiBzdWJjb21tYW5kXG4gIHByb2dyYW0uY29tbWFuZHNcbiAgICAuZmluZCgoYykgPT4gYy5uYW1lKCkgPT09IFwiYXV0aFwiKSFcbiAgICAuY29tbWFuZChcImxvZ2luXCIpXG4gICAgLmRlc2NyaXB0aW9uKFwiQXV0aGVudGljYXRlIENMSSwgbG9naW4gdG8gcmVnaXN0cnlcIilcbiAgICAuYWN0aW9uKGxvZ2luQWN0aW9uKVxuXG4gIC8vIFJlZ2lzdGVyIHRoZSB0b3AtbGV2ZWwgbG9naW4gY29tbWFuZCBhcyBhbiBhbGlhc1xuICBwcm9ncmFtXG4gICAgLmNvbW1hbmQoXCJsb2dpblwiKVxuICAgIC5kZXNjcmlwdGlvbihcIkxvZ2luIHRvIHRzY2lyY3VpdCByZWdpc3RyeVwiKVxuICAgIC5hY3Rpb24obG9naW5BY3Rpb24pXG59XG4iLCAiaW1wb3J0IHR5cGUgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiXG5pbXBvcnQgeyBjbGVhclNlc3Npb24gfSBmcm9tIFwibGliL2NsaS1jb25maWdcIlxuXG5leHBvcnQgY29uc3QgcmVnaXN0ZXJBdXRoTG9nb3V0ID0gKHByb2dyYW06IENvbW1hbmQpID0+IHtcbiAgY29uc3QgbG9nb3V0QWN0aW9uID0gKCkgPT4ge1xuICAgIGNsZWFyU2Vzc2lvbigpXG4gICAgY29uc29sZS5sb2coXCJZb3UgaGF2ZSBiZWVuIGxvZ2dlZCBvdXQhXCIpXG4gIH1cblxuICAvLyBSZWdpc3RlciB0aGUgYXV0aCBsb2dvdXQgc3ViY29tbWFuZFxuICBwcm9ncmFtLmNvbW1hbmRzXG4gICAgLmZpbmQoKGMpID0+IGMubmFtZSgpID09PSBcImF1dGhcIikhXG4gICAgLmNvbW1hbmQoXCJsb2dvdXRcIilcbiAgICAuZGVzY3JpcHRpb24oXCJMb2dvdXQgZnJvbSByZWdpc3RyeVwiKVxuICAgIC5hY3Rpb24obG9nb3V0QWN0aW9uKVxuXG4gIC8vIFJlZ2lzdGVyIHRoZSB0b3AtbGV2ZWwgbG9nb3V0IGNvbW1hbmQgYXMgYW4gYWxpYXNcbiAgcHJvZ3JhbVxuICAgIC5jb21tYW5kKFwibG9nb3V0XCIpXG4gICAgLmRlc2NyaXB0aW9uKFwiTG9nb3V0IGZyb20gdHNjaXJjdWl0IHJlZ2lzdHJ5XCIpXG4gICAgLmFjdGlvbihsb2dvdXRBY3Rpb24pXG59XG4iLCAiaW1wb3J0IHR5cGUgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiXG5cbmV4cG9ydCBjb25zdCByZWdpc3RlckF1dGggPSAocHJvZ3JhbTogQ29tbWFuZCkgPT4ge1xuICBwcm9ncmFtLmNvbW1hbmQoXCJhdXRoXCIpLmRlc2NyaXB0aW9uKFwiTG9naW4vbG9nb3V0XCIpXG59XG4iLCAiaW1wb3J0IHR5cGUgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiXG5cbmV4cG9ydCBjb25zdCByZWdpc3RlckNvbmZpZyA9IChwcm9ncmFtOiBDb21tYW5kKSA9PiB7XG4gIHByb2dyYW0uY29tbWFuZChcImNvbmZpZ1wiKS5kZXNjcmlwdGlvbihcIk1hbmFnZSB0c2NpcmN1aXQgQ0xJIGNvbmZpZ3VyYXRpb25cIilcbn1cbiIsICJpbXBvcnQgdHlwZSB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCJcbmltcG9ydCB7IGNsaUNvbmZpZyB9IGZyb20gXCJsaWIvY2xpLWNvbmZpZ1wiXG5cbmV4cG9ydCBjb25zdCByZWdpc3RlckNvbmZpZ1ByaW50ID0gKHByb2dyYW06IENvbW1hbmQpID0+IHtcbiAgcHJvZ3JhbS5jb21tYW5kc1xuICAgIC5maW5kKChjKSA9PiBjLm5hbWUoKSA9PT0gXCJjb25maWdcIikhXG4gICAgLmNvbW1hbmQoXCJwcmludFwiKVxuICAgIC5kZXNjcmlwdGlvbihcIlByaW50IHRoZSBjdXJyZW50IGNvbmZpZ1wiKVxuICAgIC5hY3Rpb24oKCkgPT4ge1xuICAgICAgY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkoY2xpQ29uZmlnLmFsbCwgbnVsbCwgMikpXG4gICAgfSlcbn1cbiIsICJpbXBvcnQgdHlwZSB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCJcbmltcG9ydCB7IGdldEt5IH0gZnJvbSBcImxpYi9yZWdpc3RyeS1hcGkvZ2V0LWt5XCJcbmltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCJcbmltcG9ydCAqIGFzIHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiXG5pbXBvcnQgeyBzZXR1cFRzY2lQcm9qZWN0IH0gZnJvbSBcImxpYi9zaGFyZWQvc2V0dXAtdHNjaS1wYWNrYWdlc1wiXG5pbXBvcnQgeyBnZW5lcmF0ZVRzQ29uZmlnIH0gZnJvbSBcImxpYi9zaGFyZWQvZ2VuZXJhdGUtdHMtY29uZmlnXCJcblxuZXhwb3J0IGNvbnN0IHJlZ2lzdGVyQ2xvbmUgPSAocHJvZ3JhbTogQ29tbWFuZCkgPT4ge1xuICBwcm9ncmFtXG4gICAgLmNvbW1hbmQoXCJjbG9uZVwiKVxuICAgIC5kZXNjcmlwdGlvbihcIkNsb25lIGEgc25pcHBldCBmcm9tIHRoZSByZWdpc3RyeVwiKVxuICAgIC5hcmd1bWVudChcIjxzbmlwcGV0PlwiLCBcIlNuaXBwZXQgdG8gY2xvbmUgKGUuZy4gYXV0aG9yL3NuaXBwZXROYW1lKVwiKVxuICAgIC5hY3Rpb24oYXN5bmMgKHNuaXBwZXRQYXRoOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IG1hdGNoID0gc25pcHBldFBhdGgubWF0Y2goL14oPzpAdHNjaVxcLyk/KFteLy5dKylbLy5dKC4rKSQvKVxuICAgICAgaWYgKCFtYXRjaCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgIFwiSW52YWxpZCBzbmlwcGV0IHBhdGguIFVzZSBmb3JtYXQ6IGF1dGhvci9zbmlwcGV0TmFtZSwgYXV0aG9yLnNuaXBwZXROYW1lLCBvciBAdHNjaS9hdXRob3Iuc25pcHBldE5hbWVcIixcbiAgICAgICAgKVxuICAgICAgICBwcm9jZXNzLmV4aXQoMSlcbiAgICAgIH1cblxuICAgICAgY29uc3QgWywgYXV0aG9yLCBzbmlwcGV0TmFtZV0gPSBtYXRjaFxuICAgICAgY29uc29sZS5sb2coYENsb25pbmcgJHthdXRob3J9LyR7c25pcHBldE5hbWV9Li4uYClcblxuICAgICAgY29uc3Qga3kgPSBnZXRLeSgpXG4gICAgICBsZXQgcGFja2FnZUZpbGVMaXN0XG4gICAgICB0cnkge1xuICAgICAgICBwYWNrYWdlRmlsZUxpc3QgPSBhd2FpdCBreVxuICAgICAgICAgIC5wb3N0PHsgcGFja2FnZV9maWxlczogQXJyYXk8eyBmaWxlX3BhdGg6IHN0cmluZyB9PiB9PihcbiAgICAgICAgICAgIFwicGFja2FnZV9maWxlcy9saXN0XCIsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGpzb246IHtcbiAgICAgICAgICAgICAgICBwYWNrYWdlX25hbWU6IGAke2F1dGhvcn0vJHtzbmlwcGV0TmFtZX1gLFxuICAgICAgICAgICAgICAgIHVzZV9sYXRlc3RfdmVyc2lvbjogdHJ1ZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKVxuICAgICAgICAgIC5qc29uKClcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgXCJGYWlsZWQgdG8gZmV0Y2ggcGFja2FnZSBmaWxlczpcIixcbiAgICAgICAgICBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IGVycm9yLFxuICAgICAgICApXG4gICAgICAgIHByb2Nlc3MuZXhpdCgxKVxuICAgICAgfVxuXG4gICAgICBjb25zdCBkaXJQYXRoID0gcGF0aC5yZXNvbHZlKGAke2F1dGhvcn0uJHtzbmlwcGV0TmFtZX1gKVxuICAgICAgZnMubWtkaXJTeW5jKGRpclBhdGgsIHsgcmVjdXJzaXZlOiB0cnVlIH0pXG5cbiAgICAgIGZvciAoY29uc3QgZmlsZUluZm8gb2YgcGFja2FnZUZpbGVMaXN0LnBhY2thZ2VfZmlsZXMpIHtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBmaWxlSW5mby5maWxlX3BhdGgucmVwbGFjZSgvXlxcL3xkaXN0XFwvL2csIFwiXCIpXG4gICAgICAgIGlmICghZmlsZVBhdGgpIGNvbnRpbnVlXG5cbiAgICAgICAgY29uc3QgZnVsbFBhdGggPSBwYXRoLmpvaW4oZGlyUGF0aCwgZmlsZVBhdGgpXG4gICAgICAgIGZzLm1rZGlyU3luYyhwYXRoLmRpcm5hbWUoZnVsbFBhdGgpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgZmlsZUNvbnRlbnQgPSBhd2FpdCBreVxuICAgICAgICAgICAgLnBvc3Q8eyBwYWNrYWdlX2ZpbGU6IHsgY29udGVudF90ZXh0OiBzdHJpbmcgfSB9PihcbiAgICAgICAgICAgICAgXCJwYWNrYWdlX2ZpbGVzL2dldFwiLFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAganNvbjoge1xuICAgICAgICAgICAgICAgICAgcGFja2FnZV9uYW1lOiBgJHthdXRob3J9LyR7c25pcHBldE5hbWV9YCxcbiAgICAgICAgICAgICAgICAgIGZpbGVfcGF0aDogZmlsZUluZm8uZmlsZV9wYXRoLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuanNvbigpXG5cbiAgICAgICAgICBsZXQgZmlsZVRleHQgPSBmaWxlQ29udGVudC5wYWNrYWdlX2ZpbGUuY29udGVudF90ZXh0XG5cbiAgICAgICAgICAvLyBFbnN1cmUgYWxsIC50c3ggZmlsZXMgY29udGFpbiBcImltcG9ydCAnQHRzY2lyY3VpdC9jb3JlJztcIlxuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIGZpbGVQYXRoLmVuZHNXaXRoKFwiLnRzeFwiKSAmJlxuICAgICAgICAgICAgIWZpbGVUZXh0LmluY2x1ZGVzKFwiQHRzY2lyY3VpdC9jb3JlXCIpXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBmaWxlVGV4dCA9IGBpbXBvcnQgXCJAdHNjaXJjdWl0L2NvcmVcIjtcXG5cXG4ke2ZpbGVUZXh0fWBcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmcy53cml0ZUZpbGVTeW5jKGZ1bGxQYXRoLCBmaWxlVGV4dClcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICBgU2tpcHBpbmcgJHtmaWxlUGF0aH0gZHVlIHRvIGVycm9yOmAsXG4gICAgICAgICAgICBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IGVycm9yLFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBmcy53cml0ZUZpbGVTeW5jKFxuICAgICAgICBwYXRoLmpvaW4oZGlyUGF0aCwgXCIubnBtcmNcIiksXG4gICAgICAgIFwiQHRzY2k6cmVnaXN0cnk9aHR0cHM6Ly9ucG0udHNjaXJjdWl0LmNvbVwiLFxuICAgICAgKVxuXG4gICAgICBnZW5lcmF0ZVRzQ29uZmlnKGRpclBhdGgpXG4gICAgICBzZXR1cFRzY2lQcm9qZWN0KGRpclBhdGgpXG5cbiAgICAgIGNvbnNvbGUubG9nKGBTdWNjZXNzZnVsbHkgY2xvbmVkIHRvICR7ZGlyUGF0aH0vYClcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICBgUnVuIFwiY2QgJHtwYXRoLmRpcm5hbWUoZGlyUGF0aCl9ICYmIHRzY2kgZGV2XCIgdG8gc3RhcnQgZGV2ZWxvcGluZy5gLFxuICAgICAgKVxuICAgIH0pXG59XG4iLCAiaW1wb3J0IHR5cGUgeyBDb21tYW5kIH0gZnJvbSBcImNvbW1hbmRlclwiXG5pbXBvcnQgeyBjcmVhdGVDaXJjdWl0V2ViV29ya2VyIH0gZnJvbSBcIkB0c2NpcmN1aXQvZXZhbFwiXG5pbXBvcnQgd2ViV29ya2VyQnVuZGxlVXJsIGZyb20gXCJAdHNjaXJjdWl0L2V2YWwvYmxvYi11cmxcIlxuaW1wb3J0IHsgZ2V0VmlydHVhbEZpbGVTeXN0ZW1Gcm9tRGlyUGF0aCB9IGZyb20gXCJtYWtlLXZmc1wiXG5pbXBvcnQgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCJcbmltcG9ydCBmcyBmcm9tIFwibm9kZTpmc1wiXG5pbXBvcnQge1xuICBjb252ZXJ0Q2lyY3VpdEpzb25Ub1NjaGVtYXRpY1N2ZyxcbiAgY29udmVydENpcmN1aXRKc29uVG9QY2JTdmcsXG59IGZyb20gXCJjaXJjdWl0LXRvLXN2Z1wiXG5pbXBvcnQgeyBjb252ZXJ0Q2lyY3VpdEpzb25Ub0RzblN0cmluZyB9IGZyb20gXCJkc24tY29udmVydGVyXCJcbmltcG9ydCB7IGNvbnZlcnRDaXJjdWl0SnNvblRvUmVhZGFibGVOZXRsaXN0IH0gZnJvbSBcImNpcmN1aXQtanNvbi10by1yZWFkYWJsZS1uZXRsaXN0XCJcblxuY29uc3QgQUxMT1dFRF9GT1JNQVRTID0gW1xuICBcImpzb25cIixcbiAgXCJjaXJjdWl0LWpzb25cIixcbiAgXCJzY2hlbWF0aWMtc3ZnXCIsXG4gIFwicGNiLXN2Z1wiLFxuICBcImdlcmJlcnNcIixcbiAgXCJyZWFkYWJsZS1uZXRsaXN0XCIsXG4gIFwiZ2x0ZlwiLFxuICBcInNwZWNjdHJhLWRzblwiLFxuXSBhcyBjb25zdFxuXG50eXBlIEZvcm1hdCA9ICh0eXBlb2YgQUxMT1dFRF9GT1JNQVRTKVtudW1iZXJdXG5cbmNvbnN0IE9VVFBVVF9FWFRFTlNJT05TID0ge1xuICBqc29uOiBcIi5jaXJjdWl0Lmpzb25cIixcbiAgXCJjaXJjdWl0LWpzb25cIjogXCIuY2lyY3VpdC5qc29uXCIsXG4gIFwic2NoZW1hdGljLXN2Z1wiOiBcIi1zY2hlbWF0aWMuc3ZnXCIsXG4gIFwicGNiLXN2Z1wiOiBcIi1wY2Iuc3ZnXCIsXG4gIGdlcmJlcnM6IFwiLWdlcmJlcnMuemlwXCIsXG4gIFwicmVhZGFibGUtbmV0bGlzdFwiOiBcIi1yZWFkYWJsZS5uZXRsaXN0XCIsXG4gIGdsdGY6IFwiLmdsdGZcIixcbiAgXCJzcGVjY3RyYS1kc25cIjogXCIuZHNuXCIsXG59XG5cbmV4cG9ydCBjb25zdCByZWdpc3RlckV4cG9ydCA9IChwcm9ncmFtOiBDb21tYW5kKSA9PiB7XG4gIHByb2dyYW1cbiAgICAuY29tbWFuZChcImV4cG9ydFwiKVxuICAgIC5kZXNjcmlwdGlvbihcIkV4cG9ydCB0c2NpcmN1aXQgY29kZSB0byB2YXJpb3VzIGZvcm1hdHNcIilcbiAgICAuYXJndW1lbnQoXCI8ZmlsZT5cIiwgXCJQYXRoIHRvIHRoZSBzbmlwcGV0IGZpbGVcIilcbiAgICAub3B0aW9uKFwiLWYsIC0tZm9ybWF0IDxmb3JtYXQ+XCIsIFwiT3V0cHV0IGZvcm1hdFwiKVxuICAgIC5vcHRpb24oXCItbywgLS1vdXRwdXQgPHBhdGg+XCIsIFwiT3V0cHV0IGZpbGUgcGF0aFwiKVxuICAgIC5hY3Rpb24oYXN5bmMgKGZpbGUsIG9wdGlvbnMpID0+IHtcbiAgICAgIGNvbnN0IHsgZm9ybWF0ID0gXCJjaXJjdWl0LWpzb25cIiB9ID0gb3B0aW9uc1xuICAgICAgbGV0IHsgb3V0cHV0IH0gPSBvcHRpb25zXG4gICAgICBpZiAoIUFMTE9XRURfRk9STUFUUy5pbmNsdWRlcyhmb3JtYXQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgSW52YWxpZCBmb3JtYXQ6ICR7Zm9ybWF0fVxcblN1cHBvcnRlZCBmb3JtYXRzOiAke0FMTE9XRURfRk9STUFUUy5qb2luKFwiLFwiKX1gLFxuICAgICAgICApXG4gICAgICB9XG5cbiAgICAgIGlmICghb3V0cHV0KSB7XG4gICAgICAgIG91dHB1dCA9IHBhdGguYmFzZW5hbWUoZmlsZSkucmVwbGFjZSgvXFwuW14uXSskLywgXCJcIilcbiAgICAgIH1cblxuICAgICAgY29uc3Qgd29ya2VyID0gYXdhaXQgY3JlYXRlQ2lyY3VpdFdlYldvcmtlcih7XG4gICAgICAgIHdlYldvcmtlclVybDogd2ViV29ya2VyQnVuZGxlVXJsLFxuICAgICAgfSlcblxuICAgICAgY29uc3QgcHJvamVjdERpciA9IHBhdGguZGlybmFtZShmaWxlKVxuXG4gICAgICBjb25zdCByZWxhdGl2ZUNvbXBvbmVudFBhdGggPSBwYXRoLnJlbGF0aXZlKHByb2plY3REaXIsIGZpbGUpXG5cbiAgICAgIGF3YWl0IHdvcmtlci5leGVjdXRlV2l0aEZzTWFwKHtcbiAgICAgICAgZW50cnlwb2ludDogXCJlbnRyeXBvaW50LnRzeFwiLFxuICAgICAgICBmc01hcDoge1xuICAgICAgICAgIC4uLigoYXdhaXQgZ2V0VmlydHVhbEZpbGVTeXN0ZW1Gcm9tRGlyUGF0aCh7XG4gICAgICAgICAgICBkaXJQYXRoOiBwcm9qZWN0RGlyLFxuICAgICAgICAgICAgY29udGVudEZvcm1hdDogXCJzdHJpbmdcIixcbiAgICAgICAgICB9KSkgYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPiksXG4gICAgICAgICAgXCJlbnRyeXBvaW50LnRzeFwiOiBgXG5pbXBvcnQgTXlDaXJjdWl0IGZyb20gXCIuLyR7cmVsYXRpdmVDb21wb25lbnRQYXRofVwiXG5cbmNpcmN1aXQuYWRkKDxNeUNpcmN1aXQgLz4pXG4gICAgICAgIGAsXG4gICAgICAgIH0sXG4gICAgICB9KVxuXG4gICAgICBhd2FpdCB3b3JrZXIucmVuZGVyVW50aWxTZXR0bGVkKClcblxuICAgICAgY29uc3QgY2lyY3VpdEpzb24gPSBhd2FpdCB3b3JrZXIuZ2V0Q2lyY3VpdEpzb24oKVxuICAgICAgY29uc3Qgb3V0cHV0UGF0aCA9IHBhdGguam9pbihcbiAgICAgICAgcHJvamVjdERpcixcbiAgICAgICAgYCR7b3V0cHV0fSR7T1VUUFVUX0VYVEVOU0lPTlNbZm9ybWF0IGFzIEZvcm1hdF19YCxcbiAgICAgIClcblxuICAgICAgbGV0IG91dHB1dENvbnRlbnQ6IHN0cmluZ1xuXG4gICAgICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgICAgICBjYXNlIFwic2NoZW1hdGljLXN2Z1wiOlxuICAgICAgICAgIG91dHB1dENvbnRlbnQgPSBjb252ZXJ0Q2lyY3VpdEpzb25Ub1NjaGVtYXRpY1N2ZyhjaXJjdWl0SnNvbilcbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIFwicGNiLXN2Z1wiOlxuICAgICAgICAgIG91dHB1dENvbnRlbnQgPSBjb252ZXJ0Q2lyY3VpdEpzb25Ub1BjYlN2ZyhjaXJjdWl0SnNvbilcbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIFwic3BlY2N0cmEtZHNuXCI6XG4gICAgICAgICAgb3V0cHV0Q29udGVudCA9IGNvbnZlcnRDaXJjdWl0SnNvblRvRHNuU3RyaW5nKGNpcmN1aXRKc29uKVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgXCJyZWFkYWJsZS1uZXRsaXN0XCI6XG4gICAgICAgICAgb3V0cHV0Q29udGVudCA9IGNvbnZlcnRDaXJjdWl0SnNvblRvUmVhZGFibGVOZXRsaXN0KGNpcmN1aXRKc29uKVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgb3V0cHV0Q29udGVudCA9IEpTT04uc3RyaW5naWZ5KGNpcmN1aXRKc29uKVxuICAgICAgfVxuXG4gICAgICBmcy53cml0ZUZpbGVTeW5jKG91dHB1dFBhdGgsIG91dHB1dENvbnRlbnQpXG5cbiAgICAgIGNvbnNvbGUubG9nKGBFeHBvcnRlZCB0byAke291dHB1dFBhdGh9YClcblxuICAgICAgcHJvY2Vzcy5leGl0KDApXG4gICAgfSlcbn1cbiIsICJpbXBvcnQgdHlwZSB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCJcbmltcG9ydCB7IGNsaUNvbmZpZyB9IGZyb20gXCJsaWIvY2xpLWNvbmZpZ1wiXG5cbmV4cG9ydCBjb25zdCByZWdpc3RlckF1dGhQcmludFRva2VuID0gKHByb2dyYW06IENvbW1hbmQpID0+IHtcbiAgcHJvZ3JhbS5jb21tYW5kc1xuICAgIC5maW5kKChjKSA9PiBjLm5hbWUoKSA9PT0gXCJhdXRoXCIpIVxuICAgIC5jb21tYW5kKFwicHJpbnQtdG9rZW5cIilcbiAgICAuZGVzY3JpcHRpb24oXCJQcmludHMgeW91ciBhdXRoIHRva2VuXCIpXG4gICAgLmFjdGlvbigoKSA9PiB7XG4gICAgICBjb25zdCB0b2tlbiA9IGNsaUNvbmZpZy5nZXQoXCJzZXNzaW9uVG9rZW5cIilcbiAgICAgIGlmICghdG9rZW4pIHJldHVybiBjb25zb2xlLmxvZyhcIllvdSBuZWVkIHRvIGxvZyBpbiB0byBhY2Nlc3MgdGhpcy5cIilcbiAgICAgIGNvbnNvbGUubG9nKFwiWW91ciBUb2tlbjpcXG5cIiwgdG9rZW4pXG4gICAgfSlcbn1cbiIsICJpbXBvcnQgdHlwZSB7IENvbW1hbmQgfSBmcm9tIFwiY29tbWFuZGVyXCJcbmltcG9ydCB7IHNldFNlc3Npb25Ub2tlbiB9IGZyb20gXCJsaWIvY2xpLWNvbmZpZ1wiXG5cbmZ1bmN0aW9uIHZhbGlkYXRlSldUTGVuZ3RoKHRva2VuOiBzdHJpbmcpIHtcbiAgY29uc3QgcGFydHMgPSB0b2tlbi5zcGxpdChcIi5cIilcblxuICBpZiAocGFydHMubGVuZ3RoID09PSAzICYmIHBhcnRzLmV2ZXJ5KChwYXJ0KSA9PiBwYXJ0Lmxlbmd0aCA+IDApKSB7XG4gICAgcmV0dXJuIHRydWVcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuZXhwb3J0IGNvbnN0IHJlZ2lzdGVyQXV0aFNldFRva2VuID0gKHByb2dyYW06IENvbW1hbmQpID0+IHtcbiAgcHJvZ3JhbS5jb21tYW5kc1xuICAgIC5maW5kKChjKSA9PiBjLm5hbWUoKSA9PT0gXCJhdXRoXCIpIVxuICAgIC5jb21tYW5kKFwic2V0LXRva2VuXCIpXG4gICAgLmRlc2NyaXB0aW9uKFwiRXhwbGljaXRseSBzZXQgeW91ciBhdXRoIHRva2VuXCIpXG4gICAgLmFyZ3VtZW50KFwiPHRva2VuPlwiLCBcIk5ldyB0b2tlbiB0byBtYW51YWxseSBjb25maWd1cmVcIilcbiAgICAuYWN0aW9uKCh0b2tlbikgPT4ge1xuICAgICAgaWYgKCF2YWxpZGF0ZUpXVExlbmd0aCh0b2tlbikpXG4gICAgICAgIHJldHVybiBjb25zb2xlLmxvZyhcIkludmFsaWQgdG9rZW4gcHJvdmlkZWRcIilcbiAgICAgIHNldFNlc3Npb25Ub2tlbih0b2tlbilcbiAgICAgIGNvbnNvbGUubG9nKFwiVG9rZW4gbWFudWFsbHkgdXBkYXRlZC5cIilcbiAgICB9KVxufVxuIiwgImltcG9ydCB7IHB1c2hTbmlwcGV0IH0gZnJvbSBcImxpYi9zaGFyZWQvcHVzaC1zbmlwcGV0XCJcbmltcG9ydCB0eXBlIHsgQ29tbWFuZCB9IGZyb20gXCJjb21tYW5kZXJcIlxuXG5leHBvcnQgY29uc3QgcmVnaXN0ZXJQdXNoID0gKHByb2dyYW06IENvbW1hbmQpID0+IHtcbiAgcHJvZ3JhbVxuICAgIC5jb21tYW5kKFwicHVzaFwiKVxuICAgIC5kZXNjcmlwdGlvbihcIlNhdmUgc25pcHBldCBjb2RlIHRvIFJlZ2lzdHJ5IEFQSVwiKVxuICAgIC5hcmd1bWVudChcIltmaWxlXVwiLCBcIlBhdGggdG8gdGhlIHNuaXBwZXQgZmlsZVwiKVxuICAgIC5hY3Rpb24oYXN5bmMgKGZpbGVQYXRoPzogc3RyaW5nKSA9PiB7XG4gICAgICBhd2FpdCBwdXNoU25pcHBldCh7XG4gICAgICAgIGZpbGVQYXRoLFxuICAgICAgICBvbkV4aXQ6IChjb2RlKSA9PiBwcm9jZXNzLmV4aXQoY29kZSksXG4gICAgICAgIG9uRXJyb3I6IChtZXNzYWdlKSA9PiBjb25zb2xlLmVycm9yKG1lc3NhZ2UpLFxuICAgICAgICBvblN1Y2Nlc3M6IChtZXNzYWdlKSA9PiBjb25zb2xlLmxvZyhtZXNzYWdlKSxcbiAgICAgIH0pXG4gICAgfSlcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7OztB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QjtBQUNuQyxVQUFNLFlBQVk7QUFBQSxNQUNoQjtBQUFBLE1BQ0EsUUFBUSxDQUFDLFNBQVMsUUFBUSxLQUFLLElBQUk7QUFBQSxNQUNuQyxTQUFTLENBQUMsWUFBWSxRQUFRLE1BQU0sT0FBTztBQUFBLE1BQzNDLFdBQVcsQ0FBQyxZQUFZLFFBQVEsSUFBSSxPQUFPO0FBQUEsSUFDN0MsQ0FBQztBQUFBLEVBQ0gsQ0FBQztBQUNMOzs7QTdCRU8sSUFBTSxVQUFVLElBQUksUUFBUTtBQUVuQyxRQUNHLEtBQUssTUFBTSxFQUNYLFlBQVksdUNBQXVDLEVBR25ELFFBQVFDLFFBQU8sSUFBSSxnQkFBSSxTQUFTLE9BQU8sS0FBSyxnQkFBSSxPQUFPO0FBRTFELGFBQWEsT0FBTztBQUVwQixZQUFZLE9BQU87QUFDbkIsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUVwQixhQUFhLE9BQU87QUFDcEIsa0JBQWtCLE9BQU87QUFDekIsbUJBQW1CLE9BQU87QUFDMUIsdUJBQXVCLE9BQU87QUFDOUIscUJBQXFCLE9BQU87QUFFNUIsZUFBZSxPQUFPO0FBQ3RCLG9CQUFvQixPQUFPO0FBRTNCLGVBQWUsT0FBTztBQUV0QixJQUFJLFFBQVEsS0FBSyxXQUFXLEdBQUc7QUFDN0IsYUFBVyxTQUFTLFFBQVEsSUFBSTtBQUNsQyxPQUFPO0FBQ0wsVUFBUSxNQUFNO0FBQ2hCOyIsCiAgIm5hbWVzIjogWyJmcyIsICJwYXRoIiwgImZzIiwgInBhdGgiLCAiZnMiLCAicGF0aCIsICJwYXRoIiwgInBhdGgiLCAicHJvZ3JhbSIsICJmcyIsICJwYXRoIiwgImZzIiwgInBhdGgiLCAia3kiLCAiZnMiLCAicGF0aCIsICJyZXNvbHZlIiwgInBhdGgiLCAiZnMiLCAiZnMiLCAicGF0aCIsICJmcyIsICJ0cyIsICJmcyIsICJwYXRoIiwgImt5IiwgInBhdGgiLCAia3kiLCAiZnMiLCAicHJvZ3JhbSIsICJwb3J0IiwgInJlc29sdmUiLCAic2VydmVyIiwgInByb2dyYW0iLCAia3kiLCAicHJvZ3JhbSIsICJwcm9ncmFtIiwgInByb2dyYW0iLCAicHJvZ3JhbSIsICJmcyIsICJwYXRoIiwgInByb2dyYW0iLCAia3kiLCAic2VtdmVyIiwgInBhdGgiLCAiZnMiLCAicHJvZ3JhbSIsICJwcm9ncmFtIiwgInByb2dyYW0iLCAicHJvZ3JhbSIsICJzZW12ZXIiXQp9Cg==