@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.
- package/.storybook/main.ts +9 -2
- package/.vscode/settings.json +1 -6
- package/README.md +276 -4
- package/eslint.config.mjs +24 -0
- package/examples/lex.config.js +18 -8
- package/examples/serverless-example/README.md +109 -0
- package/examples/serverless-example/dist/handlers/echo.js +15 -0
- package/examples/serverless-example/dist/handlers/graphql.js +137 -0
- package/examples/serverless-example/dist/handlers/hello.js +15 -0
- package/examples/serverless-example/dist/handlers/test.js +17 -0
- package/examples/serverless-example/dist/handlers/websocket.js +14 -0
- package/examples/serverless-example/lex.config.mjs +74 -0
- package/jest.config.mjs +13 -12
- package/{dist → lib}/LexConfig.d.ts +14 -6
- package/lib/LexConfig.js +268 -0
- package/lib/commands/ai/ai.js +303 -0
- package/{dist → lib}/commands/build/build.d.ts +3 -0
- package/lib/commands/build/build.js +494 -0
- package/{dist → lib}/commands/clean/clean.js +1 -1
- package/lib/commands/compile/compile.js +241 -0
- package/lib/commands/copy/copy.js +38 -0
- package/{dist → lib}/commands/create/create.js +1 -1
- package/{dist → lib}/commands/dev/dev.d.ts +2 -0
- package/lib/commands/dev/dev.js +286 -0
- package/{dist → lib}/commands/init/init.js +1 -1
- package/{dist → lib}/commands/lint/lint.d.ts +4 -1
- package/lib/commands/lint/lint.js +993 -0
- package/{dist → lib}/commands/migrate/migrate.js +1 -1
- package/lib/commands/publish/publish.js +104 -0
- package/lib/commands/serverless/serverless.d.ts +17 -0
- package/lib/commands/serverless/serverless.js +662 -0
- package/lib/commands/storybook/storybook.js +249 -0
- package/lib/commands/test/test.js +428 -0
- package/lib/commands/update/update.js +128 -0
- package/lib/commands/versions/versions.js +41 -0
- package/{dist → lib}/create/changelog.js +1 -1
- package/{dist → lib}/index.d.ts +2 -0
- package/{dist → lib}/index.js +3 -1
- package/lib/lex.js +73 -0
- package/lib/storybook/index.d.ts +5 -0
- package/lib/types.js +1 -0
- package/lib/utils/aiService.d.ts +9 -0
- package/lib/utils/aiService.js +299 -0
- package/{dist → lib}/utils/app.d.ts +3 -0
- package/lib/utils/app.js +296 -0
- package/lib/utils/deepMerge.js +26 -0
- package/{dist → lib}/utils/file.d.ts +7 -3
- package/lib/utils/file.js +229 -0
- package/lib/utils/translations.d.ts +1 -0
- package/lib/utils/translations.js +74 -0
- package/package.json +62 -50
- package/postcss.config.js +5 -3
- package/tsconfig.build.json +2 -2
- package/webpack.config.js +229 -39
- package/dist/LexConfig.js +0 -286
- package/dist/commands/ai/ai.js +0 -303
- package/dist/commands/build/build.js +0 -404
- package/dist/commands/compile/compile.js +0 -234
- package/dist/commands/copy/copy.js +0 -38
- package/dist/commands/dev/dev.js +0 -74
- package/dist/commands/lint/lint.js +0 -811
- package/dist/commands/publish/publish.js +0 -104
- package/dist/commands/storybook/storybook.js +0 -249
- package/dist/commands/test/test.js +0 -429
- package/dist/commands/update/update.js +0 -132
- package/dist/commands/versions/versions.js +0 -41
- package/dist/lex.js +0 -70
- package/dist/utils/aiService.d.ts +0 -9
- package/dist/utils/aiService.js +0 -299
- package/dist/utils/app.js +0 -267
- package/dist/utils/deepMerge.js +0 -24
- package/dist/utils/file.js +0 -185
- package/emptyModule.js +0 -0
- package/eslint.config.js +0 -7
- /package/{dist → lib}/Button.stories.d.ts +0 -0
- /package/{dist → lib}/commands/ai/ai.d.ts +0 -0
- /package/{dist → lib}/commands/ai/index.d.ts +0 -0
- /package/{dist → lib}/commands/ai/index.js +0 -0
- /package/{dist → lib}/commands/clean/clean.d.ts +0 -0
- /package/{dist → lib}/commands/compile/compile.d.ts +0 -0
- /package/{dist → lib}/commands/config/config.d.ts +0 -0
- /package/{dist → lib}/commands/config/config.js +0 -0
- /package/{dist → lib}/commands/copy/copy.d.ts +0 -0
- /package/{dist → lib}/commands/create/create.d.ts +0 -0
- /package/{dist → lib}/commands/init/init.d.ts +0 -0
- /package/{dist → lib}/commands/link/link.d.ts +0 -0
- /package/{dist → lib}/commands/link/link.js +0 -0
- /package/{dist → lib}/commands/lint/autofix.d.ts +0 -0
- /package/{dist → lib}/commands/migrate/migrate.d.ts +0 -0
- /package/{dist → lib}/commands/publish/publish.d.ts +0 -0
- /package/{dist → lib}/commands/storybook/storybook.d.ts +0 -0
- /package/{dist → lib}/commands/test/test.d.ts +0 -0
- /package/{dist → lib}/commands/update/update.d.ts +0 -0
- /package/{dist → lib}/commands/upgrade/upgrade.d.ts +0 -0
- /package/{dist → lib}/commands/upgrade/upgrade.js +0 -0
- /package/{dist → lib}/commands/versions/versions.d.ts +0 -0
- /package/{dist → lib}/create/changelog.d.ts +0 -0
- /package/{dist → lib}/lex.d.ts +0 -0
- /package/{dist/types.js → lib/storybook/index.js} +0 -0
- /package/{dist → lib}/test-react/index.d.ts +0 -0
- /package/{dist → lib}/test-react/index.js +0 -0
- /package/{dist → lib}/types.d.ts +0 -0
- /package/{dist → lib}/utils/deepMerge.d.ts +0 -0
- /package/{dist → lib}/utils/log.d.ts +0 -0
- /package/{dist → lib}/utils/log.js +0 -0
- /package/{dist → lib}/utils/reactShim.d.ts +0 -0
- /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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
|