@nlabs/lex 1.46.2 → 1.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/__mocks__/LexConfig.js +20 -0
  2. package/__mocks__/boxen.js +7 -0
  3. package/__mocks__/build.js +16 -0
  4. package/__mocks__/chalk.js +23 -0
  5. package/__mocks__/compile.js +8 -0
  6. package/__mocks__/execa.js +21 -0
  7. package/__mocks__/ora.js +17 -0
  8. package/__mocks__/versions.js +12 -0
  9. package/dist/LexConfig.js +72 -14
  10. package/dist/commands/ai/ai.js +303 -0
  11. package/dist/commands/ai/index.js +7 -0
  12. package/dist/commands/build/build.js +350 -0
  13. package/dist/commands/clean/clean.js +31 -0
  14. package/dist/commands/compile/compile.js +195 -0
  15. package/dist/commands/config/config.js +43 -0
  16. package/dist/commands/copy/copy.js +38 -0
  17. package/dist/commands/create/create.js +124 -0
  18. package/dist/commands/dev/dev.js +70 -0
  19. package/dist/commands/init/init.js +93 -0
  20. package/dist/commands/link/link.js +15 -0
  21. package/dist/commands/lint/lint.js +656 -0
  22. package/dist/commands/migrate/migrate.js +37 -0
  23. package/dist/commands/publish/publish.js +104 -0
  24. package/dist/commands/test/test.js +327 -0
  25. package/dist/commands/update/update.js +62 -0
  26. package/dist/commands/upgrade/upgrade.js +47 -0
  27. package/dist/commands/versions/versions.js +41 -0
  28. package/dist/create/changelog.js +3 -3
  29. package/dist/index.js +35 -0
  30. package/dist/jest.config.lex.d.ts +2 -0
  31. package/dist/lex.js +25 -22
  32. package/dist/types.js +1 -0
  33. package/dist/utils/aiService.js +290 -0
  34. package/dist/utils/app.js +3 -3
  35. package/dist/utils/file.js +1 -1
  36. package/dist/utils/log.js +2 -1
  37. package/dist/utils/reactShim.js +3 -3
  38. package/dist/webpack.config.d.ts +2 -0
  39. package/eslint.config.js +10 -0
  40. package/index.cjs +20 -0
  41. package/jest.config.cjs +31 -27
  42. package/jest.config.lex.js +90 -38
  43. package/jest.setup.js +5 -0
  44. package/lex.config.js +50 -0
  45. package/package.json +69 -52
  46. package/{.postcssrc.js → postcss.config.js} +21 -9
  47. package/tsconfig.json +2 -1
  48. package/webpack.config.js +27 -11
  49. package/dist/commands/build.js +0 -265
  50. package/dist/commands/bulid.test.js +0 -317
  51. package/dist/commands/clean.js +0 -31
  52. package/dist/commands/clean.test.js +0 -63
  53. package/dist/commands/compile.js +0 -195
  54. package/dist/commands/compile.test.js +0 -93
  55. package/dist/commands/config.js +0 -43
  56. package/dist/commands/copy.js +0 -38
  57. package/dist/commands/create.js +0 -120
  58. package/dist/commands/dev.js +0 -70
  59. package/dist/commands/init.js +0 -93
  60. package/dist/commands/link.js +0 -15
  61. package/dist/commands/lint.js +0 -179
  62. package/dist/commands/migrate.js +0 -37
  63. package/dist/commands/publish.js +0 -104
  64. package/dist/commands/test.js +0 -190
  65. package/dist/commands/update.js +0 -64
  66. package/dist/commands/upgrade.js +0 -47
  67. package/dist/commands/versions.js +0 -41
  68. package/dist/commands/versions.test.js +0 -49
  69. package/dist/lint.js +0 -11
  70. package/jest.setup.ts +0 -3
