@nlabs/lex 1.48.6 → 1.49.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 (107) hide show
  1. package/.storybook/main.ts +9 -2
  2. package/.vscode/settings.json +1 -6
  3. package/README.md +276 -4
  4. package/eslint.config.mjs +24 -0
  5. package/examples/lex.config.js +18 -8
  6. package/examples/serverless-example/README.md +109 -0
  7. package/examples/serverless-example/dist/handlers/echo.js +15 -0
  8. package/examples/serverless-example/dist/handlers/graphql.js +137 -0
  9. package/examples/serverless-example/dist/handlers/hello.js +15 -0
  10. package/examples/serverless-example/dist/handlers/test.js +17 -0
  11. package/examples/serverless-example/dist/handlers/websocket.js +14 -0
  12. package/examples/serverless-example/lex.config.mjs +74 -0
  13. package/jest.config.mjs +13 -12
  14. package/{dist → lib}/LexConfig.d.ts +14 -6
  15. package/lib/LexConfig.js +268 -0
  16. package/lib/commands/ai/ai.js +303 -0
  17. package/{dist → lib}/commands/build/build.d.ts +3 -0
  18. package/lib/commands/build/build.js +494 -0
  19. package/{dist → lib}/commands/clean/clean.js +1 -1
  20. package/lib/commands/compile/compile.js +241 -0
  21. package/lib/commands/copy/copy.js +38 -0
  22. package/{dist → lib}/commands/create/create.js +1 -1
  23. package/{dist → lib}/commands/dev/dev.d.ts +2 -0
  24. package/lib/commands/dev/dev.js +286 -0
  25. package/{dist → lib}/commands/init/init.js +1 -1
  26. package/{dist → lib}/commands/lint/lint.d.ts +4 -1
  27. package/lib/commands/lint/lint.js +993 -0
  28. package/{dist → lib}/commands/migrate/migrate.js +1 -1
  29. package/lib/commands/publish/publish.js +104 -0
  30. package/lib/commands/serverless/serverless.d.ts +17 -0
  31. package/lib/commands/serverless/serverless.js +662 -0
  32. package/lib/commands/storybook/storybook.js +249 -0
  33. package/lib/commands/test/test.js +428 -0
  34. package/lib/commands/update/update.js +128 -0
  35. package/lib/commands/versions/versions.js +41 -0
  36. package/{dist → lib}/create/changelog.js +1 -1
  37. package/{dist → lib}/index.d.ts +2 -0
  38. package/{dist → lib}/index.js +3 -1
  39. package/lib/lex.js +73 -0
  40. package/lib/storybook/index.d.ts +5 -0
  41. package/lib/types.js +1 -0
  42. package/lib/utils/aiService.d.ts +9 -0
  43. package/lib/utils/aiService.js +299 -0
  44. package/{dist → lib}/utils/app.d.ts +3 -0
  45. package/lib/utils/app.js +296 -0
  46. package/lib/utils/deepMerge.js +26 -0
  47. package/{dist → lib}/utils/file.d.ts +7 -3
  48. package/lib/utils/file.js +229 -0
  49. package/lib/utils/translations.d.ts +1 -0
  50. package/lib/utils/translations.js +74 -0
  51. package/package.json +62 -50
  52. package/postcss.config.js +5 -3
  53. package/tsconfig.build.json +2 -2
  54. package/webpack.config.js +229 -39
  55. package/dist/LexConfig.js +0 -286
  56. package/dist/commands/ai/ai.js +0 -303
  57. package/dist/commands/build/build.js +0 -404
  58. package/dist/commands/compile/compile.js +0 -234
  59. package/dist/commands/copy/copy.js +0 -38
  60. package/dist/commands/dev/dev.js +0 -74
  61. package/dist/commands/lint/lint.js +0 -811
  62. package/dist/commands/publish/publish.js +0 -104
  63. package/dist/commands/storybook/storybook.js +0 -249
  64. package/dist/commands/test/test.js +0 -429
  65. package/dist/commands/update/update.js +0 -132
  66. package/dist/commands/versions/versions.js +0 -41
  67. package/dist/lex.js +0 -70
  68. package/dist/utils/aiService.d.ts +0 -9
  69. package/dist/utils/aiService.js +0 -299
  70. package/dist/utils/app.js +0 -267
  71. package/dist/utils/deepMerge.js +0 -24
  72. package/dist/utils/file.js +0 -185
  73. package/emptyModule.js +0 -0
  74. package/eslint.config.js +0 -7
  75. /package/{dist → lib}/Button.stories.d.ts +0 -0
  76. /package/{dist → lib}/commands/ai/ai.d.ts +0 -0
  77. /package/{dist → lib}/commands/ai/index.d.ts +0 -0
  78. /package/{dist → lib}/commands/ai/index.js +0 -0
  79. /package/{dist → lib}/commands/clean/clean.d.ts +0 -0
  80. /package/{dist → lib}/commands/compile/compile.d.ts +0 -0
  81. /package/{dist → lib}/commands/config/config.d.ts +0 -0
  82. /package/{dist → lib}/commands/config/config.js +0 -0
  83. /package/{dist → lib}/commands/copy/copy.d.ts +0 -0
  84. /package/{dist → lib}/commands/create/create.d.ts +0 -0
  85. /package/{dist → lib}/commands/init/init.d.ts +0 -0
  86. /package/{dist → lib}/commands/link/link.d.ts +0 -0
  87. /package/{dist → lib}/commands/link/link.js +0 -0
  88. /package/{dist → lib}/commands/lint/autofix.d.ts +0 -0
  89. /package/{dist → lib}/commands/migrate/migrate.d.ts +0 -0
  90. /package/{dist → lib}/commands/publish/publish.d.ts +0 -0
  91. /package/{dist → lib}/commands/storybook/storybook.d.ts +0 -0
  92. /package/{dist → lib}/commands/test/test.d.ts +0 -0
  93. /package/{dist → lib}/commands/update/update.d.ts +0 -0
  94. /package/{dist → lib}/commands/upgrade/upgrade.d.ts +0 -0
  95. /package/{dist → lib}/commands/upgrade/upgrade.js +0 -0
  96. /package/{dist → lib}/commands/versions/versions.d.ts +0 -0
  97. /package/{dist → lib}/create/changelog.d.ts +0 -0
  98. /package/{dist → lib}/lex.d.ts +0 -0
  99. /package/{dist/types.js → lib/storybook/index.js} +0 -0
  100. /package/{dist → lib}/test-react/index.d.ts +0 -0
  101. /package/{dist → lib}/test-react/index.js +0 -0
  102. /package/{dist → lib}/types.d.ts +0 -0
  103. /package/{dist → lib}/utils/deepMerge.d.ts +0 -0
  104. /package/{dist → lib}/utils/log.d.ts +0 -0
  105. /package/{dist → lib}/utils/log.js +0 -0
  106. /package/{dist → lib}/utils/reactShim.d.ts +0 -0
  107. /package/{dist → lib}/utils/reactShim.js +0 -0
