@nlabs/lex 1.48.7 → 1.49.1
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 +249 -0
- 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 +7 -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/lib/commands/lint/lint.js +962 -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/{dist → lib}/create/changelog.js +1 -1
- package/{dist → lib}/index.d.ts +1 -0
- package/{dist → lib}/index.js +2 -1
- package/lib/lex.js +73 -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/{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 +60 -54
- package/postcss.config.js +5 -3
- package/tsconfig.build.json +2 -2
- package/webpack.config.js +229 -39
- package/dist/LexConfig.js +0 -287
- 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 -993
- 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/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/file.js +0 -185
- package/emptyModule.js +0 -0
- package/eslint.config.js +0 -3
- /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/lint/lint.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}/commands/versions/versions.js +0 -0
- /package/{dist → lib}/create/changelog.d.ts +0 -0
- /package/{dist → lib}/lex.d.ts +0 -0
- /package/{dist → lib}/storybook/index.d.ts +0 -0
- /package/{dist → 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}/types.js +0 -0
- /package/{dist → lib}/utils/deepMerge.d.ts +0 -0
- /package/{dist → lib}/utils/deepMerge.js +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
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { execa } from "execa";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { sync as globSync } from "glob";
|
|
5
|
+
import { resolve as pathResolve } from "path";
|
|
6
|
+
import { LexConfig } from "../../LexConfig.js";
|
|
7
|
+
import { createSpinner } from "../../utils/app.js";
|
|
8
|
+
import { findTailwindCssPath, resolveBinaryPath } from "../../utils/file.js";
|
|
9
|
+
import { log } from "../../utils/log.js";
|
|
10
|
+
const findStoryFiles = () => {
|
|
11
|
+
const storyPatterns = [
|
|
12
|
+
"**/*.stories.{ts,tsx,js,jsx}",
|
|
13
|
+
"**/*.story.{ts,tsx,js,jsx}",
|
|
14
|
+
"**/stories/**/*.{ts,tsx,js,jsx}"
|
|
15
|
+
];
|
|
16
|
+
const storyFiles = [];
|
|
17
|
+
storyPatterns.forEach((pattern) => {
|
|
18
|
+
const files = globSync(pattern, {
|
|
19
|
+
cwd: process.cwd(),
|
|
20
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**"]
|
|
21
|
+
});
|
|
22
|
+
storyFiles.push(...files);
|
|
23
|
+
});
|
|
24
|
+
return storyFiles;
|
|
25
|
+
};
|
|
26
|
+
const checkStorybookInitialization = () => {
|
|
27
|
+
const projectConfigDir = pathResolve(process.cwd(), ".storybook");
|
|
28
|
+
const lexConfigDir = pathResolve(LexConfig.getLexDir(), ".storybook");
|
|
29
|
+
return existsSync(projectConfigDir) || existsSync(lexConfigDir);
|
|
30
|
+
};
|
|
31
|
+
const extractProgressPercentage = (output) => {
|
|
32
|
+
const lines = output.split("\n");
|
|
33
|
+
for (const line of lines) {
|
|
34
|
+
if (line.includes("[webpack.Progress]") && line.includes("%")) {
|
|
35
|
+
const percentageMatch = line.match(/(\d+)%/);
|
|
36
|
+
if (percentageMatch) {
|
|
37
|
+
return parseInt(percentageMatch[1]);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
};
|
|
43
|
+
const filterAndBeautifyOutput = (output, isVerbose) => {
|
|
44
|
+
if (isVerbose) {
|
|
45
|
+
return output;
|
|
46
|
+
}
|
|
47
|
+
const lines = output.split("\n");
|
|
48
|
+
const filteredLines = lines.filter((line) => {
|
|
49
|
+
if (line.includes("[webpack.Progress]")) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
if (line.includes("Storybook") || line.includes("Local:") || line.includes("http://localhost") || line.includes("info =>") || line.includes("Starting") || line.includes("ready") || line.includes("error") || line.includes("warning")) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
return filteredLines.join("\n");
|
|
58
|
+
};
|
|
59
|
+
const beautifyOutput = (output) => output.replace(/Storybook v[\d.]+/g, chalk.cyan("$&")).replace(/info =>/g, chalk.blue("info =>")).replace(/Local:/g, chalk.green("Local:")).replace(/On your network:/g, chalk.green("On your network:")).replace(/Storybook.*started/g, chalk.green("$&")).replace(/Storybook.*ready/g, chalk.green("$&")).replace(/error/g, chalk.red("$&")).replace(/warning/g, chalk.yellow("$&")).replace(/(\d+)%/g, chalk.magenta("$1%"));
|
|
60
|
+
const storybook = async (cmd, callback = () => ({})) => {
|
|
61
|
+
const { cliName = "Lex", config, open = false, port = 6007, quiet, static: staticBuild = false, useLexConfig = false, variables, verbose = false } = cmd;
|
|
62
|
+
const spinner = createSpinner(quiet);
|
|
63
|
+
log(chalk.cyan(`${cliName} starting Storybook...`), "info", quiet);
|
|
64
|
+
await LexConfig.parseConfig(cmd);
|
|
65
|
+
let variablesObj = { NODE_ENV: "development" };
|
|
66
|
+
if (variables) {
|
|
67
|
+
try {
|
|
68
|
+
variablesObj = JSON.parse(variables);
|
|
69
|
+
} catch (_error) {
|
|
70
|
+
log(`
|
|
71
|
+
${cliName} Error: Environment variables option is not a valid JSON object.`, "error", quiet);
|
|
72
|
+
callback(1);
|
|
73
|
+
return 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
process.env = { ...process.env, ...variablesObj };
|
|
77
|
+
spinner.start("Finding story files...");
|
|
78
|
+
const storyFiles = findStoryFiles();
|
|
79
|
+
if (storyFiles.length === 0) {
|
|
80
|
+
spinner.fail("No story files found in the project.");
|
|
81
|
+
log("Please create story files with .stories.ts/.stories.js extensions or in a stories/ directory.", "info", quiet);
|
|
82
|
+
callback(1);
|
|
83
|
+
return 1;
|
|
84
|
+
}
|
|
85
|
+
spinner.succeed(`Found ${storyFiles.length} story file(s)`);
|
|
86
|
+
const tailwindCssPath = findTailwindCssPath();
|
|
87
|
+
console.log({ tailwindCssPath });
|
|
88
|
+
if (tailwindCssPath) {
|
|
89
|
+
if (!quiet) {
|
|
90
|
+
log(chalk.green(`\u2713 Tailwind CSS integration detected: ${tailwindCssPath}`), "info", quiet);
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
if (!quiet) {
|
|
94
|
+
log(chalk.yellow("\u26A0 No Tailwind CSS file found in project"), "info", quiet);
|
|
95
|
+
log(chalk.gray("Create a tailwind.css file with @tailwind directives for full Tailwind support"), "info", quiet);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!checkStorybookInitialization()) {
|
|
99
|
+
spinner.fail("Storybook is not initialized in this project or in Lex.");
|
|
100
|
+
log('Please run "npx storybook@latest init" to set up Storybook in your project, or ensure Lex has a valid .storybook configuration.', "info", quiet);
|
|
101
|
+
callback(1);
|
|
102
|
+
return 1;
|
|
103
|
+
}
|
|
104
|
+
const projectConfigDir = pathResolve(process.cwd(), ".storybook");
|
|
105
|
+
const lexConfigDir = pathResolve(LexConfig.getLexDir(), ".storybook");
|
|
106
|
+
let configDir = config;
|
|
107
|
+
if (!configDir) {
|
|
108
|
+
configDir = lexConfigDir;
|
|
109
|
+
if (!useLexConfig && existsSync(projectConfigDir)) {
|
|
110
|
+
configDir = projectConfigDir;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (!quiet) {
|
|
114
|
+
log(chalk.gray(`Project config dir: ${projectConfigDir} (exists: ${existsSync(projectConfigDir)})`), "info", quiet);
|
|
115
|
+
log(chalk.gray(`Lex config dir: ${lexConfigDir} (exists: ${existsSync(lexConfigDir)})`), "info", quiet);
|
|
116
|
+
if (useLexConfig) {
|
|
117
|
+
log(chalk.blue("Using Lex Storybook configuration (--use-lex-config flag)"), "info", quiet);
|
|
118
|
+
}
|
|
119
|
+
log(chalk.gray(`Initial config dir: ${configDir}`), "info", quiet);
|
|
120
|
+
}
|
|
121
|
+
if (configDir === lexConfigDir) {
|
|
122
|
+
if (!quiet) {
|
|
123
|
+
log(chalk.blue("Using Lex config, will create temporary config in project .storybook directory"), "info", quiet);
|
|
124
|
+
}
|
|
125
|
+
const projectStorybookDir = pathResolve(process.cwd(), ".storybook");
|
|
126
|
+
const fs = await import("fs/promises");
|
|
127
|
+
await fs.mkdir(projectStorybookDir, { recursive: true });
|
|
128
|
+
const lexMainPath = pathResolve(lexConfigDir, "main.ts");
|
|
129
|
+
const projectMainPath = pathResolve(projectStorybookDir, "main.ts");
|
|
130
|
+
let mainContent = await fs.readFile(lexMainPath, "utf8");
|
|
131
|
+
mainContent = mainContent.replace(
|
|
132
|
+
/stories:\s*\[.*?\]/,
|
|
133
|
+
`stories: ['${pathResolve(process.cwd(), "src/**/*.stories.@(ts|tsx)")}', '${pathResolve(process.cwd(), "src/**/*.mdx")}']`
|
|
134
|
+
);
|
|
135
|
+
const lexNodeModules = pathResolve(LexConfig.getLexDir(), "node_modules");
|
|
136
|
+
mainContent = mainContent.replace(
|
|
137
|
+
/const lexModule = \(modulePath: string\) => resolve\(getLexNodeModulesPath\(\), modulePath\);/,
|
|
138
|
+
`const lexModule = (modulePath: string) => resolve('${lexNodeModules}', modulePath);`
|
|
139
|
+
);
|
|
140
|
+
await fs.writeFile(projectMainPath, mainContent);
|
|
141
|
+
const lexPreviewPath = pathResolve(lexConfigDir, "preview.tsx");
|
|
142
|
+
if (existsSync(lexPreviewPath)) {
|
|
143
|
+
const previewContent = await fs.readFile(lexPreviewPath, "utf8");
|
|
144
|
+
await fs.writeFile(pathResolve(projectStorybookDir, "preview.tsx"), previewContent);
|
|
145
|
+
}
|
|
146
|
+
configDir = projectStorybookDir;
|
|
147
|
+
}
|
|
148
|
+
if (!existsSync(configDir)) {
|
|
149
|
+
spinner.fail("Storybook configuration not found.");
|
|
150
|
+
log(`Project config: ${projectConfigDir}`, "info", quiet);
|
|
151
|
+
log(`Lex config: ${lexConfigDir}`, "info", quiet);
|
|
152
|
+
log('Please run "npx storybook@latest init" to set up Storybook in your project, or ensure Lex has a valid .storybook configuration.', "info", quiet);
|
|
153
|
+
callback(1);
|
|
154
|
+
return 1;
|
|
155
|
+
}
|
|
156
|
+
const storybookPath = resolveBinaryPath("storybook");
|
|
157
|
+
if (!storybookPath) {
|
|
158
|
+
log(`
|
|
159
|
+
${cliName} Error: storybook binary not found in Lex's node_modules or monorepo root`, "error", quiet);
|
|
160
|
+
log("Please reinstall Lex or check your Storybook installation.", "info", quiet);
|
|
161
|
+
callback(1);
|
|
162
|
+
return 1;
|
|
163
|
+
}
|
|
164
|
+
const storybookArgs = [staticBuild ? "build" : "dev"];
|
|
165
|
+
storybookArgs.push("--config-dir", configDir);
|
|
166
|
+
if (port) {
|
|
167
|
+
storybookArgs.push("--port", port.toString());
|
|
168
|
+
}
|
|
169
|
+
if (open) {
|
|
170
|
+
storybookArgs.push("--open");
|
|
171
|
+
}
|
|
172
|
+
if (staticBuild) {
|
|
173
|
+
const outputDir = pathResolve(process.cwd(), "storybook-static");
|
|
174
|
+
storybookArgs.push("--output-dir", outputDir);
|
|
175
|
+
}
|
|
176
|
+
if (!quiet) {
|
|
177
|
+
log(chalk.gray(`Config directory: ${configDir}`), "info", quiet);
|
|
178
|
+
}
|
|
179
|
+
process.env.TAILWIND_CSS_PATH = tailwindCssPath;
|
|
180
|
+
try {
|
|
181
|
+
spinner.start(staticBuild ? "Building static Storybook..." : "Starting Storybook development server...");
|
|
182
|
+
const storybookProcess = execa(storybookPath, storybookArgs, {
|
|
183
|
+
encoding: "utf8",
|
|
184
|
+
env: {
|
|
185
|
+
...process.env,
|
|
186
|
+
LEX_QUIET: quiet,
|
|
187
|
+
LEX_VERBOSE: verbose,
|
|
188
|
+
STORYBOOK_OPEN: open,
|
|
189
|
+
...tailwindCssPath && { TAILWIND_CSS_PATH: tailwindCssPath }
|
|
190
|
+
},
|
|
191
|
+
stdio: "pipe"
|
|
192
|
+
});
|
|
193
|
+
let urlFound = false;
|
|
194
|
+
let lastProgressPercentage = 0;
|
|
195
|
+
storybookProcess.stdout?.on("data", (data) => {
|
|
196
|
+
const output = data.toString();
|
|
197
|
+
const progressPercentage = extractProgressPercentage(output);
|
|
198
|
+
if (progressPercentage !== null && progressPercentage !== lastProgressPercentage) {
|
|
199
|
+
lastProgressPercentage = progressPercentage;
|
|
200
|
+
const action = staticBuild ? "Building" : "Starting";
|
|
201
|
+
spinner.text = `${action} Storybook... ${progressPercentage}%`;
|
|
202
|
+
process.stdout.write(`
|
|
203
|
+
Webpack Progress: ${chalk.magenta(`${progressPercentage}%`)}
|
|
204
|
+
`);
|
|
205
|
+
}
|
|
206
|
+
const filteredOutput = filterAndBeautifyOutput(output, verbose);
|
|
207
|
+
const beautifiedOutput = beautifyOutput(filteredOutput);
|
|
208
|
+
if (!urlFound && (output.includes("Local:") || output.includes("http://localhost") || output.includes("Storybook"))) {
|
|
209
|
+
spinner.succeed(chalk.green("Storybook development server is ready!"));
|
|
210
|
+
urlFound = true;
|
|
211
|
+
}
|
|
212
|
+
if (filteredOutput.trim()) {
|
|
213
|
+
process.stdout.write(beautifiedOutput);
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
storybookProcess.stderr?.on("data", (data) => {
|
|
217
|
+
const output = data.toString();
|
|
218
|
+
const filteredOutput = filterAndBeautifyOutput(output, verbose);
|
|
219
|
+
const beautifiedOutput = beautifyOutput(filteredOutput);
|
|
220
|
+
if (filteredOutput.trim()) {
|
|
221
|
+
process.stderr.write(beautifiedOutput);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
try {
|
|
225
|
+
await storybookProcess;
|
|
226
|
+
if (!urlFound) {
|
|
227
|
+
spinner.succeed(chalk.green("Storybook development server started."));
|
|
228
|
+
}
|
|
229
|
+
callback(0);
|
|
230
|
+
return 0;
|
|
231
|
+
} catch (error) {
|
|
232
|
+
spinner.fail(chalk.red("There was an error while running storybook."));
|
|
233
|
+
log(`
|
|
234
|
+
${cliName} Error: ${error.message}`, "error", quiet);
|
|
235
|
+
callback(1);
|
|
236
|
+
return 1;
|
|
237
|
+
}
|
|
238
|
+
} catch (error) {
|
|
239
|
+
log(`
|
|
240
|
+
${cliName} Error: ${error.message}`, "error", quiet);
|
|
241
|
+
spinner.fail("There was an error while running storybook.");
|
|
242
|
+
callback(1);
|
|
243
|
+
return 1;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
export {
|
|
247
|
+
storybook
|
|
248
|
+
};
|
|
249
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL2NvbW1hbmRzL3N0b3J5Ym9vay9zdG9yeWJvb2sudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQge2V4ZWNhfSBmcm9tICdleGVjYSc7XG5pbXBvcnQge2V4aXN0c1N5bmN9IGZyb20gJ2ZzJztcbmltcG9ydCB7c3luYyBhcyBnbG9iU3luY30gZnJvbSAnZ2xvYic7XG5pbXBvcnQge3Jlc29sdmUgYXMgcGF0aFJlc29sdmV9IGZyb20gJ3BhdGgnO1xuXG5pbXBvcnQge0xleENvbmZpZ30gZnJvbSAnLi4vLi4vTGV4Q29uZmlnLmpzJztcbmltcG9ydCB7Y3JlYXRlU3Bpbm5lcn0gZnJvbSAnLi4vLi4vdXRpbHMvYXBwLmpzJztcbmltcG9ydCB7ZmluZFRhaWx3aW5kQ3NzUGF0aCwgcmVzb2x2ZUJpbmFyeVBhdGh9IGZyb20gJy4uLy4uL3V0aWxzL2ZpbGUuanMnO1xuaW1wb3J0IHtsb2d9IGZyb20gJy4uLy4uL3V0aWxzL2xvZy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3Rvcnlib29rT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNsaU5hbWU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNvbmZpZz86IHN0cmluZztcbiAgcmVhZG9ubHkgb3Blbj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHBvcnQ/OiBudW1iZXI7XG4gIHJlYWRvbmx5IHF1aWV0PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3RhdGljPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgdXNlTGV4Q29uZmlnPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgdmFyaWFibGVzPzogc3RyaW5nO1xuICByZWFkb25seSB2ZXJib3NlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IHR5cGUgU3Rvcnlib29rQ2FsbGJhY2sgPSAoc3RhdHVzOiBudW1iZXIpID0+IHZvaWQ7XG5cbmNvbnN0IGZpbmRTdG9yeUZpbGVzID0gKCk6IHN0cmluZ1tdID0+IHtcbiAgY29uc3Qgc3RvcnlQYXR0ZXJucyA9IFtcbiAgICAnKiovKi5zdG9yaWVzLnt0cyx0c3gsanMsanN4fScsXG4gICAgJyoqLyouc3Rvcnkue3RzLHRzeCxqcyxqc3h9JyxcbiAgICAnKiovc3Rvcmllcy8qKi8qLnt0cyx0c3gsanMsanN4fSdcbiAgXTtcblxuICBjb25zdCBzdG9yeUZpbGVzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIHN0b3J5UGF0dGVybnMuZm9yRWFjaCgocGF0dGVybikgPT4ge1xuICAgIGNvbnN0IGZpbGVzID0gZ2xvYlN5bmMocGF0dGVybiwge1xuICAgICAgY3dkOiBwcm9jZXNzLmN3ZCgpLFxuICAgICAgaWdub3JlOiBbJyoqL25vZGVfbW9kdWxlcy8qKicsICcqKi9kaXN0LyoqJywgJyoqL2J1aWxkLyoqJ11cbiAgICB9KTtcbiAgICBzdG9yeUZpbGVzLnB1c2goLi4uZmlsZXMpO1xuICB9KTtcblxuICByZXR1cm4gc3RvcnlGaWxlcztcbn07XG5cbmNvbnN0IGNoZWNrU3Rvcnlib29rSW5pdGlhbGl6YXRpb24gPSAoKTogYm9vbGVhbiA9PiB7XG4gIGNvbnN0IHByb2plY3RDb25maWdEaXIgPSBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnLnN0b3J5Ym9vaycpO1xuICBjb25zdCBsZXhDb25maWdEaXIgPSBwYXRoUmVzb2x2ZShMZXhDb25maWcuZ2V0TGV4RGlyKCksICcuc3Rvcnlib29rJyk7XG5cbiAgcmV0dXJuIGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ0RpcikgfHwgZXhpc3RzU3luYyhsZXhDb25maWdEaXIpO1xufTtcblxuY29uc3QgZXh0cmFjdFByb2dyZXNzUGVyY2VudGFnZSA9IChvdXRwdXQ6IHN0cmluZyk6IG51bWJlciB8IG51bGwgPT4ge1xuICBjb25zdCBsaW5lcyA9IG91dHB1dC5zcGxpdCgnXFxuJyk7XG4gIGZvcihjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgaWYobGluZS5pbmNsdWRlcygnW3dlYnBhY2suUHJvZ3Jlc3NdJykgJiYgbGluZS5pbmNsdWRlcygnJScpKSB7XG4gICAgICBjb25zdCBwZXJjZW50YWdlTWF0Y2ggPSBsaW5lLm1hdGNoKC8oXFxkKyklLyk7XG4gICAgICBpZihwZXJjZW50YWdlTWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHBlcmNlbnRhZ2VNYXRjaFsxXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufTtcblxuY29uc3QgZmlsdGVyQW5kQmVhdXRpZnlPdXRwdXQgPSAob3V0cHV0OiBzdHJpbmcsIGlzVmVyYm9zZTogYm9vbGVhbik6IHN0cmluZyA9PiB7XG4gIGlmKGlzVmVyYm9zZSkge1xuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cblxuICBjb25zdCBsaW5lcyA9IG91dHB1dC5zcGxpdCgnXFxuJyk7XG4gIGNvbnN0IGZpbHRlcmVkTGluZXMgPSBsaW5lcy5maWx0ZXIoKGxpbmUpID0+IHtcbiAgICBpZihsaW5lLmluY2x1ZGVzKCdbd2VicGFjay5Qcm9ncmVzc10nKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmKGxpbmUuaW5jbHVkZXMoJ1N0b3J5Ym9vaycpIHx8XG4gICAgICBsaW5lLmluY2x1ZGVzKCdMb2NhbDonKSB8fFxuICAgICAgbGluZS5pbmNsdWRlcygnaHR0cDovL2xvY2FsaG9zdCcpIHx8XG4gICAgICBsaW5lLmluY2x1ZGVzKCdpbmZvID0+JykgfHxcbiAgICAgIGxpbmUuaW5jbHVkZXMoJ1N0YXJ0aW5nJykgfHxcbiAgICAgIGxpbmUuaW5jbHVkZXMoJ3JlYWR5JykgfHxcbiAgICAgIGxpbmUuaW5jbHVkZXMoJ2Vycm9yJykgfHxcbiAgICAgIGxpbmUuaW5jbHVkZXMoJ3dhcm5pbmcnKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBmaWx0ZXJlZExpbmVzLmpvaW4oJ1xcbicpO1xufTtcblxuY29uc3QgYmVhdXRpZnlPdXRwdXQgPSAob3V0cHV0OiBzdHJpbmcpOiBzdHJpbmcgPT4gb3V0cHV0XG4gIC5yZXBsYWNlKC9TdG9yeWJvb2sgdltcXGQuXSsvZywgY2hhbGsuY3lhbignJCYnKSlcbiAgLnJlcGxhY2UoL2luZm8gPT4vZywgY2hhbGsuYmx1ZSgnaW5mbyA9PicpKVxuICAucmVwbGFjZSgvTG9jYWw6L2csIGNoYWxrLmdyZWVuKCdMb2NhbDonKSlcbiAgLnJlcGxhY2UoL09uIHlvdXIgbmV0d29yazovZywgY2hhbGsuZ3JlZW4oJ09uIHlvdXIgbmV0d29yazonKSlcbiAgLnJlcGxhY2UoL1N0b3J5Ym9vay4qc3RhcnRlZC9nLCBjaGFsay5ncmVlbignJCYnKSlcbiAgLnJlcGxhY2UoL1N0b3J5Ym9vay4qcmVhZHkvZywgY2hhbGsuZ3JlZW4oJyQmJykpXG4gIC5yZXBsYWNlKC9lcnJvci9nLCBjaGFsay5yZWQoJyQmJykpXG4gIC5yZXBsYWNlKC93YXJuaW5nL2csIGNoYWxrLnllbGxvdygnJCYnKSlcbiAgLnJlcGxhY2UoLyhcXGQrKSUvZywgY2hhbGsubWFnZW50YSgnJDElJykpO1xuXG5leHBvcnQgY29uc3Qgc3Rvcnlib29rID0gYXN5bmMgKGNtZDogU3Rvcnlib29rT3B0aW9ucywgY2FsbGJhY2s6IFN0b3J5Ym9va0NhbGxiYWNrID0gKCkgPT4gKHt9KSk6IFByb21pc2U8bnVtYmVyPiA9PiB7XG4gIGNvbnN0IHtjbGlOYW1lID0gJ0xleCcsIGNvbmZpZywgb3BlbiA9IGZhbHNlLCBwb3J0ID0gNjAwNywgcXVpZXQsIHN0YXRpYzogc3RhdGljQnVpbGQgPSBmYWxzZSwgdXNlTGV4Q29uZmlnID0gZmFsc2UsIHZhcmlhYmxlcywgdmVyYm9zZSA9IGZhbHNlfSA9IGNtZDtcblxuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgbG9nKGNoYWxrLmN5YW4oYCR7Y2xpTmFtZX0gc3RhcnRpbmcgU3Rvcnlib29rLi4uYCksICdpbmZvJywgcXVpZXQpO1xuXG4gIGF3YWl0IExleENvbmZpZy5wYXJzZUNvbmZpZyhjbWQpO1xuXG4gIGxldCB2YXJpYWJsZXNPYmo6IG9iamVjdCA9IHtOT0RFX0VOVjogJ2RldmVsb3BtZW50J307XG5cbiAgaWYodmFyaWFibGVzKSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhcmlhYmxlc09iaiA9IEpTT04ucGFyc2UodmFyaWFibGVzKTtcbiAgICB9IGNhdGNoIChfZXJyb3IpIHtcbiAgICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogRW52aXJvbm1lbnQgdmFyaWFibGVzIG9wdGlvbiBpcyBub3QgYSB2YWxpZCBKU09OIG9iamVjdC5gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICBjYWxsYmFjaygxKTtcbiAgICAgIHJldHVybiAxO1xuICAgIH1cbiAgfVxuXG4gIHByb2Nlc3MuZW52ID0gey4uLnByb2Nlc3MuZW52LCAuLi52YXJpYWJsZXNPYmp9O1xuXG4gIHNwaW5uZXIuc3RhcnQoJ0ZpbmRpbmcgc3RvcnkgZmlsZXMuLi4nKTtcbiAgY29uc3Qgc3RvcnlGaWxlcyA9IGZpbmRTdG9yeUZpbGVzKCk7XG5cbiAgaWYoc3RvcnlGaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICBzcGlubmVyLmZhaWwoJ05vIHN0b3J5IGZpbGVzIGZvdW5kIGluIHRoZSBwcm9qZWN0LicpO1xuICAgIGxvZygnUGxlYXNlIGNyZWF0ZSBzdG9yeSBmaWxlcyB3aXRoIC5zdG9yaWVzLnRzLy5zdG9yaWVzLmpzIGV4dGVuc2lvbnMgb3IgaW4gYSBzdG9yaWVzLyBkaXJlY3RvcnkuJywgJ2luZm8nLCBxdWlldCk7XG4gICAgY2FsbGJhY2soMSk7XG4gICAgcmV0dXJuIDE7XG4gIH1cblxuICBzcGlubmVyLnN1Y2NlZWQoYEZvdW5kICR7c3RvcnlGaWxlcy5sZW5ndGh9IHN0b3J5IGZpbGUocylgKTtcblxuICBjb25zdCB0YWlsd2luZENzc1BhdGggPSBmaW5kVGFpbHdpbmRDc3NQYXRoKCk7XG5cbiAgY29uc29sZS5sb2coe3RhaWx3aW5kQ3NzUGF0aH0pO1xuICBpZih0YWlsd2luZENzc1BhdGgpIHtcbiAgICBpZighcXVpZXQpIHtcbiAgICAgIGxvZyhjaGFsay5ncmVlbihgXHUyNzEzIFRhaWx3aW5kIENTUyBpbnRlZ3JhdGlvbiBkZXRlY3RlZDogJHt0YWlsd2luZENzc1BhdGh9YCksICdpbmZvJywgcXVpZXQpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZighcXVpZXQpIHtcbiAgICAgIGxvZyhjaGFsay55ZWxsb3coJ1x1MjZBMCBObyBUYWlsd2luZCBDU1MgZmlsZSBmb3VuZCBpbiBwcm9qZWN0JyksICdpbmZvJywgcXVpZXQpO1xuICAgICAgbG9nKGNoYWxrLmdyYXkoJ0NyZWF0ZSBhIHRhaWx3aW5kLmNzcyBmaWxlIHdpdGggQHRhaWx3aW5kIGRpcmVjdGl2ZXMgZm9yIGZ1bGwgVGFpbHdpbmQgc3VwcG9ydCcpLCAnaW5mbycsIHF1aWV0KTtcbiAgICB9XG4gIH1cblxuICBpZighY2hlY2tTdG9yeWJvb2tJbml0aWFsaXphdGlvbigpKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdTdG9yeWJvb2sgaXMgbm90IGluaXRpYWxpemVkIGluIHRoaXMgcHJvamVjdCBvciBpbiBMZXguJyk7XG4gICAgbG9nKCdQbGVhc2UgcnVuIFwibnB4IHN0b3J5Ym9va0BsYXRlc3QgaW5pdFwiIHRvIHNldCB1cCBTdG9yeWJvb2sgaW4geW91ciBwcm9qZWN0LCBvciBlbnN1cmUgTGV4IGhhcyBhIHZhbGlkIC5zdG9yeWJvb2sgY29uZmlndXJhdGlvbi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICBjYWxsYmFjaygxKTtcbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIGNvbnN0IHByb2plY3RDb25maWdEaXIgPSBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnLnN0b3J5Ym9vaycpO1xuICBjb25zdCBsZXhDb25maWdEaXIgPSBwYXRoUmVzb2x2ZShMZXhDb25maWcuZ2V0TGV4RGlyKCksICcuc3Rvcnlib29rJyk7XG5cbiAgbGV0IGNvbmZpZ0RpciA9IGNvbmZpZztcbiAgaWYoIWNvbmZpZ0Rpcikge1xuICAgIGNvbmZpZ0RpciA9IGxleENvbmZpZ0RpcjtcbiAgICBpZighdXNlTGV4Q29uZmlnICYmIGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ0RpcikpIHtcbiAgICAgIGNvbmZpZ0RpciA9IHByb2plY3RDb25maWdEaXI7XG4gICAgfVxuICB9XG5cbiAgaWYoIXF1aWV0KSB7XG4gICAgbG9nKGNoYWxrLmdyYXkoYFByb2plY3QgY29uZmlnIGRpcjogJHtwcm9qZWN0Q29uZmlnRGlyfSAoZXhpc3RzOiAke2V4aXN0c1N5bmMocHJvamVjdENvbmZpZ0Rpcil9KWApLCAnaW5mbycsIHF1aWV0KTtcbiAgICBsb2coY2hhbGsuZ3JheShgTGV4IGNvbmZpZyBkaXI6ICR7bGV4Q29uZmlnRGlyfSAoZXhpc3RzOiAke2V4aXN0c1N5bmMobGV4Q29uZmlnRGlyKX0pYCksICdpbmZvJywgcXVpZXQpO1xuICAgIGlmKHVzZUxleENvbmZpZykge1xuICAgICAgbG9nKGNoYWxrLmJsdWUoJ1VzaW5nIExleCBTdG9yeWJvb2sgY29uZmlndXJhdGlvbiAoLS11c2UtbGV4LWNvbmZpZyBmbGFnKScpLCAnaW5mbycsIHF1aWV0KTtcbiAgICB9XG4gICAgbG9nKGNoYWxrLmdyYXkoYEluaXRpYWwgY29uZmlnIGRpcjogJHtjb25maWdEaXJ9YCksICdpbmZvJywgcXVpZXQpO1xuICB9XG5cbiAgaWYoY29uZmlnRGlyID09PSBsZXhDb25maWdEaXIpIHtcbiAgICBpZighcXVpZXQpIHtcbiAgICAgIGxvZyhjaGFsay5ibHVlKCdVc2luZyBMZXggY29uZmlnLCB3aWxsIGNyZWF0ZSB0ZW1wb3JhcnkgY29uZmlnIGluIHByb2plY3QgLnN0b3J5Ym9vayBkaXJlY3RvcnknKSwgJ2luZm8nLCBxdWlldCk7XG4gICAgfVxuICAgIGNvbnN0IHByb2plY3RTdG9yeWJvb2tEaXIgPSBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnLnN0b3J5Ym9vaycpO1xuXG4gICAgY29uc3QgZnMgPSBhd2FpdCBpbXBvcnQoJ2ZzL3Byb21pc2VzJyk7XG4gICAgYXdhaXQgZnMubWtkaXIocHJvamVjdFN0b3J5Ym9va0Rpciwge3JlY3Vyc2l2ZTogdHJ1ZX0pO1xuXG4gICAgY29uc3QgbGV4TWFpblBhdGggPSBwYXRoUmVzb2x2ZShsZXhDb25maWdEaXIsICdtYWluLnRzJyk7XG4gICAgY29uc3QgcHJvamVjdE1haW5QYXRoID0gcGF0aFJlc29sdmUocHJvamVjdFN0b3J5Ym9va0RpciwgJ21haW4udHMnKTtcbiAgICBsZXQgbWFpbkNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShsZXhNYWluUGF0aCwgJ3V0ZjgnKTtcblxuICAgIG1haW5Db250ZW50ID0gbWFpbkNvbnRlbnQucmVwbGFjZShcbiAgICAgIC9zdG9yaWVzOlxccypcXFsuKj9cXF0vLFxuICAgICAgYHN0b3JpZXM6IFsnJHtwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnc3JjLyoqLyouc3Rvcmllcy5AKHRzfHRzeCknKX0nLCAnJHtwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnc3JjLyoqLyoubWR4Jyl9J11gXG4gICAgKTtcblxuICAgIGNvbnN0IGxleE5vZGVNb2R1bGVzID0gcGF0aFJlc29sdmUoTGV4Q29uZmlnLmdldExleERpcigpLCAnbm9kZV9tb2R1bGVzJyk7XG4gICAgbWFpbkNvbnRlbnQgPSBtYWluQ29udGVudC5yZXBsYWNlKFxuICAgICAgL2NvbnN0IGxleE1vZHVsZSA9IFxcKG1vZHVsZVBhdGg6IHN0cmluZ1xcKSA9PiByZXNvbHZlXFwoZ2V0TGV4Tm9kZU1vZHVsZXNQYXRoXFwoXFwpLCBtb2R1bGVQYXRoXFwpOy8sXG4gICAgICBgY29uc3QgbGV4TW9kdWxlID0gKG1vZHVsZVBhdGg6IHN0cmluZykgPT4gcmVzb2x2ZSgnJHtsZXhOb2RlTW9kdWxlc30nLCBtb2R1bGVQYXRoKTtgXG4gICAgKTtcblxuICAgIGF3YWl0IGZzLndyaXRlRmlsZShwcm9qZWN0TWFpblBhdGgsIG1haW5Db250ZW50KTtcblxuICAgIGNvbnN0IGxleFByZXZpZXdQYXRoID0gcGF0aFJlc29sdmUobGV4Q29uZmlnRGlyLCAncHJldmlldy50c3gnKTtcbiAgICBpZihleGlzdHNTeW5jKGxleFByZXZpZXdQYXRoKSkge1xuICAgICAgY29uc3QgcHJldmlld0NvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShsZXhQcmV2aWV3UGF0aCwgJ3V0ZjgnKTtcbiAgICAgIGF3YWl0IGZzLndyaXRlRmlsZShwYXRoUmVzb2x2ZShwcm9qZWN0U3Rvcnlib29rRGlyLCAncHJldmlldy50c3gnKSwgcHJldmlld0NvbnRlbnQpO1xuICAgIH1cblxuICAgIGNvbmZpZ0RpciA9IHByb2plY3RTdG9yeWJvb2tEaXI7XG4gIH1cbiAgaWYoIWV4aXN0c1N5bmMoY29uZmlnRGlyKSkge1xuICAgIHNwaW5uZXIuZmFpbCgnU3Rvcnlib29rIGNvbmZpZ3VyYXRpb24gbm90IGZvdW5kLicpO1xuICAgIGxvZyhgUHJvamVjdCBjb25maWc6ICR7cHJvamVjdENvbmZpZ0Rpcn1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICBsb2coYExleCBjb25maWc6ICR7bGV4Q29uZmlnRGlyfWAsICdpbmZvJywgcXVpZXQpO1xuICAgIGxvZygnUGxlYXNlIHJ1biBcIm5weCBzdG9yeWJvb2tAbGF0ZXN0IGluaXRcIiB0byBzZXQgdXAgU3Rvcnlib29rIGluIHlvdXIgcHJvamVjdCwgb3IgZW5zdXJlIExleCBoYXMgYSB2YWxpZCAuc3Rvcnlib29rIGNvbmZpZ3VyYXRpb24uJywgJ2luZm8nLCBxdWlldCk7XG4gICAgY2FsbGJhY2soMSk7XG4gICAgcmV0dXJuIDE7XG4gIH1cblxuICBjb25zdCBzdG9yeWJvb2tQYXRoID0gcmVzb2x2ZUJpbmFyeVBhdGgoJ3N0b3J5Ym9vaycpO1xuXG4gIGlmKCFzdG9yeWJvb2tQYXRoKSB7XG4gICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBzdG9yeWJvb2sgYmluYXJ5IG5vdCBmb3VuZCBpbiBMZXgncyBub2RlX21vZHVsZXMgb3IgbW9ub3JlcG8gcm9vdGAsICdlcnJvcicsIHF1aWV0KTtcbiAgICBsb2coJ1BsZWFzZSByZWluc3RhbGwgTGV4IG9yIGNoZWNrIHlvdXIgU3Rvcnlib29rIGluc3RhbGxhdGlvbi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICBjYWxsYmFjaygxKTtcbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIGNvbnN0IHN0b3J5Ym9va0FyZ3MgPSBbc3RhdGljQnVpbGQgPyAnYnVpbGQnIDogJ2RldiddO1xuICBzdG9yeWJvb2tBcmdzLnB1c2goJy0tY29uZmlnLWRpcicsIGNvbmZpZ0Rpcik7XG5cbiAgaWYocG9ydCkge1xuICAgIHN0b3J5Ym9va0FyZ3MucHVzaCgnLS1wb3J0JywgcG9ydC50b1N0cmluZygpKTtcbiAgfVxuXG4gIGlmKG9wZW4pIHtcbiAgICBzdG9yeWJvb2tBcmdzLnB1c2goJy0tb3BlbicpO1xuICB9XG5cbiAgaWYoc3RhdGljQnVpbGQpIHtcbiAgICBjb25zdCBvdXRwdXREaXIgPSBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnc3Rvcnlib29rLXN0YXRpYycpO1xuICAgIHN0b3J5Ym9va0FyZ3MucHVzaCgnLS1vdXRwdXQtZGlyJywgb3V0cHV0RGlyKTtcbiAgfVxuXG4gIGlmKCFxdWlldCkge1xuICAgIGxvZyhjaGFsay5ncmF5KGBDb25maWcgZGlyZWN0b3J5OiAke2NvbmZpZ0Rpcn1gKSwgJ2luZm8nLCBxdWlldCk7XG4gIH1cblxuICBwcm9jZXNzLmVudi5UQUlMV0lORF9DU1NfUEFUSCA9IHRhaWx3aW5kQ3NzUGF0aDtcblxuICB0cnkge1xuICAgIHNwaW5uZXIuc3RhcnQoc3RhdGljQnVpbGQgPyAnQnVpbGRpbmcgc3RhdGljIFN0b3J5Ym9vay4uLicgOiAnU3RhcnRpbmcgU3Rvcnlib29rIGRldmVsb3BtZW50IHNlcnZlci4uLicpO1xuXG4gICAgY29uc3Qgc3Rvcnlib29rUHJvY2VzcyA9IGV4ZWNhKHN0b3J5Ym9va1BhdGggYXMgYW55LCBzdG9yeWJvb2tBcmdzLCB7XG4gICAgICBlbmNvZGluZzogJ3V0ZjgnLFxuICAgICAgZW52OiB7XG4gICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICBMRVhfUVVJRVQ6IHF1aWV0LFxuICAgICAgICBMRVhfVkVSQk9TRTogdmVyYm9zZSxcbiAgICAgICAgU1RPUllCT09LX09QRU46IG9wZW4sXG4gICAgICAgIC4uLih0YWlsd2luZENzc1BhdGggJiYge1RBSUxXSU5EX0NTU19QQVRIOiB0YWlsd2luZENzc1BhdGh9KVxuICAgICAgfSBhcyBhbnksXG4gICAgICBzdGRpbzogJ3BpcGUnXG4gICAgfSk7XG5cbiAgICBsZXQgdXJsRm91bmQgPSBmYWxzZTtcbiAgICBsZXQgbGFzdFByb2dyZXNzUGVyY2VudGFnZSA9IDA7XG5cbiAgICBzdG9yeWJvb2tQcm9jZXNzLnN0ZG91dD8ub24oJ2RhdGEnLCAoZGF0YSkgPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0ID0gZGF0YS50b1N0cmluZygpO1xuICAgICAgY29uc3QgcHJvZ3Jlc3NQZXJjZW50YWdlID0gZXh0cmFjdFByb2dyZXNzUGVyY2VudGFnZShvdXRwdXQpO1xuXG4gICAgICBpZihwcm9ncmVzc1BlcmNlbnRhZ2UgIT09IG51bGwgJiYgcHJvZ3Jlc3NQZXJjZW50YWdlICE9PSBsYXN0UHJvZ3Jlc3NQZXJjZW50YWdlKSB7XG4gICAgICAgIGxhc3RQcm9ncmVzc1BlcmNlbnRhZ2UgPSBwcm9ncmVzc1BlcmNlbnRhZ2U7XG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IHN0YXRpY0J1aWxkID8gJ0J1aWxkaW5nJyA6ICdTdGFydGluZyc7XG4gICAgICAgIChzcGlubmVyIGFzIGFueSkudGV4dCA9IGAke2FjdGlvbn0gU3Rvcnlib29rLi4uICR7cHJvZ3Jlc3NQZXJjZW50YWdlfSVgO1xuICAgICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgXFxuV2VicGFjayBQcm9ncmVzczogJHtjaGFsay5tYWdlbnRhKGAke3Byb2dyZXNzUGVyY2VudGFnZX0lYCl9XFxuYCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZpbHRlcmVkT3V0cHV0ID0gZmlsdGVyQW5kQmVhdXRpZnlPdXRwdXQob3V0cHV0LCB2ZXJib3NlKTtcbiAgICAgIGNvbnN0IGJlYXV0aWZpZWRPdXRwdXQgPSBiZWF1dGlmeU91dHB1dChmaWx0ZXJlZE91dHB1dCk7XG5cbiAgICAgIGlmKCF1cmxGb3VuZCAmJiAob3V0cHV0LmluY2x1ZGVzKCdMb2NhbDonKSB8fCBvdXRwdXQuaW5jbHVkZXMoJ2h0dHA6Ly9sb2NhbGhvc3QnKSB8fCBvdXRwdXQuaW5jbHVkZXMoJ1N0b3J5Ym9vaycpKSkge1xuICAgICAgICBzcGlubmVyLnN1Y2NlZWQoY2hhbGsuZ3JlZW4oJ1N0b3J5Ym9vayBkZXZlbG9wbWVudCBzZXJ2ZXIgaXMgcmVhZHkhJykpO1xuICAgICAgICB1cmxGb3VuZCA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmKGZpbHRlcmVkT3V0cHV0LnRyaW0oKSkge1xuICAgICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShiZWF1dGlmaWVkT3V0cHV0KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHN0b3J5Ym9va1Byb2Nlc3Muc3RkZXJyPy5vbignZGF0YScsIChkYXRhKSA9PiB7XG4gICAgICBjb25zdCBvdXRwdXQgPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgICBjb25zdCBmaWx0ZXJlZE91dHB1dCA9IGZpbHRlckFuZEJlYXV0aWZ5T3V0cHV0KG91dHB1dCwgdmVyYm9zZSk7XG4gICAgICBjb25zdCBiZWF1dGlmaWVkT3V0cHV0ID0gYmVhdXRpZnlPdXRwdXQoZmlsdGVyZWRPdXRwdXQpO1xuXG4gICAgICBpZihmaWx0ZXJlZE91dHB1dC50cmltKCkpIHtcbiAgICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoYmVhdXRpZmllZE91dHB1dCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0cnkge1xuICAgICAgYXdhaXQgc3Rvcnlib29rUHJvY2VzcztcbiAgICAgIGlmKCF1cmxGb3VuZCkge1xuICAgICAgICBzcGlubmVyLnN1Y2NlZWQoY2hhbGsuZ3JlZW4oJ1N0b3J5Ym9vayBkZXZlbG9wbWVudCBzZXJ2ZXIgc3RhcnRlZC4nKSk7XG4gICAgICB9XG4gICAgICBjYWxsYmFjaygwKTtcbiAgICAgIHJldHVybiAwO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBzcGlubmVyLmZhaWwoY2hhbGsucmVkKCdUaGVyZSB3YXMgYW4gZXJyb3Igd2hpbGUgcnVubmluZyBzdG9yeWJvb2suJykpO1xuICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgY2FsbGJhY2soMSk7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIHNwaW5uZXIuZmFpbCgnVGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIHJ1bm5pbmcgc3Rvcnlib29rLicpO1xuICAgIGNhbGxiYWNrKDEpO1xuICAgIHJldHVybiAxO1xuICB9XG59OyJdLAogICJtYXBwaW5ncyI6ICJBQUFBLE9BQU8sV0FBVztBQUNsQixTQUFRLGFBQVk7QUFDcEIsU0FBUSxrQkFBaUI7QUFDekIsU0FBUSxRQUFRLGdCQUFlO0FBQy9CLFNBQVEsV0FBVyxtQkFBa0I7QUFFckMsU0FBUSxpQkFBZ0I7QUFDeEIsU0FBUSxxQkFBb0I7QUFDNUIsU0FBUSxxQkFBcUIseUJBQXdCO0FBQ3JELFNBQVEsV0FBVTtBQWdCbEIsTUFBTSxpQkFBaUIsTUFBZ0I7QUFDckMsUUFBTSxnQkFBZ0I7QUFBQSxJQUNwQjtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsRUFDRjtBQUVBLFFBQU0sYUFBdUIsQ0FBQztBQUU5QixnQkFBYyxRQUFRLENBQUMsWUFBWTtBQUNqQyxVQUFNLFFBQVEsU0FBUyxTQUFTO0FBQUEsTUFDOUIsS0FBSyxRQUFRLElBQUk7QUFBQSxNQUNqQixRQUFRLENBQUMsc0JBQXNCLGNB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
|