@nlabs/lex
Version:
253 lines (252 loc) • 37.3 kB
JavaScript
import chalk from 'chalk';
import { execa } from 'execa';
import { existsSync } from 'fs';
import { sync as globSync } from 'glob';
import { resolve as pathResolve } from 'path';
import { LexConfig } from '../../LexConfig.js';
import { createSpinner } from '../../utils/app.js';
import { findTailwindCssPath, resolveBinaryPath } from '../../utils/file.js';
import { log } from '../../utils/log.js';
const findStoryFiles = ()=>{
const storyPatterns = [
'**/*.stories.{ts,tsx,js,jsx}',
'**/*.story.{ts,tsx,js,jsx}',
'**/stories/**/*.{ts,tsx,js,jsx}'
];
const storyFiles = [];
storyPatterns.forEach((pattern)=>{
const files = globSync(pattern, {
cwd: process.cwd(),
ignore: [
'**/node_modules/**',
'**/dist/**',
'**/lib/**',
'**/build/**'
]
});
storyFiles.push(...files);
});
return storyFiles;
};
const checkStorybookInitialization = ()=>{
const projectConfigDir = pathResolve(process.cwd(), '.storybook');
const lexConfigDir = pathResolve(LexConfig.getLexDir(), '.storybook');
return existsSync(projectConfigDir) || existsSync(lexConfigDir);
};
const extractProgressPercentage = (output)=>{
const lines = output.split('\n');
for (const line of lines){
if (line.includes('[webpack.Progress]') && line.includes('%')) {
const percentageMatch = line.match(/(\d+)%/);
if (percentageMatch) {
return parseInt(percentageMatch[1]);
}
}
}
return null;
};
const filterAndBeautifyOutput = (output, isVerbose)=>{
if (isVerbose) {
return output;
}
const lines = output.split('\n');
const filteredLines = lines.filter((line)=>{
if (line.includes('[webpack.Progress]')) {
return false;
}
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')) {
return true;
}
return true;
});
return filteredLines.join('\n');
};
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%'));
export const storybook = async (cmd, callback = ()=>({}))=>{
const { cliName = 'Lex', config, open = false, port = 6007, quiet, static: staticBuild = false, useLexConfig = false, variables, verbose = false } = cmd;
const spinner = createSpinner(quiet);
log(chalk.cyan(`${cliName} starting Storybook...`), 'info', quiet);
await LexConfig.parseConfig(cmd);
let variablesObj = {
NODE_ENV: 'development'
};
if (variables) {
try {
variablesObj = JSON.parse(variables);
} catch (_error) {
log(`\n${cliName} Error: Environment variables option is not a valid JSON object.`, 'error', quiet);
callback(1);
return 1;
}
}
process.env = {
...process.env,
...variablesObj
};
spinner.start('Finding story files...');
const storyFiles = findStoryFiles();
if (storyFiles.length === 0) {
spinner.fail('No story files found in the project.');
log('Please create story files with .stories.ts/.stories.js extensions or in a stories/ directory.', 'info', quiet);
callback(1);
return 1;
}
spinner.succeed(`Found ${storyFiles.length} story file(s)`);
const tailwindCssPath = findTailwindCssPath();
console.log({
tailwindCssPath
});
if (tailwindCssPath) {
if (!quiet) {
log(chalk.green(`✓ Tailwind CSS integration detected: ${tailwindCssPath}`), 'info', quiet);
}
} else {
if (!quiet) {
log(chalk.yellow('⚠ No Tailwind CSS file found in project'), 'info', quiet);
log(chalk.gray('Create a tailwind.css file with @tailwind directives for full Tailwind support'), 'info', quiet);
}
}
if (!checkStorybookInitialization()) {
spinner.fail('Storybook is not initialized in this project or in Lex.');
log('Please run "npx storybook@latest init" to set up Storybook in your project, or ensure Lex has a valid .storybook configuration.', 'info', quiet);
callback(1);
return 1;
}
const projectConfigDir = pathResolve(process.cwd(), '.storybook');
const lexConfigDir = pathResolve(LexConfig.getLexDir(), '.storybook');
let configDir = config;
if (!configDir) {
configDir = lexConfigDir;
if (!useLexConfig && existsSync(projectConfigDir)) {
configDir = projectConfigDir;
}
}
if (!quiet) {
log(chalk.gray(`Project config dir: ${projectConfigDir} (exists: ${existsSync(projectConfigDir)})`), 'info', quiet);
log(chalk.gray(`Lex config dir: ${lexConfigDir} (exists: ${existsSync(lexConfigDir)})`), 'info', quiet);
if (useLexConfig) {
log(chalk.blue('Using Lex Storybook configuration (--use-lex-config flag)'), 'info', quiet);
}
log(chalk.gray(`Initial config dir: ${configDir}`), 'info', quiet);
}
if (configDir === lexConfigDir) {
if (!quiet) {
log(chalk.blue('Using Lex config, will create temporary config in project .storybook directory'), 'info', quiet);
}
const projectStorybookDir = pathResolve(process.cwd(), '.storybook');
const fs = await import('fs/promises');
await fs.mkdir(projectStorybookDir, {
recursive: true
});
const lexMainPath = pathResolve(lexConfigDir, 'main.ts');
const projectMainPath = pathResolve(projectStorybookDir, 'main.ts');
let mainContent = await fs.readFile(lexMainPath, 'utf8');
mainContent = mainContent.replace(/stories:\s*\[.*?\]/, `stories: ['${pathResolve(process.cwd(), 'src/**/*.stories.@(ts|tsx)')}', '${pathResolve(process.cwd(), 'src/**/*.mdx')}']`);
const lexNodeModules = pathResolve(LexConfig.getLexDir(), 'node_modules');
mainContent = mainContent.replace(/const lexModule = \(modulePath: string\) => resolve\(getLexNodeModulesPath\(\), modulePath\);/, `const lexModule = (modulePath: string) => resolve('${lexNodeModules}', modulePath);`);
await fs.writeFile(projectMainPath, mainContent);
const lexPreviewPath = pathResolve(lexConfigDir, 'preview.tsx');
if (existsSync(lexPreviewPath)) {
const previewContent = await fs.readFile(lexPreviewPath, 'utf8');
await fs.writeFile(pathResolve(projectStorybookDir, 'preview.tsx'), previewContent);
}
configDir = projectStorybookDir;
}
if (!existsSync(configDir)) {
spinner.fail('Storybook configuration not found.');
log(`Project config: ${projectConfigDir}`, 'info', quiet);
log(`Lex config: ${lexConfigDir}`, 'info', quiet);
log('Please run "npx storybook@latest init" to set up Storybook in your project, or ensure Lex has a valid .storybook configuration.', 'info', quiet);
callback(1);
return 1;
}
const storybookPath = resolveBinaryPath('storybook');
if (!storybookPath) {
log(`\n${cliName} Error: storybook binary not found in Lex's node_modules or monorepo root`, 'error', quiet);
log('Please reinstall Lex or check your Storybook installation.', 'info', quiet);
callback(1);
return 1;
}
const storybookArgs = [
staticBuild ? 'build' : 'dev'
];
storybookArgs.push('--config-dir', configDir);
if (port) {
storybookArgs.push('--port', port.toString());
}
if (open) {
storybookArgs.push('--open');
}
if (staticBuild) {
const outputDir = pathResolve(process.cwd(), 'storybook-static');
storybookArgs.push('--output-dir', outputDir);
}
if (!quiet) {
log(chalk.gray(`Config directory: ${configDir}`), 'info', quiet);
}
process.env.TAILWIND_CSS_PATH = tailwindCssPath;
try {
spinner.start(staticBuild ? 'Building static Storybook...' : 'Starting Storybook development server...');
const storybookProcess = execa(storybookPath, storybookArgs, {
encoding: 'utf8',
env: {
...process.env,
LEX_QUIET: quiet,
LEX_VERBOSE: verbose,
STORYBOOK_OPEN: open,
...tailwindCssPath && {
TAILWIND_CSS_PATH: tailwindCssPath
}
},
stdio: 'pipe'
});
let urlFound = false;
let lastProgressPercentage = 0;
storybookProcess.stdout?.on('data', (data)=>{
const output = data.toString();
const progressPercentage = extractProgressPercentage(output);
if (progressPercentage !== null && progressPercentage !== lastProgressPercentage) {
lastProgressPercentage = progressPercentage;
const action = staticBuild ? 'Building' : 'Starting';
spinner.text = `${action} Storybook... ${progressPercentage}%`;
process.stdout.write(`\nWebpack Progress: ${chalk.magenta(`${progressPercentage}%`)}\n`);
}
const filteredOutput = filterAndBeautifyOutput(output, verbose);
const beautifiedOutput = beautifyOutput(filteredOutput);
if (!urlFound && (output.includes('Local:') || output.includes('http://localhost') || output.includes('Storybook'))) {
spinner.succeed(chalk.green('Storybook development server is ready!'));
urlFound = true;
}
if (filteredOutput.trim()) {
process.stdout.write(beautifiedOutput);
}
});
storybookProcess.stderr?.on('data', (data)=>{
const output = data.toString();
const filteredOutput = filterAndBeautifyOutput(output, verbose);
const beautifiedOutput = beautifyOutput(filteredOutput);
if (filteredOutput.trim()) {
process.stderr.write(beautifiedOutput);
}
});
try {
await storybookProcess;
if (!urlFound) {
spinner.succeed(chalk.green('Storybook development server started.'));
}
callback(0);
return 0;
} catch (error) {
spinner.fail(chalk.red('There was an error while running storybook.'));
log(`\n${cliName} Error: ${error.message}`, 'error', quiet);
callback(1);
return 1;
}
} catch (error) {
log(`\n${cliName} Error: ${error.message}`, 'error', quiet);
spinner.fail('There was an error while running storybook.');
callback(1);
return 1;
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9jb21tYW5kcy9zdG9yeWJvb2svc3Rvcnlib29rLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQge2V4ZWNhfSBmcm9tICdleGVjYSc7XG5pbXBvcnQge2V4aXN0c1N5bmN9IGZyb20gJ2ZzJztcbmltcG9ydCB7c3luYyBhcyBnbG9iU3luY30gZnJvbSAnZ2xvYic7XG5pbXBvcnQge3Jlc29sdmUgYXMgcGF0aFJlc29sdmV9IGZyb20gJ3BhdGgnO1xuXG5pbXBvcnQge0xleENvbmZpZ30gZnJvbSAnLi4vLi4vTGV4Q29uZmlnLmpzJztcbmltcG9ydCB7Y3JlYXRlU3Bpbm5lcn0gZnJvbSAnLi4vLi4vdXRpbHMvYXBwLmpzJztcbmltcG9ydCB7ZmluZFRhaWx3aW5kQ3NzUGF0aCwgcmVzb2x2ZUJpbmFyeVBhdGh9IGZyb20gJy4uLy4uL3V0aWxzL2ZpbGUuanMnO1xuaW1wb3J0IHtsb2d9IGZyb20gJy4uLy4uL3V0aWxzL2xvZy5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3Rvcnlib29rT3B0aW9ucyB7XG4gIHJlYWRvbmx5IGNsaU5hbWU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNvbmZpZz86IHN0cmluZztcbiAgcmVhZG9ubHkgb3Blbj86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHBvcnQ/OiBudW1iZXI7XG4gIHJlYWRvbmx5IHF1aWV0PzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgc3RhdGljPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgdXNlTGV4Q29uZmlnPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgdmFyaWFibGVzPzogc3RyaW5nO1xuICByZWFkb25seSB2ZXJib3NlPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IHR5cGUgU3Rvcnlib29rQ2FsbGJhY2sgPSAoc3RhdHVzOiBudW1iZXIpPT4gdm9pZDtcblxuY29uc3QgZmluZFN0b3J5RmlsZXMgPSAoKTogc3RyaW5nW10gPT4ge1xuICBjb25zdCBzdG9yeVBhdHRlcm5zID0gW1xuICAgICcqKi8qLnN0b3JpZXMue3RzLHRzeCxqcyxqc3h9JyxcbiAgICAnKiovKi5zdG9yeS57dHMsdHN4LGpzLGpzeH0nLFxuICAgICcqKi9zdG9yaWVzLyoqLyoue3RzLHRzeCxqcyxqc3h9J1xuICBdO1xuXG4gIGNvbnN0IHN0b3J5RmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgc3RvcnlQYXR0ZXJucy5mb3JFYWNoKChwYXR0ZXJuKSA9PiB7XG4gICAgY29uc3QgZmlsZXMgPSBnbG9iU3luYyhwYXR0ZXJuLCB7XG4gICAgICBjd2Q6IHByb2Nlc3MuY3dkKCksXG4gICAgICBpZ25vcmU6IFsnKiovbm9kZV9tb2R1bGVzLyoqJywgJyoqL2Rpc3QvKionLCAnKiovbGliLyoqJywgJyoqL2J1aWxkLyoqJ11cbiAgICB9KTtcbiAgICBzdG9yeUZpbGVzLnB1c2goLi4uZmlsZXMpO1xuICB9KTtcblxuICByZXR1cm4gc3RvcnlGaWxlcztcbn07XG5cbmNvbnN0IGNoZWNrU3Rvcnlib29rSW5pdGlhbGl6YXRpb24gPSAoKTogYm9vbGVhbiA9PiB7XG4gIGNvbnN0IHByb2plY3RDb25maWdEaXIgPSBwYXRoUmVzb2x2ZShwcm9jZXNzLmN3ZCgpLCAnLnN0b3J5Ym9vaycpO1xuICBjb25zdCBsZXhDb25maWdEaXIgPSBwYXRoUmVzb2x2ZShMZXhDb25maWcuZ2V0TGV4RGlyKCksICcuc3Rvcnlib29rJyk7XG5cbiAgcmV0dXJuIGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ0RpcikgfHwgZXhpc3RzU3luYyhsZXhDb25maWdEaXIpO1xufTtcblxuY29uc3QgZXh0cmFjdFByb2dyZXNzUGVyY2VudGFnZSA9IChvdXRwdXQ6IHN0cmluZyk6IG51bWJlciB8IG51bGwgPT4ge1xuICBjb25zdCBsaW5lcyA9IG91dHB1dC5zcGxpdCgnXFxuJyk7XG4gIGZvcihjb25zdCBsaW5lIG9mIGxpbmVzKSB7XG4gICAgaWYobGluZS5pbmNsdWRlcygnW3dlYnBhY2suUHJvZ3Jlc3NdJykgJiYgbGluZS5pbmNsdWRlcygnJScpKSB7XG4gICAgICBjb25zdCBwZXJjZW50YWdlTWF0Y2ggPSBsaW5lLm1hdGNoKC8oXFxkKyklLyk7XG4gICAgICBpZihwZXJjZW50YWdlTWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KHBlcmNlbnRhZ2VNYXRjaFsxXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufTtcblxuY29uc3QgZmlsdGVyQW5kQmVhdXRpZnlPdXRwdXQgPSAob3V0cHV0OiBzdHJpbmcsIGlzVmVyYm9zZTogYm9vbGVhbik6IHN0cmluZyA9PiB7XG4gIGlmKGlzVmVyYm9zZSkge1xuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cblxuICBjb25zdCBsaW5lcyA9IG91dHB1dC5zcGxpdCgnXFxuJyk7XG4gIGNvbnN0IGZpbHRlcmVkTGluZXMgPSBsaW5lcy5maWx0ZXIoKGxpbmUpID0+IHtcbiAgICBpZihsaW5lLmluY2x1ZGVzKCdbd2VicGFjay5Qcm9ncmVzc10nKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmKGxpbmUuaW5jbHVkZXMoJ1N0b3J5Ym9vaycpIHx8XG4gICAgICBsaW5lLmluY2x1ZGVzKCdMb2NhbDonKSB8fFxuICAgICAgbGluZS5pbmNsdWRlcygnaHR0cDovL2xvY2FsaG9zdCcpIHx8XG4gICAgICBsaW5lLmluY2x1ZGVzKCdpbmZvID0+JykgfHxcbiAgICAgIGxpbmUuaW5jbHVkZXMoJ1N0YXJ0aW5nJykgfHxcbiAgICAgIGxpbmUuaW5jbHVkZXMoJ3JlYWR5JykgfHxcbiAgICAgIGxpbmUuaW5jbHVkZXMoJ2Vycm9yJykgfHxcbiAgICAgIGxpbmUuaW5jbHVkZXMoJ3dhcm5pbmcnKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBmaWx0ZXJlZExpbmVzLmpvaW4oJ1xcbicpO1xufTtcblxuY29uc3QgYmVhdXRpZnlPdXRwdXQgPSAob3V0cHV0OiBzdHJpbmcpOiBzdHJpbmcgPT4gb3V0cHV0XG4gIC5yZXBsYWNlKC9TdG9yeWJvb2sgdltcXGQuXSsvZywgY2hhbGsuY3lhbignJCYnKSlcbiAgLnJlcGxhY2UoL2luZm8gPT4vZywgY2hhbGsuYmx1ZSgnaW5mbyA9PicpKVxuICAucmVwbGFjZSgvTG9jYWw6L2csIGNoYWxrLmdyZWVuKCdMb2NhbDonKSlcbiAgLnJlcGxhY2UoL09uIHlvdXIgbmV0d29yazovZywgY2hhbGsuZ3JlZW4oJ09uIHlvdXIgbmV0d29yazonKSlcbiAgLnJlcGxhY2UoL1N0b3J5Ym9vay4qc3RhcnRlZC9nLCBjaGFsay5ncmVlbignJCYnKSlcbiAgLnJlcGxhY2UoL1N0b3J5Ym9vay4qcmVhZHkvZywgY2hhbGsuZ3JlZW4oJyQmJykpXG4gIC5yZXBsYWNlKC9lcnJvci9nLCBjaGFsay5yZWQoJyQmJykpXG4gIC5yZXBsYWNlKC93YXJuaW5nL2csIGNoYWxrLnllbGxvdygnJCYnKSlcbiAgLnJlcGxhY2UoLyhcXGQrKSUvZywgY2hhbGsubWFnZW50YSgnJDElJykpO1xuXG5leHBvcnQgY29uc3Qgc3Rvcnlib29rID0gYXN5bmMgKGNtZDogU3Rvcnlib29rT3B0aW9ucywgY2FsbGJhY2s6IFN0b3J5Ym9va0NhbGxiYWNrID0gKCkgPT4gKHt9KSk6IFByb21pc2U8bnVtYmVyPiA9PiB7XG4gIGNvbnN0IHtjbGlOYW1lID0gJ0xleCcsIGNvbmZpZywgb3BlbiA9IGZhbHNlLCBwb3J0ID0gNjAwNywgcXVpZXQsIHN0YXRpYzogc3RhdGljQnVpbGQgPSBmYWxzZSwgdXNlTGV4Q29uZmlnID0gZmFsc2UsIHZhcmlhYmxlcywgdmVyYm9zZSA9IGZhbHNlfSA9IGNtZDtcblxuICBjb25zdCBzcGlubmVyID0gY3JlYXRlU3Bpbm5lcihxdWlldCk7XG5cbiAgbG9nKGNoYWxrLmN5YW4oYCR7Y2xpTmFtZX0gc3RhcnRpbmcgU3Rvcnlib29rLi4uYCksICdpbmZvJywgcXVpZXQpO1xuXG4gIGF3YWl0IExleENvbmZpZy5wYXJzZUNvbmZpZyhjbWQpO1xuXG4gIGxldCB2YXJpYWJsZXNPYmo6IG9iamVjdCA9IHtOT0RFX0VOVjogJ2RldmVsb3BtZW50J307XG5cbiAgaWYodmFyaWFibGVzKSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhcmlhYmxlc09iaiA9IEpTT04ucGFyc2UodmFyaWFibGVzKTtcbiAgICB9IGNhdGNoKF9lcnJvcikge1xuICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgb3B0aW9uIGlzIG5vdCBhIHZhbGlkIEpTT04gb2JqZWN0LmAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIGNhbGxiYWNrKDEpO1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICB9XG5cbiAgcHJvY2Vzcy5lbnYgPSB7Li4ucHJvY2Vzcy5lbnYsIC4uLnZhcmlhYmxlc09ian07XG5cbiAgc3Bpbm5lci5zdGFydCgnRmluZGluZyBzdG9yeSBmaWxlcy4uLicpO1xuICBjb25zdCBzdG9yeUZpbGVzID0gZmluZFN0b3J5RmlsZXMoKTtcblxuICBpZihzdG9yeUZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgIHNwaW5uZXIuZmFpbCgnTm8gc3RvcnkgZmlsZXMgZm91bmQgaW4gdGhlIHByb2plY3QuJyk7XG4gICAgbG9nKCdQbGVhc2UgY3JlYXRlIHN0b3J5IGZpbGVzIHdpdGggLnN0b3JpZXMudHMvLnN0b3JpZXMuanMgZXh0ZW5zaW9ucyBvciBpbiBhIHN0b3JpZXMvIGRpcmVjdG9yeS4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICBjYWxsYmFjaygxKTtcbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIHNwaW5uZXIuc3VjY2VlZChgRm91bmQgJHtzdG9yeUZpbGVzLmxlbmd0aH0gc3RvcnkgZmlsZShzKWApO1xuXG4gIGNvbnN0IHRhaWx3aW5kQ3NzUGF0aCA9IGZpbmRUYWlsd2luZENzc1BhdGgoKTtcblxuICBjb25zb2xlLmxvZyh7dGFpbHdpbmRDc3NQYXRofSk7XG4gIGlmKHRhaWx3aW5kQ3NzUGF0aCkge1xuICAgIGlmKCFxdWlldCkge1xuICAgICAgbG9nKGNoYWxrLmdyZWVuKGDinJMgVGFpbHdpbmQgQ1NTIGludGVncmF0aW9uIGRldGVjdGVkOiAke3RhaWx3aW5kQ3NzUGF0aH1gKSwgJ2luZm8nLCBxdWlldCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmKCFxdWlldCkge1xuICAgICAgbG9nKGNoYWxrLnllbGxvdygn4pqgIE5vIFRhaWx3aW5kIENTUyBmaWxlIGZvdW5kIGluIHByb2plY3QnKSwgJ2luZm8nLCBxdWlldCk7XG4gICAgICBsb2coY2hhbGsuZ3JheSgnQ3JlYXRlIGEgdGFpbHdpbmQuY3NzIGZpbGUgd2l0aCBAdGFpbHdpbmQgZGlyZWN0aXZlcyBmb3IgZnVsbCBUYWlsd2luZCBzdXBwb3J0JyksICdpbmZvJywgcXVpZXQpO1xuICAgIH1cbiAgfVxuXG4gIGlmKCFjaGVja1N0b3J5Ym9va0luaXRpYWxpemF0aW9uKCkpIHtcbiAgICBzcGlubmVyLmZhaWwoJ1N0b3J5Ym9vayBpcyBub3QgaW5pdGlhbGl6ZWQgaW4gdGhpcyBwcm9qZWN0IG9yIGluIExleC4nKTtcbiAgICBsb2coJ1BsZWFzZSBydW4gXCJucHggc3Rvcnlib29rQGxhdGVzdCBpbml0XCIgdG8gc2V0IHVwIFN0b3J5Ym9vayBpbiB5b3VyIHByb2plY3QsIG9yIGVuc3VyZSBMZXggaGFzIGEgdmFsaWQgLnN0b3J5Ym9vayBjb25maWd1cmF0aW9uLicsICdpbmZvJywgcXVpZXQpO1xuICAgIGNhbGxiYWNrKDEpO1xuICAgIHJldHVybiAxO1xuICB9XG5cbiAgY29uc3QgcHJvamVjdENvbmZpZ0RpciA9IHBhdGhSZXNvbHZlKHByb2Nlc3MuY3dkKCksICcuc3Rvcnlib29rJyk7XG4gIGNvbnN0IGxleENvbmZpZ0RpciA9IHBhdGhSZXNvbHZlKExleENvbmZpZy5nZXRMZXhEaXIoKSwgJy5zdG9yeWJvb2snKTtcblxuICBsZXQgY29uZmlnRGlyID0gY29uZmlnO1xuICBpZighY29uZmlnRGlyKSB7XG4gICAgY29uZmlnRGlyID0gbGV4Q29uZmlnRGlyO1xuICAgIGlmKCF1c2VMZXhDb25maWcgJiYgZXhpc3RzU3luYyhwcm9qZWN0Q29uZmlnRGlyKSkge1xuICAgICAgY29uZmlnRGlyID0gcHJvamVjdENvbmZpZ0RpcjtcbiAgICB9XG4gIH1cblxuICBpZighcXVpZXQpIHtcbiAgICBsb2coY2hhbGsuZ3JheShgUHJvamVjdCBjb25maWcgZGlyOiAke3Byb2plY3RDb25maWdEaXJ9IChleGlzdHM6ICR7ZXhpc3RzU3luYyhwcm9qZWN0Q29uZmlnRGlyKX0pYCksICdpbmZvJywgcXVpZXQpO1xuICAgIGxvZyhjaGFsay5ncmF5KGBMZXggY29uZmlnIGRpcjogJHtsZXhDb25maWdEaXJ9IChleGlzdHM6ICR7ZXhpc3RzU3luYyhsZXhDb25maWdEaXIpfSlgKSwgJ2luZm8nLCBxdWlldCk7XG4gICAgaWYodXNlTGV4Q29uZmlnKSB7XG4gICAgICBsb2coY2hhbGsuYmx1ZSgnVXNpbmcgTGV4IFN0b3J5Ym9vayBjb25maWd1cmF0aW9uICgtLXVzZS1sZXgtY29uZmlnIGZsYWcpJyksICdpbmZvJywgcXVpZXQpO1xuICAgIH1cbiAgICBsb2coY2hhbGsuZ3JheShgSW5pdGlhbCBjb25maWcgZGlyOiAke2NvbmZpZ0Rpcn1gKSwgJ2luZm8nLCBxdWlldCk7XG4gIH1cblxuICBpZihjb25maWdEaXIgPT09IGxleENvbmZpZ0Rpcikge1xuICAgIGlmKCFxdWlldCkge1xuICAgICAgbG9nKGNoYWxrLmJsdWUoJ1VzaW5nIExleCBjb25maWcsIHdpbGwgY3JlYXRlIHRlbXBvcmFyeSBjb25maWcgaW4gcHJvamVjdCAuc3Rvcnlib29rIGRpcmVjdG9yeScpLCAnaW5mbycsIHF1aWV0KTtcbiAgICB9XG4gICAgY29uc3QgcHJvamVjdFN0b3J5Ym9va0RpciA9IHBhdGhSZXNvbHZlKHByb2Nlc3MuY3dkKCksICcuc3Rvcnlib29rJyk7XG5cbiAgICBjb25zdCBmcyA9IGF3YWl0IGltcG9ydCgnZnMvcHJvbWlzZXMnKTtcbiAgICBhd2FpdCBmcy5ta2Rpcihwcm9qZWN0U3Rvcnlib29rRGlyLCB7cmVjdXJzaXZlOiB0cnVlfSk7XG5cbiAgICBjb25zdCBsZXhNYWluUGF0aCA9IHBhdGhSZXNvbHZlKGxleENvbmZpZ0RpciwgJ21haW4udHMnKTtcbiAgICBjb25zdCBwcm9qZWN0TWFpblBhdGggPSBwYXRoUmVzb2x2ZShwcm9qZWN0U3Rvcnlib29rRGlyLCAnbWFpbi50cycpO1xuICAgIGxldCBtYWluQ29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGxleE1haW5QYXRoLCAndXRmOCcpO1xuXG4gICAgbWFpbkNvbnRlbnQgPSBtYWluQ29udGVudC5yZXBsYWNlKFxuICAgICAgL3N0b3JpZXM6XFxzKlxcWy4qP1xcXS8sXG4gICAgICBgc3RvcmllczogWycke3BhdGhSZXNvbHZlKHByb2Nlc3MuY3dkKCksICdzcmMvKiovKi5zdG9yaWVzLkAodHN8dHN4KScpfScsICcke3BhdGhSZXNvbHZlKHByb2Nlc3MuY3dkKCksICdzcmMvKiovKi5tZHgnKX0nXWBcbiAgICApO1xuXG4gICAgY29uc3QgbGV4Tm9kZU1vZHVsZXMgPSBwYXRoUmVzb2x2ZShMZXhDb25maWcuZ2V0TGV4RGlyKCksICdub2RlX21vZHVsZXMnKTtcbiAgICBtYWluQ29udGVudCA9IG1haW5Db250ZW50LnJlcGxhY2UoXG4gICAgICAvY29uc3QgbGV4TW9kdWxlID0gXFwobW9kdWxlUGF0aDogc3RyaW5nXFwpID0+IHJlc29sdmVcXChnZXRMZXhOb2RlTW9kdWxlc1BhdGhcXChcXCksIG1vZHVsZVBhdGhcXCk7LyxcbiAgICAgIGBjb25zdCBsZXhNb2R1bGUgPSAobW9kdWxlUGF0aDogc3RyaW5nKSA9PiByZXNvbHZlKCcke2xleE5vZGVNb2R1bGVzfScsIG1vZHVsZVBhdGgpO2BcbiAgICApO1xuXG4gICAgYXdhaXQgZnMud3JpdGVGaWxlKHByb2plY3RNYWluUGF0aCwgbWFpbkNvbnRlbnQpO1xuXG4gICAgY29uc3QgbGV4UHJldmlld1BhdGggPSBwYXRoUmVzb2x2ZShsZXhDb25maWdEaXIsICdwcmV2aWV3LnRzeCcpO1xuICAgIGlmKGV4aXN0c1N5bmMobGV4UHJldmlld1BhdGgpKSB7XG4gICAgICBjb25zdCBwcmV2aWV3Q29udGVudCA9IGF3YWl0IGZzLnJlYWRGaWxlKGxleFByZXZpZXdQYXRoLCAndXRmOCcpO1xuICAgICAgYXdhaXQgZnMud3JpdGVGaWxlKHBhdGhSZXNvbHZlKHByb2plY3RTdG9yeWJvb2tEaXIsICdwcmV2aWV3LnRzeCcpLCBwcmV2aWV3Q29udGVudCk7XG4gICAgfVxuXG4gICAgY29uZmlnRGlyID0gcHJvamVjdFN0b3J5Ym9va0RpcjtcbiAgfVxuICBpZighZXhpc3RzU3luYyhjb25maWdEaXIpKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdTdG9yeWJvb2sgY29uZmlndXJhdGlvbiBub3QgZm91bmQuJyk7XG4gICAgbG9nKGBQcm9qZWN0IGNvbmZpZzogJHtwcm9qZWN0Q29uZmlnRGlyfWAsICdpbmZvJywgcXVpZXQpO1xuICAgIGxvZyhgTGV4IGNvbmZpZzogJHtsZXhDb25maWdEaXJ9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgbG9nKCdQbGVhc2UgcnVuIFwibnB4IHN0b3J5Ym9va0BsYXRlc3QgaW5pdFwiIHRvIHNldCB1cCBTdG9yeWJvb2sgaW4geW91ciBwcm9qZWN0LCBvciBlbnN1cmUgTGV4IGhhcyBhIHZhbGlkIC5zdG9yeWJvb2sgY29uZmlndXJhdGlvbi4nLCAnaW5mbycsIHF1aWV0KTtcbiAgICBjYWxsYmFjaygxKTtcbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIGNvbnN0IHN0b3J5Ym9va1BhdGggPSByZXNvbHZlQmluYXJ5UGF0aCgnc3Rvcnlib29rJyk7XG5cbiAgaWYoIXN0b3J5Ym9va1BhdGgpIHtcbiAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6IHN0b3J5Ym9vayBiaW5hcnkgbm90IGZvdW5kIGluIExleCdzIG5vZGVfbW9kdWxlcyBvciBtb25vcmVwbyByb290YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIGxvZygnUGxlYXNlIHJlaW5zdGFsbCBMZXggb3IgY2hlY2sgeW91ciBTdG9yeWJvb2sgaW5zdGFsbGF0aW9uLicsICdpbmZvJywgcXVpZXQpO1xuICAgIGNhbGxiYWNrKDEpO1xuICAgIHJldHVybiAxO1xuICB9XG5cbiAgY29uc3Qgc3Rvcnlib29rQXJncyA9IFtzdGF0aWNCdWlsZCA/ICdidWlsZCcgOiAnZGV2J107XG4gIHN0b3J5Ym9va0FyZ3MucHVzaCgnLS1jb25maWctZGlyJywgY29uZmlnRGlyKTtcblxuICBpZihwb3J0KSB7XG4gICAgc3Rvcnlib29rQXJncy5wdXNoKCctLXBvcnQnLCBwb3J0LnRvU3RyaW5nKCkpO1xuICB9XG5cbiAgaWYob3Blbikge1xuICAgIHN0b3J5Ym9va0FyZ3MucHVzaCgnLS1vcGVuJyk7XG4gIH1cblxuICBpZihzdGF0aWNCdWlsZCkge1xuICAgIGNvbnN0IG91dHB1dERpciA9IHBhdGhSZXNvbHZlKHByb2Nlc3MuY3dkKCksICdzdG9yeWJvb2stc3RhdGljJyk7XG4gICAgc3Rvcnlib29rQXJncy5wdXNoKCctLW91dHB1dC1kaXInLCBvdXRwdXREaXIpO1xuICB9XG5cbiAgaWYoIXF1aWV0KSB7XG4gICAgbG9nKGNoYWxrLmdyYXkoYENvbmZpZyBkaXJlY3Rvcnk6ICR7Y29uZmlnRGlyfWApLCAnaW5mbycsIHF1aWV0KTtcbiAgfVxuXG4gIHByb2Nlc3MuZW52LlRBSUxXSU5EX0NTU19QQVRIID0gdGFpbHdpbmRDc3NQYXRoO1xuXG4gIHRyeSB7XG4gICAgc3Bpbm5lci5zdGFydChzdGF0aWNCdWlsZCA/ICdCdWlsZGluZyBzdGF0aWMgU3Rvcnlib29rLi4uJyA6ICdTdGFydGluZyBTdG9yeWJvb2sgZGV2ZWxvcG1lbnQgc2VydmVyLi4uJyk7XG5cbiAgICBjb25zdCBzdG9yeWJvb2tQcm9jZXNzID0gZXhlY2Eoc3Rvcnlib29rUGF0aCBhcyBhbnksIHN0b3J5Ym9va0FyZ3MsIHtcbiAgICAgIGVuY29kaW5nOiAndXRmOCcsXG4gICAgICBlbnY6IHtcbiAgICAgICAgLi4ucHJvY2Vzcy5lbnYsXG4gICAgICAgIExFWF9RVUlFVDogcXVpZXQsXG4gICAgICAgIExFWF9WRVJCT1NFOiB2ZXJib3NlLFxuICAgICAgICBTVE9SWUJPT0tfT1BFTjogb3BlbixcbiAgICAgICAgLi4uKHRhaWx3aW5kQ3NzUGF0aCAmJiB7VEFJTFdJTkRfQ1NTX1BBVEg6IHRhaWx3aW5kQ3NzUGF0aH0pXG4gICAgICB9IGFzIGFueSxcbiAgICAgIHN0ZGlvOiAncGlwZSdcbiAgICB9KTtcblxuICAgIGxldCB1cmxGb3VuZCA9IGZhbHNlO1xuICAgIGxldCBsYXN0UHJvZ3Jlc3NQZXJjZW50YWdlID0gMDtcblxuICAgIHN0b3J5Ym9va1Byb2Nlc3Muc3Rkb3V0Py5vbignZGF0YScsIChkYXRhKSA9PiB7XG4gICAgICBjb25zdCBvdXRwdXQgPSBkYXRhLnRvU3RyaW5nKCk7XG4gICAgICBjb25zdCBwcm9ncmVzc1BlcmNlbnRhZ2UgPSBleHRyYWN0UHJvZ3Jlc3NQZXJjZW50YWdlKG91dHB1dCk7XG5cbiAgICAgIGlmKHByb2dyZXNzUGVyY2VudGFnZSAhPT0gbnVsbCAmJiBwcm9ncmVzc1BlcmNlbnRhZ2UgIT09IGxhc3RQcm9ncmVzc1BlcmNlbnRhZ2UpIHtcbiAgICAgICAgbGFzdFByb2dyZXNzUGVyY2VudGFnZSA9IHByb2dyZXNzUGVyY2VudGFnZTtcbiAgICAgICAgY29uc3QgYWN0aW9uID0gc3RhdGljQnVpbGQgPyAnQnVpbGRpbmcnIDogJ1N0YXJ0aW5nJztcbiAgICAgICAgKHNwaW5uZXIgYXMgYW55KS50ZXh0ID0gYCR7YWN0aW9ufSBTdG9yeWJvb2suLi4gJHtwcm9ncmVzc1BlcmNlbnRhZ2V9JWA7XG4gICAgICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGBcXG5XZWJwYWNrIFByb2dyZXNzOiAke2NoYWxrLm1hZ2VudGEoYCR7cHJvZ3Jlc3NQZXJjZW50YWdlfSVgKX1cXG5gKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZmlsdGVyZWRPdXRwdXQgPSBmaWx0ZXJBbmRCZWF1dGlmeU91dHB1dChvdXRwdXQsIHZlcmJvc2UpO1xuICAgICAgY29uc3QgYmVhdXRpZmllZE91dHB1dCA9IGJlYXV0aWZ5T3V0cHV0KGZpbHRlcmVkT3V0cHV0KTtcblxuICAgICAgaWYoIXVybEZvdW5kICYmIChvdXRwdXQuaW5jbHVkZXMoJ0xvY2FsOicpIHx8IG91dHB1dC5pbmNsdWRlcygnaHR0cDovL2xvY2FsaG9zdCcpIHx8IG91dHB1dC5pbmNsdWRlcygnU3Rvcnlib29rJykpKSB7XG4gICAgICAgIHNwaW5uZXIuc3VjY2VlZChjaGFsay5ncmVlbignU3Rvcnlib29rIGRldmVsb3BtZW50IHNlcnZlciBpcyByZWFkeSEnKSk7XG4gICAgICAgIHVybEZvdW5kID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYoZmlsdGVyZWRPdXRwdXQudHJpbSgpKSB7XG4gICAgICAgIHByb2Nlc3Muc3Rkb3V0LndyaXRlKGJlYXV0aWZpZWRPdXRwdXQpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgc3Rvcnlib29rUHJvY2Vzcy5zdGRlcnI/Lm9uKCdkYXRhJywgKGRhdGEpID0+IHtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGRhdGEudG9TdHJpbmcoKTtcbiAgICAgIGNvbnN0IGZpbHRlcmVkT3V0cHV0ID0gZmlsdGVyQW5kQmVhdXRpZnlPdXRwdXQob3V0cHV0LCB2ZXJib3NlKTtcbiAgICAgIGNvbnN0IGJlYXV0aWZpZWRPdXRwdXQgPSBiZWF1dGlmeU91dHB1dChmaWx0ZXJlZE91dHB1dCk7XG5cbiAgICAgIGlmKGZpbHRlcmVkT3V0cHV0LnRyaW0oKSkge1xuICAgICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZShiZWF1dGlmaWVkT3V0cHV0KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBzdG9yeWJvb2tQcm9jZXNzO1xuICAgICAgaWYoIXVybEZvdW5kKSB7XG4gICAgICAgIHNwaW5uZXIuc3VjY2VlZChjaGFsay5ncmVlbignU3Rvcnlib29rIGRldmVsb3BtZW50IHNlcnZlciBzdGFydGVkLicpKTtcbiAgICAgIH1cbiAgICAgIGNhbGxiYWNrKDApO1xuICAgICAgcmV0dXJuIDA7XG4gICAgfSBjYXRjaChlcnJvcikge1xuICAgICAgc3Bpbm5lci5mYWlsKGNoYWxrLnJlZCgnVGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIHJ1bm5pbmcgc3Rvcnlib29rLicpKTtcbiAgICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIGNhbGxiYWNrKDEpO1xuICAgICAgcmV0dXJuIDE7XG4gICAgfVxuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgIHNwaW5uZXIuZmFpbCgnVGhlcmUgd2FzIGFuIGVycm9yIHdoaWxlIHJ1bm5pbmcgc3Rvcnlib29rLicpO1xuICAgIGNhbGxiYWNrKDEpO1xuICAgIHJldHVybiAxO1xuICB9XG59OyJdLCJuYW1lcyI6WyJjaGFsayIsImV4ZWNhIiwiZXhpc3RzU3luYyIsInN5bmMiLCJnbG9iU3luYyIsInJlc29sdmUiLCJwYXRoUmVzb2x2ZSIsIkxleENvbmZpZyIsImNyZWF0ZVNwaW5uZXIiLCJmaW5kVGFpbHdpbmRDc3NQYXRoIiwicmVzb2x2ZUJpbmFyeVBhdGgiLCJsb2ciLCJmaW5kU3RvcnlGaWxlcyIsInN0b3J5UGF0dGVybnMiLCJzdG9yeUZpbGVzIiwiZm9yRWFjaCIsInBhdHRlcm4iLCJmaWxlcyIsImN3ZCIsInByb2Nlc3MiLCJpZ25vcmUiLCJwdXNoIiwiY2hlY2tTdG9yeWJvb2tJbml0aWFsaXphdGlvbiIsInByb2plY3RDb25maWdEaXIiLCJsZXhDb25maWdEaXIiLCJnZXRMZXhEaXIiLCJleHRyYWN0UHJvZ3Jlc3NQZXJjZW50YWdlIiwib3V0cHV0IiwibGluZXMiLCJzcGxpdCIsImxpbmUiLCJpbmNsdWRlcyIsInBlcmNlbnRhZ2VNYXRjaCIsIm1hdGNoIiwicGFyc2VJbnQiLCJmaWx0ZXJBbmRCZWF1dGlmeU91dHB1dCIsImlzVmVyYm9zZSIsImZpbHRlcmVkTGluZXMiLCJmaWx0ZXIiLCJqb2luIiwiYmVhdXRpZnlPdXRwdXQiLCJyZXBsYWNlIiwiY3lhbiIsImJsdWUiLCJncmVlbiIsInJlZCIsInllbGxvdyIsIm1hZ2VudGEiLCJzdG9yeWJvb2siLCJjbWQiLCJjYWxsYmFjayIsImNsaU5hbWUiLCJjb25maWciLCJvcGVuIiwicG9ydCIsInF1aWV0Iiwic3RhdGljIiwic3RhdGljQnVpbGQiLCJ1c2VMZXhDb25maWciLCJ2YXJpYWJsZXMiLCJ2ZXJib3NlIiwic3Bpbm5lciIsInBhcnNlQ29uZmlnIiwidmFyaWFibGVzT2JqIiwiTk9ERV9FTlYiLCJKU09OIiwicGFyc2UiLCJfZXJyb3IiLCJlbnYiLCJzdGFydCIsImxlbmd0aCIsImZhaWwiLCJzdWNjZWVkIiwidGFpbHdpbmRDc3NQYXRoIiwiY29uc29sZSIsImdyYXkiLCJjb25maWdEaXIiLCJwcm9qZWN0U3Rvcnlib29rRGlyIiwiZnMiLCJta2RpciIsInJlY3Vyc2l2ZSIsImxleE1haW5QYXRoIiwicHJvamVjdE1haW5QYXRoIiwibWFpbkNvbnRlbnQiLCJyZWFkRmlsZSIsImxleE5vZGVNb2R1bGVzIiwid3JpdGVGaWxlIiwibGV4UHJldmlld1BhdGgiLCJwcmV2aWV3Q29udGVudCIsInN0b3J5Ym9va1BhdGgiLCJzdG9yeWJvb2tBcmdzIiwidG9TdHJpbmciLCJvdXRwdXREaXIiLCJUQUlMV0lORF9DU1NfUEFUSCIsInN0b3J5Ym9va1Byb2Nlc3MiLCJlbmNvZGluZyIsIkxFWF9RVUlFVCIsIkxFWF9WRVJCT1NFIiwiU1RPUllCT09LX09QRU4iLCJzdGRpbyIsInVybEZvdW5kIiwibGFzdFByb2dyZXNzUGVyY2VudGFnZSIsInN0ZG91dCIsIm9uIiwiZGF0YSIsInByb2dyZXNzUGVyY2VudGFnZSIsImFjdGlvbiIsInRleHQiLCJ3cml0ZSIsImZpbHRlcmVkT3V0cHV0IiwiYmVhdXRpZmllZE91dHB1dCIsInRyaW0iLCJzdGRlcnIiLCJlcnJvciIsIm1lc3NhZ2UiXSwibWFwcGluZ3MiOiJBQUFBLE9BQU9BLFdBQVcsUUFBUTtBQUMxQixTQUFRQyxLQUFLLFFBQU8sUUFBUTtBQUM1QixTQUFRQyxVQUFVLFFBQU8sS0FBSztBQUM5QixTQUFRQyxRQUFRQyxRQUFRLFFBQU8sT0FBTztBQUN0QyxTQUFRQyxXQUFXQyxXQUFXLFFBQU8sT0FBTztBQUU1QyxTQUFRQyxTQUFTLFFBQU8scUJBQXFCO0FBQzdDLFNBQVFDLGFBQWEsUUFBTyxxQkFBcUI7QUFDakQsU0FBUUMsbUJBQW1CLEVBQUVDLGlCQUFpQixRQUFPLHNCQUFzQjtBQUMzRSxTQUFRQyxHQUFHLFFBQU8scUJBQXFCO0FBZ0J2QyxNQUFNQyxpQkFBaUI7SUFDckIsTUFBTUMsZ0JBQWdCO1FBQ3BCO1FBQ0E7UUFDQTtLQUNEO0lBRUQsTUFBTUMsYUFBdUIsRUFBRTtJQUUvQkQsY0FBY0UsT0FBTyxDQUFDLENBQUNDO1FBQ3JCLE1BQU1DLFFBQVFiLFNBQVNZLFNBQVM7WUFDOUJFLEtBQUtDLFFBQVFELEdBQUc7WUFDaEJFLFFBQVE7Z0JBQUM7Z0JBQXNCO2dCQUFjO2dCQUFhO2FBQWM7UUFDMUU7UUFDQU4sV0FBV08sSUFBSSxJQUFJSjtJQUNyQjtJQUVBLE9BQU9IO0FBQ1Q7QUFFQSxNQUFNUSwrQkFBK0I7SUFDbkMsTUFBTUMsbUJBQW1CakIsWUFBWWEsUUFBUUQsR0FBRyxJQUFJO0lBQ3BELE1BQU1NLGVBQWVsQixZQUFZQyxVQUFVa0IsU0FBUyxJQUFJO0lBRXhELE9BQU92QixXQUFXcUIscUJBQXFCckIsV0FBV3NCO0FBQ3BEO0FBRUEsTUFBTUUsNEJBQTRCLENBQUNDO0lBQ2pDLE1BQU1DLFFBQVFELE9BQU9FLEtBQUssQ0FBQztJQUMzQixLQUFJLE1BQU1DLFFBQVFGLE1BQU87UUFDdkIsSUFBR0UsS0FBS0MsUUFBUSxDQUFDLHlCQUF5QkQsS0FBS0MsUUFBUSxDQUFDLE1BQU07WUFD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