@@ -1,811 +0,0 @@
1
- import { execa } from "execa";
2
- import { existsSync, readFileSync, unlinkSync, writeFileSync } from "fs";
3
- import { dirname, resolve as pathResolve } from "path";
4
- import { LexConfig } from "../../LexConfig.js";
5
- import { createSpinner } from "../../utils/app.js";
6
- import { resolveBinaryPath } from "../../utils/file.js";
7
- import { log } from "../../utils/log.js";
8
- let currentFilename;
9
- let currentDirname;
10
- try {
11
- currentFilename = eval('require("url").fileURLToPath(import.meta.url)');
12
- currentDirname = dirname(currentFilename);
13
- } catch {
14
- currentFilename = process.cwd();
15
- currentDirname = process.cwd();
16
- }
17
- const createDefaultESLintConfig = (useTypescript, cwd) => {
18
- const configPath = pathResolve(cwd, "eslint.config.ts");
19
- let originalConfig;
20
- if (existsSync(configPath)) {
21
- try {
22
- originalConfig = readFileSync(configPath, "utf8");
23
- } catch (_error) {
24
- }
25
- }
26
- const possiblePaths = [
27
- pathResolve(currentDirname, "../../../../eslint.config.ts"),
28
- pathResolve(process.env.LEX_HOME || "/usr/local/lib/node_modules/@nlabs/lex", "eslint.config.ts")
29
- ];
30
- let foundConfig = "";
31
- for (const path of possiblePaths) {
32
- if (existsSync(path)) {
33
- foundConfig = path;
34
- break;
35
- }
36
- }
37
- let eslintConfig;
38
- if (foundConfig) {
39
- try {
40
- eslintConfig = readFileSync(foundConfig, "utf8");
41
- } catch (_error) {
42
- eslintConfig = createBasicESLintConfig(useTypescript);
43
- }
44
- } else {
45
- eslintConfig = createBasicESLintConfig(useTypescript);
46
- }
47
- writeFileSync(configPath, eslintConfig, "utf8");
48
- return {
49
- configPath,
50
- originalConfig
51
- };
52
- };
53
- const createBasicESLintConfig = (useTypescript) => {
54
- let config = `// ESLint configuration
55
- import { typescriptConfig } from 'eslint-config-styleguidejs';
56
-
57
- const config = [
58
- {
59
- ignores: ['**/node_modules/**', '**/dist/**', '**/build/**']
60
- },
61
- // Config for JavaScript files
62
- {
63
- files: ['**/*.{js,jsx}'],
64
- languageOptions: {
65
- ecmaVersion: 'latest',
66
- sourceType: 'module'
67
- },
68
- rules: {
69
- 'indent': ['error', 2],
70
- 'quotes': ['error', 'single'],
71
- 'semi': ['error', 'always'],
72
- 'no-unused-vars': ['warn', { 'argsIgnorePattern': '^_', 'varsIgnorePattern': '^_', 'caughtErrors': 'all', 'caughtErrorsIgnorePattern': '^_' }],
73
- 'eqeqeq': ['error', 'always']
74
- }
75
- }`;
76
- if (useTypescript) {
77
- config += `,
78
- // Config for TypeScript files
79
- {
80
- files: ['**/*.{ts,tsx}'],
81
- languageOptions: {
82
- ecmaVersion: 'latest',
83
- sourceType: 'module',
84
- parser: {
85
- importSource: '@typescript-eslint/parser'
86
- },
87
- parserOptions: {
88
- project: getTypeScriptConfigPath('tsconfig.lint.json')
89
- }
90
- },
91
- plugins: {
92
- '@typescript-eslint': {
93
- importSource: '@typescript-eslint/eslint-plugin'
94
- }
95
- },
96
- rules: {
97
- 'indent': ['error', 2],
98
- 'quotes': ['error', 'single'],
99
- 'semi': ['error', 'always'],
100
- 'no-unused-vars': 'off',
101
- '@typescript-eslint/no-unused-vars': ['warn', { 'argsIgnorePattern': '^_', 'varsIgnorePattern': '^_', 'caughtErrors': 'all', 'caughtErrorsIgnorePattern': '^_' }],
102
- 'eqeqeq': ['error', 'always']
103
- }
104
- }`;
105
- }
106
- config += `
107
- ];
108
-
109
- export default config;`;
110
- return config;
111
- };
112
- const detectTypeScript = (cwd) => existsSync(pathResolve(cwd, "tsconfig.json"));
113
- const ensureModuleType = (cwd) => {
114
- const packageJsonPath = pathResolve(cwd, "package.json");
115
- if (existsSync(packageJsonPath)) {
116
- try {
117
- const packageJsonContent = readFileSync(packageJsonPath, "utf8");
118
- const packageJson = JSON.parse(packageJsonContent);
119
- if (packageJson.type !== "module") {
120
- log('Warning: package.json should have "type": "module" for ESM support. Please add this manually.', "warn", false);
121
- }
122
- } catch (_error) {
123
- }
124
- }
125
- };
126
- const installDependencies = async (cwd, useTypescript, quiet) => {
127
- if (useTypescript) {
128
- log("Using TypeScript ESLint from Lex...", "info", quiet);
129
- } else {
130
- log("Using ESLint from Lex...", "info", quiet);
131
- }
132
- };
133
- const runEslintWithLex = async (cwd, quiet, cliName, fix, debug, useTypescript, captureOutput) => {
134
- const spinner = createSpinner(quiet);
135
- try {
136
- const projectConfigPath = pathResolve(cwd, "eslint.config.js");
137
- const projectConfigPathTs = pathResolve(cwd, "eslint.config.ts");
138
- const hasProjectConfig = existsSync(projectConfigPath) || existsSync(projectConfigPathTs);
139
- const possiblePaths = [
140
- pathResolve(currentDirname, "../../../../eslint.config.ts"),
141
- pathResolve(process.env.LEX_HOME || "/usr/local/lib/node_modules/@nlabs/lex", "eslint.config.ts")
142
- ];
143
- let lexConfigPath = "";
144
- for (const path of possiblePaths) {
145
- if (existsSync(path)) {
146
- lexConfigPath = path;
147
- break;
148
- }
149
- }
150
- const configPath = hasProjectConfig ? existsSync(projectConfigPathTs) ? projectConfigPathTs : projectConfigPath : lexConfigPath || projectConfigPath;
151
- const eslintBinary = resolveBinaryPath("eslint", "eslint");
152
- if (!eslintBinary) {
153
- log(`
154
- ${cliName} Error: ESLint binary not found in Lex's node_modules`, "error", quiet);
155
- log("Please reinstall Lex or check your installation.", "info", quiet);
156
- return 1;
157
- }
158
- const jsResult = await execa(eslintBinary, [
159
- "src/**/*.{js,jsx}",
160
- "--config",
161
- configPath,
162
- ...fix ? ["--fix"] : [],
163
- ...debug ? ["--debug"] : [],
164
- "--no-error-on-unmatched-pattern"
165
- ], {
166
- reject: false,
167
- stdio: "pipe",
168
- cwd,
169
- shell: true
170
- });
171
- if (jsResult.stdout) {
172
- console.log(jsResult.stdout);
173
- if (captureOutput) {
174
- captureOutput(jsResult.stdout);
175
- }
176
- }
177
- if (jsResult.stderr) {
178
- console.error(jsResult.stderr);
179
- if (captureOutput) {
180
- captureOutput(jsResult.stderr);
181
- }
182
- }
183
- let tsResult = { exitCode: 0, stdout: "", stderr: "" };
184
- if (useTypescript) {
185
- tsResult = await execa(eslintBinary, [
186
- "src/**/*.{ts,tsx}",
187
- "--config",
188
- configPath,
189
- ...fix ? ["--fix"] : [],
190
- ...debug ? ["--debug"] : [],
191
- "--no-error-on-unmatched-pattern"
192
- ], {
193
- reject: false,
194
- stdio: "pipe",
195
- cwd,
196
- shell: true
197
- });
198
- if (tsResult.stdout) {
199
- console.log(tsResult.stdout);
200
- }
201
- if (tsResult.stderr) {
202
- console.error(tsResult.stderr);
203
- }
204
- }
205
- const eslintNotFound = jsResult.stderr?.includes("command not found") || jsResult.stderr?.includes("eslint: command not found");
206
- if (eslintNotFound) {
207
- spinner.fail("ESLint not found!");
208
- log(`
209
- ${cliName} Error: Lex's ESLint binary not found. Please reinstall Lex or check your installation.`, "error", quiet);
210
- return 1;
211
- }
212
- if (jsResult.exitCode === 0 && tsResult.exitCode === 0) {
213
- spinner.succeed("Linting completed!");
214
- return 0;
215
- }
216
- 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"));
217
- if (noFilesFound) {
218
- spinner.succeed("No files found to lint");
219
- return 0;
220
- }
221
- spinner.fail("Linting failed!");
222
- log(`
223
- ${cliName} Error: ESLint found issues in your code.`, "error", quiet);
224
- return 1;
225
- } catch (error) {
226
- spinner.fail("Linting failed!");
227
- log(`
228
- ${cliName} Error: ${error.message}`, "error", quiet);
229
- return 1;
230
- }
231
- };
232
- const applyAIFix = async (cwd, errors, quiet) => {
233
- const spinner = createSpinner(quiet);
234
- spinner.start("Using AI to fix remaining lint issues...");
235
- try {
236
- const fileErrorMap = /* @__PURE__ */ new Map();
237
- const lines = errors.split("\n");
238
- let currentFile = "";
239
- for (const line of lines) {
240
- if (line.match(/^(\/|[A-Z]:\\).*?\.(js|jsx|ts|tsx)$/)) {
241
- currentFile = line.trim();
242
- if (!fileErrorMap.has(currentFile)) {
243
- fileErrorMap.set(currentFile, []);
244
- }
245
- } else if (currentFile && line.trim() && line.match(/\s+\d+:\d+\s+(error|warning)\s+/)) {
246
- const errorArray = fileErrorMap.get(currentFile);
247
- if (errorArray) {
248
- errorArray.push(line.trim());
249
- }
250
- }
251
- }
252
- if (fileErrorMap.size === 0) {
253
- log("Using alternative error parsing strategy", "info", quiet);
254
- const sections = errors.split("\n\n");
255
- for (const section of sections) {
256
- if (section.trim() === "") {
257
- continue;
258
- }
259
- const lines2 = section.split("\n");
260
- const filePath = lines2[0].trim();
261
- if (filePath.match(/\.(js|jsx|ts|tsx)$/)) {
262
- fileErrorMap.set(filePath, []);
263
- for (let i = 1; i < lines2.length; i++) {
264
- if (lines2[i].trim() !== "") {
265
- fileErrorMap.get(filePath)?.push(lines2[i].trim());
266
- }
267
- }
268
- }
269
- }
270
- }
271
- if (fileErrorMap.size === 0) {
272
- log("Using direct file path extraction", "info", quiet);
273
- const filePathRegex = /(?:\/|[A-Z]:\\)(?:[^:\n]+\/)*[^:\n]+\.(js|jsx|ts|tsx)/g;
274
- const filePaths = errors.match(filePathRegex) || [];
275
- for (const filePath of filePaths) {
276
- if (!fileErrorMap.has(filePath) && existsSync(filePath)) {
277
- fileErrorMap.set(filePath, []);
278
- }
279
- }
280
- const knownFiles = [
281
- pathResolve(cwd, "src/create/changelog.ts"),
282
- pathResolve(cwd, "src/utils/aiService.ts"),
283
- pathResolve(cwd, "src/utils/app.ts"),
284
- pathResolve(cwd, "src/utils/reactShim.ts"),
285
- pathResolve(cwd, "src/commands/lint/autofix.js")
286
- ];
287
- for (const file of knownFiles) {
288
- if (existsSync(file) && !fileErrorMap.has(file)) {
289
- fileErrorMap.set(file, []);
290
- }
291
- }
292
- }
293
- for (const filePath of fileErrorMap.keys()) {
294
- if (!existsSync(filePath)) {
295
- log(`File not found: ${filePath}`, "warn", quiet);
296
- continue;
297
- }
298
- log(`Processing file: ${filePath}`, "info", quiet);
299
- const isCursorIDE = LexConfig.config.ai?.provider === "cursor" || process.env.CURSOR_IDE === "true";
300
- if (isCursorIDE) {
301
- try {
302
- const prompt = `Fix all ESLint errors in this file. Focus on:
303
- 1. Fixing naming conventions
304
- 2. Fixing sort-keys issues
305
- 3. Replacing console.log with log utility
306
- 4. Fixing no-plusplus issues
307
- 5. Fixing unnecessary escape characters
308
- 6. Fixing other ESLint errors
309
-
310
- CRITICAL REQUIREMENTS:
311
- - ONLY fix the specific lines with ESLint errors
312
- - DO NOT modify any other lines of code
313
- - DO NOT remove line breaks unless they are specifically causing ESLint errors
314
- - DO NOT condense multi-line structures to single lines
315
- - PRESERVE all existing line breaks and formatting that is not causing errors
316
-
317
- SPECIFIC FORMATTING RULES:
318
- - Maintain proper indentation (2 spaces)
319
- - Keep line breaks between class/interface declaration and their members
320
- - Keep line breaks between methods
321
- - Ensure there is a line break after opening braces for classes, interfaces, and methods
322
- - DO NOT place class/interface properties or methods on the same line as the opening brace
323
- - Preserve empty lines between logical code blocks
324
- - PRESERVE multi-line imports - do not condense them to single lines
325
- - PRESERVE multi-line object/array declarations - do not condense them to single lines
326
-
327
- SORT-KEYS RULE (HIGHEST PRIORITY):
328
- - All object literal keys MUST be sorted alphabetically in ascending order
329
- - This applies to ALL objects in the file, not just those with explicit sort-keys errors
330
- - Example: {b: 2, a: 1, c: 3} should become {a: 1, b: 2, c: 3}
331
- - Preserve the original formatting and line breaks when sorting
332
-
333
- Example of CORRECT formatting (DO NOT CHANGE):
334
- export class UserConstants {
335
- static readonly ADD_ITEM_ERROR: string = 'USER_ADD_ITEM_ERROR';
336
- static readonly OTHER_CONSTANT: string = 'OTHER_CONSTANT';
337
- }
338
-
339
- constructor(flux: FluxFramework, CustomAdapter: typeof Event = Event) {
340
- this.CustomAdapter = CustomAdapter;
341
- this.flux = flux;
342
- }
343
-
344
- import {
345
- app,
346
- events,
347
- images,
348
- locations,
349
- messages,
350
- posts,
351
- tags,
352
- users,
353
- websocket
354
- } from './stores';
355
-
356
- const config = {
357
- apiKey: 'value',
358
- baseUrl: 'https://api.example.com',
359
- timeout: 5000
360
- };
361
-
362
- Example of INCORRECT formatting (FIX THIS):
363
- export class UserConstants {static readonly ADD_ITEM_ERROR: string = 'USER_ADD_ITEM_ERROR';
364
- static readonly OTHER_CONSTANT: string = 'OTHER_CONSTANT';
365
- }
366
-
367
- constructor(flux: FluxFramework, CustomAdapter: typeof Event = Event) {this.CustomAdapter = CustomAdapter;
368
- this.flux = flux;}
369
-
370
- import {app, events, images, locations, messages, posts, tags, users, websocket} from './stores';
371
-
372
- const config = {baseUrl: 'https://api.example.com', apiKey: 'value', timeout: 5000};
373
-
374
- Fix ONLY the specific ESLint errors. Return the properly formatted code.`;
375
- try {
376
- const promptFile = pathResolve(cwd, ".cursor_prompt_temp.txt");
377
- writeFileSync(promptFile, prompt, "utf8");
378
- await execa("cursor", ["edit", "--file", filePath, "--prompt-file", promptFile], {
379
- reject: false,
380
- stdio: "pipe",
381
- cwd
382
- });
383
- try {
384
- unlinkSync(promptFile);
385
- } catch (_error) {
386
- }
387
- log(`Applied Cursor AI fixes to ${filePath}`, "info", quiet);
388
- } catch (error) {
389
- const wasModified = await applyDirectFixes(filePath, quiet);
390
- if (wasModified) {
391
- log(`Applied direct fixes to ${filePath}`, "info", quiet);
392
- }
393
- }
394
- } catch (error) {
395
- log(`Error using Cursor AI: ${error.message}`, "error", quiet);
396
- await applyDirectFixes(filePath, quiet);
397
- }
398
- } else {
399
- const wasModified = await applyDirectFixes(filePath, quiet);
400
- if (wasModified) {
401
- log(`Applied direct fixes to ${filePath}`, "info", quiet);
402
- }
403
- const fileErrors = fileErrorMap.get(filePath) || [];
404
- if (fileErrors.length > 0) {
405
- try {
406
- const { callAIService } = await import("../../utils/aiService.js");
407
- const fileContent = readFileSync(filePath, "utf8");
408
- const prompt = `Fix the following ESLint errors in this code:
409
- ${fileErrors.join("\n")}
410
-
411
- Here's the code:
412
- \`\`\`
413
- ${fileContent}
414
- \`\`\`
415
-
416
- CRITICAL REQUIREMENTS:
417
- - ONLY fix the specific lines with ESLint errors
418
- - DO NOT modify any other lines of code
419
- - DO NOT remove line breaks unless they are specifically causing ESLint errors
420
- - DO NOT condense multi-line structures to single lines
421
- - PRESERVE all existing line breaks and formatting that is not causing errors
422
-
423
- SPECIFIC FORMATTING RULES:
424
- - Maintain proper indentation (2 spaces)
425
- - Keep line breaks between class/interface declaration and their members
426
- - Keep line breaks between methods
427
- - Ensure there is a line break after opening braces for classes, interfaces, and methods
428
- - DO NOT place class/interface properties or methods on the same line as the opening brace
429
- - Preserve empty lines between logical code blocks
430
- - PRESERVE multi-line imports - do not condense them to single lines
431
- - PRESERVE multi-line object/array declarations - do not condense them to single lines
432
-
433
- SORT-KEYS RULE (HIGHEST PRIORITY):
434
- - All object literal keys MUST be sorted alphabetically in ascending order
435
- - This applies to ALL objects in the file, not just those with explicit sort-keys errors
436
- - Example: {b: 2, a: 1, c: 3} should become {a: 1, b: 2, c: 3}
437
- - Preserve the original formatting and line breaks when sorting
438
-
439
- WHAT TO FIX:
440
- 1. Sorting all object keys alphabetically (sort-keys rule) - ALL objects must have sorted keys
441
- 2. Fixing naming conventions - ONLY for variables/functions with naming errors
442
- 3. Replacing console.log with log utility - ONLY for console.log statements
443
- 4. Fixing no-plusplus issues - ONLY for ++/-- operators
444
- 5. Fixing unnecessary escape characters - ONLY for escaped characters that don't need escaping
445
- 6. Proper indentation and spacing - ONLY where specifically required by errors
446
- 7. String quotes consistency (use single quotes) - ONLY for string literals with quote errors
447
- 8. Import order and spacing - ONLY for imports with order/spacing errors
448
- 9. Function parameter formatting - ONLY for functions with parameter errors
449
- 10. Variable naming conventions - ONLY for variables with naming errors
450
- 11. No unused variables or imports - ONLY for unused variables/imports
451
- 12. Avoiding nested ternaries - ONLY for nested ternary expressions
452
- 13. Any other ESLint errors - ONLY for the specific errors listed above
453
-
454
- WHAT NOT TO FIX:
455
- - Do not change properly formatted multi-line structures
456
- - Do not remove line breaks that are not causing errors
457
- - Do not change indentation that is already correct
458
- - Do not modify spacing that is already correct
459
- - Do not condense readable multi-line code to single lines
460
- - Do not modify code that is not mentioned in the ESLint errors
461
-
462
- Example of CORRECT formatting (DO NOT CHANGE):
463
- export class UserConstants {
464
- static readonly ADD_ITEM_ERROR: string = 'USER_ADD_ITEM_ERROR';
465
- static readonly OTHER_CONSTANT: string = 'OTHER_CONSTANT';
466
- }
467
-
468
- constructor(flux: FluxFramework, CustomAdapter: typeof Event = Event) {
469
- this.CustomAdapter = CustomAdapter;
470
- this.flux = flux;
471
- }
472
-
473
- import {
474
- app,
475
- events,
476
- images,
477
- locations,
478
- messages,
479
- posts,
480
- tags,
481
- users,
482
- websocket
483
- } from './stores';
484
-
485
- const config = {
486
- apiKey: 'value',
487
- baseUrl: 'https://api.example.com',
488
- timeout: 5000
489
- };
490
-
491
- Example of INCORRECT formatting (FIX THIS):
492
- export class UserConstants {static readonly ADD_ITEM_ERROR: string = 'USER_ADD_ITEM_ERROR';
493
- static readonly OTHER_CONSTANT: string = 'OTHER_CONSTANT';
494
- }
495
-
496
- constructor(flux: FluxFramework, CustomAdapter: typeof Event = Event) {this.CustomAdapter = CustomAdapter;
497
- this.flux = flux;}
498
-
499
- import {app, events, images, locations, messages, posts, tags, users, websocket} from './stores';
500
-
501
- const config = {baseUrl: 'https://api.example.com', apiKey: 'value', timeout: 5000};
502
-
503
- Fix ONLY the specific ESLint errors listed above. Review the entire file for compliance with all ESLint rules.
504
- Return only the properly formatted fixed code without any explanations.`;
505
- const fixedContent = await callAIService(prompt, quiet);
506
- if (fixedContent && fixedContent !== fileContent) {
507
- writeFileSync(filePath, fixedContent, "utf8");
508
- log(`Applied AI fixes to ${filePath}`, "info", quiet);
509
- }
510
- } catch (error) {
511
- log(`Error applying AI fixes to ${filePath}: ${error.message}`, "error", quiet);
512
- }
513
- }
514
- }
515
- }
516
- spinner.succeed("AI fixes applied successfully!");
517
- } catch (error) {
518
- spinner.fail("Failed to apply AI fixes");
519
- log(`Error: ${error.message}`, "error", quiet);
520
- if (!quiet) {
521
- console.error(error);
522
- }
523
- }
524
- };
525
- const applyDirectFixes = async (filePath, quiet) => {
526
- let wasModified = false;
527
- try {
528
- const fileContent = readFileSync(filePath, "utf8");
529
- let newContent = fileContent;
530
- if (filePath.includes("aiService.ts")) {
531
- log("Fixing issues in aiService.ts", "info", quiet);
532
- newContent = newContent.replace(
533
- /'Content-Type': 'application\/json',\s*'Authorization': `Bearer/g,
534
- "'Authorization': `Bearer', 'Content-Type': 'application/json'"
535
- );
536
- newContent = newContent.replace(
537
- /headers: {([^}]*)},\s*method: 'POST'/g,
538
- "method: 'POST',\n headers: {$1}"
539
- );
540
- newContent = newContent.replace(
541
- /{role: 'system', content:/g,
542
- "{content:, role: 'system',"
543
- );
544
- newContent = newContent.replace(
545
- /{role: 'user', content:/g,
546
- "{content:, role: 'user',"
547
- );
548
- newContent = newContent.replace(
549
- /\(([^)]*?)_([a-zA-Z0-9]+)(\s*:[^)]*)\)/g,
550
- "($1$2$3)"
551
- );
552
- newContent = newContent.replace(/console\.log\(/g, "log(");
553
- if (!newContent.includes("import {log}") && newContent.includes("log(")) {
554
- newContent = newContent.replace(
555
- /import {([^}]*)} from '(.*)';/,
556
- "import {$1} from '$2';\nimport {log} from './log.js';"
557
- );
558
- }
559
- }
560
- if (filePath.includes("reactShim.ts")) {
561
- log("Fixing naming-convention issues in reactShim.ts", "info", quiet);
562
- newContent = newContent.replace(
563
- "import * as React from",
564
- "import * as react from"
565
- );
566
- newContent = newContent.replace(/React\./g, "react.");
567
- }
568
- if (filePath.includes("changelog.ts")) {
569
- log("Fixing issues in changelog.ts", "info", quiet);
570
- newContent = newContent.replace(/(\w+)\+\+/g, "$1 += 1");
571
- newContent = newContent.replace(/\\\$/g, "$");
572
- newContent = newContent.replace(/\\\./g, ".");
573
- newContent = newContent.replace(/\\\*/g, "*");
574
- newContent = newContent.replace(/\\:/g, ":");
575
- }
576
- if (filePath.includes("app.ts")) {
577
- log("Fixing issues in app.ts", "info", quiet);
578
- newContent = newContent.replace(/console\.log\(/g, "log(");
579
- if (!newContent.includes("import {log}") && newContent.includes("log(")) {
580
- newContent = newContent.replace(
581
- /import boxen from 'boxen';/,
582
- "import boxen from 'boxen';\nimport {log} from './log.js';"
583
- );
584
- }
585
- newContent = newContent.replace(/\\\//g, "/");
586
- }
587
- if (filePath.includes("autofix.js")) {
588
- log("Fixing issues in autofix.js", "info", quiet);
589
- newContent = newContent.replace(
590
- /import {([^}]*)} from 'path';[\s\n]*import {([^}]*)} from 'path';/,
591
- "import {$1, $2} from 'path';"
592
- );
593
- newContent = newContent.replace(
594
- /__filename/g,
595
- "currentFilename"
596
- );
597
- newContent = newContent.replace(
598
- /__dirname/g,
599
- "currentDirname"
600
- );
601
- newContent = newContent.replace(
602
- /const prefix = type === 'error' \? '❌ ' : type === 'success' \? '✅ ' : 'ℹ️ ';/,
603
- "let prefix = '\u2139\uFE0F ';\nif(type === 'error') {\n prefix = '\u274C ';\n} else if(type === 'success') {\n prefix = '\u2705 ';\n}"
604
- );
605
- newContent = newContent.replace(
606
- /async function runEslintFix\(\)/g,
607
- "const runEslintFix = async ()"
608
- );
609
- newContent = newContent.replace(
610
- /async function getFilesWithErrors\(\)/g,
611
- "const getFilesWithErrors = async ()"
612
- );
613
- newContent = newContent.replace(
614
- /async function isCursorAvailable\(\)/g,
615
- "const isCursorAvailable = async ()"
616
- );
617
- newContent = newContent.replace(
618
- /async function fixFileWithCursorAI\(filePath\)/g,
619
- "const fixFileWithCursorAI = async (filePath)"
620
- );
621
- newContent = newContent.replace(
622
- /async function main\(\)/g,
623
- "const main = async ()"
624
- );
625
- newContent = newContent.replace(
626
- /import {existsSync, readFileSync, writeFileSync}/g,
627
- "import {writeFileSync}"
628
- );
629
- newContent = newContent.replace(
630
- /console\.log\(`\${prefix} \${message}`\);/g,
631
- "process.stdout.write(`${prefix} ${message}\\n`);"
632
- );
633
- newContent = newContent.replace(
634
- /} catch\(error\) {[\s\n]*\/\/ Ignore cleanup errors/g,
635
- "} catch(_) {\n // Ignore cleanup errors"
636
- );
637
- newContent = newContent.replace(
638
- /} catch\(error\) {[\s\n]*log\(/g,
639
- "} catch(err) {\n log("
640
- );
641
- newContent = newContent.replace(
642
- /} catch\(error\) {[\s\n]*return false;/g,
643
- "} catch(_) {\n return false;"
644
- );
645
- newContent = newContent.replace(
646
- /for\(const filePath of filesWithErrors\) {[\s\n]*const success = await fixFileWithCursorAI\(filePath\);/g,
647
- "const fixResults = await Promise.all(filesWithErrors.map(filePath => fixFileWithCursorAI(filePath)));\nfor(const success of fixResults) {"
648
- );
649
- newContent = newContent.replace(
650
- /fixedCount\+\+;/g,
651
- "fixedCount += 1;"
652
- );
653
- }
654
- if (newContent !== fileContent) {
655
- writeFileSync(filePath, newContent, "utf8");
656
- log(`Fixed issues in ${filePath}`, "info", quiet);
657
- wasModified = true;
658
- }
659
- return wasModified;
660
- } catch (error) {
661
- log(`Error applying direct fixes to ${filePath}: ${error.message}`, "error", quiet);
662
- return false;
663
- }
664
- };
665
- const loadAIConfig = async (cwd, quiet) => {
666
- const configFormats = ["js", "mjs", "cjs", "ts", "json"];
667
- const configBaseName = "lex.config";
668
- let lexConfigPath = "";
669
- for (const format of configFormats) {
670
- const potentialPath = pathResolve(cwd, `./${configBaseName}.${format}`);
671
- if (existsSync(potentialPath)) {
672
- lexConfigPath = potentialPath;
673
- break;
674
- }
675
- }
676
- if (lexConfigPath) {
677
- try {
678
- const lexConfig = await import(lexConfigPath);
679
- if (lexConfig.default && lexConfig.default.ai) {
680
- log(`Found AI configuration in ${pathResolve(cwd, lexConfigPath)}, applying settings...`, "info", quiet);
681
- LexConfig.config.ai = { ...LexConfig.config.ai, ...lexConfig.default.ai };
682
- }
683
- } catch (error) {
684
- log(`Error loading AI configuration from ${lexConfigPath}: ${error.message}`, "warn", quiet);
685
- }
686
- }
687
- };
688
- const lint = async (cmd, callback = process.exit) => {
689
- const {
690
- cliName = "Lex",
691
- fix = false,
692
- debug = false,
693
- quiet = false,
694
- config = null
695
- } = cmd;
696
- log(`${cliName} linting...`, "info", quiet);
697
- const cwd = process.cwd();
698
- const spinner = createSpinner(quiet);
699
- await loadAIConfig(cwd, quiet);
700
- let originalConfig = null;
701
- let tempConfigPath = null;
702
- try {
703
- const useTypescript = detectTypeScript(cwd);
704
- log(`TypeScript ${useTypescript ? "detected" : "not detected"} from tsconfig.json`, "info", quiet);
705
- if (useTypescript) {
706
- LexConfig.checkLintTypescriptConfig();
707
- }
708
- ensureModuleType(cwd);
709
- await installDependencies(cwd, useTypescript, quiet);
710
- const projectConfigPath = pathResolve(cwd, "eslint.config.js");
711
- const projectConfigPathTs = pathResolve(cwd, "eslint.config.ts");
712
- const hasEslintConfig = existsSync(projectConfigPath) || existsSync(projectConfigPathTs) || existsSync(pathResolve(cwd, ".eslintrc.js")) || existsSync(pathResolve(cwd, ".eslintrc.json")) || existsSync(pathResolve(cwd, ".eslintrc.yml")) || existsSync(pathResolve(cwd, ".eslintrc.yaml")) || existsSync(pathResolve(cwd, ".eslintrc"));
713
- if (existsSync(pathResolve(cwd, ".eslintrc.json"))) {
714
- unlinkSync(pathResolve(cwd, ".eslintrc.json"));
715
- }
716
- let lexConfigPath = "";
717
- let shouldCreateTempConfig = false;
718
- if (!hasEslintConfig) {
719
- const possiblePaths = [
720
- pathResolve(currentDirname, "../../../../eslint.config.ts"),
721
- pathResolve(process.env.LEX_HOME || "/usr/local/lib/node_modules/@nlabs/lex", "eslint.config.ts")
722
- ];
723
- for (const path of possiblePaths) {
724
- if (existsSync(path)) {
725
- lexConfigPath = path;
726
- break;
727
- }
728
- }
729
- if (debug) {
730
- log(`Current directory: ${currentDirname}`, "info", quiet);
731
- log(`Project config path: ${projectConfigPath}`, "info", quiet);
732
- log(`Project config exists: ${hasEslintConfig}`, "info", quiet);
733
- log(`Found Lex config: ${lexConfigPath}`, "info", quiet);
734
- log(`Lex config exists: ${!!lexConfigPath && existsSync(lexConfigPath)}`, "info", quiet);
735
- }
736
- if (lexConfigPath && existsSync(lexConfigPath)) {
737
- log("No ESLint configuration found in project. Using Lex's default configuration.", "info", quiet);
738
- } else {
739
- shouldCreateTempConfig = true;
740
- }
741
- }
742
- if (config) {
743
- const userConfigPath = pathResolve(cwd, config);
744
- if (existsSync(userConfigPath)) {
745
- log(`Using specified ESLint configuration: ${config}`, "info", quiet);
746
- shouldCreateTempConfig = false;
747
- } else {
748
- log(`Specified ESLint configuration not found: ${config}. Using Lex's default configuration.`, "warn", quiet);
749
- }
750
- }
751
- if (shouldCreateTempConfig) {
752
- log("No ESLint configuration found. Creating a temporary configuration...", "info", quiet);
753
- const configResult = createDefaultESLintConfig(useTypescript, cwd);
754
- tempConfigPath = configResult.configPath;
755
- originalConfig = configResult.originalConfig;
756
- }
757
- let eslintOutput = "";
758
- const captureOutput = (output) => {
759
- eslintOutput += `${output}
760
- `;
761
- };
762
- const result = await runEslintWithLex(cwd, quiet, cliName, true, debug, useTypescript, captureOutput);
763
- if (result !== 0 && fix) {
764
- const aiConfigured = LexConfig.config.ai?.provider && LexConfig.config.ai.provider !== "none";
765
- if (aiConfigured) {
766
- log("Applying AI fixes to remaining issues...", "info", quiet);
767
- await applyAIFix(cwd, eslintOutput, quiet);
768
- const afterFixResult = await runEslintWithLex(cwd, quiet, cliName, false, debug, useTypescript);
769
- callback(afterFixResult);
770
- return afterFixResult;
771
- }
772
- log("ESLint could not fix all issues automatically.", "warn", quiet);
773
- log("To enable AI-powered fixes, add AI configuration to your lex.config file:", "info", quiet);
774
- log(`
775
- // In lex.config.js (or lex.config.mjs, lex.config.cjs, etc.)
776
- export default {
777
- // Your existing config
778
- ai: {
779
- provider: 'cursor' // or 'openai', 'anthropic', etc.
780
- // Additional provider-specific settings
781
- }
782
- };`, "info", quiet);
783
- }
784
- callback(result);
785
- return result;
786
- } catch (error) {
787
- log(`
788
- ${cliName} Error: ${error.message}`, "error", quiet);
789
- if (spinner) {
790
- spinner.fail("Linting failed!");
791
- }
792
- callback(1);
793
- return 1;
794
- } finally {
795
- if (tempConfigPath && originalConfig) {
796
- try {
797
- writeFileSync(tempConfigPath, originalConfig, "utf8");
798
- } catch (_error) {
799
- }
800
- } else if (tempConfigPath) {
801
- try {
802
- unlinkSync(tempConfigPath);
803
- } catch (_error) {
804
- }
805
- }
806
- }
807
- };
808
- export {
809
- lint
810
- };
811
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL2xpbnQvbGludC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjItUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCB7ZXhlY2F9IGZyb20gJ2V4ZWNhJztcbmltcG9ydCB7ZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jLCB1bmxpbmtTeW5jLCB3cml0ZUZpbGVTeW5jfSBmcm9tICdmcyc7XG5pbXBvcnQge2Rpcm5hbWUsIHJlc29sdmUgYXMgcGF0aFJlc29sdmV9IGZyb20gJ3BhdGgnO1xuXG5pbXBvcnQge0xleENvbmZpZ30gZnJvbSAnLi4vLi4vTGV4Q29uZmlnLmpzJztcbmltcG9ydCB7Y3JlYXRlU3Bpbm5lcn0gZnJvbSAnLi4vLi4vdXRpbHMvYXBwLmpzJztcbmltcG9ydCB7cmVzb2x2ZUJpbmFyeVBhdGh9IGZyb20gJy4uLy4uL3V0aWxzL2ZpbGUuanMnO1xuaW1wb3J0IHtsb2d9IGZyb20gJy4uLy4uL3V0aWxzL2xvZy5qcyc7XG5cbmxldCBjdXJyZW50RmlsZW5hbWU6IHN0cmluZztcbmxldCBjdXJyZW50RGlybmFtZTogc3RyaW5nO1xuXG50cnkge1xuICBjdXJyZW50RmlsZW5hbWUgPSBldmFsKCdyZXF1aXJlKFwidXJsXCIpLmZpbGVVUkxUb1BhdGgoaW1wb3J0Lm1ldGEudXJsKScpO1xuICBjdXJyZW50RGlybmFtZSA9IGRpcm5hbWUoY3VycmVudEZpbGVuYW1lKTtcbn0gY2F0Y2h7XG4gIGN1cnJlbnRGaWxlbmFtZSA9IHByb2Nlc3MuY3dkKCk7XG4gIGN1cnJlbnREaXJuYW1lID0gcHJvY2Vzcy5jd2QoKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMaW50T3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNhY2hlPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgY2FjaGVGaWxlPzogc3RyaW5nO1xuICByZWFkb25seSBjYWNoZUxvY2F0aW9uPzogc3RyaW5nO1xuICByZWFkb25seSBjbGlOYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBjb2xvcj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGNvbmZpZz86IHN0cmluZztcbiAgcmVhZG9ubHkgZGVidWc/OiBib29sZWFuO1xuICByZWFkb25seSBlbnY/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGVudkluZm8/OiBib29sZWFuO1xuICByZWFkb25seSBleHQ/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZpeD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGZpeERyeVJ1bj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGZpeFR5cGU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGZvcm1hdD86IHN0cmluZztcbiAgcmVhZG9ubHkgZ2xvYmFsPzogc3RyaW5nO1xuICByZWFkb25seSBpZ25vcmVQYXRoPzogc3RyaW5nO1xuICByZWFkb25seSBpZ25vcmVQYXR0ZXJuPzogc3RyaW5nO1xuICByZWFkb25seSBpbml0PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbWF4V2FybmluZ3M/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG5vQ29sb3I/OiBib29sZWFuO1xuICByZWFkb25seSBub0VzbGludHJjPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgbm9JZ25vcmU/OiBib29sZWFuO1xuICByZWFkb25seSBub0lubGluZUNvbmZpZz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IG91dHB1dEZpbGU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhcnNlcj86IHN0cmluZztcbiAgcmVhZG9ubHkgcGFyc2VyT3B0aW9ucz86IHN0cmluZztcbiAgcmVhZG9ubHkgcGx1Z2luPzogc3RyaW5nO1xuICByZWFkb25seSBwcmludENvbmZpZz86IHN0cmluZztcbiAgcmVhZG9ubHkgcXVpZXQ/OiBib29sZWFuO1xuICByZWFkb25seSByZXBvcnRVbnVzZWREaXNhYmxlRGlyZWN0aXZlcz86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHJlc29sdmVQbHVnaW5zUmVsYXRpdmVUbz86IHN0cmluZztcbiAgcmVhZG9ubHkgcnVsZT86IHN0cmluZztcbiAgcmVhZG9ubHkgcnVsZXNkaXI/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN0ZGluPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3RkaW5GaWxlbmFtZT86IHN0cmluZztcbn1cblxuZXhwb3J0IHR5cGUgTGludENhbGxiYWNrID0gdHlwZW9mIHByb2Nlc3MuZXhpdDtcblxuaW50ZXJmYWNlIENvbmZpZ1Jlc3VsdCB7XG4gIGNvbmZpZ1BhdGg6IHN0cmluZztcbiAgb3JpZ2luYWxDb25maWc6IHN0cmluZyB8IG51bGw7XG59XG5cbmNvbnN0IGNyZWF0ZURlZmF1bHRFU0xpbnRDb25maWcgPSAodXNlVHlwZXNjcmlwdDogYm9vbGVhbiwgY3dkOiBzdHJpbmcpOiBDb25maWdSZXN1bHQgPT4ge1xuICBjb25zdCBjb25maWdQYXRoID0gcGF0aFJlc29sdmUoY3dkLCAnZXNsaW50LmNvbmZpZy50cycpO1xuICBsZXQgb3JpZ2luYWxDb25maWc7XG5cbiAgaWYoZXhpc3RzU3luYyhjb25maWdQYXRoKSkge1xuICAgIHRyeSB7XG4gICAgICBvcmlnaW5hbENvbmZpZyA9IHJlYWRGaWxlU3luYyhjb25maWdQYXRoLCAndXRmOCcpO1xuICAgIH0gY2F0Y2goX2Vycm9yKSB7XG4gICAgICAvLyBJZ25vcmUgZXJyb3JzXG4gICAgfVxuICB9XG5cbiAgY29uc3QgcG9zc2libGVQYXRocyA9IFtcbiAgICBwYXRoUmVzb2x2ZShjdXJyZW50RGlybmFtZSwgJy4uLy4uLy4uLy4uL2VzbGludC5jb25maWcudHMnKSxcbiAgICBwYXRoUmVzb2x2ZShwcm9jZXNzLmVudi5MRVhfSE9NRSB8fCAnL3Vzci9sb2NhbC9saWIvbm9kZV9tb2R1bGVzL0BubGFicy9sZXgnLCAnZXNsaW50LmNvbmZpZy50cycpXG4gIF07XG5cbiAgbGV0IGZvdW5kQ29uZmlnID0gJyc7XG5cbiAgZm9yKGNvbnN0IHBhdGggb2YgcG9zc2libGVQYXRocykge1xuICAgIGlmKGV4aXN0c1N5bmMocGF0aCkpIHtcbiAgICAgIGZvdW5kQ29uZmlnID0gcGF0aDtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGxldCBlc2xpbnRDb25maWc7XG5cbiAgaWYoZm91bmRDb25maWcpIHtcbiAgICB0cnkge1xuICAgICAgZXNsaW50Q29uZmlnID0gcmVhZEZpbGVTeW5jKGZvdW5kQ29uZmlnLCAndXRmOCcpO1xuICAgIH0gY2F0Y2goX2Vycm9yKSB7XG4gICAgICBlc2xpbnRDb25maWcgPSBjcmVhdGVCYXNpY0VTTGludENvbmZpZyh1c2VUeXBlc2NyaXB0KTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgZXNsaW50Q29uZmlnID0gY3JlYXRlQmFzaWNFU0xpbnRDb25maWcodXNlVHlwZXNjcmlwdCk7XG4gIH1cblxuICB3cml0ZUZpbGVTeW5jKGNvbmZpZ1BhdGgsIGVzbGludENvbmZpZywgJ3V0ZjgnKTtcblxuICByZXR1cm4ge1xuICAgIGNvbmZpZ1BhdGgsXG4gICAgb3JpZ2luYWxDb25maWdcbiAgfTtcbn07XG5cbmNvbnN0IGNyZWF0ZUJhc2ljRVNMaW50Q29uZmlnID0gKHVzZVR5cGVzY3JpcHQ6IGJvb2xlYW4pOiBzdHJpbmcgPT4ge1xuICBsZXQgY29uZmlnID0gYC8vIEVTTGludCBjb25maWd1cmF0aW9uXG5pbXBvcnQgeyB0eXBlc2NyaXB0Q29uZmlnIH0gZnJvbSAnZXNsaW50LWNvbmZpZy1zdHlsZWd1aWRlanMnO1xuXG5jb25zdCBjb25maWcgPSBbXG4gIHtcbiAgICBpZ25vcmVzOiBbJyoqL25vZGVfbW9kdWxlcy8qKicsICcqKi9kaXN0LyoqJywgJyoqL2J1aWxkLyoqJ11cbiAgfSxcbiAgLy8gQ29uZmlnIGZvciBKYXZhU2NyaXB0IGZpbGVzXG4gIHtcbiAgICBmaWxlczogWycqKi8qLntqcyxqc3h9J10sXG4gICAgbGFuZ3VhZ2VPcHRpb25zOiB7XG4gICAgICBlY21hVmVyc2lvbjogJ2xhdGVzdCcsXG4gICAgICBzb3VyY2VUeXBlOiAnbW9kdWxlJ1xuICAgIH0sXG4gICAgcnVsZXM6IHtcbiAgICAgICdpbmRlbnQnOiBbJ2Vycm9yJywgMl0sXG4gICAgICAncXVvdGVzJzogWydlcnJvcicsICdzaW5nbGUnXSxcbiAgICAgICdzZW1pJzogWydlcnJvcicsICdhbHdheXMnXSxcbiAgICAgICduby11bnVzZWQtdmFycyc6IFsnd2FybicsIHsgJ2FyZ3NJZ25vcmVQYXR0ZXJuJzogJ15fJywgJ3ZhcnNJZ25vcmVQYXR0ZXJuJzogJ15fJywgJ2NhdWdodEVycm9ycyc6ICdhbGwnLCAnY2F1Z2h0RXJyb3JzSWdub3JlUGF0dGVybic6ICdeXycgfV0sXG4gICAgICAnZXFlcWVxJzogWydlcnJvcicsICdhbHdheXMnXVxuICAgIH1cbiAgfWA7XG5cbiAgLy8gQWRkIFR5cGVTY3JpcHQgY29uZmlndXJhdGlvbiBpZiBuZWVkZWRcbiAgaWYodXNlVHlwZXNjcmlwdCkge1xuICAgIGNvbmZpZyArPSBgLFxuICAvLyBDb25maWcgZm9yIFR5cGVTY3JpcHQgZmlsZXNcbiAge1xuICAgIGZpbGVzOiBbJyoqLyoue3RzLHRzeH0nXSxcbiAgICBsYW5ndWFnZU9wdGlvbnM6IHtcbiAgICAgIGVjbWFWZXJzaW9uOiAnbGF0ZXN0JyxcbiAgICAgIHNvdXJjZVR5cGU6ICdtb2R1bGUnLFxuICAgICAgcGFyc2VyOiB7XG4gICAgICAgIGltcG9ydFNvdXJjZTogJ0B0eXBlc2NyaXB0LWVzbGludC9wYXJzZXInXG4gICAgICB9LFxuICAgICAgICAgICAgICBwYXJzZXJPcHRpb25zOiB7XG4gICAgICAgICAgcHJvamVjdDogZ2V0VHlwZVNjcmlwdENvbmZpZ1BhdGgoJ3RzY29uZmlnLmxpbnQuanNvbicpXG4gICAgICAgIH1cbiAgICB9LFxuICAgIHBsdWdpbnM6IHtcbiAgICAgICdAdHlwZXNjcmlwdC1lc2xpbnQnOiB7XG4gICAgICAgIGltcG9ydFNvdXJjZTogJ0B0eXBlc2NyaXB0LWVzbGludC9lc2xpbnQtcGx1Z2luJ1xuICAgICAgfVxuICAgIH0sXG4gICAgcnVsZXM6IHtcbiAgICAgICdpbmRlbnQnOiBbJ2Vycm9yJywgMl0sXG4gICAgICAncXVvdGVzJzogWydlcnJvcicsICdzaW5nbGUnXSxcbiAgICAgICdzZW1pJzogWydlcnJvcicsICdhbHdheXMnXSxcbiAgICAgICduby11bnVzZWQtdmFycyc6ICdvZmYnLFxuICAgICAgJ0B0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycyc6IFsnd2FybicsIHsgJ2FyZ3NJZ25vcmVQYXR0ZXJuJzogJ15fJywgJ3ZhcnNJZ25vcmVQYXR0ZXJuJzogJ15fJywgJ2NhdWdodEVycm9ycyc6ICdhbGwnLCAnY2F1Z2h0RXJyb3JzSWdub3JlUGF0dGVybic6ICdeXycgfV0sXG4gICAgICAnZXFlcWVxJzogWydlcnJvcicsICdhbHdheXMnXVxuICAgIH1cbiAgfWA7XG4gIH1cblxuICAvLyBDbG9zZSB0aGUgYXJyYXkgYW5kIGV4cG9ydFxuICBjb25maWcgKz0gYFxuXTtcblxuZXhwb3J0IGRlZmF1bHQgY29uZmlnO2A7XG5cbiAgcmV0dXJuIGNvbmZpZztcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgVHlwZVNjcmlwdCBpcyBiZWluZyB1c2VkIGJ5IGxvb2tpbmcgZm9yIHRzY29uZmlnLmpzb25cbiAqL1xuY29uc3QgZGV0ZWN0VHlwZVNjcmlwdCA9IChjd2Q6IHN0cmluZyk6IGJvb2xlYW4gPT4gZXhpc3RzU3luYyhwYXRoUmVzb2x2ZShjd2QsICd0c2NvbmZpZy5qc29uJykpO1xuXG4vKipcbiAqIEVuc3VyZSBwYWNrYWdlLmpzb24gaGFzIHR5cGU6IG1vZHVsZSBmb3IgRVNNIHN1cHBvcnRcbiAqL1xuY29uc3QgZW5zdXJlTW9kdWxlVHlwZSA9IChjd2Q6IHN0cmluZyk6IHZvaWQgPT4ge1xuICBjb25zdCBwYWNrYWdlSnNvblBhdGggPSBwYXRoUmVzb2x2ZShjd2QsICdwYWNrYWdlLmpzb24nKTtcblxuICBpZihleGlzdHNTeW5jKHBhY2thZ2VKc29uUGF0aCkpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcGFja2FnZUpzb25Db250ZW50ID0gcmVhZEZpbGVTeW5jKHBhY2thZ2VKc29uUGF0aCwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IHBhY2thZ2VKc29uID0gSlNPTi5wYXJzZShwYWNrYWdlSnNvbkNvbnRlbnQpO1xuXG4gICAgICAvLyBJZiB0eXBlIGlzIG5vdCBzZXQgdG8gbW9kdWxlLCB3YXJuIGluc3RlYWQgb2YgYXV0by1tb2RpZnlpbmdcbiAgICAgIGlmKHBhY2thZ2VKc29uLnR5cGUgIT09ICdtb2R1bGUnKSB7XG4gICAgICAgIGxvZygnV2FybmluZzogcGFja2FnZS5qc29uIHNob3VsZCBoYXZlIFwidHlwZVwiOiBcIm1vZHVsZVwiIGZvciBFU00gc3VwcG9ydC4gUGxlYXNlIGFkZCB0aGlzIG1hbnVhbGx5LicsICd3YXJuJywgZmFsc2UpO1xuICAgICAgfVxuICAgIH0gY2F0Y2goX2Vycm9yKSB7XG4gICAgICAvLyBJZ25vcmUgZXJyb3JzXG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBpbnN0YWxsRGVwZW5kZW5jaWVzID0gYXN5bmMgKGN3ZDogc3RyaW5nLCB1c2VUeXBlc2NyaXB0OiBib29sZWFuLCBxdWlldDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZih1c2VUeXBlc2NyaXB0KSB7XG4gICAgbG9nKCdVc2luZyBUeXBlU2NyaXB0IEVTTGludCBmcm9tIExleC4uLicsICdpbmZvJywgcXVpZXQpO1xuICB9IGVsc2Uge1xuICAgIGxvZygnVXNpbmcgRVNMaW50IGZyb20gTGV4Li4uJywgJ2luZm8nLCBxdWlldCk7XG4gIH1cbn07XG5cbmNvbnN0IHJ1bkVzbGludFdpdGhMZXggPSBhc3luYyAoXG4gIGN3ZDogc3RyaW5nLFxuICBxdWlldDogYm9vbGVhbixcbiAgY2xpTmFtZTogc3RyaW5nLFxuICBmaXg6IGJvb2xlYW4sXG4gIGRlYnVnOiBib29sZWFuLFxuICB1c2VUeXBlc2NyaXB0OiBib29sZWFuLFxuICBjYXB0dXJlT3V0cHV0PzogKG91dHB1dDogc3RyaW5nKSA9PiB2b2lkXG4pOiBQcm9taXNlPG51bWJlcj4gPT4ge1xuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBwcm9qZWN0Q29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgJ2VzbGludC5jb25maWcuanMnKTtcbiAgICBjb25zdCBwcm9qZWN0Q29uZmlnUGF0aFRzID0gcGF0aFJlc29sdmUoY3dkLCAnZXNsaW50LmNvbmZpZy50cycpO1xuICAgIGNvbnN0IGhhc1Byb2plY3RDb25maWcgPSBleGlzdHNTeW5jKHByb2plY3RDb25maWdQYXRoKSB8fCBleGlzdHNTeW5jKHByb2plY3RDb25maWdQYXRoVHMpO1xuXG4gICAgY29uc3QgcG9zc2libGVQYXRocyA9IFtcbiAgICAgIHBhdGhSZXNvbHZlKGN1cnJlbnREaXJuYW1lLCAnLi4vLi4vLi4vLi4vZXNsaW50LmNvbmZpZy50cycpLFxuICAgICAgcGF0aFJlc29sdmUocHJvY2Vzcy5lbnYuTEVYX0hPTUUgfHwgJy91c3IvbG9jYWwvbGliL25vZGVfbW9kdWxlcy9AbmxhYnMvbGV4JywgJ2VzbGludC5jb25maWcudHMnKVxuICAgIF07XG5cbiAgICBsZXQgbGV4Q29uZmlnUGF0aCA9ICcnO1xuICAgIGZvcihjb25zdCBwYXRoIG9mIHBvc3NpYmxlUGF0aHMpIHtcbiAgICAgIGlmKGV4aXN0c1N5bmMocGF0aCkpIHtcbiAgICAgICAgbGV4Q29uZmlnUGF0aCA9IHBhdGg7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGNvbmZpZ1BhdGggPSBoYXNQcm9qZWN0Q29uZmlnID8gKGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGhUcykgPyBwcm9qZWN0Q29uZmlnUGF0aFRzIDogcHJvamVjdENvbmZpZ1BhdGgpIDogKGxleENvbmZpZ1BhdGggfHwgcHJvamVjdENvbmZpZ1BhdGgpO1xuXG4gICAgY29uc3QgZXNsaW50QmluYXJ5ID0gcmVzb2x2ZUJpbmFyeVBhdGgoJ2VzbGludCcsICdlc2xpbnQnKTtcblxuICAgIGlmKCFlc2xpbnRCaW5hcnkpIHtcbiAgICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogRVNMaW50IGJpbmFyeSBub3QgZm91bmQgaW4gTGV4J3Mgbm9kZV9tb2R1bGVzYCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgbG9nKCdQbGVhc2UgcmVpbnN0YWxsIExleCBvciBjaGVjayB5b3VyIGluc3RhbGxhdGlvbi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIGNvbnN0IGpzUmVzdWx0ID0gYXdhaXQgZXhlY2EoZXNsaW50QmluYXJ5LCBbXG4gICAgICAnc3JjLyoqLyoue2pzLGpzeH0nLFxuICAgICAgJy0tY29uZmlnJywgY29uZmlnUGF0aCxcbiAgICAgIC4uLihmaXggPyBbJy0tZml4J10gOiBbXSksXG4gICAgICAuLi4oZGVidWcgPyBbJy0tZGVidWcnXSA6IFtdKSxcbiAgICAgICctLW5vLWVycm9yLW9uLXVubWF0Y2hlZC1wYXR0ZXJuJ1xuICAgIF0sIHtcbiAgICAgIHJlamVjdDogZmFsc2UsXG4gICAgICBzdGRpbzogJ3BpcGUnLFxuICAgICAgY3dkLFxuICAgICAgc2hlbGw6IHRydWVcbiAgICB9KTtcblxuICAgIGlmKGpzUmVzdWx0LnN0ZG91dCkge1xuICAgICAgY29uc29sZS5sb2coanNSZXN1bHQuc3Rkb3V0KTtcbiAgICAgIGlmKGNhcHR1cmVPdXRwdXQpIHtcbiAgICAgICAgY2FwdHVyZU91dHB1dChqc1Jlc3VsdC5zdGRvdXQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGpzUmVzdWx0LnN0ZGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihqc1Jlc3VsdC5zdGRlcnIpO1xuICAgICAgaWYoY2FwdHVyZU91dHB1dCkge1xuICAgICAgICBjYXB0dXJlT3V0cHV0KGpzUmVzdWx0LnN0ZGVycik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IHRzUmVzdWx0OiBhbnkgPSB7ZXhpdENvZGU6IDAsIHN0ZG91dDogJycsIHN0ZGVycjogJyd9O1xuICAgIGlmKHVzZVR5cGVzY3JpcHQpIHtcbiAgICAgIHRzUmVzdWx0ID0gYXdhaXQgZXhlY2EoZXNsaW50QmluYXJ5LCBbXG4gICAgICAgICdzcmMvKiovKi57dHMsdHN4fScsXG4gICAgICAgICctLWNvbmZpZycsIGNvbmZpZ1BhdGgsXG4gICAgICAgIC4uLihmaXggPyBbJy0tZml4J10gOiBbXSksXG4gICAgICAgIC4uLihkZWJ1ZyA/IFsnLS1kZWJ1ZyddIDogW10pLFxuICAgICAgICAnLS1uby1lcnJvci1vbi11bm1hdGNoZWQtcGF0dGVybidcbiAgICAgIF0sIHtcbiAgICAgICAgcmVqZWN0OiBmYWxzZSxcbiAgICAgICAgc3RkaW86ICdwaXBlJyxcbiAgICAgICAgY3dkLFxuICAgICAgICBzaGVsbDogdHJ1ZVxuICAgICAgfSk7XG5cbiAgICAgIGlmKHRzUmVzdWx0LnN0ZG91dCkge1xuICAgICAgICBjb25zb2xlLmxvZyh0c1Jlc3VsdC5zdGRvdXQpO1xuICAgICAgfVxuXG4gICAgICBpZih0c1Jlc3VsdC5zdGRlcnIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcih0c1Jlc3VsdC5zdGRlcnIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGVzbGludE5vdEZvdW5kID0ganNSZXN1bHQuc3RkZXJyPy5pbmNsdWRlcygnY29tbWFuZCBub3QgZm91bmQnKSB8fCBqc1Jlc3VsdC5zdGRlcnI/LmluY2x1ZGVzKCdlc2xpbnQ6IGNvbW1hbmQgbm90IGZvdW5kJyk7XG4gICAgaWYoZXNsaW50Tm90Rm91bmQpIHtcbiAgICAgIHNwaW5uZXIuZmFpbCgnRVNMaW50IG5vdCBmb3VuZCEnKTtcbiAgICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogTGV4J3MgRVNMaW50IGJpbmFyeSBub3QgZm91bmQuIFBsZWFzZSByZWluc3RhbGwgTGV4IG9yIGNoZWNrIHlvdXIgaW5zdGFsbGF0aW9uLmAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIGlmKGpzUmVzdWx0LmV4aXRDb2RlID09PSAwICYmIHRzUmVzdWx0LmV4aXRDb2RlID09PSAwKSB7XG4gICAgICBzcGlubmVyLnN1Y2NlZWQoJ0xpbnRpbmcgY29tcGxldGVkIScpO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9GaWxlc0ZvdW5kID1cbiAgICAgIChqc1Jlc3VsdC5zdGRlcnI/LmluY2x1ZGVzKCdObyBzdWNoIGZpbGUgb3IgZGlyZWN0b3J5JykgfHwganNSZXN1bHQuc3Rkb3V0Py5pbmNsdWRlcygnTm8gc3VjaCBmaWxlIG9yIGRpcmVjdG9yeScpKSAmJlxuICAgICAgKCF1c2VUeXBlc2NyaXB0IHx8IHRzUmVzdWx0LnN0ZGVycj8uaW5jbHVkZXMoJ05vIHN1Y2ggZmlsZSBvciBkaXJlY3RvcnknKSB8fCB0c1Jlc3VsdC5zdGRvdXQ/LmluY2x1ZGVzKCdObyBzdWNoIGZpbGUgb3IgZGlyZWN0b3J5JykpO1xuXG4gICAgaWYobm9GaWxlc0ZvdW5kKSB7XG4gICAgICBzcGlubmVyLnN1Y2NlZWQoJ05vIGZpbGVzIGZvdW5kIHRvIGxpbnQnKTtcbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgICBzcGlubmVyLmZhaWwoJ0xpbnRpbmcgZmFpbGVkIScpO1xuICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogRVNMaW50IGZvdW5kIGlzc3VlcyBpbiB5b3VyIGNvZGUuYCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIHJldHVybiAxO1xuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdMaW50aW5nIGZhaWxlZCEnKTtcbiAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgcmV0dXJuIDE7XG4gIH1cbn07XG5cbmNvbnN0IGFwcGx5QUlGaXggPSBhc3luYyAoXG4gIGN3ZDogc3RyaW5nLFxuICBlcnJvcnM6IHN0cmluZyxcbiAgcXVpZXQ6IGJvb2xlYW5cbik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG4gIHNwaW5uZXIuc3RhcnQoJ1VzaW5nIEFJIHRvIGZpeCByZW1haW5pbmcgbGludCBpc3N1ZXMuLi4nKTtcblxuICB0cnkge1xuICAgIGNvbnN0IGZpbGVFcnJvck1hcCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgICBjb25zdCBsaW5lcyA9IGVycm9ycy5zcGxpdCgnXFxuJyk7XG4gICAgbGV0IGN1cnJlbnRGaWxlID0gJyc7XG5cbiAgICBmb3IoY29uc3QgbGluZSBvZiBsaW5lcykge1xuICAgICAgaWYobGluZS5tYXRjaCgvXihcXC98W0EtWl06XFxcXCkuKj9cXC4oanN8anN4fHRzfHRzeCkkLykpIHtcbiAgICAgICAgY3VycmVudEZpbGUgPSBsaW5lLnRyaW0oKTtcbiAgICAgICAgaWYoIWZpbGVFcnJvck1hcC5oYXMoY3VycmVudEZpbGUpKSB7XG4gICAgICAgICAgZmlsZUVycm9yTWFwLnNldChjdXJyZW50RmlsZSwgW10pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYoY3VycmVudEZpbGUgJiYgbGluZS50cmltKCkgJiYgbGluZS5tYXRjaCgvXFxzK1xcZCs6XFxkK1xccysoZXJyb3J8d2FybmluZylcXHMrLykpIHtcbiAgICAgICAgY29uc3QgZXJyb3JBcnJheSA9IGZpbGVFcnJvck1hcC5nZXQoY3VycmVudEZpbGUpO1xuICAgICAgICBpZihlcnJvckFycmF5KSB7XG4gICAgICAgICAgZXJyb3JBcnJheS5wdXNoKGxpbmUudHJpbSgpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGZpbGVFcnJvck1hcC5zaXplID09PSAwKSB7XG4gICAgICBsb2coJ1VzaW5nIGFsdGVybmF0aXZlIGVycm9yIHBhcnNpbmcgc3RyYXRlZ3knLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgY29uc3Qgc2VjdGlvbnMgPSBlcnJvcnMuc3BsaXQoJ1xcblxcbicpO1xuXG4gICAgICBmb3IoY29uc3Qgc2VjdGlvbiBvZiBzZWN0aW9ucykge1xuICAgICAgICBpZihzZWN0aW9uLnRyaW0oKSA9PT0gJycpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGxpbmVzID0gc2VjdGlvbi5zcGxpdCgnXFxuJyk7XG4gICAgICAgIGNvbnN0IGZpbGVQYXRoID0gbGluZXNbMF0udHJpbSgpO1xuXG4gICAgICAgIGlmKGZpbGVQYXRoLm1hdGNoKC9cXC4oanN8anN4fHRzfHRzeCkkLykpIHtcbiAgICAgICAgICBmaWxlRXJyb3JNYXAuc2V0KGZpbGVQYXRoLCBbXSk7XG5cbiAgICAgICAgICBmb3IobGV0IGkgPSAxOyBpIDwgbGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmKGxpbmVzW2ldLnRyaW0oKSAhPT0gJycpIHtcbiAgICAgICAgICAgICAgZmlsZUVycm9yTWFwLmdldChmaWxlUGF0aCk/LnB1c2gobGluZXNbaV0udHJpbSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZihmaWxlRXJyb3JNYXAuc2l6ZSA9PT0gMCkge1xuICAgICAgbG9nKCdVc2luZyBkaXJlY3QgZmlsZSBwYXRoIGV4dHJhY3Rpb24nLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgY29uc3QgZmlsZVBhdGhSZWdleCA9IC8oPzpcXC98W0EtWl06XFxcXCkoPzpbXjpcXG5dK1xcLykqW146XFxuXStcXC4oanN8anN4fHRzfHRzeCkvZztcbiAgICAgIGNvbnN0IGZpbGVQYXRocyA9IGVycm9ycy5tYXRjaChmaWxlUGF0aFJlZ2V4KSB8fCBbXTtcblxuICAgICAgZm9yKGNvbnN0IGZpbGVQYXRoIG9mIGZpbGVQYXRocykge1xuICAgICAgICBpZighZmlsZUVycm9yTWFwLmhhcyhmaWxlUGF0aCkgJiYgZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgICAgICBmaWxlRXJyb3JNYXAuc2V0KGZpbGVQYXRoLCBbXSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qga25vd25GaWxlcyA9IFtcbiAgICAgICAgcGF0aFJlc29sdmUoY3dkLCAnc3JjL2NyZWF0ZS9jaGFuZ2Vsb2cudHMnKSxcbiAgICAgICAgcGF0aFJlc29sdmUoY3dkLCAnc3JjL3V0aWxzL2FpU2VydmljZS50cycpLFxuICAgICAgICBwYXRoUmVzb2x2ZShjd2QsICdzcmMvdXRpbHMvYXBwLnRzJyksXG4gICAgICAgIHBhdGhSZXNvbHZlKGN3ZCwgJ3NyYy91dGlscy9yZWFjdFNoaW0udHMnKSxcbiAgICAgICAgcGF0aFJlc29sdmUoY3dkLCAnc3JjL2NvbW1hbmRzL2xpbnQvYXV0b2ZpeC5qcycpXG4gICAgICBdO1xuXG4gICAgICBmb3IoY29uc3QgZmlsZSBvZiBrbm93bkZpbGVzKSB7XG4gICAgICAgIGlmKGV4aXN0c1N5bmMoZmlsZSkgJiYgIWZpbGVFcnJvck1hcC5oYXMoZmlsZSkpIHtcbiAgICAgICAgICBmaWxlRXJyb3JNYXAuc2V0KGZpbGUsIFtdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGZvcihjb25zdCBmaWxlUGF0aCBvZiBmaWxlRXJyb3JNYXAua2V5cygpKSB7XG4gICAgICBpZighZXhpc3RzU3luYyhmaWxlUGF0aCkpIHtcbiAgICAgICAgbG9nKGBGaWxlIG5vdCBmb3VuZDogJHtmaWxlUGF0aH1gLCAnd2FybicsIHF1aWV0KTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGxvZyhgUHJvY2Vzc2luZyBmaWxlOiAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBjb25zdCBpc0N1cnNvcklERSA9IExleENvbmZpZy5jb25maWcuYWk/LnByb3ZpZGVyID09PSAnY3Vyc29yJyB8fCBwcm9jZXNzLmVudi5DVVJTT1JfSURFID09PSAndHJ1ZSc7XG5cbiAgICAgIGlmKGlzQ3Vyc29ySURFKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcHJvbXB0ID0gYEZpeCBhbGwgRVNMaW50IGVycm9ycyBpbiB0aGlzIGZpbGUuIEZvY3VzIG9uOlxuMS4gRml4aW5nIG5hbWluZyBjb252ZW50aW9uc1xuMi4gRml4aW5nIHNvcnQta2V5cyBpc3N1ZXNcbjMuIFJlcGxhY2luZyBjb25zb2xlLmxvZyB3aXRoIGxvZyB1dGlsaXR5XG40LiBGaXhpbmcgbm8tcGx1c3BsdXMgaXNzdWVzXG41LiBGaXhpbmcgdW5uZWNlc3NhcnkgZXNjYXBlIGNoYXJhY3RlcnNcbjYuIEZpeGluZyBvdGhlciBFU0xpbnQgZXJyb3JzXG5cbkNSSVRJQ0FMIFJFUVVJUkVNRU5UUzpcbi0gT05MWSBmaXggdGhlIHNwZWNpZmljIGxpbmVzIHdpdGggRVNMaW50IGVycm9yc1xuLSBETyBOT1QgbW9kaWZ5IGFueSBvdGhlciBsaW5lcyBvZiBjb2RlXG4tIERPIE5PVCByZW1vdmUgbGluZSBicmVha3MgdW5sZXNzIHRoZXkgYXJlIHNwZWNpZmljYWxseSBjYXVzaW5nIEVTTGludCBlcnJvcnNcbi0gRE8gTk9UIGNvbmRlbnNlIG11bHRpLWxpbmUgc3RydWN0dXJlcyB0byBzaW5nbGUgbGluZXNcbi0gUFJFU0VSVkUgYWxsIGV4aXN0aW5nIGxpbmUgYnJlYWtzIGFuZCBmb3JtYXR0aW5nIHRoYXQgaXMgbm90IGNhdXNpbmcgZXJyb3JzXG5cblNQRUNJRklDIEZPUk1BVFRJTkcgUlVMRVM6XG4tIE1haW50YWluIHByb3BlciBpbmRlbnRhdGlvbiAoMiBzcGFjZXMpXG4tIEtlZXAgbGluZSBicmVha3MgYmV0d2VlbiBjbGFzcy9pbnRlcmZhY2UgZGVjbGFyYXRpb24gYW5kIHRoZWlyIG1lbWJlcnNcbi0gS2VlcCBsaW5lIGJyZWFrcyBiZXR3ZWVuIG1ldGhvZHNcbi0gRW5zdXJlIHRoZXJlIGlzIGEgbGluZSBicmVhayBhZnRlciBvcGVuaW5nIGJyYWNlcyBmb3IgY2xhc3NlcywgaW50ZXJmYWNlcywgYW5kIG1ldGhvZHNcbi0gRE8gTk9UIHBsYWNlIGNsYXNzL2ludGVyZmFjZSBwcm9wZXJ0aWVzIG9yIG1ldGhvZHMgb24gdGhlIHNhbWUgbGluZSBhcyB0aGUgb3BlbmluZyBicmFjZVxuLSBQcmVzZXJ2ZSBlbXB0eSBsaW5lcyBiZXR3ZWVuIGxvZ2ljYWwgY29kZSBibG9ja3Ncbi0gUFJFU0VSVkUgbXVsdGktbGluZSBpbXBvcnRzIC0gZG8gbm90IGNvbmRlbnNlIHRoZW0gdG8gc2luZ2xlIGxpbmVzXG4tIFBSRVNFUlZFIG11bHRpLWxpbmUgb2JqZWN0L2FycmF5IGRlY2xhcmF0aW9ucyAtIGRvIG5vdCBjb25kZW5zZSB0aGVtIHRvIHNpbmdsZSBsaW5lc1xuXG5TT1JULUtFWVMgUlVMRSAoSElHSEVTVCBQUklPUklUWSk6XG4tIEFsbCBvYmplY3QgbGl0ZXJhbCBrZXlzIE1VU1QgYmUgc29ydGVkIGFscGhhYmV0aWNhbGx5IGluIGFzY2VuZGluZyBvcmRlclxuLSBUaGlzIGFwcGxpZXMgdG8gQUxMIG9iamVjdHMgaW4gdGhlIGZpbGUsIG5vdCBqdXN0IHRob3NlIHdpdGggZXhwbGljaXQgc29ydC1rZXlzIGVycm9yc1xuLSBFeGFtcGxlOiB7YjogMiwgYTogMSwgYzogM30gc2hvdWxkIGJlY29tZSB7YTogMSwgYjogMiwgYzogM31cbi0gUHJlc2VydmUgdGhlIG9yaWdpbmFsIGZvcm1hdHRpbmcgYW5kIGxpbmUgYnJlYWtzIHdoZW4gc29ydGluZ1xuXG5FeGFtcGxlIG9mIENPUlJFQ1QgZm9ybWF0dGluZyAoRE8gTk9UIENIQU5HRSk6XG5leHBvcnQgY2xhc3MgVXNlckNvbnN0YW50cyB7XG4gIHN0YXRpYyByZWFkb25seSBBRERfSVRFTV9FUlJPUjogc3RyaW5nID0gJ1VTRVJfQUREX0lURU1fRVJST1InO1xuICBzdGF0aWMgcmVhZG9ubHkgT1RIRVJfQ09OU1RBTlQ6IHN0cmluZyA9ICdPVEhFUl9DT05TVEFOVCc7XG59XG5cbmNvbnN0cnVjdG9yKGZsdXg6IEZsdXhGcmFtZXdvcmssIEN1c3RvbUFkYXB0ZXI6IHR5cGVvZiBFdmVudCA9IEV2ZW50KSB7XG4gIHRoaXMuQ3VzdG9tQWRhcHRlciA9IEN1c3RvbUFkYXB0ZXI7XG4gIHRoaXMuZmx1eCA9IGZsdXg7XG59XG5cbmltcG9ydCB7XG4gIGFwcCxcbiAgZXZlbnRzLFxuICBpbWFnZXMsXG4gIGxvY2F0aW9ucyxcbiAgbWVzc2FnZXMsXG4gIHBvc3RzLFxuICB0YWdzLFxuICB1c2VycyxcbiAgd2Vic29ja2V0XG59IGZyb20gJy4vc3RvcmVzJztcblxuY29uc3QgY29uZmlnID0ge1xuICBhcGlLZXk6ICd2YWx1ZScsXG4gIGJhc2VVcmw6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsXG4gIHRpbWVvdXQ6IDUwMDBcbn07XG5cbkV4YW1wbGUgb2YgSU5DT1JSRUNUIGZvcm1hdHRpbmcgKEZJWCBUSElTKTpcbmV4cG9ydCBjbGFzcyBVc2VyQ29uc3RhbnRzIHtzdGF0aWMgcmVhZG9ubHkgQUREX0lURU1fRVJST1I6IHN0cmluZyA9ICdVU0VSX0FERF9JVEVNX0VSUk9SJztcbiAgc3RhdGljIHJlYWRvbmx5IE9USEVSX0NPTlNUQU5UOiBzdHJpbmcgPSAnT1RIRVJfQ09OU1RBTlQnO1xufVxuXG5jb25zdHJ1Y3RvcihmbHV4OiBGbHV4RnJhbWV3b3JrLCBDdXN0b21BZGFwdGVyOiB0eXBlb2YgRXZlbnQgPSBFdmVudCkge3RoaXMuQ3VzdG9tQWRhcHRlciA9IEN1c3RvbUFkYXB0ZXI7XG4gIHRoaXMuZmx1eCA9IGZsdXg7fVxuXG5pbXBvcnQge2FwcCwgZXZlbnRzLCBpbWFnZXMsIGxvY2F0aW9ucywgbWVzc2FnZXMsIHBvc3RzLCB0YWdzLCB1c2Vycywgd2Vic29ja2V0fSBmcm9tICcuL3N0b3Jlcyc7XG5cbmNvbnN0IGNvbmZpZyA9IHtiYXNlVXJsOiAnaHR0cHM6Ly9hcGkuZXhhbXBsZS5jb20nLCBhcGlLZXk6ICd2YWx1ZScsIHRpbWVvdXQ6IDUwMDB9O1xuXG5GaXggT05MWSB0aGUgc3BlY2lmaWMgRVNMaW50IGVycm9ycy4gUmV0dXJuIHRoZSBwcm9wZXJseSBmb3JtYXR0ZWQgY29kZS5gO1xuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHByb21wdEZpbGUgPSBwYXRoUmVzb2x2ZShjd2QsICcuY3Vyc29yX3Byb21wdF90ZW1wLnR4dCcpO1xuICAgICAgICAgICAgd3JpdGVGaWxlU3luYyhwcm9tcHRGaWxlLCBwcm9tcHQsICd1dGY4Jyk7XG5cbiAgICAgICAgICAgIC8vIFVzZSBDdXJzb3IgQ0xJIHRvIGZpeCB0aGUgZmlsZVxuICAgICAgICAgICAgYXdhaXQgZXhlY2EoJ2N1cnNvcicsIFsnZWRpdCcsICctLWZpbGUnLCBmaWxlUGF0aCwgJy0tcHJvbXB0LWZpbGUnLCBwcm9tcHRGaWxlXSwge1xuICAgICAgICAgICAgICByZWplY3Q6IGZhbHNlLFxuICAgICAgICAgICAgICBzdGRpbzogJ3BpcGUnLFxuICAgICAgICAgICAgICBjd2RcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICB1bmxpbmtTeW5jKHByb21wdEZpbGUpO1xuICAgICAgICAgICAgfSBjYXRjaChfZXJyb3IpIHtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbG9nKGBBcHBsaWVkIEN1cnNvciBBSSBmaXhlcyB0byAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgIH0gY2F0Y2goZXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnN0IHdhc01vZGlmaWVkID0gYXdhaXQgYXBwbHlEaXJlY3RGaXhlcyhmaWxlUGF0aCwgcXVpZXQpO1xuICAgICAgICAgICAgaWYod2FzTW9kaWZpZWQpIHtcbiAgICAgICAgICAgICAgbG9nKGBBcHBsaWVkIGRpcmVjdCBmaXhlcyB0byAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgIGxvZyhgRXJyb3IgdXNpbmcgQ3Vyc29yIEFJOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgICAgIGF3YWl0IGFwcGx5RGlyZWN0Rml4ZXMoZmlsZVBhdGgsIHF1aWV0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3Qgd2FzTW9kaWZpZWQgPSBhd2FpdCBhcHBseURpcmVjdEZpeGVzKGZpbGVQYXRoLCBxdWlldCk7XG4gICAgICAgIGlmKHdhc01vZGlmaWVkKSB7XG4gICAgICAgICAgbG9nKGBBcHBsaWVkIGRpcmVjdCBmaXhlcyB0byAke2ZpbGVQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZmlsZUVycm9ycyA9IGZpbGVFcnJvck1hcC5nZXQoZmlsZVBhdGgpIHx8IFtdO1xuICAgICAgICBpZihmaWxlRXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3Qge2NhbGxBSVNlcnZpY2V9ID0gYXdhaXQgaW1wb3J0KCcuLi8uLi91dGlscy9haVNlcnZpY2UuanMnKTtcblxuICAgICAgICAgICAgY29uc3QgZmlsZUNvbnRlbnQgPSByZWFkRmlsZVN5bmMoZmlsZVBhdGgsICd1dGY4Jyk7XG5cbiAgICAgICAgICAgIGNvbnN0IHByb21wdCA9IGBGaXggdGhlIGZvbGxvd2luZyBFU0xpbnQgZXJyb3JzIGluIHRoaXMgY29kZTpcbiR7ZmlsZUVycm9ycy5qb2luKCdcXG4nKX1cblxuSGVyZSdzIHRoZSBjb2RlOlxuXFxgXFxgXFxgXG4ke2ZpbGVDb250ZW50fVxuXFxgXFxgXFxgXG5cbkNSSVRJQ0FMIFJFUVVJUkVNRU5UUzpcbi0gT05MWSBmaXggdGhlIHNwZWNpZmljIGxpbmVzIHdpdGggRVNMaW50IGVycm9yc1xuLSBETyBOT1QgbW9kaWZ5IGFueSBvdGhlciBsaW5lcyBvZiBjb2RlXG4tIERPIE5PVCByZW1vdmUgbGluZSBicmVha3MgdW5sZXNzIHRoZXkgYXJlIHNwZWNpZmljYWxseSBjYXVzaW5nIEVTTGludCBlcnJvcnNcbi0gRE8gTk9UIGNvbmRlbnNlIG11bHRpLWxpbmUgc3RydWN0dXJlcyB0byBzaW5nbGUgbGluZXNcbi0gUFJFU0VSVkUgYWxsIGV4aXN0aW5nIGxpbmUgYnJlYWtzIGFuZCBmb3JtYXR0aW5nIHRoYXQgaXMgbm90IGNhdXNpbmcgZXJyb3JzXG5cblNQRUNJRklDIEZPUk1BVFRJTkcgUlVMRVM6XG4tIE1haW50YWluIHByb3BlciBpbmRlbnRhdGlvbiAoMiBzcGFjZXMpXG4tIEtlZXAgbGluZSBicmVha3MgYmV0d2VlbiBjbGFzcy9pbnRlcmZhY2UgZGVjbGFyYXRpb24gYW5kIHRoZWlyIG1lbWJlcnNcbi0gS2VlcCBsaW5lIGJyZWFrcyBiZXR3ZWVuIG1ldGhvZHNcbi0gRW5zdXJlIHRoZXJlIGlzIGEgbGluZSBicmVhayBhZnRlciBvcGVuaW5nIGJyYWNlcyBmb3IgY2xhc3NlcywgaW50ZXJmYWNlcywgYW5kIG1ldGhvZHNcbi0gRE8gTk9UIHBsYWNlIGNsYXNzL2ludGVyZmFjZSBwcm9wZXJ0aWVzIG9yIG1ldGhvZHMgb24gdGhlIHNhbWUgbGluZSBhcyB0aGUgb3BlbmluZyBicmFjZVxuLSBQcmVzZXJ2ZSBlbXB0eSBsaW5lcyBiZXR3ZWVuIGxvZ2ljYWwgY29kZSBibG9ja3Ncbi0gUFJFU0VSVkUgbXVsdGktbGluZSBpbXBvcnRzIC0gZG8gbm90IGNvbmRlbnNlIHRoZW0gdG8gc2luZ2xlIGxpbmVzXG4tIFBSRVNFUlZFIG11bHRpLWxpbmUgb2JqZWN0L2FycmF5IGRlY2xhcmF0aW9ucyAtIGRvIG5vdCBjb25kZW5zZSB0aGVtIHRvIHNpbmdsZSBsaW5lc1xuXG5TT1JULUtFWVMgUlVMRSAoSElHSEVTVCBQUklPUklUWSk6XG4tIEFsbCBvYmplY3QgbGl0ZXJhbCBrZXlzIE1VU1QgYmUgc29ydGVkIGFscGhhYmV0aWNhbGx5IGluIGFzY2VuZGluZyBvcmRlclxuLSBUaGlzIGFwcGxpZXMgdG8gQUxMIG9iamVjdHMgaW4gdGhlIGZpbGUsIG5vdCBqdXN0IHRob3NlIHdpdGggZXhwbGljaXQgc29ydC1rZXlzIGVycm9yc1xuLSBFeGFtcGxlOiB7YjogMiwgYTogMSwgYzogM30gc2hvdWxkIGJlY29tZSB7YTogMSwgYjogMiwgYzogM31cbi0gUHJlc2VydmUgdGhlIG9yaWdpbmFsIGZvcm1hdHRpbmcgYW5kIGxpbmUgYnJlYWtzIHdoZW4gc29ydGluZ1xuXG5XSEFUIFRPIEZJWDpcbjEuIFNvcnRpbmcgYWxsIG9iamVjdCBrZXlzIGFscGhhYmV0aWNhbGx5IChzb3J0LWtleXMgcnVsZSkgLSBBTEwgb2JqZWN0cyBtdXN0IGhhdmUgc29ydGVkIGtleXNcbjIuIEZpeGluZyBuYW1pbmcgY29udmVudGlvbnMgLSBPTkxZIGZvciB2YXJpYWJsZXMvZnVuY3Rpb25zIHdpdGggbmFtaW5nIGVycm9yc1xuMy4gUmVwbGFjaW5nIGNvbnNvbGUubG9nIHdpdGggbG9nIHV0aWxpdHkgLSBPTkxZIGZvciBjb25zb2xlLmxvZyBzdGF0ZW1lbnRzXG40LiBGaXhpbmcgbm8tcGx1c3BsdXMgaXNzdWVzIC0gT05MWSBmb3IgKysvLS0gb3BlcmF0b3JzXG41LiBGaXhpbmcgdW5uZWNlc3NhcnkgZXNjYXBlIGNoYXJhY3RlcnMgLSBPTkxZIGZvciBlc2NhcGVkIGNoYXJhY3RlcnMgdGhhdCBkb24ndCBuZWVkIGVzY2FwaW5nXG42LiBQcm9wZXIgaW5kZW50YXRpb24gYW5kIHNwYWNpbmcgLSBPTkxZIHdoZXJlIHNwZWNpZmljYWxseSByZXF1aXJlZCBieSBlcnJvcnNcbjcuIFN0cmluZyBxdW90ZXMgY29uc2lzdGVuY3kgKHVzZSBzaW5nbGUgcXVvdGVzKSAtIE9OTFkgZm9yIHN0cmluZyBsaXRlcmFscyB3aXRoIHF1b3RlIGVycm9yc1xuOC4gSW1wb3J0IG9yZGVyIGFuZCBzcGFjaW5nIC0gT05MWSBmb3IgaW1wb3J0cyB3aXRoIG9yZGVyL3NwYWNpbmcgZXJyb3JzXG45LiBGdW5jdGlvbiBwYXJhbWV0ZXIgZm9ybWF0dGluZyAtIE9OTFkgZm9yIGZ1bmN0aW9ucyB3aXRoIHBhcmFtZXRlciBlcnJvcnNcbjEwLiBWYXJpYWJsZSBuYW1pbmcgY29udmVudGlvbnMgLSBPTkxZIGZvciB2YXJpYWJsZXMgd2l0aCBuYW1pbmcgZXJyb3JzXG4xMS4gTm8gdW51c2VkIHZhcmlhYmxlcyBvciBpbXBvcnRzIC0gT05MWSBmb3IgdW51c2VkIHZhcmlhYmxlcy9pbXBvcnRzXG4xMi4gQXZvaWRpbmcgbmVzdGVkIHRlcm5hcmllcyAtIE9OTFkgZm9yIG5lc3RlZCB0ZXJuYXJ5IGV4cHJlc3Npb25zXG4xMy4gQW55IG90aGVyIEVTTGludCBlcnJvcnMgLSBPTkxZIGZvciB0aGUgc3BlY2lmaWMgZXJyb3JzIGxpc3RlZCBhYm92ZVxuXG5XSEFUIE5PVCBUTyBGSVg6XG4tIERvIG5vdCBjaGFuZ2UgcHJvcGVybHkgZm9ybWF0dGVkIG11bHRpLWxpbmUgc3RydWN0dXJlc1xuLSBEbyBub3QgcmVtb3ZlIGxpbmUgYnJlYWtzIHRoYXQgYXJlIG5vdCBjYXVzaW5nIGVycm9yc1xuLSBEbyBub3QgY2hhbmdlIGluZGVudGF0aW9uIHRoYXQgaXMgYWxyZWFkeSBjb3JyZWN0XG4tIERvIG5vdCBtb2RpZnkgc3BhY2luZyB0aGF0IGlzIGFscmVhZHkgY29ycmVjdFxuLSBEbyBub3QgY29uZGVuc2UgcmVhZGFibGUgbXVsdGktbGluZSBjb2RlIHRvIHNpbmdsZSBsaW5lc1xuLSBEbyBub3QgbW9kaWZ5IGNvZGUgdGhhdCBpcyBub3QgbWVudGlvbmVkIGluIHRoZSBFU0xpbnQgZXJyb3JzXG5cbkV4YW1wbGUgb2YgQ09SUkVDVCBmb3JtYXR0aW5nIChETyBOT1QgQ0hBTkdFKTpcbmV4cG9ydCBjbGFzcyBVc2VyQ29uc3RhbnRzIHtcbiAgc3RhdGljIHJlYWRvbmx5IEFERF9JVEVNX0VSUk9SOiBzdHJpbmcgPSAnVVNFUl9BRERfSVRFTV9FUlJPUic7XG4gIHN0YXRpYyByZWFkb25seSBPVEhFUl9DT05TVEFOVDogc3RyaW5nID0gJ09USEVSX0NPTlNUQU5UJztcbn1cblxuY29uc3RydWN0b3IoZmx1eDogRmx1eEZyYW1ld29yaywgQ3VzdG9tQWRhcHRlcjogdHlwZW9mIEV2ZW50ID0gRXZlbnQpIHtcbiAgdGhpcy5DdXN0b21BZGFwdGVyID0gQ3VzdG9tQWRhcHRlcjtcbiAgdGhpcy5mbHV4ID0gZmx1eDtcbn1cblxuaW1wb3J0IHtcbiAgYXBwLFxuICBldmVudHMsXG4gIGltYWdlcyxcbiAgbG9jYXRpb25zLFxuICBtZXNzYWdlcyxcbiAgcG9zdHMsXG4gIHRhZ3MsXG4gIHVzZXJzLFxuICB3ZWJzb2NrZXRcbn0gZnJvbSAnLi9zdG9yZXMnO1xuXG5jb25zdCBjb25maWcgPSB7XG4gIGFwaUtleTogJ3ZhbHVlJyxcbiAgYmFzZVVybDogJ2h0dHBzOi8vYXBpLmV4YW1wbGUuY29tJyxcbiAgdGltZW91dDogNTAwMFxufTtcblxuRXhhbXBsZSBvZiBJTkNPUlJFQ1QgZm9ybWF0dGluZyAoRklYIFRISVMpOlxuZXhwb3J0IGNsYXNzIFVzZXJDb25zdGFudHMge3N0YXRpYyByZWFkb25seSBBRERfSVRFTV9FUlJPUjogc3RyaW5nID0gJ1VTRVJfQUREX0lURU1fRVJST1InO1xuICBzdGF0aWMgcmVhZG9ubHkgT1RIRVJfQ09OU1RBTlQ6IHN0cmluZyA9ICdPVEhFUl9DT05TVEFOVCc7XG59XG5cbmNvbnN0cnVjdG9yKGZsdXg6IEZsdXhGcmFtZXdvcmssIEN1c3RvbUFkYXB0ZXI6IHR5cGVvZiBFdmVudCA9IEV2ZW50KSB7dGhpcy5DdXN0b21BZGFwdGVyID0gQ3VzdG9tQWRhcHRlcjtcbiAgdGhpcy5mbHV4ID0gZmx1eDt9XG5cbmltcG9ydCB7YXBwLCBldmVudHMsIGltYWdlcywgbG9jYXRpb25zLCBtZXNzYWdlcywgcG9zdHMsIHRhZ3MsIHVzZXJzLCB3ZWJzb2NrZXR9IGZyb20gJy4vc3RvcmVzJztcblxuY29uc3QgY29uZmlnID0ge2Jhc2VVcmw6ICdodHRwczovL2FwaS5leGFtcGxlLmNvbScsIGFwaUtleTogJ3ZhbHVlJywgdGltZW91dDogNTAwMH07XG5cbkZpeCBPTkxZIHRoZSBzcGVjaWZpYyBFU0xpbnQgZXJyb3JzIGxpc3RlZCBhYm92ZS4gUmV2aWV3IHRoZSBlbnRpcmUgZmlsZSBmb3IgY29tcGxpYW5jZSB3aXRoIGFsbCBFU0xpbnQgcnVsZXMuXG5SZXR1cm4gb25seSB0aGUgcHJvcGVybHkgZm9ybWF0dGVkIGZpeGVkIGNvZGUgd2l0aG91dCBhbnkgZXhwbGFuYXRpb25zLmA7XG5cbiAgICAgICAgICAgIGNvbnN0IGZpeGVkQ29udGVudCA9IGF3YWl0IGNhbGxBSVNlcnZpY2UocHJvbXB0LCBxdWlldCk7XG5cbiAgICAgICAgICAgIGlmKGZpeGVkQ29udGVudCAmJiBmaXhlZENvbnRlbnQgIT09IGZpbGVDb250ZW50KSB7XG4gICAgICAgICAgICAgIHdyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIGZpeGVkQ29udGVudCwgJ3V0ZjgnKTtcbiAgICAgICAgICAgICAgbG9nKGBBcHBsaWVkIEFJIGZpeGVzIHRvICR7ZmlsZVBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgICAgICAgbG9nKGBFcnJvciBhcHBseWluZyBBSSBmaXhlcyB0byAke2ZpbGVQYXRofTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBzcGlubmVyLnN1Y2NlZWQoJ0FJIGZpeGVzIGFwcGxpZWQgc3VjY2Vzc2Z1bGx5IScpO1xuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gYXBwbHkgQUkgZml4ZXMnKTtcbiAgICBsb2coYEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIGlmKCFxdWlldCkge1xuICAgICAgY29uc29sZS5lcnJvcihlcnJvcik7XG4gICAgfVxuICB9XG59O1xuXG5jb25zdCBhcHBseURpcmVjdEZpeGVzID0gYXN5bmMgKGZpbGVQYXRoOiBzdHJpbmcsIHF1aWV0OiBib29sZWFuKTogUHJvbWlzZTxib29sZWFuPiA9PiB7XG4gIGxldCB3YXNNb2RpZmllZCA9IGZhbHNlO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgZmlsZUNvbnRlbnQgPSByZWFkRmlsZVN5bmMoZmlsZVBhdGgsICd1dGY4Jyk7XG4gICAgbGV0IG5ld0NvbnRlbnQgPSBmaWxlQ29udGVudDtcblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdhaVNlcnZpY2UudHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGFpU2VydmljZS50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvblxcL2pzb24nLFxccyonQXV0aG9yaXphdGlvbic6IGBCZWFyZXIvZyxcbiAgICAgICAgJ1xcJ0F1dGhvcml6YXRpb25cXCc6IGBCZWFyZXJcXCcsIFxcJ0NvbnRlbnQtVHlwZVxcJzogXFwnYXBwbGljYXRpb24vanNvblxcJydcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9oZWFkZXJzOiB7KFtefV0qKX0sXFxzKm1ldGhvZDogJ1BPU1QnL2csXG4gICAgICAgICdtZXRob2Q6IFxcJ1BPU1RcXCcsXFxuICAgICAgaGVhZGVyczogeyQxfSdcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC97cm9sZTogJ3N5c3RlbScsIGNvbnRlbnQ6L2csXG4gICAgICAgICd7Y29udGVudDosIHJvbGU6IFxcJ3N5c3RlbVxcJywnXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL3tyb2xlOiAndXNlcicsIGNvbnRlbnQ6L2csXG4gICAgICAgICd7Y29udGVudDosIHJvbGU6IFxcJ3VzZXJcXCcsJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL1xcKChbXildKj8pXyhbYS16QS1aMC05XSspKFxccyo6W14pXSopXFwpL2csXG4gICAgICAgICcoJDEkMiQzKSdcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoL2NvbnNvbGVcXC5sb2dcXCgvZywgJ2xvZygnKTtcblxuICAgICAgaWYoIW5ld0NvbnRlbnQuaW5jbHVkZXMoJ2ltcG9ydCB7bG9nfScpICYmIG5ld0NvbnRlbnQuaW5jbHVkZXMoJ2xvZygnKSkge1xuICAgICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAgIC9pbXBvcnQgeyhbXn1dKil9IGZyb20gJyguKiknOy8sXG4gICAgICAgICAgJ2ltcG9ydCB7JDF9IGZyb20gXFwnJDJcXCc7XFxuaW1wb3J0IHtsb2d9IGZyb20gXFwnLi9sb2cuanNcXCc7J1xuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdyZWFjdFNoaW0udHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgbmFtaW5nLWNvbnZlbnRpb24gaXNzdWVzIGluIHJlYWN0U2hpbS50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAnaW1wb3J0ICogYXMgUmVhY3QgZnJvbScsXG4gICAgICAgICdpbXBvcnQgKiBhcyByZWFjdCBmcm9tJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvUmVhY3RcXC4vZywgJ3JlYWN0LicpO1xuICAgIH1cblxuICAgIGlmKGZpbGVQYXRoLmluY2x1ZGVzKCdjaGFuZ2Vsb2cudHMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGNoYW5nZWxvZy50cycsICdpbmZvJywgcXVpZXQpO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKC8oXFx3KylcXCtcXCsvZywgJyQxICs9IDEnKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcJC9nLCAnJCcpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcLi9nLCAnLicpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXFxcKi9nLCAnKicpO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvXFxcXDovZywgJzonKTtcbiAgICB9XG5cbiAgICBpZihmaWxlUGF0aC5pbmNsdWRlcygnYXBwLnRzJykpIHtcbiAgICAgIGxvZygnRml4aW5nIGlzc3VlcyBpbiBhcHAudHMnLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZSgvY29uc29sZVxcLmxvZ1xcKC9nLCAnbG9nKCcpO1xuXG4gICAgICBpZighbmV3Q29udGVudC5pbmNsdWRlcygnaW1wb3J0IHtsb2d9JykgJiYgbmV3Q29udGVudC5pbmNsdWRlcygnbG9nKCcpKSB7XG4gICAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgICAgL2ltcG9ydCBib3hlbiBmcm9tICdib3hlbic7LyxcbiAgICAgICAgICAnaW1wb3J0IGJveGVuIGZyb20gXFwnYm94ZW5cXCc7XFxuaW1wb3J0IHtsb2d9IGZyb20gXFwnLi9sb2cuanNcXCc7J1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKC9cXFxcXFwvL2csICcvJyk7XG4gICAgfVxuXG4gICAgaWYoZmlsZVBhdGguaW5jbHVkZXMoJ2F1dG9maXguanMnKSkge1xuICAgICAgbG9nKCdGaXhpbmcgaXNzdWVzIGluIGF1dG9maXguanMnLCAnaW5mbycsIHF1aWV0KTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2ltcG9ydCB7KFtefV0qKX0gZnJvbSAncGF0aCc7W1xcc1xcbl0qaW1wb3J0IHsoW159XSopfSBmcm9tICdwYXRoJzsvLFxuICAgICAgICAnaW1wb3J0IHskMSwgJDJ9IGZyb20gXFwncGF0aFxcJzsnXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvX19maWxlbmFtZS9nLFxuICAgICAgICAnY3VycmVudEZpbGVuYW1lJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9fX2Rpcm5hbWUvZyxcbiAgICAgICAgJ2N1cnJlbnREaXJuYW1lJ1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2NvbnN0IHByZWZpeCA9IHR5cGUgPT09ICdlcnJvcicgXFw/ICdcdTI3NEMgJyA6IHR5cGUgPT09ICdzdWNjZXNzJyBcXD8gJ1x1MjcwNSAnIDogJ1x1MjEzOVx1RkUwRiAnOy8sXG4gICAgICAgICdsZXQgcHJlZml4ID0gXFwnXHUyMTM5XHVGRTBGIFxcJztcXG5pZih0eXBlID09PSBcXCdlcnJvclxcJykge1xcbiAgcHJlZml4ID0gXFwnXHUyNzRDIFxcJztcXG59IGVsc2UgaWYodHlwZSA9PT0gXFwnc3VjY2Vzc1xcJykge1xcbiAgcHJlZml4ID0gXFwnXHUyNzA1IFxcJztcXG59J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIHJ1bkVzbGludEZpeFxcKFxcKS9nLFxuICAgICAgICAnY29uc3QgcnVuRXNsaW50Rml4ID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIGdldEZpbGVzV2l0aEVycm9yc1xcKFxcKS9nLFxuICAgICAgICAnY29uc3QgZ2V0RmlsZXNXaXRoRXJyb3JzID0gYXN5bmMgKCknXG4gICAgICApO1xuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2FzeW5jIGZ1bmN0aW9uIGlzQ3Vyc29yQXZhaWxhYmxlXFwoXFwpL2csXG4gICAgICAgICdjb25zdCBpc0N1cnNvckF2YWlsYWJsZSA9IGFzeW5jICgpJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9hc3luYyBmdW5jdGlvbiBmaXhGaWxlV2l0aEN1cnNvckFJXFwoZmlsZVBhdGhcXCkvZyxcbiAgICAgICAgJ2NvbnN0IGZpeEZpbGVXaXRoQ3Vyc29yQUkgPSBhc3luYyAoZmlsZVBhdGgpJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9hc3luYyBmdW5jdGlvbiBtYWluXFwoXFwpL2csXG4gICAgICAgICdjb25zdCBtYWluID0gYXN5bmMgKCknXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvaW1wb3J0IHtleGlzdHNTeW5jLCByZWFkRmlsZVN5bmMsIHdyaXRlRmlsZVN5bmN9L2csXG4gICAgICAgICdpbXBvcnQge3dyaXRlRmlsZVN5bmN9J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL2NvbnNvbGVcXC5sb2dcXChgXFwke3ByZWZpeH0gXFwke21lc3NhZ2V9YFxcKTsvZyxcbiAgICAgICAgJ3Byb2Nlc3Muc3Rkb3V0LndyaXRlKGAke3ByZWZpeH0gJHttZXNzYWdlfVxcXFxuYCk7J1xuICAgICAgKTtcblxuICAgICAgbmV3Q29udGVudCA9IG5ld0NvbnRlbnQucmVwbGFjZShcbiAgICAgICAgL30gY2F0Y2hcXChlcnJvclxcKSB7W1xcc1xcbl0qXFwvXFwvIElnbm9yZSBjbGVhbnVwIGVycm9ycy9nLFxuICAgICAgICAnfSBjYXRjaChfKSB7XFxuICAgICAgLy8gSWdub3JlIGNsZWFudXAgZXJyb3JzJ1xuICAgICAgKTtcbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC99IGNhdGNoXFwoZXJyb3JcXCkge1tcXHNcXG5dKmxvZ1xcKC9nLFxuICAgICAgICAnfSBjYXRjaChlcnIpIHtcXG4gICAgbG9nKCdcbiAgICAgICk7XG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvfSBjYXRjaFxcKGVycm9yXFwpIHtbXFxzXFxuXSpyZXR1cm4gZmFsc2U7L2csXG4gICAgICAgICd9IGNhdGNoKF8pIHtcXG4gICAgcmV0dXJuIGZhbHNlOydcbiAgICAgICk7XG5cbiAgICAgIG5ld0NvbnRlbnQgPSBuZXdDb250ZW50LnJlcGxhY2UoXG4gICAgICAgIC9mb3JcXChjb25zdCBmaWxlUGF0aCBvZiBmaWxlc1dpdGhFcnJvcnNcXCkge1tcXHNcXG5dKmNvbnN0IHN1Y2Nlc3MgPSBhd2FpdCBmaXhGaWxlV2l0aEN1cnNvckFJXFwoZmlsZVBhdGhcXCk7L2csXG4gICAgICAgICdjb25zdCBmaXhSZXN1bHRzID0gYXdhaXQgUHJvbWlzZS5hbGwoZmlsZXNXaXRoRXJyb3JzLm1hcChmaWxlUGF0aCA9PiBmaXhGaWxlV2l0aEN1cnNvckFJKGZpbGVQYXRoKSkpO1xcbmZvcihjb25zdCBzdWNjZXNzIG9mIGZpeFJlc3VsdHMpIHsnXG4gICAgICApO1xuXG4gICAgICBuZXdDb250ZW50ID0gbmV3Q29udGVudC5yZXBsYWNlKFxuICAgICAgICAvZml4ZWRDb3VudFxcK1xcKzsvZyxcbiAgICAgICAgJ2ZpeGVkQ291bnQgKz0gMTsnXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmKG5ld0NvbnRlbnQgIT09IGZpbGVDb250ZW50KSB7XG4gICAgICB3cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCBuZXdDb250ZW50LCAndXRmOCcpO1xuICAgICAgbG9nKGBGaXhlZCBpc3N1ZXMgaW4gJHtmaWxlUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIHdhc01vZGlmaWVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gd2FzTW9kaWZpZWQ7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICBsb2coYEVycm9yIGFwcGx5aW5nIGRpcmVjdCBmaXhlcyB0byAke2ZpbGVQYXRofTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmNvbnN0IGxvYWRBSUNvbmZpZyA9IGFzeW5jIChjd2Q6IHN0cmluZywgcXVpZXQ6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgY29uc3QgY29uZmlnRm9ybWF0cyA9IFsnanMnLCAnbWpzJywgJ2NqcycsICd0cycsICdqc29uJ107XG4gIGNvbnN0IGNvbmZpZ0Jhc2VOYW1lID0gJ2xleC5jb25maWcnO1xuICBsZXQgbGV4Q29uZmlnUGF0aCA9ICcnO1xuXG4gIGZvcihjb25zdCBmb3JtYXQgb2YgY29uZmlnRm9ybWF0cykge1xuICAgIGNvbnN0IHBvdGVudGlhbFBhdGggPSBwYXRoUmVzb2x2ZShjd2QsIGAuLyR7Y29uZmlnQmFzZU5hbWV9LiR7Zm9ybWF0fWApO1xuICAgIGlmKGV4aXN0c1N5bmMocG90ZW50aWFsUGF0aCkpIHtcbiAgICAgIGxleENvbmZpZ1BhdGggPSBwb3RlbnRpYWxQYXRoO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgaWYobGV4Q29uZmlnUGF0aCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBsZXhDb25maWcgPSBhd2FpdCBpbXBvcnQobGV4Q29uZmlnUGF0aCk7XG4gICAgICBpZihsZXhDb25maWcuZGVmYXVsdCAmJiBsZXhDb25maWcuZGVmYXVsdC5haSkge1xuICAgICAgICBsb2coYEZvdW5kIEFJIGNvbmZpZ3VyYXRpb24gaW4gJHtwYXRoUmVzb2x2ZShjd2QsIGxleENvbmZpZ1BhdGgpfSwgYXBwbHlpbmcgc2V0dGluZ3MuLi5gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgTGV4Q29uZmlnLmNvbmZpZy5haSA9IHsuLi5MZXhDb25maWcuY29uZmlnLmFpLCAuLi5sZXhDb25maWcuZGVmYXVsdC5haX07XG4gICAgICB9XG4gICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgbG9nKGBFcnJvciBsb2FkaW5nIEFJIGNvbmZpZ3VyYXRpb24gZnJvbSAke2xleENvbmZpZ1BhdGh9OiAke2Vycm9yLm1lc3NhZ2V9YCwgJ3dhcm4nLCBxdWlldCk7XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgY29uc3QgbGludCA9IGFzeW5jIChjbWQ6IExpbnRPcHRpb25zLCBjYWxsYmFjazogTGludENhbGxiYWNrID0gcHJvY2Vzcy5leGl0KTogUHJvbWlzZTxudW1iZXI+ID0+IHtcbiAgY29uc3Qge1xuICAgIGNsaU5hbWUgPSAnTGV4JyxcbiAgICBmaXggPSBmYWxzZSxcbiAgICBkZWJ1ZyA9IGZhbHNlLFxuICAgIHF1aWV0ID0gZmFsc2UsXG4gICAgY29uZmlnID0gbnVsbFxuICB9ID0gY21kO1xuXG4gIGxvZyhgJHtjbGlOYW1lfSBsaW50aW5nLi4uYCwgJ2luZm8nLCBxdWlldCk7XG5cbiAgY29uc3QgY3dkID0gcHJvY2Vzcy5jd2QoKTtcbiAgY29uc3Qgc3Bpbm5lciA9IGNyZWF0ZVNwaW5uZXIocXVpZXQpO1xuXG4gIGF3YWl0IGxvYWRBSUNvbmZpZyhjd2QsIHF1aWV0KTtcblxuICBsZXQgb3JpZ2luYWxDb25maWc6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBsZXQgdGVtcENvbmZpZ1BhdGg6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgdXNlVHlwZXNjcmlwdCA9IGRldGVjdFR5cGVTY3JpcHQoY3dkKTtcbiAgICBsb2coYFR5cGVTY3JpcHQgJHt1c2VUeXBlc2NyaXB0ID8gJ2RldGVjdGVkJyA6ICdub3QgZGV0ZWN0ZWQnfSBmcm9tIHRzY29uZmlnLmpzb25gLCAnaW5mbycsIHF1aWV0KTtcblxuICAgIGlmKHVzZVR5cGVzY3JpcHQpIHtcbiAgICAgIExleENvbmZpZy5jaGVja0xpbnRUeXBlc2NyaXB0Q29uZmlnKCk7XG4gICAgfVxuXG4gICAgZW5zdXJlTW9kdWxlVHlwZShjd2QpO1xuXG4gICAgYXdhaXQgaW5zdGFsbERlcGVuZGVuY2llcyhjd2QsIHVzZVR5cGVzY3JpcHQsIHF1aWV0KTtcblxuICAgIGNvbnN0IHByb2plY3RDb25maWdQYXRoID0gcGF0aFJlc29sdmUoY3dkLCAnZXNsaW50LmNvbmZpZy5qcycpO1xuICAgIGNvbnN0IHByb2plY3RDb25maWdQYXRoVHMgPSBwYXRoUmVzb2x2ZShjd2QsICdlc2xpbnQuY29uZmlnLnRzJyk7XG4gICAgY29uc3QgaGFzRXNsaW50Q29uZmlnID0gZXhpc3RzU3luYyhwcm9qZWN0Q29uZmlnUGF0aCkgfHxcbiAgICAgIGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGhUcykgfHxcbiAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLmpzJykpIHx8XG4gICAgICBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYy5qc29uJykpIHx8XG4gICAgICBleGlzdHNTeW5jKHBhdGhSZXNvbHZlKGN3ZCwgJy5lc2xpbnRyYy55bWwnKSkgfHxcbiAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjLnlhbWwnKSkgfHxcbiAgICAgIGV4aXN0c1N5bmMocGF0aFJlc29sdmUoY3dkLCAnLmVzbGludHJjJykpO1xuXG4gICAgaWYoZXhpc3RzU3luYyhwYXRoUmVzb2x2ZShjd2QsICcuZXNsaW50cmMuanNvbicpKSkge1xuICAgICAgdW5saW5rU3luYyhwYXRoUmVzb2x2ZShjd2QsICcuZXNsaW50cmMuanNvbicpKTtcbiAgICB9XG5cbiAgICBsZXQgbGV4Q29uZmlnUGF0aCA9ICcnO1xuICAgIGxldCBzaG91bGRDcmVhdGVUZW1wQ29uZmlnID0gZmFsc2U7XG5cbiAgICBpZighaGFzRXNsaW50Q29uZmlnKSB7XG4gICAgICBjb25zdCBwb3NzaWJsZVBhdGhzID0gW1xuICAgICAgICBwYXRoUmVzb2x2ZShjdXJyZW50RGlybmFtZSwgJy4uLy4uLy4uLy4uL2VzbGludC5jb25maWcudHMnKSxcbiAgICAgICAgcGF0aFJlc29sdmUocHJvY2Vzcy5lbnYuTEVYX0hPTUUgfHwgJy91c3IvbG9jYWwvbGliL25vZGVfbW9kdWxlcy9AbmxhYnMvbGV4JywgJ2VzbGludC5jb25maWcudHMnKVxuICAgICAgXTtcblxuICAgICAgZm9yKGNvbnN0IHBhdGggb2YgcG9zc2libGVQYXRocykge1xuICAgICAgICBpZihleGlzdHNTeW5jKHBhdGgpKSB7XG4gICAgICAgICAgbGV4Q29uZmlnUGF0aCA9IHBhdGg7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgbG9nKGBDdXJyZW50IGRpcmVjdG9yeTogJHtjdXJyZW50RGlybmFtZX1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgbG9nKGBQcm9qZWN0IGNvbmZpZyBwYXRoOiAke3Byb2plY3RDb25maWdQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBsb2coYFByb2plY3QgY29uZmlnIGV4aXN0czogJHtoYXNFc2xpbnRDb25maWd9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIGxvZyhgRm91bmQgTGV4IGNvbmZpZzogJHtsZXhDb25maWdQYXRofWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgICBsb2coYExleCBjb25maWcgZXhpc3RzOiAkeyEhbGV4Q29uZmlnUGF0aCAmJiBleGlzdHNTeW5jKGxleENvbmZpZ1BhdGgpfWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfVxuXG4gICAgICBpZihsZXhDb25maWdQYXRoICYmIGV4aXN0c1N5bmMobGV4Q29uZmlnUGF0aCkpIHtcbiAgICAgICAgbG9nKCdObyBFU0xpbnQgY29uZmlndXJhdGlvbiBmb3VuZCBpbiBwcm9qZWN0LiBVc2luZyBMZXhcXCdzIGRlZmF1bHQgY29uZmlndXJhdGlvbi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNob3VsZENyZWF0ZVRlbXBDb25maWcgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGNvbmZpZykge1xuICAgICAgY29uc3QgdXNlckNvbmZpZ1BhdGggPSBwYXRoUmVzb2x2ZShjd2QsIGNvbmZpZyk7XG4gICAgICBpZihleGlzdHNTeW5jKHVzZXJDb25maWdQYXRoKSkge1xuICAgICAgICBsb2coYFVzaW5nIHNwZWNpZmllZCBFU0xpbnQgY29uZmlndXJhdGlvbjogJHtjb25maWd9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIHNob3VsZENyZWF0ZVRlbXBDb25maWcgPSBmYWxzZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZyhgU3BlY2lmaWVkIEVTTGludCBjb25maWd1cmF0aW9uIG5vdCBmb3VuZDogJHtjb25maWd9LiBVc2luZyBMZXgncyBkZWZhdWx0IGNvbmZpZ3VyYXRpb24uYCwgJ3dhcm4nLCBxdWlldCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYoc2hvdWxkQ3JlYXRlVGVtcENvbmZpZykge1xuICAgICAgbG9nKCdObyBFU0xpbnQgY29uZmlndXJhdGlvbiBmb3VuZC4gQ3JlYXRpbmcgYSB0ZW1wb3JhcnkgY29uZmlndXJhdGlvbi4uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgY29uc3QgY29uZmlnUmVzdWx0ID0gY3JlYXRlRGVmYXVsdEVTTGludENvbmZpZyh1c2VUeXBlc2NyaXB0LCBjd2QpO1xuICAgICAgdGVtcENvbmZpZ1BhdGggPSBjb25maWdSZXN1bHQuY29uZmlnUGF0aDtcbiAgICAgIG9yaWdpbmFsQ29uZmlnID0gY29uZmlnUmVzdWx0Lm9yaWdpbmFsQ29uZmlnO1xuICAgIH1cblxuICAgIGxldCBlc2xpbnRPdXRwdXQgPSAnJztcbiAgICBjb25zdCBjYXB0dXJlT3V0cHV0ID0gKG91dHB1dDogc3RyaW5nKSA9PiB7XG4gICAgICBlc2xpbnRPdXRwdXQgKz0gYCR7b3V0cHV0fVxcbmA7XG4gICAgfTtcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHJ1bkVzbGludFdpdGhMZXgoY3dkLCBxdWlldCwgY2xpTmFtZSwgdHJ1ZSwgZGVidWcsIHVzZVR5cGVzY3JpcHQsIGNhcHR1cmVPdXRwdXQpO1xuXG4gICAgaWYocmVzdWx0ICE9PSAwICYmIGZpeCkge1xuICAgICAgY29uc3QgYWlDb25maWd1cmVkID0gTGV4Q29uZmlnLmNvbmZpZy5haT8ucHJvdmlkZXIgJiYgTGV4Q29uZmlnLmNvbmZpZy5haS5wcm92aWRlciAhPT0gJ25vbmUnO1xuXG4gICAgICBpZihhaUNvbmZpZ3VyZWQpIHtcbiAgICAgICAgbG9nKCdBcHBseWluZyBBSSBmaXhlcyB0byByZW1haW5pbmcgaXNzdWVzLi4uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIGF3YWl0IGFwcGx5QUlGaXgoY3dkLCBlc2xpbnRPdXRwdXQsIHF1aWV0KTtcblxuICAgICAgICBjb25zdCBhZnRlckZpeFJlc3VsdCA9IGF3YWl0IHJ1bkVzbGludFdpdGhMZXgoY3dkLCBxdWlldCwgY2xpTmFtZSwgZmFsc2UsIGRlYnVnLCB1c2VUeXBlc2NyaXB0KTtcblxuICAgICAgICBjYWxsYmFjayhhZnRlckZpeFJlc3VsdCk7XG4gICAgICAgIHJldHVybiBhZnRlckZpeFJlc3VsdDtcbiAgICAgIH1cbiAgICAgIGxvZygnRVNMaW50IGNvdWxkIG5vdCBmaXggYWxsIGlzc3VlcyBhdXRvbWF0aWNhbGx5LicsICd3YXJuJywgcXVpZXQpO1xuICAgICAgbG9nKCdUbyBlbmFibGUgQUktcG93ZXJlZCBmaXhlcywgYWRkIEFJIGNvbmZpZ3VyYXRpb24gdG8geW91ciBsZXguY29uZmlnIGZpbGU6JywgJ2luZm8nLCBxdWlldCk7XG4gICAgICBsb2coYFxuLy8gSW4gbGV4LmNvbmZpZy5qcyAob3IgbGV4LmNvbmZpZy5tanMsIGxleC5jb25maWcuY2pzLCBldGMuKVxuZXhwb3J0IGRlZmF1bHQge1xuICAvLyBZb3VyIGV4aXN0aW5nIGNvbmZpZ1xuICBhaToge1xuICAgIHByb3ZpZGVyOiAnY3Vyc29yJyAvLyBvciAnb3BlbmFpJywgJ2FudGhyb3BpYycsIGV0Yy5cbiAgICAvLyBBZGRpdGlvbmFsIHByb3ZpZGVyLXNwZWNpZmljIHNldHRpbmdzXG4gIH1cbn07YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgfVxuXG4gICAgY2FsbGJhY2socmVzdWx0KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIGlmKHNwaW5uZXIpIHtcbiAgICAgIHNwaW5uZXIuZmFpbCgnTGludGluZyBmYWlsZWQhJyk7XG4gICAgfVxuICAgIGNhbGxiYWNrKDEpO1xuICAgIHJldHVybiAxO1xuICB9IGZpbmFsbHkge1xuICAgIGlmKHRlbXBDb25maWdQYXRoICYmIG9yaWdpbmFsQ29uZmlnKSB7XG4gICAgICB0cnkge1xuICAgICAgICB3cml0ZUZpbGVTeW5jKHRlbXBDb25maWdQYXRoLCBvcmlnaW5hbENvbmZpZywgJ3V0ZjgnKTtcbiAgICAgIH0gY2F0Y2goX2Vycm9yKSB7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmKHRlbXBDb25maWdQYXRoKSB7XG4gICAgICB0cnkge1xuICAgICAgICB1bmxpbmtTeW5jKHRlbXBDb25maWdQYXRoKTtcbiAgICAgIH0gY2F0Y2go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