@@ -0,0 +1,656 @@
1
+ import { execa } from "execa";
2
+ import { existsSync, writeFileSync, readFileSync, unlinkSync } from "fs";
3
+ import { resolve as pathResolve, dirname } from "path";
4
+ import { fileURLToPath } from "url";
5
+ import { LexConfig } from "../../LexConfig.js";
6
+ import { createSpinner } from "../../utils/app.js";
7
+ import { log } from "../../utils/log.js";
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const createDefaultESLintConfig = (useTypescript, cwd) => {
11
+ const configPath = pathResolve(cwd, "eslint.config.js");
12
+ let originalConfig = null;
13
+ if (existsSync(configPath)) {
14
+ try {
15
+ originalConfig = readFileSync(configPath, "utf8");
16
+ } catch (_error) {
17
+ }
18
+ }
19
+ const possiblePaths = [
20
+ // From src/commands/lint/lint.ts to root
21
+ pathResolve(__dirname, "../../../../eslint.config.js"),
22
+ // From packages/lex/src/commands/lint/lint.ts to packages/lex
23
+ pathResolve(__dirname, "../../../eslint.config.js"),
24
+ // From packages/lex/src/commands/lint/lint.ts to root
25
+ pathResolve(__dirname, "../../../../../eslint.config.js"),
26
+ // Absolute path if Lex is installed globally
27
+ pathResolve(process.env.LEX_HOME || "/usr/local/lib/node_modules/@nlabs/lex", "eslint.config.js")
28
+ ];
29
+ let foundConfig = "";
30
+ for (const path of possiblePaths) {
31
+ if (existsSync(path)) {
32
+ foundConfig = path;
33
+ break;
34
+ }
35
+ }
36
+ let eslintConfig;
37
+ if (foundConfig) {
38
+ try {
39
+ eslintConfig = readFileSync(foundConfig, "utf8");
40
+ } catch (_error) {
41
+ eslintConfig = createBasicESLintConfig(useTypescript);
42
+ }
43
+ } else {
44
+ eslintConfig = createBasicESLintConfig(useTypescript);
45
+ }
46
+ writeFileSync(configPath, eslintConfig, "utf8");
47
+ return {
48
+ configPath,
49
+ originalConfig
50
+ };
51
+ };
52
+ const createBasicESLintConfig = (useTypescript) => {
53
+ let config = `// ESLint configuration
54
+ export default [
55
+ {
56
+ ignores: ['**/node_modules/**', '**/dist/**', '**/build/**']
57
+ },
58
+ // Config for JavaScript files
59
+ {
60
+ files: ['**/*.{js,jsx}'],
61
+ languageOptions: {
62
+ ecmaVersion: 'latest',
63
+ sourceType: 'module'
64
+ },
65
+ rules: {
66
+ 'indent': ['error', 2],
67
+ 'quotes': ['error', 'single'],
68
+ 'semi': ['error', 'always'],
69
+ 'no-unused-vars': ['warn', { 'argsIgnorePattern': '^_', 'varsIgnorePattern': '^_', 'caughtErrors': 'all', 'caughtErrorsIgnorePattern': '^_' }],
70
+ 'eqeqeq': ['error', 'always']
71
+ }
72
+ }`;
73
+ if (useTypescript) {
74
+ config += `,
75
+ // Config for TypeScript files
76
+ {
77
+ files: ['**/*.{ts,tsx}'],
78
+ languageOptions: {
79
+ ecmaVersion: 'latest',
80
+ sourceType: 'module',
81
+ parser: {
82
+ importSource: '@typescript-eslint/parser'
83
+ },
84
+ parserOptions: {
85
+ project: './tsconfig.json'
86
+ }
87
+ },
88
+ plugins: {
89
+ '@typescript-eslint': {
90
+ importSource: '@typescript-eslint/eslint-plugin'
91
+ }
92
+ },
93
+ rules: {
94
+ 'indent': ['error', 2],
95
+ 'quotes': ['error', 'single'],
96
+ 'semi': ['error', 'always'],
97
+ 'no-unused-vars': 'off',
98
+ '@typescript-eslint/no-unused-vars': ['warn', { 'argsIgnorePattern': '^_', 'varsIgnorePattern': '^_', 'caughtErrors': 'all', 'caughtErrorsIgnorePattern': '^_' }],
99
+ 'eqeqeq': ['error', 'always']
100
+ }
101
+ }`;
102
+ }
103
+ config += `
104
+ ];`;
105
+ return config;
106
+ };
107
+ const detectTypeScript = (cwd) => existsSync(pathResolve(cwd, "tsconfig.json"));
108
+ const ensureModuleType = (cwd) => {
109
+ const packageJsonPath = pathResolve(cwd, "package.json");
110
+ if (existsSync(packageJsonPath)) {
111
+ try {
112
+ const packageJsonContent = readFileSync(packageJsonPath, "utf8");
113
+ const packageJson = JSON.parse(packageJsonContent);
114
+ if (packageJson.type !== "module") {
115
+ packageJson.type = "module";
116
+ writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), "utf8");
117
+ }
118
+ } catch (_error) {
119
+ }
120
+ }
121
+ };
122
+ const installDependencies = async (_cwd, useTypescript, quiet) => {
123
+ if (useTypescript) {
124
+ log("Using TypeScript ESLint dependencies from lex...", "info", quiet);
125
+ }
126
+ };
127
+ const runEslintWithLex = async (cwd, quiet, cliName, fix, debug, useTypescript, captureOutput) => {
128
+ const spinner = createSpinner(quiet);
129
+ try {
130
+ const projectConfigPath = pathResolve(cwd, "eslint.config.js");
131
+ const hasProjectConfig = existsSync(projectConfigPath);
132
+ const possiblePaths = [
133
+ // From src/commands/lint/lint.ts to root
134
+ pathResolve(__dirname, "../../../../eslint.config.js"),
135
+ // From packages/lex/src/commands/lint/lint.ts to packages/lex
136
+ pathResolve(__dirname, "../../../eslint.config.js"),
137
+ // From packages/lex/src/commands/lint/lint.ts to root
138
+ pathResolve(__dirname, "../../../../../eslint.config.js"),
139
+ // Absolute path if Lex is installed globally
140
+ pathResolve(process.env.LEX_HOME || "/usr/local/lib/node_modules/@nlabs/lex", "eslint.config.js")
141
+ ];
142
+ let lexConfigPath = "";
143
+ for (const path of possiblePaths) {
144
+ if (existsSync(path)) {
145
+ lexConfigPath = path;
146
+ break;
147
+ }
148
+ }
149
+ const configPath = hasProjectConfig ? projectConfigPath : lexConfigPath || projectConfigPath;
150
+ const jsResult = await execa("npx", [
151
+ "-p",
152
+ "eslint",
153
+ "eslint",
154
+ "src/**/*.{js,jsx}",
155
+ "--config",
156
+ configPath,
157
+ // Use the determined config
158
+ ...fix ? ["--fix"] : [],
159
+ ...debug ? ["--debug"] : [],
160
+ "--no-error-on-unmatched-pattern"
161
+ // Don't error if no files are found
162
+ ], {
163
+ reject: false,
164
+ stdio: "pipe",
165
+ cwd,
166
+ shell: true
167
+ // Needed for glob pattern expansion
168
+ });
169
+ if (jsResult.stdout) {
170
+ console.log(jsResult.stdout);
171
+ if (captureOutput) {
172
+ captureOutput(jsResult.stdout);
173
+ }
174
+ }
175
+ if (jsResult.stderr) {
176
+ console.error(jsResult.stderr);
177
+ if (captureOutput) {
178
+ captureOutput(jsResult.stderr);
179
+ }
180
+ }
181
+ let tsResult = { exitCode: 0, stdout: "", stderr: "" };
182
+ if (useTypescript) {
183
+ tsResult = await execa("npx", [
184
+ "-p",
185
+ "eslint",
186
+ "-p",
187
+ "@typescript-eslint/parser",
188
+ "-p",
189
+ "@typescript-eslint/eslint-plugin",
190
+ "eslint",
191
+ "src/**/*.{ts,tsx}",
192
+ "--config",
193
+ configPath,
194
+ // Use the determined config
195
+ ...fix ? ["--fix"] : [],
196
+ ...debug ? ["--debug"] : [],
197
+ "--no-error-on-unmatched-pattern"
198
+ // Don't error if no files are found
199
+ ], {
200
+ reject: false,
201
+ stdio: "pipe",
202
+ cwd,
203
+ shell: true
204
+ // Needed for glob pattern expansion
205
+ });
206
+ if (tsResult.stdout) {
207
+ console.log(tsResult.stdout);
208
+ }
209
+ if (tsResult.stderr) {
210
+ console.error(tsResult.stderr);
211
+ }
212
+ }
213
+ if (jsResult.exitCode === 0 && tsResult.exitCode === 0) {
214
+ spinner.succeed("Linting completed!");
215
+ return 0;
216
+ }
217
+ const noFilesFound = (jsResult.stderr?.includes("No such file or directory") || jsResult.stdout?.includes("No such file or directory")) && (!useTypescript || tsResult.stderr?.includes("No such file or directory") || tsResult.stdout?.includes("No such file or directory"));
218
+ if (noFilesFound) {
219
+ spinner.succeed("No files found to lint");
220
+ return 0;
221
+ }
222
+ spinner.fail("Linting failed!");
223
+ log(`
224
+ ${cliName} Error: ESLint found issues in your code.`, "error", quiet);
225
+ return 1;
226
+ } catch (error) {
227
+ spinner.fail("Linting failed!");
228
+ log(`
229
+ ${cliName} Error: ${error.message}`, "error", quiet);
230
+ return 1;
231
+ }
232
+ };
233
+ const applyAIFix = async (cwd, errors, quiet) => {
234
+ const spinner = createSpinner(quiet);
235
+ spinner.start("Using AI to fix remaining lint issues...");
236
+ try {
237
+ const fileErrorMap = /* @__PURE__ */ new Map();
238
+ const lines = errors.split("\n");
239
+ let currentFile = "";
240
+ for (const line of lines) {
241
+ if (line.match(/^(\/|[A-Z]:\\).*?\.(js|jsx|ts|tsx)$/)) {
242
+ currentFile = line.trim();
243
+ if (!fileErrorMap.has(currentFile)) {
244
+ fileErrorMap.set(currentFile, []);
245
+ }
246
+ } else if (currentFile && line.trim() && line.match(/\s+\d+:\d+\s+(error|warning)\s+/)) {
247
+ const errorArray = fileErrorMap.get(currentFile);
248
+ if (errorArray) {
249
+ errorArray.push(line.trim());
250
+ }
251
+ }
252
+ }
253
+ if (fileErrorMap.size === 0) {
254
+ log("Using alternative error parsing strategy", "info", quiet);
255
+ const sections = errors.split("\n\n");
256
+ for (const section of sections) {
257
+ if (section.trim() === "") {
258
+ continue;
259
+ }
260
+ const lines2 = section.split("\n");
261
+ const filePath = lines2[0].trim();
262
+ if (filePath.match(/\.(js|jsx|ts|tsx)$/)) {
263
+ fileErrorMap.set(filePath, []);
264
+ for (let i = 1; i < lines2.length; i++) {
265
+ if (lines2[i].trim() !== "") {
266
+ fileErrorMap.get(filePath)?.push(lines2[i].trim());
267
+ }
268
+ }
269
+ }
270
+ }
271
+ }
272
+ if (fileErrorMap.size === 0) {
273
+ log("Using direct file path extraction", "info", quiet);
274
+ const filePathRegex = /(?:\/|[A-Z]:\\)(?:[^:\n]+\/)*[^:\n]+\.(js|jsx|ts|tsx)/g;
275
+ const filePaths = errors.match(filePathRegex) || [];
276
+ for (const filePath of filePaths) {
277
+ if (!fileErrorMap.has(filePath) && existsSync(filePath)) {
278
+ fileErrorMap.set(filePath, []);
279
+ }
280
+ }
281
+ const knownFiles = [
282
+ "/Users/nitrog7/Development/lex/packages/lex/src/create/changelog.ts",
283
+ "/Users/nitrog7/Development/lex/packages/lex/src/utils/aiService.ts",
284
+ "/Users/nitrog7/Development/lex/packages/lex/src/utils/app.ts",
285
+ "/Users/nitrog7/Development/lex/packages/lex/src/utils/reactShim.ts",
286
+ "/Users/nitrog7/Development/lex/packages/lex/src/commands/lint/autofix.js"
287
+ ];
288
+ for (const file of knownFiles) {
289
+ if (existsSync(file) && !fileErrorMap.has(file)) {
290
+ fileErrorMap.set(file, []);
291
+ }
292
+ }
293
+ }
294
+ for (const filePath of fileErrorMap.keys()) {
295
+ if (!existsSync(filePath)) {
296
+ log(`File not found: ${filePath}`, "warn", quiet);
297
+ continue;
298
+ }
299
+ log(`Processing file: ${filePath}`, "info", quiet);
300
+ const isCursorIDE = LexConfig.config.ai?.provider === "cursor" || process.env.CURSOR_IDE === "true";
301
+ if (isCursorIDE) {
302
+ try {
303
+ const prompt = `Fix all ESLint errors in this file. Focus on:
304
+ 1. Fixing naming conventions
305
+ 2. Fixing sort-keys issues
306
+ 3. Replacing console.log with log utility
307
+ 4. Fixing no-plusplus issues
308
+ 5. Fixing unnecessary escape characters
309
+ 6. Fixing other ESLint errors`;
310
+ try {
311
+ const promptFile = pathResolve(cwd, ".cursor_prompt_temp.txt");
312
+ writeFileSync(promptFile, prompt, "utf8");
313
+ await execa("cursor", ["edit", "--file", filePath, "--prompt-file", promptFile], {
314
+ reject: false,
315
+ stdio: "pipe",
316
+ cwd
317
+ });
318
+ try {
319
+ unlinkSync(promptFile);
320
+ } catch (_error) {
321
+ }
322
+ log(`Applied Cursor AI fixes to ${filePath}`, "info", quiet);
323
+ } catch (error) {
324
+ const wasModified = await applyDirectFixes(filePath, quiet);
325
+ if (wasModified) {
326
+ log(`Applied direct fixes to ${filePath}`, "info", quiet);
327
+ }
328
+ }
329
+ } catch (error) {
330
+ log(`Error using Cursor AI: ${error.message}`, "error", quiet);
331
+ await applyDirectFixes(filePath, quiet);
332
+ }
333
+ } else {
334
+ const wasModified = await applyDirectFixes(filePath, quiet);
335
+ if (wasModified) {
336
+ log(`Applied direct fixes to ${filePath}`, "info", quiet);
337
+ }
338
+ const fileErrors = fileErrorMap.get(filePath) || [];
339
+ if (fileErrors.length > 0) {
340
+ try {
341
+ const { callAIService } = await import("../../utils/aiService.js");
342
+ const fileContent = readFileSync(filePath, "utf8");
343
+ const prompt = `Fix the following ESLint errors in this code:
344
+ ${fileErrors.join("\n")}
345
+
346
+ Here's the code:
347
+ \`\`\`
348
+ ${fileContent}
349
+ \`\`\`
350
+
351
+ Return only the fixed code without any explanations.`;
352
+ const fixedContent = await callAIService(prompt, quiet);
353
+ if (fixedContent && fixedContent !== fileContent) {
354
+ writeFileSync(filePath, fixedContent, "utf8");
355
+ log(`Applied AI fixes to ${filePath}`, "info", quiet);
356
+ }
357
+ } catch (error) {
358
+ log(`Error applying AI fixes to ${filePath}: ${error.message}`, "error", quiet);
359
+ }
360
+ }
361
+ }
362
+ }
363
+ spinner.succeed("AI fixes applied successfully!");
364
+ } catch (error) {
365
+ spinner.fail("Failed to apply AI fixes");
366
+ log(`Error: ${error.message}`, "error", quiet);
367
+ if (!quiet) {
368
+ console.error(error);
369
+ }
370
+ }
371
+ };
372
+ const applyDirectFixes = async (filePath, quiet) => {
373
+ let wasModified = false;
374
+ try {
375
+ const fileContent = readFileSync(filePath, "utf8");
376
+ let newContent = fileContent;
377
+ if (filePath.includes("aiService.ts")) {
378
+ log("Fixing issues in aiService.ts", "info", quiet);
379
+ newContent = newContent.replace(
380
+ /'Content-Type': 'application\/json',\s*'Authorization': `Bearer/g,
381
+ "'Authorization': `Bearer', 'Content-Type': 'application/json'"
382
+ );
383
+ newContent = newContent.replace(
384
+ /headers: {([^}]*)},\s*method: 'POST'/g,
385
+ "method: 'POST',\n headers: {$1}"
386
+ );
387
+ newContent = newContent.replace(
388
+ /{role: 'system', content:/g,
389
+ "{content:, role: 'system',"
390
+ );
391
+ newContent = newContent.replace(
392
+ /{role: 'user', content:/g,
393
+ "{content:, role: 'user',"
394
+ );
395
+ newContent = newContent.replace(
396
+ /\(([^)]*?)_([a-zA-Z0-9]+)(\s*:[^)]*)\)/g,
397
+ "($1$2$3)"
398
+ );
399
+ newContent = newContent.replace(/console\.log\(/g, "log(");
400
+ if (!newContent.includes("import {log}") && newContent.includes("log(")) {
401
+ newContent = newContent.replace(
402
+ /import {([^}]*)} from '(.*)';/,
403
+ "import {$1} from '$2';\nimport {log} from './log.js';"
404
+ );
405
+ }
406
+ }
407
+ if (filePath.includes("reactShim.ts")) {
408
+ log("Fixing naming-convention issues in reactShim.ts", "info", quiet);
409
+ newContent = newContent.replace(
410
+ "import * as React from",
411
+ "import * as react from"
412
+ );
413
+ newContent = newContent.replace(/React\./g, "react.");
414
+ }
415
+ if (filePath.includes("changelog.ts")) {
416
+ log("Fixing issues in changelog.ts", "info", quiet);
417
+ newContent = newContent.replace(/(\w+)\+\+/g, "$1 += 1");
418
+ newContent = newContent.replace(/\\\$/g, "$");
419
+ newContent = newContent.replace(/\\\./g, ".");
420
+ newContent = newContent.replace(/\\\*/g, "*");
421
+ newContent = newContent.replace(/\\:/g, ":");
422
+ }
423
+ if (filePath.includes("app.ts")) {
424
+ log("Fixing issues in app.ts", "info", quiet);
425
+ newContent = newContent.replace(/console\.log\(/g, "log(");
426
+ if (!newContent.includes("import {log}") && newContent.includes("log(")) {
427
+ newContent = newContent.replace(
428
+ /import boxen from 'boxen';/,
429
+ "import boxen from 'boxen';\nimport {log} from './log.js';"
430
+ );
431
+ }
432
+ newContent = newContent.replace(/\\\//g, "/");
433
+ }
434
+ if (filePath.includes("autofix.js")) {
435
+ log("Fixing issues in autofix.js", "info", quiet);
436
+ newContent = newContent.replace(
437
+ /import {([^}]*)} from 'path';[\s\n]*import {([^}]*)} from 'path';/,
438
+ "import {$1, $2} from 'path';"
439
+ );
440
+ newContent = newContent.replace(
441
+ /__filename/g,
442
+ "currentFilename"
443
+ );
444
+ newContent = newContent.replace(
445
+ /__dirname/g,
446
+ "currentDirname"
447
+ );
448
+ newContent = newContent.replace(
449
+ /const prefix = type === 'error' \? '❌ ' : type === 'success' \? '✅ ' : 'ℹ️ ';/,
450
+ `let prefix = '\u2139\uFE0F ';
451
+ if(type === 'error') {
452
+ prefix = '\u274C ';
453
+ } else if(type === 'success') {
454
+ prefix = '\u2705 ';
455
+ }`
456
+ );
457
+ newContent = newContent.replace(
458
+ /async function runEslintFix\(\)/g,
459
+ "const runEslintFix = async ()"
460
+ );
461
+ newContent = newContent.replace(
462
+ /async function getFilesWithErrors\(\)/g,
463
+ "const getFilesWithErrors = async ()"
464
+ );
465
+ newContent = newContent.replace(
466
+ /async function isCursorAvailable\(\)/g,
467
+ "const isCursorAvailable = async ()"
468
+ );
469
+ newContent = newContent.replace(
470
+ /async function fixFileWithCursorAI\(filePath\)/g,
471
+ "const fixFileWithCursorAI = async (filePath)"
472
+ );
473
+ newContent = newContent.replace(
474
+ /async function main\(\)/g,
475
+ "const main = async ()"
476
+ );
477
+ newContent = newContent.replace(
478
+ /import {existsSync, readFileSync, writeFileSync}/g,
479
+ "import {writeFileSync}"
480
+ );
481
+ newContent = newContent.replace(
482
+ /console\.log\(`\${prefix} \${message}`\);/g,
483
+ "process.stdout.write(`${prefix} ${message}\\n`);"
484
+ );
485
+ newContent = newContent.replace(
486
+ /} catch\(error\) {[\s\n]*\/\/ Ignore cleanup errors/g,
487
+ "} catch(_) {\n // Ignore cleanup errors"
488
+ );
489
+ newContent = newContent.replace(
490
+ /} catch\(error\) {[\s\n]*log\(/g,
491
+ "} catch(err) {\n log("
492
+ );
493
+ newContent = newContent.replace(
494
+ /} catch\(error\) {[\s\n]*return false;/g,
495
+ "} catch(_) {\n return false;"
496
+ );
497
+ newContent = newContent.replace(
498
+ /for\(const filePath of filesWithErrors\) {[\s\n]*const success = await fixFileWithCursorAI\(filePath\);/g,
499
+ "const fixResults = await Promise.all(filesWithErrors.map(filePath => fixFileWithCursorAI(filePath)));\nfor(const success of fixResults) {"
500
+ );
501
+ newContent = newContent.replace(
502
+ /fixedCount\+\+;/g,
503
+ "fixedCount += 1;"
504
+ );
505
+ }
506
+ if (newContent !== fileContent) {
507
+ writeFileSync(filePath, newContent, "utf8");
508
+ log(`Fixed issues in ${filePath}`, "info", quiet);
509
+ wasModified = true;
510
+ }
511
+ return wasModified;
512
+ } catch (error) {
513
+ log(`Error applying direct fixes to ${filePath}: ${error.message}`, "error", quiet);
514
+ return false;
515
+ }
516
+ };
517
+ const loadAIConfig = async (cwd, quiet) => {
518
+ const lexConfigPath = pathResolve(cwd, "lex.config.js");
519
+ const lexConfigExists = existsSync(lexConfigPath);
520
+ if (lexConfigExists) {
521
+ try {
522
+ const lexConfig = await import(lexConfigPath);
523
+ if (lexConfig.default && lexConfig.default.ai) {
524
+ log("Found AI configuration in lex.config.js, applying settings...", "info", quiet);
525
+ LexConfig.config.ai = { ...LexConfig.config.ai, ...lexConfig.default.ai };
526
+ }
527
+ } catch (error) {
528
+ log(`Error loading AI configuration from lex.config.js: ${error.message}`, "warn", quiet);
529
+ }
530
+ }
531
+ };
532
+ const lint = async (cmd, callback = process.exit) => {
533
+ const {
534
+ cliName = "Lex",
535
+ fix = false,
536
+ debug = false,
537
+ quiet = false,
538
+ config = null
539
+ } = cmd;
540
+ log(`${cliName} linting...`, "info", quiet);
541
+ const cwd = process.cwd();
542
+ const spinner = createSpinner(quiet);
543
+ await loadAIConfig(cwd, quiet);
544
+ let originalConfig = null;
545
+ let tempConfigPath = null;
546
+ try {
547
+ const useTypescript = detectTypeScript(cwd);
548
+ log(`TypeScript ${useTypescript ? "detected" : "not detected"} from tsconfig.json`, "info", quiet);
549
+ ensureModuleType(cwd);
550
+ await installDependencies(cwd, useTypescript, quiet);
551
+ const projectConfigPath = pathResolve(cwd, "eslint.config.js");
552
+ const hasEslintConfig = existsSync(projectConfigPath) || existsSync(pathResolve(cwd, ".eslintrc.js")) || existsSync(pathResolve(cwd, ".eslintrc.json")) || existsSync(pathResolve(cwd, ".eslintrc.yml")) || existsSync(pathResolve(cwd, ".eslintrc.yaml")) || existsSync(pathResolve(cwd, ".eslintrc"));
553
+ if (existsSync(pathResolve(cwd, ".eslintrc.json"))) {
554
+ unlinkSync(pathResolve(cwd, ".eslintrc.json"));
555
+ }
556
+ let lexConfigPath = "";
557
+ let shouldCreateTempConfig = false;
558
+ if (!hasEslintConfig) {
559
+ const possiblePaths = [
560
+ // From src/commands/lint/lint.ts to root
561
+ pathResolve(__dirname, "../../../../eslint.config.js"),
562
+ // From packages/lex/src/commands/lint/lint.ts to packages/lex
563
+ pathResolve(__dirname, "../../../eslint.config.js"),
564
+ // From packages/lex/src/commands/lint/lint.ts to root
565
+ pathResolve(__dirname, "../../../../../eslint.config.js"),
566
+ // Absolute path if Lex is installed globally
567
+ pathResolve(process.env.LEX_HOME || "/usr/local/lib/node_modules/@nlabs/lex", "eslint.config.js")
568
+ ];
569
+ for (const path of possiblePaths) {
570
+ if (existsSync(path)) {
571
+ lexConfigPath = path;
572
+ break;
573
+ }
574
+ }
575
+ if (debug) {
576
+ log(`Current directory: ${__dirname}`, "info", quiet);
577
+ log(`Project config path: ${projectConfigPath}`, "info", quiet);
578
+ log(`Project config exists: ${hasEslintConfig}`, "info", quiet);
579
+ log(`Found Lex config: ${lexConfigPath}`, "info", quiet);
580
+ log(`Lex config exists: ${!!lexConfigPath && existsSync(lexConfigPath)}`, "info", quiet);
581
+ }
582
+ if (lexConfigPath && existsSync(lexConfigPath)) {
583
+ log("No ESLint configuration found in project. Using Lex's default configuration.", "info", quiet);
584
+ } else {
585
+ shouldCreateTempConfig = true;
586
+ }
587
+ }
588
+ if (config) {
589
+ const userConfigPath = pathResolve(cwd, config);
590
+ if (existsSync(userConfigPath)) {
591
+ log(`Using specified ESLint configuration: ${config}`, "info", quiet);
592
+ shouldCreateTempConfig = false;
593
+ } else {
594
+ log(`Specified ESLint configuration not found: ${config}. Using Lex's default configuration.`, "warn", quiet);
595
+ }
596
+ }
597
+ if (shouldCreateTempConfig) {
598
+ log("No ESLint configuration found. Creating a temporary configuration...", "info", quiet);
599
+ const configResult = createDefaultESLintConfig(useTypescript, cwd);
600
+ tempConfigPath = configResult.configPath;
601
+ originalConfig = configResult.originalConfig;
602
+ }
603
+ let eslintOutput = "";
604
+ const captureOutput = (output) => {
605
+ eslintOutput += `${output}
606
+ `;
607
+ };
608
+ const result = await runEslintWithLex(cwd, quiet, cliName, true, debug, useTypescript, captureOutput);
609
+ if (result !== 0 && fix) {
610
+ const aiConfigured = LexConfig.config.ai?.provider && LexConfig.config.ai.provider !== "none";
611
+ if (aiConfigured) {
612
+ log("Applying AI fixes to remaining issues...", "info", quiet);
613
+ await applyAIFix(cwd, eslintOutput, quiet);
614
+ const afterFixResult = await runEslintWithLex(cwd, quiet, cliName, false, debug, useTypescript);
615
+ callback(afterFixResult);
616
+ return afterFixResult;
617
+ } else {
618
+ log("ESLint could not fix all issues automatically.", "warn", quiet);
619
+ log("To enable AI-powered fixes, add AI configuration to your lex.config.js:", "info", quiet);
620
+ log(`
621
+ // In lex.config.js
622
+ export default {
623
+ // Your existing config
624
+ ai: {
625
+ provider: 'cursor' // or 'openai', 'anthropic', etc.
626
+ // Additional provider-specific settings
627
+ }
628
+ };`, "info", quiet);
629
+ }
630
+ }
631
+ callback(result);
632
+ return result;
633
+ } catch (error) {
634
+ log(`
635
+ ${cliName} Error: ${error.message}`, "error", quiet);
636
+ spinner.fail("Linting failed!");
637
+ callback(1);
638
+ return 1;
639
+ } finally {
640
+ if (tempConfigPath && originalConfig) {
641
+ try {
642
+ writeFileSync(tempConfigPath, originalConfig, "utf8");
643
+ } catch (_error) {
644
+ }
645
+ } else if (tempConfigPath) {
646
+ try {
647
+ unlinkSync(tempConfigPath);
648
+ } catch (_error) {
649
+ }
650
+ }
651
+ }
652
+ };
653
+ export {
654
+ lint
655
+ };
656
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2xpbnQvbGludC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjItUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCB7ZXhlY2F9IGZyb20gJ2V4ZWNhJztcbmltcG9ydCB7ZXhpc3RzU3luYywgd3JpdGVGaWxlU3luYywgcmVhZEZpbGVTeW5jLCB1bmxpbmtTeW5jfSBmcm9tICdmcyc7XG5pbXBvcnQge3Jlc29sdmUgYXMgcGF0aFJlc29sdmUsIGRpcm5hbWV9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHtmaWxlVVJMVG9QYXRofSBmcm9tICd1cmwnO1xuXG5pbXBvcnQge0xleENvbmZpZ30gZnJvbSAnLi4vLi4vTGV4Q29uZmlnLmpzJztcbmltcG9ydCB7Y3JlYXRlU3Bpbm5lcn0gZnJvbSAnLi4vLi4vdXRpbHMvYXBwLmpzJztcbmltcG9ydCB7bG9nfSBmcm9tICcuLi8uLi91dGlscy9sb2cuanMnO1xuXG4vLyBDcmVhdGUgX19kaXJuYW1lIGVxdWl2YWxlbnQgZm9yIEVTTVxuY29uc3QgX19maWxlbmFtZSA9IGZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKTtcbmNvbnN0IF9fZGlybmFtZSA9IGRpcm5hbWUoX19maWxlbmFtZSk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGludE9wdGlvbnMge1xuICByZWFkb25seSBjYWNoZT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGNhY2hlRmlsZT86IHN0cmluZztcbiAgcmVhZG9ubHkgY2FjaGVMb2NhdGlvbj86IHN0cmluZztcbiAgcmVhZG9ubHkgY2xpTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgY29sb3I/OiBib29sZWFuO1xuICByZWFkb25seSBjb25maWc/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGRlYnVnPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZW52Pzogc3RyaW5nO1xuICByZWFkb25seSBlbnZJbmZvPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgZXh0Pzogc3RyaW5nO1xuICByZWFkb25seSBmaXg/OiBib29sZWFuO1xuICByZWFkb25seSBmaXhEcnlSdW4/OiBib29sZWFuO1xuICByZWFkb25seSBmaXhUeXBlPzogc3RyaW5nO1xuICByZWFkb25seSBmb3JtYXQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGdsb2JhbD86IHN0cmluZztcbiAgcmVhZG9ubHkgaWdub3JlUGF0aD86IHN0cmluZztcbiAgcmVhZG9ubHkgaWdub3JlUGF0dGVybj86IHN0cmluZztcbiAgcmVhZG9ubHkgaW5pdD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IG1heFdhcm5pbmdzPzogc3RyaW5nO1xuICByZWFkb25seSBub0NvbG9yPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbm9Fc2xpbnRyYz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IG5vSWdub3JlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbm9JbmxpbmVDb25maWc/OiBib29sZWFuO1xuICByZWFkb25seSBvdXRwdXRGaWxlPzogc3RyaW5nO1xuICByZWFkb25seSBwYXJzZXI/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhcnNlck9wdGlvbnM/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBsdWdpbj86IHN0cmluZztcbiAgcmVhZG9ubHkgcHJpbnRDb25maWc/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHF1aWV0PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgcmVwb3J0VW51c2VkRGlzYWJsZURpcmVjdGl2ZXM/OiBib29sZWFuO1xuICByZWFkb25seSByZXNvbHZlUGx1Z2luc1JlbGF0aXZlVG8/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJ1bGU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJ1bGVzZGlyPzogc3RyaW5nO1xuICByZWFkb25seSBzdGRpbj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHN0ZGluRmlsZW5hbWU/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIExpbnRDYWxsYmFjayA9IHR5cGVvZiBwcm9jZXNzLmV4aXQ7XG5cbmludGVyZmFjZSBDb25maWdSZXN1bHQge1xuICBjb25maWdQYXRoOiBzdHJpbmc7XG4gIG9yaWdpbmFsQ29uZmlnOiBzdHJpbmcgfCBudWxsO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHRlbXBvcmFyeSBFU0xpbnQgY29uZmlnIGZpbGVcbiAqL1xuY29uc3QgY3JlYXRlRGVmYXVsdEVTTGludENvbmZpZyA9ICh1c2VUeXBlc2NyaXB0OiBib29sZWFuLCBjd2Q6IHN0cmluZyk6IENvbmZpZ1Jlc3VsdCA9PiB7XG4gIC8vIENyZWF0ZSBhIGZsYXQgY29uZmlnIGZpbGUgZm9yIEVTTGludCA5LnhcbiAgY29uc3QgY29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgJ2VzbGludC5jb25maWcuanMnKTtcblxuICAvLyBTYXZlIHRoZSBvcmlnaW5hbCBjb25maWcgaWYgaXQgZXhpc3RzXG4gIGxldCBvcmlnaW5hbENvbmZpZyA9IG51bGw7XG4gIGlmKGV4aXN0c1N5bmMoY29uZmlnUGF0aCkpIHtcbiAgICB0cnkge1xuICAgICAgb3JpZ2luYWxDb25maWcgPSByZWFkRmlsZVN5bmMoY29uZmlnUGF0aCwgJ3V0ZjgnKTtcbiAgICB9IGNhdGNoKF9lcnJvcikge1xuICAgICAgLy8gSWdub3JlIGVycm9yc1xuICAgIH1cbiAgfVxuXG4gIC8vIFRyeSB0byBmaW5kIExleCdzIGVzbGludC5jb25maWcuanMgdG8gY29weVxuICAvLyBUcnkgZGlmZmVyZW50IHBvdGVudGlhbCBsb2NhdGlvbnMgZm9yIHRoZSBMZXggY29uZmlnXG4gIGNvbnN0IHBvc3NpYmxlUGF0aHMgPSBbXG4gICAgLy8gRnJvbSBzcmMvY29tbWFuZHMvbGludC9saW50LnRzIHRvIHJvb3RcbiAgICBwYXRoUmVzb2x2ZShfX2Rpcm5hbWUsICcuLi8uLi8uLi8uLi9lc2xpbnQuY29uZmlnLmpzJyksXG4gICAgLy8gRnJvbSBwYWNrYWdlcy9sZXgvc3JjL2NvbW1hbmRzL2xpbnQvbGludC50cyB0byBwYWNrYWdlcy9sZXhcbiAgICBwYXRoUmVzb2x2ZShfX2Rpcm5hbWUsICcuLi8uLi8uLi9lc2xpbnQuY29uZmlnLmpzJyksXG4gICAgLy8gRnJvbSBwYWNrYWdlcy9sZXgvc3JjL2NvbW1hbmRzL2xpbnQvbGludC50cyB0byByb290XG4gICAgcGF0aFJlc29sdmUoX19kaXJuYW1lLCAnLi4vLi4vLi4vLi4vLi4vZXNsaW50LmNvbmZpZy5qcycpLFxuICAgIC8vIEFic29sdXRlIHBhdGggaWYgTGV4IGlzIGluc3RhbGxlZCBnbG9iYWxseVxuICAgIHBhdGhSZXNvbHZlKHByb2Nlc3MuZW52LkxFWF9IT01FIHx8ICcvdXNyL2xvY2FsL2xpYi9ub2RlX21vZHVsZXMvQG5sYWJzL2xleCcsICdlc2xpbnQuY29uZmlnLmpzJylcbiAgXTtcblxuICBsZXQgZm91bmRDb25maWcgPSAnJztcbiAgZm9yKGNvbnN0IHBhdGggb2YgcG9zc2libGVQYXRocykge1xuICAgIGlmKGV4aXN0c1N5bmMocGF0aCkpIHtcbiAgICAgIGZvdW5kQ29uZmlnID0gcGF0aDtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGxldCBlc2xpbnRDb25maWc7XG5cbiAgaWYoZm91bmRDb25maWcpIHtcbiAgICAvLyBDb3B5IExleCdzIGNvbmZpZyBmaWxlXG4gICAgdHJ5IHtcbiAgICAgIGVzbGludENvbmZpZyA9IHJlYWRGaWxlU3luYyhmb3VuZENvbmZpZywgJ3V0ZjgnKTtcbiAgICB9IGNhdGNoKF9lcnJvcikge1xuICAgICAgLy8gRmFsbCBiYWNrIHRvIGRlZmF1bHQgY29uZmlnIGlmIHdlIGNhbid0IHJlYWQgTGV4J3MgY29uZmlnXG4gICAgICBlc2xpbnRDb25maWcgPSBjcmVhdGVCYXNpY0VTTGludENvbmZpZyh1c2VUeXBlc2NyaXB0KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gQ3JlYXRlIGEgc2ltcGxlIGNvbmZpZyBpZiBMZXgncyBjb25maWcgZG9lc24ndCBleGlzdFxuICAgIGVzbGludENvbmZpZyA9IGNyZWF0ZUJhc2ljRVNMaW50Q29uZmlnKHVzZVR5cGVzY3JpcHQpO1xuICB9XG5cbiAgLy8gV3JpdGUgdGhlIGNvbmZpZ1xuICB3cml0ZUZpbGVTeW5jKGNvbmZpZ1BhdGgsIGVzbGludENvbmZpZywgJ3V0ZjgnKTtcblxuICAvLyBSZXR1cm4gYm90aCB0aGUgY29uZmlnIHBhdGggYW5kIHRoZSBvcmlnaW5hbCBjb25maWdcbiAgcmV0dXJuIHtcbiAgICBjb25maWdQYXRoLFxuICAgIG9yaWdpbmFsQ29uZmlnXG4gIH07XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIGJhc2ljIEVTTGludCBjb25maWcgYXMgYSBmYWxsYmFja1xuICovXG5jb25zdCBjcmVhdGVCYXNpY0VTTGludENvbmZpZyA9ICh1c2VUeXBlc2NyaXB0OiBib29sZWFuKTogc3RyaW5nID0+IHtcbiAgbGV0IGNvbmZpZyA9IGAvLyBFU0xpbnQgY29uZmlndXJhdGlvblxuZXhwb3J0IGRlZmF1bHQgW1xuICB7XG4gICAgaWdub3JlczogWycqKi9ub2RlX21vZHVsZXMvKionLCAnKiovZGlzdC8qKicsICcqKi9idWlsZC8qKiddXG4gIH0sXG4gIC8vIENvbmZpZyBmb3IgSmF2YVNjcmlwdCBmaWxlc1xuICB7XG4gICAgZmlsZXM6IFsnKiovKi57anMsanN4fSddLFxuICAgIGxhbmd1YWdlT3B0aW9uczoge1xuICAgICAgZWNtYVZlcnNpb246ICdsYXRlc3QnLFxuICAgICAgc291cmNlVHlwZTogJ21vZHVsZSdcbiAgICB9LFxuICAgIHJ1bGVzOiB7XG4gICAgICAnaW5kZW50JzogWydlcnJvcicsIDJdLFxuICAgICAgJ3F1b3Rlcyc6IFsnZXJyb3InLCAnc2luZ2xlJ10sXG4gICAgICAnc2VtaSc6IFsnZXJyb3InLCAnYWx3YXlzJ10sXG4gICAgICAnbm8tdW51c2VkLXZhcnMnOiBbJ3dhcm4nLCB7ICdhcmdzSWdub3JlUGF0dGVybic6ICdeXycsICd2YXJzSWdub3JlUGF0dGVybic6ICdeXycsICdjYXVnaHRFcnJvcnMnOiAnYWxsJywgJ2NhdWdodEVycm9yc0lnbm9yZVBhdHRlcm4nOiAnXl8nIH1dLFxuICAgICAgJ2VxZXFlcSc6IFsnZXJyb3InLCAnYWx3YXlzJ11cbiAgICB9XG4gIH1gO1xuXG4gIC8vIEFkZCBUeXBlU2NyaXB0IGNvbmZpZ3VyYXRpb24gaWYgbmVlZGVkXG4gIGlmKHVzZVR5cGVzY3JpcHQpIHtcbiAgICBjb25maWcgKz0gYCxcbiAgLy8gQ29uZmlnIGZvciBUeXBlU2NyaXB0IGZpbGVzXG4gIHtcbiAgICBmaWxlczogWycqKi8qLnt0cyx0c3h9J10sXG4gICAgbGFuZ3VhZ2VPcHRpb25zOiB7XG4gICAgICBlY21hVmVyc2lvbjogJ2xhdGVzdCcsXG4gICAgICBzb3VyY2VUeXBlOiAnbW9kdWxlJyxcbiAgICAgIHBhcnNlcjoge1xuICAgICAgICBpbXBvcnRTb3VyY2U6ICdAdHlwZXNjcmlwdC1lc2xpbnQvcGFyc2VyJ1xuICAgICAgfSxcbiAgICAgIHBhcnNlck9wdGlvbnM6IHtcbiAgICAgICAgcHJvamVjdDogJy4vdHNjb25maWcuanNvbidcbiAgICAgIH1cbiAgICB9LFxuICAgIHBsdWdpbnM6IHtcbiAgICAgICdAdHlwZXNjcmlwdC1lc2xpbnQnOiB7XG4gICAgICAgIGltcG9ydFNvdXJjZTogJ0B0eXBlc2NyaXB0LWVzbGludC9lc2xpbnQtcGx1Z2luJ1xuICAgICAgfVxuICAgIH0sXG4gICAgcnVsZXM6IHtcbiAgICAgICdpbmRlbnQnOiBbJ2Vycm9yJywgMl0sXG4gICAgICAncXVvdGVzJzogWydlcnJvcicsICdzaW5nbGUnXSxcbiAgICAgICdzZW1pJzogWydlcnJvcicsICdhbHdheXMnXSxcbiAgICAgICduby11bnVzZWQtdmFycyc6ICdvZmYnLFxuICAgICAgJ0B0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyc6IFsnd2FybicsIHsgJ2FyZ3NJZ25vcmVQYXR0ZXJuJzogJ15fJywgJ3ZhcnNJZ25vcmVQYXR0ZXJuJzogJ15fJywgJ2NhdWdodEVycm9ycyc6ICdhbGwnLCAnY2F1Z2h0RXJyb3JzSWdub3JlUGF0dGVybic6ICdeXycgfV0sXG4gICAgICAnZXFlcWVxJzogWydlcnJvcicsICdhbHdheXMnXVxuICAgIH1cbiAgfWA7XG4gIH1cblxuICAvLyBDbG9zZSB0aGUgYXJyYXlcbiAgY29uZmlnICs9IGBcbl07YDtcblxuICByZXR1cm4gY29uZmlnO1xufTtcblxuLyoqXG4gKiBDaGVjayBpZiBUeXBlU2NyaXB0IGlzIGJlaW5nIHVzZWQgYnkgbG9va2luZyBmb3IgdHNjb25maWcuanNvblxuICovXG5jb25zdCBkZXRlY3RUeXBlU2NyaXB0ID0gKGN3ZDogc3RyaW5nKTogYm9vbGVhbiA9PiBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJ3RzY29uZmlnLmpzb24nKSk7XG5cbi8qKlxuICogRW5zdXJlIHBhY2thZ2UuanNvbiBoYXMgdHlwZTogbW9kdWxlIGZvciBFU00gc3VwcG9ydFxuICovXG5jb25zdCBlbnN1cmVNb2R1bGVUeXBlID0gKGN3ZDogc3RyaW5nKTogdm9pZCA9PiB7XG4gIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgJ3BhY2thZ2UuanNvbicpO1xuXG4gIGlmKGV4aXN0c1N5bmMocGFja2FnZUpzb25QYXRoKSkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYWNrYWdlSnNvbkNvbnRlbnQgPSByZWFkRmlsZVN5bmMocGFja2FnZUpzb25QYXRoLCAndXRmOCcpO1xuICAgICAgY29uc3QgcGFja2FnZUpzb24gPSBKU09OLnBhcnNlKHBhY2thZ2VKc29uQ29udGVudCk7XG5cbiAgICAgIC8vIElmIHR5cGUgaXMgbm90IHNldCB0byBtb2R1bGUsIHNldCBpdFxuICAgICAgaWYocGFja2FnZUpzb24udHlwZSAhPT0gJ21vZHVsZScpIHtcbiAgICAgICAgcGFja2FnZUpzb24udHlwZSA9ICdtb2R1bGUnO1xuICAgICAgICB3cml0ZUZpbGVTeW5jKHBhY2thZ2VKc29uUGF0aCwgSlNPTi5zdHJpbmdpZnkocGFja2FnZUpzb24sIG51bGwsIDIpLCAndXRmOCcpO1xuICAgICAgfVxuICAgIH0gY2F0Y2goX2Vycm9yKSB7XG4gICAgICAvLyBJZ25vcmUgZXJyb3JzXG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIE5vIG5lZWQgdG8gaW5zdGFsbCBkZXBlbmRlbmNpZXMgYXMgd2UnbGwgdXNlIHRoZSBvbmVzIGZyb20gbGV4XG4gKi9cbmNvbnN0IGluc3RhbGxEZXBlbmRlbmNpZXMgPSBhc3luYyAoX2N3ZDogc3RyaW5nLCB1c2VUeXBlc2NyaXB0OiBib29sZWFuLCBxdWlldDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZih1c2VUeXBlc2NyaXB0KSB7XG4gICAgbG9nKCdVc2luZyBUeXBlU2NyaXB0IEVTTGludCBkZXBlbmRlbmNpZXMgZnJvbSBsZXguLi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgfVxufTtcblxuLy8gRnVuY3Rpb24gcmVtb3ZlZCBhcyBpdCdzIG5vIGxvbmdlciBuZWVkZWRcblxuLyoqXG4gKiBSdW4gRVNMaW50IGRpcmVjdGx5IGZyb20gbGV4J3Mgbm9kZV9tb2R1bGVzXG4gKi9cbmNvbnN0IHJ1bkVzbGludFdpdGhMZXggPSBhc3luYyAoXG4gIGN3ZDogc3RyaW5nLFxuICBxdWlldDogYm9vbGVhbixcbiAgY2xpTmFtZTogc3RyaW5nLFxuICBmaXg6IGJvb2xlYW4sXG4gIGRlYnVnOiBib29sZWFuLFxuICB1c2VUeXBlc2NyaXB0OiBib29sZWFuLFxuICBjYXB0dXJlT3V0cHV0PzogKG91dHB1dDogc3RyaW5nKSA9PiB2b2lkXG4pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgdHJ5IHtcbiAgICAvLyBEZXRlcm1pbmUgd2hpY2ggRVNMaW50IGNvbmZpZyB0byB1c2VcbiAgICAvLyBGaXJzdCBjaGVjayBpZiB0aGUgcHJvamVjdCBoYXMgaXRzIG93biBlc2xpbnQuY29uZmlnLmpzXG4gICAgY29uc3QgcHJvamVjdENvbmZpZ1BhdGggPSBwYXRoUmVzb2x2ZShjd2QsICdlc2xpbnQuY29uZmlnLmpzJyk7XG4gICAgY29uc3QgaGFzUHJvamVjdENvbmZpZyA9IGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGgpO1xuXG4gICAgLy8gSWYgbm90LCB0cnkgdG8gZmluZCBMZXgncyBkZWZhdWx0IGNvbmZpZ1xuICAgIC8vIFRyeSBkaWZmZXJlbnQgcG90ZW50aWFsIGxvY2F0aW9ucyBmb3IgdGhlIExleCBjb25maWdcbiAgICBjb25zdCBwb3NzaWJsZVBhdGhzID0gW1xuICAgICAgLy8gRnJvbSBzcmMvY29tbWFuZHMvbGludC9saW50LnRzIHRvIHJvb3RcbiAgICAgIHBhdGhSZXNvbHZlKF9fZGlybmFtZSwgJy4uLy4uLy4uLy4uL2VzbGludC5jb25maWcuanMnKSxcbiAgICAgIC8vIEZyb20gcGFja2FnZXMvbGV4L3NyYy9jb21tYW5kcy9saW50L2xpbnQudHMgdG8gcGFja2FnZXMvbGV4XG4gICAgICBwYXRoUmVzb2x2ZShfX2Rpcm5hbWUsICcuLi8uLi8uLi9lc2xpbnQuY29uZmlnLmpzJyksXG4gICAgICAvLyBGcm9tIHBhY2thZ2VzL2xleC9zcmMvY29tbWFuZHMvbGludC9saW50LnRzIHRvIHJvb3RcbiAgICAgIHBhdGhSZXNvbHZlKF9fZGlybmFtZSwgJy4uLy4uLy4uLy4uLy4uL2VzbGludC5jb25maWcuanMnKSxcbiAgICAgIC8vIEFic29sdXRlIHBhdGggaWYgTGV4IGlzIGluc3RhbGxlZCBnbG9iYWxseVxuICAgICAgcGF0aFJlc29sdmUocHJvY2Vzcy5lbnYuTEVYX0hPTUUgfHwgJy91c3IvbG9jYWwvbGliL25vZGVfbW9kdWxlcy9AbmxhYnMvbGV4JywgJ2VzbGludC5jb25maWcuanMnKVxuICAgIF07XG5cbiAgICBsZXQgbGV4Q29uZmlnUGF0aCA9ICcnO1xuICAgIGZvcihjb25zdCBwYXRoIG9mIHBvc3NpYmxlUGF0aHMpIHtcbiAgICAgIGlmKGV4aXN0c1N5bmMocGF0aCkpIHtcbiAgICAgICAgbGV4Q29uZmlnUGF0aCA9IHBhdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIERldGVybWluZSB3aGljaCBjb25maWcgZmlsZSB0byB1c2VcbiAgICBjb25zdCBjb25maWdQYXRoID0gaGFzUHJvamVjdENvbmZpZyA/IHByb2plY3RDb25maWdQYXRoIDogKGxleENvbmZpZ1BhdGggfHwgcHJvamVjdENvbmZpZ1BhdGgpO1xuXG4gICAgLy8gVXNlIG5weCB0byBydW4gZXNsaW50IC0gdGhpcyB3aWxsIHVzZSB0aGUgb25lIGZyb20gbGV4IGlmIGF2YWlsYWJsZVxuICAgIC8vIG9yIGRvd25sb2FkIGEgdGVtcG9yYXJ5IG9uZSBpZiBuZWVkZWRcblxuICAgIC8vIFJ1biBlc2xpbnQgb24gSlMgZmlsZXMgd2l0aCBjb25maWcgdXNpbmcgbnB4IHdpdGggcGFja2FnZSBzcGVjaWZpY2F0aW9uXG4gICAgY29uc3QganNSZXN1bHQgPSBhd2FpdCBleGVjYSgnbnB4JywgW1xuICAgICAgJy1wJywgJ2VzbGludCcsXG4gICAgICAnZXNsaW50JyxcbiAgICAgICdzcmMvKiovKi57anMsanN4fScsXG4gICAgICAnLS1jb25maWcnLCBjb25maWdQYXRoLCAvLyBVc2UgdGhlIGRldGVybWluZWQgY29uZmlnXG4gICAgICAuLi4oZml4ID8gWyctLWZpeCddIDogW10pLFxuICAgICAgLi4uKGRlYnVnID8gWyctLWRlYnVnJ10gOiBbXSksXG4gICAgICAnLS1uby1lcnJvci1vbi11bm1hdGNoZWQtcGF0dGVybicgLy8gRG9uJ3QgZXJyb3IgaWYgbm8gZmlsZXMgYXJlIGZvdW5kXG4gICAgXSwge1xuICAgICAgcmVqZWN0OiBmYWxzZSxcbiAgICAgIHN0ZGlvOiAncGlwZScsXG4gICAgICBjd2QsXG4gICAgICBzaGVsbDogdHJ1ZSAvLyBOZWVkZWQgZm9yIGdsb2IgcGF0dGVybiBleHBhbnNpb25cbiAgICB9KTtcblxuICAgIC8vIERpc3BsYXkgSlMgb3V0cHV0IGFuZCBjYXB0dXJlIGl0IGlmIG5lZWRlZFxuICAgIGlmKGpzUmVzdWx0LnN0ZG91dCkge1xuICAgICAgY29uc29sZS5sb2coanNSZXN1bHQuc3Rkb3V0KTtcbiAgICAgIGlmKGNhcHR1cmVPdXRwdXQpIHtcbiAgICAgICAgY2FwdHVyZU91dHB1dChqc1Jlc3VsdC5zdGRvdXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGpzUmVzdWx0LnN0ZGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihqc1Jlc3VsdC5zdGRlcnIpO1xuICAgICAgaWYoY2FwdHVyZU91dHB1dCkge1xuICAgICAgICBjYXB0dXJlT3V0cHV0KGpzUmVzdWx0LnN0ZGVycik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUnVuIGVzbGludCBvbiBUUyBmaWxlcyBpZiBuZWVkZWRcbiAgICBsZXQgdHNSZXN1bHQ6IGFueSA9IHtleGl0Q29kZTogMCwgc3Rkb3V0OiAnJywgc3RkZXJyOiAnJ307XG4gICAgaWYodXNlVHlwZXNjcmlwdCkge1xuICAgICAgdHNSZXN1bHQgPSBhd2FpdCBleGVjYSgnbnB4JywgW1xuICAgICAgICAnLXAnLCAnZXNsaW50JyxcbiAgICAgICAgJy1wJywgJ0B0eXBlc2NyaXB0LWVzbGludC9wYXJzZXInLFxuICAgICAgICAnLXAnLCAnQHR5cGVzY3JpcHQtZXNsaW50L2VzbGludC1wbHVnaW4nLFxuICAgICAgICAnZXNsaW50JyxcbiAgICAgICAgJ3NyYy8qKi8qLnt0cyx0c3h9JyxcbiAgICAgICAgJy0tY29uZmlnJywgY29uZmlnUGF0aCwgLy8gVXNlIHRoZSBkZXRlcm1pbmVkIGNvbmZpZ1xuICAgICAgICAuLi4oZml4ID8gWyctLWZpeCddIDogW10pLFxuICAgICAgICAuLi4oZGVidWcgPyBbJy0tZGVidWcnXSA6IFtdKSxcbiAgICAgICAgJy0tbm8tZXJyb3Itb24tdW5tYXRjaGVkLXBhdHRlcm4nIC8vIERvbid0IGVycm9yIGlmIG5vIGZpbGVzIGFyZSBmb3VuZFxuICAgICAgXSwge1xuICAgICAgICByZWplY3Q6IGZhbHNlLFxuICAgICAgICBzdGRpbzogJ3BpcGUnLFxuICAgICAgICBjd2QsXG4gICAgICAgIHNoZWxsOiB0cnVlIC8vIE5lZWRlZCBmb3IgZ2xvYiBwYXR0ZXJuIGV4cGFuc2lvblxuICAgICAgfSk7XG5cbiAgICAgIC8vIERpc3BsYXkgVFMgb3V0cHV0XG4gICAgICBpZih0c1Jlc3VsdC5zdGRvdXQpIHtcbiAgICAgICAgY29uc29sZS5sb2codHNSZXN1bHQuc3Rkb3V0KTtcbiAgICAgIH1cblxuICAgICAgaWYodHNSZXN1bHQuc3RkZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IodHNSZXN1bHQuc3RkZXJyKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTdWNjZXNzIGlmIGJvdGggZXhpdCBjb2RlcyBhcmUgMFxuICAgIGlmKGpzUmVzdWx0LmV4aXRDb2RlID09PSAwICYmIHRzUmVzdWx0LmV4aXRDb2RlID09PSAwKSB7XG4gICAgICBzcGlubmVyLnN1Y2NlZWQoJ0xpbnRpbmcgY29tcGxldGVkIScpO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIC8vIENoZWNrIGZvciBzcGVjaWFsIGNhc2VzIC0gbm8gZmlsZXMgZm91bmRcbiAgICBjb25zdCBub0ZpbGVzRm91bmQgPVxuICAgICAgICAoanNSZXN1bHQuc3RkZXJyPy5pbmNsdWRlcygnTm8gc3VjaCBmaWxlIG9yIGRpcmVjdG9yeScpIHx8IGpzUmVzdWx0LnN0ZG91dD8uaW5jbHVkZXMoJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknKSkgJiZcbiAgICAgICAgKCF1c2VUeXBlc2NyaXB0IHx8IHRzUmVzdWx0LnN0ZGVycj8uaW5jbHVkZXMoJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknKSB8fCB0c1Jlc3VsdC5zdGRvdXQ/LmluY2x1ZGVzKCdObyBzdWNoIGZpbGUgb3IgZGlyZWN0b3J5JykpO1xuXG4gICAgaWYobm9GaWxlc0ZvdW5kKSB7XG4gICAgICBzcGlubmVyLnN1Y2NlZWQoJ05vIGZpbGVzIGZvdW5kIHRvIGxpbnQnKTtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBzcGlubmVyLmZhaWwoJ0xpbnRpbmcgZmFpbGVkIScpO1xuICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogRVNMaW50IGZvdW5kIGlzc3VlcyBpbiB5b3VyIGNvZGUuYCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIHJldHVybiAxO1xuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdMaW50aW5nIGZhaWxlZCEnKTtcbiAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgcmV0dXJuIDE7XG4gIH1cbn07XG5cbi8qKlxuICogVXNlIEFJIHRvIGZpeCBsaW50aW5nIGVycm9ycyB0aGF0IGNvdWxkbid0IGJlIGZpeGVkIGF1dG9tYXRpY2FsbHlcbiAqL1xuY29uc3QgYXBwbHlBSUZpeCA9IGFzeW5jIChcbiAgY3dkOiBzdHJpbmcsXG4gIGVycm9yczogc3RyaW5nLFxuICBxdWlldDogYm9vbGVhblxuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGNvbnN0IHNwaW5uZXIgPSBjcmVhdGVTcGlubmVyKHF1aWV0KTtcbiAgc3Bpbm5lci5zdGFydCgnVXNpbmcgQUkgdG8gZml4IHJlbWFpbmluZyBsaW50IGlzc3Vlcy4uLicpO1xuXG4gIHRyeSB7XG4gICAgLy8gRXh0cmFjdCBmaWxlIHBhdGhzIGFuZCBlcnJvcnMgZnJvbSB0aGUgRVNMaW50IG91dHB1dFxuICAgIGNvbnN0IGZpbGVFcnJvck1hcCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgICBjb25zdCBsaW5lcyA9IGVycm9ycy5zcGxpdCgnXFxuJyk7XG4gICAgbGV0IGN1cnJlbnRGaWxlID0gJyc7XG5cbiAgICAvLyBJbXByb3ZlZCBwYXJzaW5nIG9mIEVTTGludCBvdXRwdXRcbiAgICBmb3IoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgICAgLy8gTWF0Y2ggZmlsZSBwYXRocyAodGhleSB0eXBpY2FsbHkgc3RhcnQgd2l0aCAvIG9yIEM6XFwgb24gV2luZG93cylcbiAgICAgIGlmKGxpbmUubWF0Y2goL14oXFwvfFtBLVpdOlxcXFwpLio/XFwuKGpzfGpzeHx0c3x0c3gpJC8pKSB7XG4gICAgICAgIGN1cnJlbnRGaWxlID0gbGluZS50cmltKCk7XG4gICAgICAgIGlmKCFmaWxlRXJyb3JNYXAuaGFzKGN1cnJlbnRGaWxlKSkge1xuICAgICAgICAgIGZpbGVFcnJvck1hcC5zZXQoY3VycmVudEZpbGUsIFtdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gTWF0Y2ggZXJyb3IgbGluZXMgKHRoZXkgdHlwaWNhbGx5IGhhdmUgbGluZTpjb2x1bW4gZm9ybWF0KVxuICAgICAgZWxzZSBpZihjdXJyZW50RmlsZSAmJiBsaW5lLnRyaW0oKSAmJiBsaW5lLm1hdGNoKC9cXHMrXFxkKzpcXGQrXFxzKyhlcnJvcnx3YXJuaW5nKVxccysvKSkge1xuICAgICAgICBjb25zdCBlcnJvckFycmF5ID0gZmlsZUVycm9yTWFwLmdldChjdXJyZW50RmlsZSk7XG4gICAgICAgIGlmKGVycm9yQXJyYXkpIHtcbiAgICAgICAgICBlcnJvckFycmF5LnB1c2gobGluZS50cmltKCkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSWYgbm8gZXJyb3JzIHdlcmUgZm91bmQgdXNpbmcgdGhlIHJlZ2V4IGFwcHJvYWNoLCB0cnkgYSBkaWZmZXJlbnQgcGFyc2luZyBzdHJhdGVneVxuICAgIGlmKGZpbGVFcnJvck1hcC5zaXplID09PSAwKSB7XG4gICAgICBsb2coJ1VzaW5nIGFsdGVybmF0aXZlIGVycm9yIHBhcnNpbmcgc3RyYXRlZ3knLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgLy8gUmVzZXQgYW5kIHRyeSBhIGRpZmZlcmVudCBwYXJzaW5nIGFwcHJvYWNoXG4gICAgICBjb25zdCBzZWN0aW9ucyA9IGVycm9ycy5zcGxpdCgnXFxuXFxuJyk7XG5cbiAgICAgIGZvcihjb25zdCBzZWN0aW9uIG9mIHNlY3Rpb25zKSB7XG4gICAgICAgIGlmKHNlY3Rpb24udHJpbSgpID09PSAnJykge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGluZXMgPSBzZWN0aW9uLnNwbGl0KCdcXG4nKTtcbiAgICAgICAgY29uc3QgZmlsZVBhdGggPSBsaW5lc1swXS50cmltKCk7XG5cbiAgICAgICAgLy8gT25seSBwcm9jZXNzIGlmIGl0IGxvb2tzIGxpa2UgYSBmaWxlIHBhdGhcbiAgICAgICAgaWYoZmlsZVBhdGgubWF0Y2goL1xcLihqc3xqc3h8dHN8dHN4KSQvKSkge1xuICAgICAgICAgIGZpbGVFcnJvck1hcC5zZXQoZmlsZVBhdGgsIFtdKTtcblxuICAgICAgICAgIGZvcihsZXQgaSA9IDE7IGkgPCBsaW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYobGluZXNbaV0udHJpbSgpICE9PSAnJykge1xuICAgICAgICAgICAgICBmaWxlRXJyb3JNYXAuZ2V0KGZpbGVQYXRoKT8ucHVzaChsaW5lc1tpXS50cmltKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIElmIHN0aWxsIG5vIGZpbGVzIGZvdW5kLCB0cnkgdG8gZXh0cmFjdCBmaWxlIHBhdGhzIGRpcmVjdGx5XG4gICAgaWYoZmlsZUVycm9yTWFwLnNpemUgPT09IDApIHtcbiAgICAgIGxvZygnVXNpbmcgZGlyZWN0IGZpbGUgcGF0aCBleHRyYWN0aW9uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICBcbiAgICAgIC8vIEZpbmQgYWxsIGZpbGUgcGF0aHMgaW4gdGhlIGVycm9yIG91dHB1dFxuICAgICAgY29uc3QgZmlsZVBhdGhSZWdleCA9IC8oPzpcXC98W0EtWl06XFxcXCkoPzpbXjpcXG5dK1xcLykqW146XFxuXStcXC4oanN8anN4fHRzfHRzeCkvZztcbiAgICAgIGNvbnN0IGZpbGVQYXRocyA9IGVycm9ycy5tYXRjaChmaWxlUGF0aFJlZ2V4KSB8fCBbXTtcbiAgICAgIFxuICAgICAgZm9yKGNvbnN0IGZpbGVQYXRoIG9mIGZpbGVQYXRocykge1xuICAgICAgICBpZighZmlsZUVycm9yTWFwLmhhcyhmaWxlUGF0aCkgJiYgZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICBmaWxlRXJyb3JNYXAuc2V0KGZpbGVQYXRoLCBbXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gQWRkIGtub3duIHByb2JsZW1hdGljIGZpbGVzIGlmIHRoZXkgZXhpc3RcbiAgICAgIGNvbnN0IGtub3duRmlsZXMgPSBbXG4gICAgICAgICcvVXNlcnMvbml0cm9nNy9EZXZlbG9wbWVudC9sZXgvcGFja2FnZXMvbGV4L3NyYy9jcmVhdGUvY2hhbmdlbG9nLnRzJyxcbiAgICAgICAgJy9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L2xleC9wYWNrYWdlcy9sZXgvc3JjL3V0aWxzL2FpU2VydmljZS50cycsXG4gICAgICAgICcvVXNlcnMvbml0cm9nNy9EZXZlbG9wbWVudC9sZXgvcGFja2FnZXMvbGV4L3NyYy91dGlscy9hcHAudHMnLFxuICAgICAgICAnL1VzZXJzL25pdHJvZzcvRGV2ZWxvcG1lbnQvbGV4L3BhY2thZ2VzL2xleC9zcmMvdXRpbHMvcmVhY3RTaGltLnRzJyxcbiAgICAgICAgJy9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L2xleC9wYWNrYWdlcy9sZXgvc3JjL2NvbW1hbmRzL2xpbnQvYXV0b2ZpeC5qcydcbiAgICAgIF07XG4gICAgICBcbiAgICAgIGZvcihjb25zdCBmaWxlIG9mIGtub3duRmlsZXMpIHtcbiAgICAgICAgaWYoZXhpc3RzU3luYyhmaWxlKSAmJiAhZmlsZUVycm9yTWFwLmhhcyhmaWxlKSkge1xuICAgICAgICAgIGZpbGVFcnJvck1hcC5zZXQoZmlsZSwgW10pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUHJvY2VzcyBlYWNoIGZpbGUgd2l0aCBlcnJvcnNcbiAgICBmb3IoY29uc3QgZmlsZVBhdGggb2YgZmlsZUVycm9yTWFwLmtleXMoKSkge1xuICAgICAgaWYoIWV4aXN0c1N5bmMoZmlsZVBhdGgpKSB7XG4gICAgICAgIGxvZyhgRmlsZSBub3QgZm91bmQ6ICR7ZmlsZVBhdGh9YCwgJ3dhcm4nLCBxdWlldCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBsb2coYFByb2Nlc3NpbmcgZmlsZTogJHtmaWxlUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIFxuICAgICAgLy8gQ2hlY2sgaWYgd2UncmUgcnVubmluZyBpbiBDdXJzb3IgSURFXG4gICAgICBjb25zdCBpc0N1cnNvcklERSA9IExleENvbmZpZy5jb25maWcuYWk/LnByb3ZpZGVyID09PSAnY3Vyc29yJyB8fCBwcm9jZXNzLmVudi5DVVJTT1JfSURFID09PSAndHJ1ZSc7XG4gICAgICBcbiAgICAgIGlmKGlzQ3Vyc29ySURFKSB7XG4gICAgICAgIC8vIElmIHdlJ3JlIGluIEN1cnNvciBJREUsIHVzZSBpdHMgYnVpbHQtaW4gQUkgY2FwYWJpbGl0aWVzXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgLy8gQ3JlYXRlIGEgcHJvbXB0IGZvciBDdXJzb3IgQUlcbiAgICAgICAgICBjb25zdCBwcm9tcHQgPSBgRml4IGFsbCBFU0xpbnQgZXJyb3JzIGluIHRoaXMgZmlsZS4gRm9jdXMgb246XG4xLiBGaXhpbmcgbmFtaW5nIGNvbnZlbnRpb25zXG4yLiBGaXhpbmcgc29ydC1rZXlzIGlzc3Vlc1xuMy4gUmVwbGFjaW5nIGNvbnNvbGUubG9nIHdpdGggbG9nIHV0aWxpdHlcbjQuIEZpeGluZyBuby1wbHVzcGx1cyBpc3N1ZXNcbjUuIEZpeGluZyB1bm5lY2Vzc2FyeSBlc2NhcGUgY2hhcmFjdGVyc1xuNi4gRml4aW5nIG90aGVyIEVTTGludCBlcnJvcnNgO1xuXG4gICAgICAgICAgLy8gVHJ5IHRvIHVzZSBDdXJzb3IgQ0xJIGlmIGF2YWlsYWJsZVxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBDcmVhdGUgYSB0ZW1wb3JhcnkgcHJvbXB0IGZpbGVcbiAgICAgICAgICAgIGNvbnN0IHByb21wdEZpbGUgPSBwYXRoUmVzb2x2ZShjd2QsICcuY3Vyc29yX3Byb21wdF90ZW1wLnR4dCcpO1xuICAgICAgICAgICAgd3JpdGVGaWxlU3luYyhwcm9tcHRGaWxlLCBwcm9tcHQsICd1dGY4Jyk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIFVzZSBDdXJzb3IgQ0xJIHRvIGZpeCB0aGUgZmlsZVxuICAgICAgICAgICAgYXdhaXQgZXhlY2EoJ2N1cnNvcicsIFsnZWRpdCcsICctLWZpbGUnLCBmaWxlUGF0aCwgJy0tcHJvbXB0LWZpbGUnLCBwcm9tcHRGaWxlXSwge1xuICAgICAgICAgICAgICByZWplY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICBzdGRpbzogJ3BpcGUnLFxuICAgICAgICAgICAgICBjd2RcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBDbGVhbiB1cFxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgdW5saW5rU3luYyhwcm9tcHRGaWxlKTtcbiAgICAgICAgICAgIH0gY2F0Y2goX2Vycm9yKSB7XG4gICAgICAgICAgICAgIC8vIElnbm9yZSBjbGVhbnVwIGVycm9yc1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICBsb2coYEFwcGxpZWQgQ3Vyc29yIEFJIGZpeGVzIHRvICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgICAgLy8gSWYgQ3Vyc29yIENMSSBmYWlscywgZmFsbCBiYWNrIHRvIGRpcmVjdCBmaXhlc1xuICAgICAgICAgICAgY29uc3Qgd2FzTW9kaWZpZWQgPSBhd2FpdCBhcHBseURpcmVjdEZpeGVzKGZpbGVQYXRoLCBxdWlldCk7XG4gICAgICAgICAgICBpZih3YXNNb2RpZmllZCkge1xuICAgICAgICAgICAgICBsb2coYEFwcGxpZWQgZGlyZWN0IGZpeGVzIHRvICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoKGVycm9yKSB7XG4gICAgICAgICAgbG9nKGBFcnJvciB1c2luZyBDdXJzb3IgQUk6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICAgICAgLy8gRmFsbCBiYWNrIHRvIGRpcmVjdCBmaXhlc1xuICAgICAgICAgIGF3YWl0IGFwcGx5RGlyZWN0Rml4ZXMoZmlsZVBhdGgsIHF1aWV0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRm9yIG5vbi1DdXJzb3IgZW52aXJvbm1lbnRzLCBhcHBseSBkaXJlY3QgZml4ZXMgYW5kIHRoZW4gdXNlIEFJIHNlcnZpY2VcbiAgICAgICAgY29uc3Qgd2FzTW9kaWZpZWQgPSBhd2FpdCBhcHBseURpcmVjdEZpeGVzKGZpbGVQYXRoLCBxdWlldCk7XG4gICAgICAgIGlmKHdhc01vZGlmaWVkKSB7XG4gICAgICAgICAgbG9nKGBBcHBsaWVkIGRpcmVjdCBmaXhlcyB0byAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBGb3IgcmVtYWluaW5nIGlzc3VlcywgdXNlIHRoZSBBSSBzZXJ2aWNlXG4gICAgICAgIGNvbnN0IGZpbGVFcnJvcnMgPSBmaWxlRXJyb3JNYXAuZ2V0KGZpbGVQYXRoKSB8fCBbXTtcbiAgICAgICAgaWYoZmlsZUVycm9ycy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIEltcG9ydCB0aGUgQUkgc2VydmljZSBkeW5hbWljYWxseSB0byBhdm9pZCBjaXJjdWxhciBkZXBlbmRlbmNpZXNcbiAgICAgICAgICAgIGNvbnN0IHtjYWxsQUlTZXJ2aWNlfSA9IGF3YWl0IGltcG9ydCgnLi4vLi4vdXRpbHMvYWlTZXJ2aWNlLmpzJyk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIFJlYWQgdGhlIGZpbGUgY29udGVudCBhZ2FpbiBpbiBjYXNlIGl0IHdhcyBtb2RpZmllZCBieSBhdXRvbWF0ZWQgZml4ZXNcbiAgICAgICAgICAgIGNvbnN0IGZpbGVDb250ZW50ID0gcmVhZEZpbGVTeW5jKGZpbGVQYXRoLCAndXRmOCcpO1xuICAgICAgICAgICAgXG4gICAgICAgICAgICAvLyBQcmVwYXJlIGEgcHJvbXB0IGZvciBBSVxuICAgICAgICAgICAgY29uc3QgcHJvbXB0ID0gYEZpeCB0aGUgZm9sbG93aW5nIEVTTGludCBlcnJvcnMgaW4gdGhpcyBjb2RlOlxuJHtmaWxlRXJyb3JzLmpvaW4oJ1xcbicpfVxuXG5IZXJlJ3MgdGhlIGNvZGU6XG5cXGBcXGBcXGBcbiR7ZmlsZUNvbnRlbnR9XG5cXGBcXGBcXGBcblxuUmV0dXJuIG9ubHkgdGhlIGZpeGVkIGNvZGUgd2l0aG91dCBhbnkgZXhwbGFuYXRpb25zLmA7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIC8vIENhbGwgdGhlIEFJIHNlcnZpY2UgdG8gZ2V0IGZpeGVkIGNvZGVcbiAgICAgICAgICAgIGNvbnN0IGZpeGVkQ29udGVudCA9IGF3YWl0IGNhbGxBSVNlcnZpY2UocHJvbXB0LCBxdWlldCk7XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIGlmKGZpeGVkQ29udGVudCAmJiBmaXhlZENvbnRlbnQgIT09IGZpbGVDb250ZW50KSB7XG4gICAgICAgICAgICAgIHdyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIGZpeGVkQ29udGVudCwgJ3V0ZjgnKTtcbiAgICAgICAgICAgICAgbG9nKGBBcHBsaWVkIEFJIGZpeGVzIHRvICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgICAgbG9nKGBFcnJvciBhcHBseWluZyBBSSBmaXhlcyB0byAke2ZpbGVQYXRofTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBzcGlubmVyLnN1Y2NlZWQoJ0FJIGZpeGVzIGFwcGxpZWQgc3VjY2Vzc2Z1bGx5IScpO1xuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gYXBwbHkgQUkgZml4ZXMnKTtcbiAgICBsb2coYEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIGlmKCFxdWlldCkge1xuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgfVxuICB9XG59O1xuXG4vKipcbiAqIEFwcGx5IGRpcmVjdCBmaXhlcyB0byBjb21tb24gRVNMaW50IGlzc3Vlc1xuICovXG5jb25zdCBhcHBseURpcmVjdEZpeGVzID0gYXN5bmMgKGZpbGVQYXRoOiBzdHJpbmcsIHF1aWV0OiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gIGxldCB3YXNNb2RpZmllZCA9IGZhbHNlO1xuICBcbiAgdHJ5IHtcbiAgICAvLyBSZWFkIGZpbGUgY29udGVudFxuICAgIGNvbnN0IGZpbGVDb250ZW50ID0gcmVhZEZpbGVTeW5jKGZpbGVQYXRoLCAndXRmOCcpO1xuICAgIGxldCBuZXdDb250ZW50ID0gZmlsZUNvbnRlbnQ7XG4gICAgXG4gICAgLy8gRml4IGlzc3VlcyBiYXNlZCBvbiBmaWxlbmFtZVxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdhaVNlcnZpY2UudHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGFpU2VydmljZS50cycsICdpbmZvJywgcXVpZXQpO1xuICAgICAgXG4gICAgICAvLyBGaXggdGhlIG9yZGVyIG9mIGtleXMgaW4gaGVhZGVycyBvYmplY3RzXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvblxcL2pzb24nLFxccyonQXV0aG9yaXphdGlvbic6IGBCZWFyZXIvZyxcbiAgICAgICAgJ1xcJ0F1dGhvcml6YXRpb25cXCc6IGBCZWFyZXJcXCcsIFxcJ0NvbnRlbnQtVHlwZVxcJzogXFwnYXBwbGljYXRpb24vanNvblxcJydcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCBtZXRob2QgYW5kIGhlYWRlcnMgb3JkZXJcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9oZWFkZXJzOiB7KFtefV0qKX0sXFxzKm1ldGhvZDogJ1BPU1QnL2csXG4gICAgICAgICdtZXRob2Q6IFxcJ1BPU1RcXCcsXFxuICAgICAgaGVhZGVyczogeyQxfSdcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCByb2xlIGFuZCBjb250ZW50IG9yZGVyXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAve3JvbGU6ICdzeXN0ZW0nLCBjb250ZW50Oi9nLFxuICAgICAgICAne2NvbnRlbnQ6LCByb2xlOiBcXCdzeXN0ZW1cXCcsJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC97cm9sZTogJ3VzZXInLCBjb250ZW50Oi9nLFxuICAgICAgICAne2NvbnRlbnQ6LCByb2xlOiBcXCd1c2VyXFwnLCdcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCBuYW1pbmcgY29udmVudGlvbiBpc3N1ZXMgLSBwYXJhbWV0ZXIgbmFtZXMgd2l0aCBsZWFkaW5nIHVuZGVyc2NvcmVzXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvXFwoKFteKV0qPylfKFthLXpBLVowLTldKykoXFxzKjpbXildKilcXCkvZyxcbiAgICAgICAgJygkMSQyJDMpJ1xuICAgICAgKTtcbiAgICAgIFxuICAgICAgLy8gUmVwbGFjZSBjb25zb2xlLmxvZyBzdGF0ZW1lbnRzXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKC9jb25zb2xlXFwubG9nXFwoL2csICdsb2coJyk7XG4gICAgICBcbiAgICAgIC8vIEFkZCBsb2cgaW1wb3J0IGlmIG5lZWRlZFxuICAgICAgaWYoIW5ld0NvbnRlbnQuaW5jbHVkZXMoJ2ltcG9ydCB7bG9nfScpICYmIG5ld0NvbnRlbnQuaW5jbHVkZXMoJ2xvZygnKSkge1xuICAgICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAgIC9pbXBvcnQgeyhbXn1dKil9IGZyb20gJyguKiknOy8sXG4gICAgICAgICAgJ2ltcG9ydCB7JDF9IGZyb20gXFwnJDJcXCc7XFxuaW1wb3J0IHtsb2d9IGZyb20gXFwnLi9sb2cuanNcXCc7J1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICAvLyBGaXggcmVhY3RTaGltLnRzIG5hbWluZyBjb252ZW50aW9uc1xuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdyZWFjdFNoaW0udHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgbmFtaW5nLWNvbnZlbnRpb24gaXNzdWVzIGluIHJlYWN0U2hpbS50cycsICdpbmZvJywgcXVpZXQpO1xuICAgICAgXG4gICAgICAvLyBGaXggUmVhY3QgaW1wb3J0IG5hbWluZ1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgJ2ltcG9ydCAqIGFzIFJlYWN0IGZyb20nLFxuICAgICAgICAnaW1wb3J0ICogYXMgcmVhY3QgZnJvbSdcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCBSZWFjdCB1c2FnZVxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvUmVhY3RcXC4vZywgJ3JlYWN0LicpO1xuICAgIH1cbiAgICBcbiAgICAvLyBGaXggY2hhbmdlbG9nLnRzIGlzc3Vlc1xuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdjaGFuZ2Vsb2cudHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGNoYW5nZWxvZy50cycsICdpbmZvJywgcXVpZXQpO1xuICAgICAgXG4gICAgICAvLyBGaXggbm8tcGx1c3BsdXNcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoLyhcXHcrKVxcK1xcKy9nLCAnJDEgKz0gMScpO1xuICAgICAgXG4gICAgICAvLyBGaXggdW5uZWNlc3NhcnkgZXNjYXBlIGNoYXJhY3RlcnNcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoL1xcXFxcXCQvZywgJyQnKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoL1xcXFxcXC4vZywgJy4nKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoL1xcXFxcXCovZywgJyonKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoL1xcXFw6L2csICc6Jyk7XG4gICAgfVxuICAgIFxuICAgIC8vIEZpeCBhcHAudHMgaXNzdWVzXG4gICAgaWYoZmlsZVBhdGguaW5jbHVkZXMoJ2FwcC50cycpKSB7XG4gICAgICBsb2coJ0ZpeGluZyBpc3N1ZXMgaW4gYXBwLnRzJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICBcbiAgICAgIC8vIEZpeCBjb25zb2xlLmxvZ1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvY29uc29sZVxcLmxvZ1xcKC9nLCAnbG9nKCcpO1xuICAgICAgXG4gICAgICAvLyBBZGQgbG9nIGltcG9ydCBpZiBuZWVkZWRcbiAgICAgIGlmKCFuZXdDb250ZW50LmluY2x1ZGVzKCdpbXBvcnQge2xvZ30nKSAmJiBuZXdDb250ZW50LmluY2x1ZGVzKCdsb2coJykpIHtcbiAgICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgICAvaW1wb3J0IGJveGVuIGZyb20gJ2JveGVuJzsvLFxuICAgICAgICAgICdpbXBvcnQgYm94ZW4gZnJvbSBcXCdib3hlblxcJztcXG5pbXBvcnQge2xvZ30gZnJvbSBcXCcuL2xvZy5qc1xcJzsnXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEZpeCB1bm5lY2Vzc2FyeSBlc2NhcGUgY2hhcmFjdGVyc1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcLy9nLCAnLycpO1xuICAgIH1cbiAgICBcbiAgICAvLyBGaXggYXV0b2ZpeC5qcyBpc3N1ZXNcbiAgICBpZihmaWxlUGF0aC5pbmNsdWRlcygnYXV0b2ZpeC5qcycpKSB7XG4gICAgICBsb2coJ0ZpeGluZyBpc3N1ZXMgaW4gYXV0b2ZpeC5qcycsICdpbmZvJywgcXVpZXQpO1xuICAgICAgXG4gICAgICAvLyBGaXggaW1wb3J0IHN0eWxlXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvaW1wb3J0IHsoW159XSopfSBmcm9tICdwYXRoJztbXFxzXFxuXSppbXBvcnQgeyhbXn1dKil9IGZyb20gJ3BhdGgnOy8sXG4gICAgICAgICdpbXBvcnQgeyQxLCAkMn0gZnJvbSBcXCdwYXRoXFwnOydcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCB2YXJpYWJsZSBuYW1pbmcgY29udmVudGlvblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL19fZmlsZW5hbWUvZyxcbiAgICAgICAgJ2N1cnJlbnRGaWxlbmFtZSdcbiAgICAgICk7XG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvX19kaXJuYW1lL2csXG4gICAgICAgICdjdXJyZW50RGlybmFtZSdcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCBuZXN0ZWQgdGVybmFyeVxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2NvbnN0IHByZWZpeCA9IHR5cGUgPT09ICdlcnJvcicgXFw/ICdcdTI3NEMgJyA6IHR5cGUgPT09ICdzdWNjZXNzJyBcXD8gJ1x1MjcwNSAnIDogJ1x1MjEzOVx1RkUwRiAnOy8sXG4gICAgICAgIGBsZXQgcHJlZml4ID0gJ1x1MjEzOVx1RkUwRiAnO1xcbmlmKHR5cGUgPT09ICdlcnJvcicpIHtcXG4gIHByZWZpeCA9ICdcdTI3NEMgJztcXG59IGVsc2UgaWYodHlwZSA9PT0gJ3N1Y2Nlc3MnKSB7XFxuICBwcmVmaXggPSAnXHUyNzA1ICc7XFxufWBcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCBmdW5jdGlvbiBzdHlsZVxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIHJ1bkVzbGludEZpeFxcKFxcKS9nLFxuICAgICAgICAnY29uc3QgcnVuRXNsaW50Rml4ID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIGdldEZpbGVzV2l0aEVycm9yc1xcKFxcKS9nLFxuICAgICAgICAnY29uc3QgZ2V0RmlsZXNXaXRoRXJyb3JzID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIGlzQ3Vyc29yQXZhaWxhYmxlXFwoXFwpL2csXG4gICAgICAgICdjb25zdCBpc0N1cnNvckF2YWlsYWJsZSA9IGFzeW5jICgpJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9hc3luYyBmdW5jdGlvbiBmaXhGaWxlV2l0aEN1cnNvckFJXFwoZmlsZVBhdGhcXCkvZyxcbiAgICAgICAgJ2NvbnN0IGZpeEZpbGVXaXRoQ3Vyc29yQUkgPSBhc3luYyAoZmlsZVBhdGgpJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9hc3luYyBmdW5jdGlvbiBtYWluXFwoXFwpL2csXG4gICAgICAgICdjb25zdCBtYWluID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgXG4gICAgICAvLyBGaXggdW51c2VkIHZhcmlhYmxlc1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2ltcG9ydCB7ZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jLCB3cml0ZUZpbGVTeW5jfS9nLFxuICAgICAgICAnaW1wb3J0IHt3cml0ZUZpbGVTeW5jfSdcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCBjb25zb2xlLmxvZ1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2NvbnNvbGVcXC5sb2dcXChgXFwke3ByZWZpeH0gXFwke21lc3NhZ2V9YFxcKTsvZyxcbiAgICAgICAgJ3Byb2Nlc3Muc3Rkb3V0LndyaXRlKGAke3ByZWZpeH0gJHttZXNzYWdlfVxcXFxuYCk7J1xuICAgICAgKTtcbiAgICAgIFxuICAgICAgLy8gRml4IHVudXNlZCBlcnJvciB2YXJpYWJsZXNcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC99IGNhdGNoXFwoZXJyb3JcXCkge1tcXHNcXG5dKlxcL1xcLyBJZ25vcmUgY2xlYW51cCBlcnJvcnMvZyxcbiAgICAgICAgJ30gY2F0Y2goXykge1xcbiAgICAgIC8vIElnbm9yZSBjbGVhbnVwIGVycm9ycydcbiAgICAgICk7XG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvfSBjYXRjaFxcKGVycm9yXFwpIHtbXFxzXFxuXSpsb2dcXCgvZyxcbiAgICAgICAgJ30gY2F0Y2goZXJyKSB7XFxuICAgIGxvZygnXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL30gY2F0Y2hcXChlcnJvclxcKSB7W1xcc1xcbl0qcmV0dXJuIGZhbHNlOy9nLFxuICAgICAgICAnfSBjYXRjaChfKSB7XFxuICAgIHJldHVybiBmYWxzZTsnXG4gICAgICApO1xuICAgICAgXG4gICAgICAvLyBGaXggYXdhaXQgaW4gbG9vcFxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2ZvclxcKGNvbnN0IGZpbGVQYXRoIG9mIGZpbGVzV2l0aEVycm9yc1xcKSB7W1xcc1xcbl0qY29uc3Qgc3VjY2VzcyA9IGF3YWl0IGZpeEZpbGVXaXRoQ3Vyc29yQUlcXChmaWxlUGF0aFxcKTsvZyxcbiAgICAgICAgJ2NvbnN0IGZpeFJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChmaWxlc1dpdGhFcnJvcnMubWFwKGZpbGVQYXRoID0+IGZpeEZpbGVXaXRoQ3Vyc29yQUkoZmlsZVBhdGgpKSk7XFxuZm9yKGNvbnN0IHN1Y2Nlc3Mgb2YgZml4UmVzdWx0cykgeydcbiAgICAgICk7XG4gICAgICBcbiAgICAgIC8vIEZpeCBpbmNyZW1lbnRcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9maXhlZENvdW50XFwrXFwrOy9nLFxuICAgICAgICAnZml4ZWRDb3VudCArPSAxOydcbiAgICAgICk7XG4gICAgfVxuICAgIFxuICAgIC8vIFdyaXRlIHRoZSBtb2RpZmllZCBjb250ZW50IGJhY2sgaWYgY2hhbmdlcyB3ZXJlIG1hZGVcbiAgICBpZihuZXdDb250ZW50ICE9PSBmaWxlQ29udGVudCkge1xuICAgICAgd3JpdGVGaWxlU3luYyhmaWxlUGF0aCwgbmV3Q29udGVudCwgJ3V0ZjgnKTtcbiAgICAgIGxvZyhgRml4ZWQgaXNzdWVzIGluICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICB3YXNNb2RpZmllZCA9IHRydWU7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB3YXNNb2RpZmllZDtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIGxvZyhgRXJyb3IgYXBwbHlpbmcgZGlyZWN0IGZpeGVzIHRvICR7ZmlsZVBhdGh9OiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuLyoqXG4gKiBDaGVjayBmb3IgQUkgY29uZmlndXJhdGlvbiBpbiBtYWluIGxleC5jb25maWcuanMgZmlsZVxuICovXG5jb25zdCBsb2FkQUlDb25maWcgPSBhc3luYyAoY3dkOiBzdHJpbmcsIHF1aWV0OiBib29sZWFuKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGNvbnN0IGxleENvbmZpZ1BhdGggPSBwYXRoUmVzb2x2ZShjd2QsICdsZXguY29uZmlnLmpzJyk7XG4gIGNvbnN0IGxleENvbmZpZ0V4aXN0cyA9IGV4aXN0c1N5bmMobGV4Q29uZmlnUGF0aCk7XG5cbiAgaWYobGV4Q29uZmlnRXhpc3RzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGxleENvbmZpZyA9IGF3YWl0IGltcG9ydChsZXhDb25maWdQYXRoKTtcbiAgICAgIGlmKGxleENvbmZpZy5kZWZhdWx0ICYmIGxleENvbmZpZy5kZWZhdWx0LmFpKSB7XG4gICAgICAgIGxvZygnRm91bmQgQUkgY29uZmlndXJhdGlvbiBpbiBsZXguY29uZmlnLmpzLCBhcHBseWluZyBzZXR0aW5ncy4uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAvLyBVcGRhdGUgdGhlIEFJIGNvbmZpZ3VyYXRpb24gaW4gTGV4Q29uZmlnXG4gICAgICAgIExleENvbmZpZy5jb25maWcuYWkgPSB7Li4uTGV4Q29uZmlnLmNvbmZpZy5haSwgLi4ubGV4Q29uZmlnLmRlZmF1bHQuYWl9O1xuICAgICAgfVxuICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgIGxvZyhgRXJyb3IgbG9hZGluZyBBSSBjb25maWd1cmF0aW9uIGZyb20gbGV4LmNvbmZpZy5qczogJHtlcnJvci5tZXNzYWdlfWAsICd3YXJuJywgcXVpZXQpO1xuICAgIH1cbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGxpbnQgPSBhc3luYyAoY21kOiBMaW50T3B0aW9ucywgY2FsbGJhY2s6IExpbnRDYWxsYmFjayA9IHByb2Nlc3MuZXhpdCk6IFByb21pc2U8bnVtYmVyPiA9PiB7XG4gIGNvbnN0IHtcbiAgICBjbGlOYW1lID0gJ0xleCcsXG4gICAgZml4ID0gZmFsc2UsXG4gICAgZGVidWcgPSBmYWxzZSxcbiAgICBxdWlldCA9IGZhbHNlLFxuICAgIGNvbmZpZyA9IG51bGxcbiAgfSA9IGNtZDtcblxuICBsb2coYCR7Y2xpTmFtZX0gbGludGluZy4uLmAsICdpbmZvJywgcXVpZXQpO1xuXG4gIGNvbnN0IGN3ZCA9IHByb2Nlc3MuY3dkKCk7XG4gIGNvbnN0IHNwaW5uZXIgPSBjcmVhdGVTcGlubmVyKHF1aWV0KTtcblxuICAvLyBMb2FkIEFJIGNvbmZpZ3VyYXRpb24gaWYgYXZhaWxhYmxlXG4gIGF3YWl0IGxvYWRBSUNvbmZpZyhjd2QsIHF1aWV0KTtcblxuICAvLyBUcmFjayBpZiB3ZSBuZWVkIHRvIHJlc3RvcmUgYW4gb3JpZ2luYWwgY29uZmlnXG4gIGxldCBvcmlnaW5hbENvbmZpZzogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIGxldCB0ZW1wQ29uZmlnUGF0aDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICAvLyBEZXRlY3QgVHlwZVNjcmlwdCBkaXJlY3RseVxuICAgIGNvbnN0IHVzZVR5cGVzY3JpcHQgPSBkZXRlY3RUeXBlU2NyaXB0KGN3ZCk7XG4gICAgbG9nKGBUeXBlU2NyaXB0ICR7dXNlVHlwZXNjcmlwdCA/ICdkZXRlY3RlZCcgOiAnbm90IGRldGVjdGVkJ30gZnJvbSB0c2NvbmZpZy5qc29uYCwgJ2luZm8nLCBxdWlldCk7XG5cbiAgICAvLyBFbnN1cmUgcGFja2FnZS5qc29uIGhhcyB0eXBlOiBtb2R1bGUgZm9yIEVTTSBzdXBwb3J0XG4gICAgZW5zdXJlTW9kdWxlVHlwZShjd2QpO1xuXG4gICAgLy8gSW5zdGFsbCBuZWNlc3NhcnkgZGVwZW5kZW5jaWVzXG4gICAgYXdhaXQgaW5zdGFsbERlcGVuZGVuY2llcyhjd2QsIHVzZVR5cGVzY3JpcHQsIHF1aWV0KTtcblxuICAgIC8vIENoZWNrIGZvciBFU0xpbnQgY29uZmlndXJhdGlvbiBmaWxlc1xuICAgIGNvbnN0IHByb2plY3RDb25maWdQYXRoID0gcGF0aFJlc29sdmUoY3dkLCAnZXNsaW50LmNvbmZpZy5qcycpO1xuICAgIGNvbnN0IGhhc0VzbGludENvbmZpZyA9IGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGgpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLmpzJykpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLmpzb24nKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RzU3luYyhwYXRoUmVzb2x2ZShjd2QsICcuZXNsaW50cmMueW1sJykpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLnlhbWwnKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgZXhpc3RzU3luYyhwYXRoUmVzb2x2ZShjd2QsICcuZXNsaW50cmMnKSk7XG5cbiAgICAvLyBSZW1vdmUgYW55IGV4aXN0aW5nIC5lc2xpbnRyYy5qc29uIGZpbGUgdG8gYXZvaWQgY29uZmxpY3RzIHdpdGggZXNsaW50LmNvbmZpZy5qc1xuICAgIGlmKGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLmpzb24nKSkpIHtcbiAgICAgIHVubGlua1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLmpzb24nKSk7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHRvIGZpbmQgTGV4J3MgRVNMaW50IGNvbmZpZyBpZiBuZWVkZWRcbiAgICBsZXQgbGV4Q29uZmlnUGF0aCA9ICcnO1xuICAgIGxldCBzaG91bGRDcmVhdGVUZW1wQ29uZmlnID0gZmFsc2U7XG5cbiAgICBpZighaGFzRXNsaW50Q29uZmlnKSB7XG4gICAgICAvLyBUcnkgZGlmZmVyZW50IHBvdGVudGlhbCBsb2NhdGlvbnMgZm9yIHRoZSBMZXggY29uZmlnXG4gICAgICBjb25zdCBwb3NzaWJsZVBhdGhzID0gW1xuICAgICAgICAvLyBGcm9tIHNyYy9jb21tYW5kcy9saW50L2xpbnQudHMgdG8gcm9vdFxuICAgICAgICBwYXRoUmVzb2x2ZShfX2Rpcm5hbWUsICcuLi8uLi8uLi8uLi9lc2xpbnQuY29uZmlnLmpzJyksXG4gICAgICAgIC8vIEZyb20gcGFja2FnZXMvbGV4L3NyYy9jb21tYW5kcy9saW50L2xpbnQudHMgdG8gcGFja2FnZXMvbGV4XG4gICAgICAgIHBhdGhSZXNvbHZlKF9fZGlybmFtZSwgJy4uLy4uLy4uL2VzbGludC5jb25maWcuanMnKSxcbiAgICAgICAgLy8gRnJvbSBwYWNrYWdlcy9sZXgvc3JjL2NvbW1hbmRzL2xpbnQvbGludC50cyB0byByb290XG4gICAgICAgIHBhdGhSZXNvbHZlKF9fZGlybmFtZSwgJy4uLy4uLy4uLy4uLy4uL2VzbGludC5jb25maWcuanMnKSxcbiAgICAgICAgLy8gQWJzb2x1dGUgcGF0aCBpZiBMZXggaXMgaW5zdGFsbGVkIGdsb2JhbGx5XG4gICAgICAgIHBhdGhSZXNvbHZlKHByb2Nlc3MuZW52LkxFWF9IT01FIHx8ICcvdXNyL2xvY2FsL2xpYi9ub2RlX21vZHVsZXMvQG5sYWJzL2xleCcsICdlc2xpbnQuY29uZmlnLmpzJylcbiAgICAgIF07XG5cbiAgICAgIC8vIEZpbmQgdGhlIGZpcnN0IGV4aXN0aW5nIGNvbmZpZ1xuICAgICAgZm9yKGNvbnN0IHBhdGggb2YgcG9zc2libGVQYXRocykge1xuICAgICAgICBpZihleGlzdHNTeW5jKHBhdGgpKSB7XG4gICAgICAgICAgbGV4Q29uZmlnUGF0aCA9IHBhdGg7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgbG9nKGBDdXJyZW50IGRpcmVjdG9yeTogJHtfX2Rpcm5hbWV9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIGxvZyhgUHJvamVjdCBjb25maWcgcGF0aDogJHtwcm9qZWN0Q29uZmlnUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgbG9nKGBQcm9qZWN0IGNvbmZpZyBleGlzdHM6ICR7aGFzRXNsaW50Q29uZmlnfWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBsb2coYEZvdW5kIExleCBjb25maWc6ICR7bGV4Q29uZmlnUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgbG9nKGBMZXggY29uZmlnIGV4aXN0czogJHshIWxleENvbmZpZ1BhdGggJiYgZXhpc3RzU3luYyhsZXhDb25maWdQYXRoKX1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIH1cblxuICAgICAgLy8gSWYgd2UgZm91bmQgTGV4J3MgY29uZmlnLCB1c2UgaXRcbiAgICAgIGlmKGxleENvbmZpZ1BhdGggJiYgZXhpc3RzU3luYyhsZXhDb25maWdQYXRoKSkge1xuICAgICAgICBsb2coJ05vIEVTTGludCBjb25maWd1cmF0aW9uIGZvdW5kIGluIHByb2plY3QuIFVzaW5nIExleFxcJ3MgZGVmYXVsdCBjb25maWd1cmF0aW9uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gT3RoZXJ3aXNlLCB3ZSBuZWVkIHRvIGNyZWF0ZSBhIHRlbXBvcmFyeSBjb25maWdcbiAgICAgICAgc2hvdWxkQ3JlYXRlVGVtcENvbmZpZyA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSWYgdXNlciBzcGVjaWZpZWQgYSBjb25maWcgZmlsZSwgdXNlIHRoYXRcbiAgICBpZihjb25maWcpIHtcbiAgICAgIGNvbnN0IHVzZXJDb25maWdQYXRoID0gcGF0aFJlc29sdmUoY3dkLCBjb25maWcpO1xuICAgICAgaWYoZXhpc3RzU3luYyh1c2VyQ29uZmlnUGF0aCkpIHtcbiAgICAgICAgbG9nKGBVc2luZyBzcGVjaWZpZWQgRVNMaW50IGNvbmZpZ3VyYXRpb246ICR7Y29uZmlnfWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAvLyBVc2VyLXNwZWNpZmllZCBjb25maWcgdGFrZXMgcHJlY2VkZW5jZVxuICAgICAgICBzaG91bGRDcmVhdGVUZW1wQ29uZmlnID0gZmFsc2U7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsb2coYFNwZWNpZmllZCBFU0xpbnQgY29uZmlndXJhdGlvbiBub3QgZm91bmQ6ICR7Y29uZmlnfS4gVXNpbmcgTGV4J3MgZGVmYXVsdCBjb25maWd1cmF0aW9uLmAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENyZWF0ZSBhIHRlbXBvcmFyeSBjb25maWcgaWYgbmVlZGVkXG4gICAgaWYoc2hvdWxkQ3JlYXRlVGVtcENvbmZpZykge1xuICAgICAgbG9nKCdObyBFU0xpbnQgY29uZmlndXJhdGlvbiBmb3VuZC4gQ3JlYXRpbmcgYSB0ZW1wb3JhcnkgY29uZmlndXJhdGlvbi4uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgY29uc3QgY29uZmlnUmVzdWx0ID0gY3JlYXRlRGVmYXVsdEVTTGludENvbmZpZyh1c2VUeXBlc2NyaXB0LCBjd2QpO1xuICAgICAgdGVtcENvbmZpZ1BhdGggPSBjb25maWdSZXN1bHQuY29uZmlnUGF0aDtcbiAgICAgIG9yaWdpbmFsQ29uZmlnID0gY29uZmlnUmVzdWx0Lm9yaWdpbmFsQ29uZmlnO1xuICAgIH1cblxuICAgIC8vIENhcHR1cmUgdGhlIEVTTGludCBvdXRwdXQgZm9yIEFJIGZpeCBpZiBuZWVkZWRcbiAgICBsZXQgZXNsaW50T3V0cHV0ID0gJyc7XG4gICAgY29uc3QgY2FwdHVyZU91dHB1dCA9IChvdXRwdXQ6IHN0cmluZykgPT4ge1xuICAgICAgZXNsaW50T3V0cHV0ICs9IGAke291dHB1dH1cXG5gO1xuICAgIH07XG5cbiAgICAvLyBBbHdheXMgcnVuIEVTTGludCB3aXRoIC0tZml4IGZpcnN0IHRvIGFwcGx5IGJ1aWx0LWluIGZpeGVzXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcnVuRXNsaW50V2l0aExleChjd2QsIHF1aWV0LCBjbGlOYW1lLCB0cnVlLCBkZWJ1ZywgdXNlVHlwZXNjcmlwdCwgY2FwdHVyZU91dHB1dCk7XG5cbiAgICAvLyBJZiB0aGVyZSBhcmUgc3RpbGwgZXJyb3JzIGFuZCBmaXggZmxhZyBpcyBzZXQsIHRyeSB0byBmaXggdGhlbSB3aXRoIEFJXG4gICAgaWYocmVzdWx0ICE9PSAwICYmIGZpeCkge1xuICAgICAgLy8gQ2hlY2sgaWYgQUkgaXMgY29uZmlndXJlZFxuICAgICAgY29uc3QgYWlDb25maWd1cmVkID0gTGV4Q29uZmlnLmNvbmZpZy5haT8ucHJvdmlkZXIgJiYgTGV4Q29uZmlnLmNvbmZpZy5haS5wcm92aWRlciAhPT0gJ25vbmUnO1xuXG4gICAgICBpZihhaUNvbmZpZ3VyZWQpIHtcbiAgICAgICAgbG9nKCdBcHBseWluZyBBSSBmaXhlcyB0byByZW1haW5pbmcgaXNzdWVzLi4uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIGF3YWl0IGFwcGx5QUlGaXgoY3dkLCBlc2xpbnRPdXRwdXQsIHF1aWV0KTtcblxuICAgICAgICAvLyBSdW4gRVNMaW50IGFnYWluIHRvIGNoZWNrIGlmIGFsbCBpc3N1ZXMgYXJlIGZpeGVkXG4gICAgICAgIGNvbnN0IGFmdGVyRml4UmVzdWx0ID0gYXdhaXQgcnVuRXNsaW50V2l0aExleChjd2QsIHF1aWV0LCBjbGlOYW1lLCBmYWxzZSwgZGVidWcsIHVzZVR5cGVzY3JpcHQpO1xuXG4gICAgICAgIC8vIFJldHVybiB0aGUgcmVzdWx0IG9mIHRoZSBzZWNvbmQgcnVuXG4gICAgICAgIGNhbGxiYWNrKGFmdGVyRml4UmVzdWx0KTtcbiAgICAgICAgcmV0dXJuIGFmdGVyRml4UmVzdWx0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gSWYgQUkgaXMgbm90IGNvbmZpZ3VyZWQsIHN1Z2dlc3QgY29uZmlndXJpbmcgaXRcbiAgICAgICAgbG9nKCdFU0xpbnQgY291bGQgbm90IGZpeCBhbGwgaXNzdWVzIGF1dG9tYXRpY2FsbHkuJywgJ3dhcm4nLCBxdWlldCk7XG4gICAgICAgIGxvZygnVG8gZW5hYmxlIEFJLXBvd2VyZWQgZml4ZXMsIGFkZCBBSSBjb25maWd1cmF0aW9uIHRvIHlvdXIgbGV4LmNvbmZpZy5qczonLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgbG9nKGBcbi8vIEluIGxleC5jb25maWcuanNcbmV4cG9ydCBkZWZhdWx0IHtcbiAgLy8gWW91ciBleGlzdGluZyBjb25maWdcbiAgYWk6IHtcbiAgICBwcm92aWRlcjogJ2N1cnNvcicgLy8gb3IgJ29wZW5haScsICdhbnRocm9waWMnLCBldGMuXG4gICAgLy8gQWRkaXRpb25hbCBwcm92aWRlci1zcGVjaWZpYyBzZXR0aW5nc1xuICB9XG59O2AsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNhbGxiYWNrKHJlc3VsdCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIC8vIERpc3BsYXkgZXJyb3IgbWVzc2FnZVxuICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICBzcGlubmVyLmZhaWwoJ0xpbnRpbmcgZmFpbGVkIScpO1xuICAgIGNhbGxiYWNrKDEpO1xuICAgIHJldHVybiAxO1xuICB9IGZpbmFsbHkge1xuICAgIC8vIFJlc3RvcmUgdGhlIG9yaWdpbmFsIGNvbmZpZyBpZiB3ZSBjcmVhdGVkIGEgdGVtcG9yYXJ5IG9uZVxuICAgIGlmKHRlbXBDb25maWdQYXRoICYmIG9yaWdpbmFsQ29uZmlnKSB7XG4gICAgICB0cnkge1xuICAgICAgICB3cml0ZUZpbGVTeW5jKHRlbXBDb25maWdQYXRoLCBvcmlnaW5hbENvbmZpZywgJ3V0ZjgnKTtcbiAgICAgIH0gY2F0Y2goX2Vycm9yKSB7XG4gICAgICAgIC8vIElnbm9yZSBlcnJvcnNcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYodGVtcENvbmZpZ1BhdGgpIHtcbiAgICAgIC8vIFJlbW92ZSB0aGUgdGVtcG9yYXJ5IGNvbmZpZyBpZiB0aGVyZSB3YXMgbm8gb3JpZ2luYWxcbiAgICAgIHRyeSB7XG4gICAgICAgIHVubGlua1N5bmModGVtcENvbmZpZ1BhdGgpO1xuICAgICAgfSBjYXRjaChfZXJyb3IpIHtcbiAgICAgICAgLy8gSWdub3JlIGVycm9yc1xuICAgICAgfVxuICAgIH1cbiAgfVxufTsiXSwKICAibWFwcGluZ3MiOiAiQUFJQSxTQUFRLGFBQVk7QUFDcEIsU0FBUSxZQUFZLGVBQWUsY0FBYyxrQkFBaUI7QUFDbEUsU0FBUSxXQUFXLGFBQWEsZUFBYztBQUM5QyxTQUFRLHFCQUFvQjtBQUU1QixTQUFRLGlCQUFnQjtBQUN4QixTQUFRLHFCQUFvQjtBQUM1QixTQUFRLFdBQVU7QUFHbEIsTUFBTSxhQUFhLGNBQWMsWUFBWSxHQUFHO0FBQ2hELE1BQU0sWUFBWSxRQUFRLFVBQVU7QUFrRHBDLE1BQU0sNEJBQTRCLENBQUMsZUFBd0IsUUFBOEI7QUFFdkYsUUFBTSxhQUFhLFlBQVksS0FBSyxrQkFBa0I7QUFHdEQsTUFBSSxpQkFBaUI7QUFDckIsTUFBRyxXQUFXLFVBQVUsR0FBRztBQUN6QixRQUFJO0FBQ0YsdUJBQWlCLGFBQWEsWUFBWSxNQUFNO0FBQUEsSUFDbEQsU0FBUSxRQUFRO0FBQUEsSUFFaEI7QUFBQSxFQUNGO0FBSUEsUUFBTSxnQkFBZ0I7QUFBQTtBQUFBLElBRXBCLFlBQVks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