@nlabs/lex
Version:
302 lines (301 loc) • 38 kB
JavaScript
/**
* Copyright (c) 2018-Present, Nitrogen Labs, Inc.
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
*/ import boxen from 'boxen';
import chalk from 'chalk';
import { copyFile, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'fs';
import { sync as globSync } from 'glob';
import isEmpty from 'lodash/isEmpty.js';
import ora from 'ora';
import { basename as pathBasename, join as pathJoin, relative as pathRelative, resolve as pathResolve } from 'path';
import { rimrafSync } from 'rimraf';
import { log } from './log.js';
export const cwd = process.cwd();
export const getFilenames = (props)=>{
const { callback, cliName, name, quiet, type, useTypescript } = props;
let nameCaps;
const itemTypes = [
'stores',
'views'
];
if (!name) {
if (itemTypes.includes(type)) {
log(`\n${cliName} Error: ${type} name is required. Please use 'lex -h' for options.`, 'error', quiet);
callback?.(1);
return undefined;
}
} else {
nameCaps = `${name.charAt(0).toUpperCase()}${name.substr(1)}`;
}
log(`${cliName} adding ${name} ${type}...`, 'info', quiet);
let templatePath;
let templateExt;
let templateReact;
if (useTypescript) {
templatePath = '../../templates/typescript';
templateExt = '.ts';
templateReact = '.tsx';
} else {
templatePath = '../../templates/flow';
templateExt = '.js';
templateReact = '.js';
}
return {
nameCaps,
templateExt,
templatePath,
templateReact
};
};
export const createSpinner = (quiet = false)=>{
if (quiet) {
return {
fail: ()=>{},
start: ()=>{},
succeed: ()=>{}
};
}
return ora({
color: 'yellow'
});
};
export const createProgressBar = (percentage)=>{
const width = 20;
const filled = Math.round(percentage / 100 * width);
const empty = width - filled;
const filledBar = chalk.cyan('█').repeat(filled);
const emptyBar = chalk.gray('░').repeat(empty);
return filledBar + emptyBar;
};
export const handleWebpackProgress = (output, spinner, quiet, emoji, action)=>{
if (quiet) {
return;
}
const progressMatch = output.match(/\[webpack\.Progress\] (\d+)%/);
if (progressMatch) {
const progress = parseInt(progressMatch[1]);
const progressBar = createProgressBar(progress);
spinner.text = `${emoji} ${action}: ${progressBar} ${progress}%`;
} else if (output.includes('[webpack.Progress]')) {
const generalProgressMatch = output.match(/(\d+)%/);
if (generalProgressMatch) {
const progress = parseInt(generalProgressMatch[1]);
const progressBar = createProgressBar(progress);
spinner.text = `${emoji} ${action}: ${progressBar} ${progress}%`;
}
}
};
export const copyFiles = async (files, typeName, spinner, config)=>{
const { outputFullPath, sourceFullPath } = config;
const items = files.map((fileName)=>({
from: fileName,
to: pathResolve(outputFullPath, pathRelative(sourceFullPath, fileName))
}));
try {
spinner.start(`Copying ${typeName} files...`);
await Promise.all(items.map(({ from, to })=>new Promise((resolve, reject)=>{
mkdirSync(pathResolve(to, '..'), {
recursive: true
});
return copyFile(from, to, (copyError)=>{
if (copyError) {
reject();
} else {
resolve(true);
}
});
})));
spinner.succeed(`Successfully copied ${files.length} ${typeName} files!`);
} catch (error) {
spinner.fail(`Copying of ${typeName} files failed.`);
log(`Error: ${error.message}`, 'error');
log(error, 'error');
}
};
export const copyConfiguredFiles = async (spinner, config, quiet)=>{
const { copyFiles: copyFilesConfig, outputFullPath, sourceFullPath, sourcePath } = config;
if (!copyFilesConfig || copyFilesConfig.length === 0) {
return;
}
try {
spinner.start('Copying configured files...');
let totalCopied = 0;
const baseDir = sourceFullPath || (sourcePath ? pathResolve(cwd, sourcePath) : cwd);
const allCopyPromises = [];
for (const pattern of copyFilesConfig){
const resolvedPattern = pathResolve(baseDir, pattern);
const matchingFiles = globSync(resolvedPattern, {
absolute: true,
nodir: true
});
if (matchingFiles.length === 0) {
if (!quiet) {
log(`Warning: No files found matching pattern: ${pattern}`, 'warn', quiet);
}
continue;
}
const copyPromises = matchingFiles.map((sourceFile)=>{
const relativePath = pathRelative(baseDir, sourceFile);
const destPath = pathResolve(outputFullPath, relativePath);
const destDir = pathResolve(destPath, '..');
mkdirSync(destDir, {
recursive: true
});
return new Promise((resolve, reject)=>{
copyFile(sourceFile, destPath, (copyError)=>{
if (copyError) {
reject(copyError);
} else {
resolve(true);
}
});
});
});
allCopyPromises.push(...copyPromises);
totalCopied += matchingFiles.length;
}
await Promise.all(allCopyPromises);
if (totalCopied > 0) {
spinner.succeed(`Successfully copied ${totalCopied} configured files!`);
} else {
spinner.succeed('No configured files to copy');
}
} catch (error) {
spinner.fail('Failed to copy configured files');
log(`Error copying configured files: ${error.message}`, 'error', quiet);
throw error;
}
};
export const copyFileSync = (source, target)=>{
let targetFile = target;
if (existsSync(target)) {
if (lstatSync(target).isDirectory()) {
targetFile = pathJoin(target, pathBasename(source));
}
}
writeFileSync(targetFile, readFileSync(source));
};
export const copyFolderRecursiveSync = (source, target)=>{
let files = [];
const targetFolder = pathJoin(target, pathBasename(source));
if (!existsSync(targetFolder)) {
mkdirSync(targetFolder);
}
if (lstatSync(source).isDirectory()) {
files = readdirSync(source);
files.forEach((file)=>{
const curSource = pathJoin(source, file);
if (lstatSync(curSource).isDirectory()) {
copyFolderRecursiveSync(curSource, targetFolder);
} else {
copyFileSync(curSource, targetFolder);
}
});
}
};
export const getPackageJson = (packagePath)=>{
const formatPath = packagePath || `${process.cwd()}/package.json`;
const packageData = readFileSync(formatPath).toString();
return JSON.parse(packageData);
};
export const getFilesByExt = (ext, config)=>{
const { sourceFullPath } = config;
return globSync(`**/**${ext}`, {
absolute: true,
cwd: sourceFullPath,
nodir: true
});
};
export const removeConflictModules = (moduleList)=>{
const updatedList = {
...moduleList
};
Object.keys(updatedList).forEach((moduleName)=>{
const regex = new RegExp('^(?!@types/).*?(jest|webpack).*$', 'gi');
if (regex.test(moduleName)) {
delete updatedList[moduleName];
}
});
return updatedList;
};
export const removeFiles = (fileName, isRelative = false)=>new Promise((resolve, reject)=>{
const filePath = isRelative ? pathResolve(cwd, fileName) : fileName;
try {
rimrafSync(filePath);
return resolve(null);
} catch (error) {
return reject(error);
}
});
export const removeModules = ()=>new Promise(async (resolve, reject)=>{
try {
await removeFiles('./node_modules', true);
await removeFiles('./yarn.lock', true);
await removeFiles('./package-lock.json', true);
resolve(null);
} catch (error) {
reject(error);
}
});
export const setPackageJson = (json, packagePath)=>{
if (!json) {
return;
}
const formatPath = packagePath || `${process.cwd()}/package.json`;
writeFileSync(formatPath, JSON.stringify(json, null, 2));
};
export const linkedModules = (startPath)=>{
const workingPath = startPath || process.cwd();
let modulePath;
let prefix;
if (workingPath.includes('@')) {
prefix = `@${workingPath.split('@').pop()}`;
modulePath = workingPath;
} else {
modulePath = pathJoin(workingPath, 'node_modules');
}
const foundPaths = globSync('*', {
absolute: true,
cwd: modulePath,
nodir: false
});
return foundPaths.reduce((list, foundPath)=>{
try {
const stats = lstatSync(foundPath);
if (stats.isDirectory()) {
const deepList = linkedModules(foundPath);
list.push(...deepList);
} else if (stats.isSymbolicLink()) {
const moduleNames = [
prefix,
pathBasename(foundPath)
].filter((item)=>!isEmpty(item));
list.push({
name: `${moduleNames.join('/')}`,
path: foundPath
});
}
return list;
} catch {
return list;
}
}, []);
};
export const checkLinkedModules = ()=>{
const linked = linkedModules();
if (linked.length) {
const msgModule = linked.length > 1 ? 'Modules' : 'Module';
const linkedMsg = linked.reduce((msg, linkedModule)=>`${msg}\n * ${linkedModule.name}`, `Linked ${msgModule}:`);
log(boxen(linkedMsg, {
dimBorder: true,
padding: 1
}), 'warn');
}
};
export const updateTemplateName = (filePath, replace, replaceCaps)=>{
let data = readFileSync(filePath, 'utf8');
data = data.replace(/sample/g, replace);
data = data.replace(/Sample/g, replaceCaps);
writeFileSync(filePath, data, 'utf8');
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91dGlscy9hcHAudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cblxuaW1wb3J0IGJveGVuIGZyb20gJ2JveGVuJztcbmltcG9ydCBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQge2NvcHlGaWxlLCBleGlzdHNTeW5jLCBsc3RhdFN5bmMsIG1rZGlyU3luYywgcmVhZGRpclN5bmMsIHJlYWRGaWxlU3luYywgd3JpdGVGaWxlU3luY30gZnJvbSAnZnMnO1xuaW1wb3J0IHtzeW5jIGFzIGdsb2JTeW5jfSBmcm9tICdnbG9iJztcbmltcG9ydCBpc0VtcHR5IGZyb20gJ2xvZGFzaC9pc0VtcHR5LmpzJztcbmltcG9ydCBvcmEgZnJvbSAnb3JhJztcbmltcG9ydCB7YmFzZW5hbWUgYXMgcGF0aEJhc2VuYW1lLCBqb2luIGFzIHBhdGhKb2luLCByZWxhdGl2ZSBhcyBwYXRoUmVsYXRpdmUsIHJlc29sdmUgYXMgcGF0aFJlc29sdmV9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHtyaW1yYWZTeW5jfSBmcm9tICdyaW1yYWYnO1xuXG5cbmltcG9ydCB7bG9nfSBmcm9tICcuL2xvZy5qcyc7XG5cbmltcG9ydCB0eXBlIHtMZXhDb25maWdUeXBlfSBmcm9tICcuLi9MZXhDb25maWcuanMnO1xuXG5cbmV4cG9ydCBjb25zdCBjd2Q6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0RmlsZW5hbWVzUHJvcHMge1xuICByZWFkb25seSBjYWxsYmFjaz86IChzdGF0dXM6IG51bWJlcik9PiB2b2lkO1xuICByZWFkb25seSBjbGlOYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBuYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBxdWlldD86IGJvb2xlYW47XG4gIHJlYWRvbmx5IHR5cGU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHVzZVR5cGVzY3JpcHQ/OiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgRmlsZW5hbWVzUmVzdWx0IHtcbiAgbmFtZUNhcHM6IHN0cmluZztcbiAgdGVtcGxhdGVFeHQ6IHN0cmluZztcbiAgdGVtcGxhdGVQYXRoOiBzdHJpbmc7XG4gIHRlbXBsYXRlUmVhY3Q6IHN0cmluZztcbn1cblxuZXhwb3J0IGNvbnN0IGdldEZpbGVuYW1lcyA9IChwcm9wczogR2V0RmlsZW5hbWVzUHJvcHMpOiBGaWxlbmFtZXNSZXN1bHQgfCB1bmRlZmluZWQgPT4ge1xuICBjb25zdCB7Y2FsbGJhY2ssIGNsaU5hbWUsIG5hbWUsIHF1aWV0LCB0eXBlLCB1c2VUeXBlc2NyaXB0fSA9IHByb3BzO1xuXG4gIGxldCBuYW1lQ2Fwczogc3RyaW5nO1xuICBjb25zdCBpdGVtVHlwZXM6IHN0cmluZ1tdID0gWydzdG9yZXMnLCAndmlld3MnXTtcblxuICBpZighbmFtZSkge1xuICAgIGlmKGl0ZW1UeXBlcy5pbmNsdWRlcyh0eXBlKSkge1xuICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiAke3R5cGV9IG5hbWUgaXMgcmVxdWlyZWQuIFBsZWFzZSB1c2UgJ2xleCAtaCcgZm9yIG9wdGlvbnMuYCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgY2FsbGJhY2s/LigxKTtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIG5hbWVDYXBzID0gYCR7bmFtZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke25hbWUuc3Vic3RyKDEpfWA7XG4gIH1cblxuICBsb2coYCR7Y2xpTmFtZX0gYWRkaW5nICR7bmFtZX0gJHt0eXBlfS4uLmAsICdpbmZvJywgcXVpZXQpO1xuXG4gIGxldCB0ZW1wbGF0ZVBhdGg6IHN0cmluZztcbiAgbGV0IHRlbXBsYXRlRXh0OiBzdHJpbmc7XG4gIGxldCB0ZW1wbGF0ZVJlYWN0OiBzdHJpbmc7XG5cbiAgaWYodXNlVHlwZXNjcmlwdCkge1xuICAgIHRlbXBsYXRlUGF0aCA9ICcuLi8uLi90ZW1wbGF0ZXMvdHlwZXNjcmlwdCc7XG4gICAgdGVtcGxhdGVFeHQgPSAnLnRzJztcbiAgICB0ZW1wbGF0ZVJlYWN0ID0gJy50c3gnO1xuICB9IGVsc2Uge1xuICAgIHRlbXBsYXRlUGF0aCA9ICcuLi8uLi90ZW1wbGF0ZXMvZmxvdyc7XG4gICAgdGVtcGxhdGVFeHQgPSAnLmpzJztcbiAgICB0ZW1wbGF0ZVJlYWN0ID0gJy5qcyc7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIG5hbWVDYXBzLFxuICAgIHRlbXBsYXRlRXh0LFxuICAgIHRlbXBsYXRlUGF0aCxcbiAgICB0ZW1wbGF0ZVJlYWN0XG4gIH07XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIFNwaW5uZXIge1xuICBmYWlsOiAodGV4dD86IHN0cmluZyk9PiB2b2lkO1xuICBzdGFydDogKHRleHQ/OiBzdHJpbmcpPT4gdm9pZDtcbiAgc3VjY2VlZDogKHRleHQ/OiBzdHJpbmcpPT4gdm9pZDtcbiAgdGV4dD86IHN0cmluZztcbn1cblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVNwaW5uZXIgPSAocXVpZXQgPSBmYWxzZSk6IFNwaW5uZXIgPT4ge1xuICBpZihxdWlldCkge1xuICAgIHJldHVybiB7XG4gICAgICBmYWlsOiAoKSA9PiB7fSxcbiAgICAgIHN0YXJ0OiAoKSA9PiB7fSxcbiAgICAgIHN1Y2NlZWQ6ICgpID0+IHt9XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBvcmEoe2NvbG9yOiAneWVsbG93J30pO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVByb2dyZXNzQmFyID0gKHBlcmNlbnRhZ2U6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IHdpZHRoID0gMjA7XG4gIGNvbnN0IGZpbGxlZCA9IE1hdGgucm91bmQoKHBlcmNlbnRhZ2UgLyAxMDApICogd2lkdGgpO1xuICBjb25zdCBlbXB0eSA9IHdpZHRoIC0gZmlsbGVkO1xuXG4gIGNvbnN0IGZpbGxlZEJhciA9IGNoYWxrLmN5YW4oJ+KWiCcpLnJlcGVhdChmaWxsZWQpO1xuICBjb25zdCBlbXB0eUJhciA9IGNoYWxrLmdyYXkoJ+KWkScpLnJlcGVhdChlbXB0eSk7XG5cbiAgcmV0dXJuIGZpbGxlZEJhciArIGVtcHR5QmFyO1xufTtcblxuZXhwb3J0IGNvbnN0IGhhbmRsZVdlYnBhY2tQcm9ncmVzcyA9IChcbiAgb3V0cHV0OiBzdHJpbmcsXG4gIHNwaW5uZXI6IFNwaW5uZXIsXG4gIHF1aWV0OiBib29sZWFuLFxuICBlbW9qaTogc3RyaW5nLFxuICBhY3Rpb246IHN0cmluZ1xuKTogdm9pZCA9PiB7XG4gIGlmKHF1aWV0KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgcHJvZ3Jlc3NNYXRjaCA9IG91dHB1dC5tYXRjaCgvXFxbd2VicGFja1xcLlByb2dyZXNzXFxdIChcXGQrKSUvKTtcbiAgaWYocHJvZ3Jlc3NNYXRjaCkge1xuICAgIGNvbnN0IHByb2dyZXNzID0gcGFyc2VJbnQocHJvZ3Jlc3NNYXRjaFsxXSk7XG4gICAgY29uc3QgcHJvZ3Jlc3NCYXIgPSBjcmVhdGVQcm9ncmVzc0Jhcihwcm9ncmVzcyk7XG4gICAgc3Bpbm5lci50ZXh0ID0gYCR7ZW1vaml9ICR7YWN0aW9ufTogJHtwcm9ncmVzc0Jhcn0gJHtwcm9ncmVzc30lYDtcbiAgfSBlbHNlIGlmKG91dHB1dC5pbmNsdWRlcygnW3dlYnBhY2suUHJvZ3Jlc3NdJykpIHtcbiAgICBjb25zdCBnZW5lcmFsUHJvZ3Jlc3NNYXRjaCA9IG91dHB1dC5tYXRjaCgvKFxcZCspJS8pO1xuICAgIGlmKGdlbmVyYWxQcm9ncmVzc01hdGNoKSB7XG4gICAgICBjb25zdCBwcm9ncmVzcyA9IHBhcnNlSW50KGdlbmVyYWxQcm9ncmVzc01hdGNoWzFdKTtcbiAgICAgIGNvbnN0IHByb2dyZXNzQmFyID0gY3JlYXRlUHJvZ3Jlc3NCYXIocHJvZ3Jlc3MpO1xuICAgICAgc3Bpbm5lci50ZXh0ID0gYCR7ZW1vaml9ICR7YWN0aW9ufTogJHtwcm9ncmVzc0Jhcn0gJHtwcm9ncmVzc30lYDtcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBjb3B5RmlsZXMgPSBhc3luYyAoZmlsZXM6IHN0cmluZ1tdLCB0eXBlTmFtZTogc3RyaW5nLCBzcGlubmVyLCBjb25maWc6IExleENvbmZpZ1R5cGUpID0+IHtcbiAgY29uc3Qge291dHB1dEZ1bGxQYXRoLCBzb3VyY2VGdWxsUGF0aH0gPSBjb25maWc7XG4gIGNvbnN0IGl0ZW1zID0gZmlsZXMubWFwKChmaWxlTmFtZTogc3RyaW5nKSA9PiAoe1xuICAgIGZyb206IGZpbGVOYW1lLFxuICAgIHRvOiBwYXRoUmVzb2x2ZShvdXRwdXRGdWxsUGF0aCwgcGF0aFJlbGF0aXZlKHNvdXJjZUZ1bGxQYXRoLCBmaWxlTmFtZSkpXG4gIH0pKTtcblxuICB0cnkge1xuICAgIHNwaW5uZXIuc3RhcnQoYENvcHlpbmcgJHt0eXBlTmFtZX0gZmlsZXMuLi5gKTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChpdGVtcy5tYXAoKHtmcm9tLCB0b30pID0+IG5ldyBQcm9taXNlKFxuICAgICAgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBta2RpclN5bmMocGF0aFJlc29sdmUodG8sICcuLicpLCB7cmVjdXJzaXZlOiB0cnVlfSk7XG4gICAgICAgIHJldHVybiBjb3B5RmlsZShmcm9tLCB0bywgKGNvcHlFcnJvcikgPT4ge1xuICAgICAgICAgIGlmKGNvcHlFcnJvcikge1xuICAgICAgICAgICAgcmVqZWN0KCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICApKSk7XG4gICAgc3Bpbm5lci5zdWNjZWVkKGBTdWNjZXNzZnVsbHkgY29waWVkICR7ZmlsZXMubGVuZ3RofSAke3R5cGVOYW1lfSBmaWxlcyFgKTtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIHNwaW5uZXIuZmFpbChgQ29weWluZyBvZiAke3R5cGVOYW1lfSBmaWxlcyBmYWlsZWQuYCk7XG4gICAgbG9nKGBFcnJvcjogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicpO1xuICAgIGxvZyhlcnJvciwgJ2Vycm9yJyk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBjb3B5Q29uZmlndXJlZEZpbGVzID0gYXN5bmMgKHNwaW5uZXIsIGNvbmZpZzogTGV4Q29uZmlnVHlwZSwgcXVpZXQ6IGJvb2xlYW4pID0+IHtcbiAgY29uc3Qge2NvcHlGaWxlczogY29weUZpbGVzQ29uZmlnLCBvdXRwdXRGdWxsUGF0aCwgc291cmNlRnVsbFBhdGgsIHNvdXJjZVBhdGh9ID0gY29uZmlnO1xuICBpZighY29weUZpbGVzQ29uZmlnIHx8IGNvcHlGaWxlc0NvbmZpZy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB0cnkge1xuICAgIHNwaW5uZXIuc3RhcnQoJ0NvcHlpbmcgY29uZmlndXJlZCBmaWxlcy4uLicpO1xuICAgIGxldCB0b3RhbENvcGllZCA9IDA7XG5cbiAgICBjb25zdCBiYXNlRGlyID0gc291cmNlRnVsbFBhdGggfHwgKHNvdXJjZVBhdGggPyBwYXRoUmVzb2x2ZShjd2QsIHNvdXJjZVBhdGgpIDogY3dkKTtcbiAgICBjb25zdCBhbGxDb3B5UHJvbWlzZXM6IFByb21pc2U8dW5rbm93bj5bXSA9IFtdO1xuXG4gICAgZm9yKGNvbnN0IHBhdHRlcm4gb2YgY29weUZpbGVzQ29uZmlnKSB7XG4gICAgICBjb25zdCByZXNvbHZlZFBhdHRlcm4gPSBwYXRoUmVzb2x2ZShiYXNlRGlyLCBwYXR0ZXJuKTtcbiAgICAgIGNvbnN0IG1hdGNoaW5nRmlsZXMgPSBnbG9iU3luYyhyZXNvbHZlZFBhdHRlcm4sIHtcbiAgICAgICAgYWJzb2x1dGU6IHRydWUsXG4gICAgICAgIG5vZGlyOiB0cnVlXG4gICAgICB9KTtcblxuICAgICAgaWYobWF0Y2hpbmdGaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgaWYoIXF1aWV0KSB7XG4gICAgICAgICAgbG9nKGBXYXJuaW5nOiBObyBmaWxlcyBmb3VuZCBtYXRjaGluZyBwYXR0ZXJuOiAke3BhdHRlcm59YCwgJ3dhcm4nLCBxdWlldCk7XG4gICAgICAgIH1cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvcHlQcm9taXNlcyA9IG1hdGNoaW5nRmlsZXMubWFwKChzb3VyY2VGaWxlKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IHBhdGhSZWxhdGl2ZShiYXNlRGlyLCBzb3VyY2VGaWxlKTtcbiAgICAgICAgY29uc3QgZGVzdFBhdGggPSBwYXRoUmVzb2x2ZShvdXRwdXRGdWxsUGF0aCwgcmVsYXRpdmVQYXRoKTtcbiAgICAgICAgY29uc3QgZGVzdERpciA9IHBhdGhSZXNvbHZlKGRlc3RQYXRoLCAnLi4nKTtcbiAgICAgICAgbWtkaXJTeW5jKGRlc3REaXIsIHtyZWN1cnNpdmU6IHRydWV9KTtcblxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgIGNvcHlGaWxlKHNvdXJjZUZpbGUsIGRlc3RQYXRoLCAoY29weUVycm9yKSA9PiB7XG4gICAgICAgICAgICBpZihjb3B5RXJyb3IpIHtcbiAgICAgICAgICAgICAgcmVqZWN0KGNvcHlFcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBhbGxDb3B5UHJvbWlzZXMucHVzaCguLi5jb3B5UHJvbWlzZXMpO1xuICAgICAgdG90YWxDb3BpZWQgKz0gbWF0Y2hpbmdGaWxlcy5sZW5ndGg7XG4gICAgfVxuXG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoYWxsQ29weVByb21pc2VzKTtcblxuICAgIGlmKHRvdGFsQ29waWVkID4gMCkge1xuICAgICAgc3Bpbm5lci5zdWNjZWVkKGBTdWNjZXNzZnVsbHkgY29waWVkICR7dG90YWxDb3BpZWR9IGNvbmZpZ3VyZWQgZmlsZXMhYCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwaW5uZXIuc3VjY2VlZCgnTm8gY29uZmlndXJlZCBmaWxlcyB0byBjb3B5Jyk7XG4gICAgfVxuICB9IGNhdGNoKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gY29weSBjb25maWd1cmVkIGZpbGVzJyk7XG4gICAgbG9nKGBFcnJvciBjb3B5aW5nIGNvbmZpZ3VyZWQgZmlsZXM6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBjb3B5RmlsZVN5bmMgPSAoc291cmNlOiBzdHJpbmcsIHRhcmdldDogc3RyaW5nKSA9PiB7XG4gIGxldCB0YXJnZXRGaWxlOiBzdHJpbmcgPSB0YXJnZXQ7XG5cbiAgaWYoZXhpc3RzU3luYyh0YXJnZXQpKSB7XG4gICAgaWYobHN0YXRTeW5jKHRhcmdldCkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgdGFyZ2V0RmlsZSA9IHBhdGhKb2luKHRhcmdldCwgcGF0aEJhc2VuYW1lKHNvdXJjZSkpO1xuICAgIH1cbiAgfVxuXG4gIHdyaXRlRmlsZVN5bmModGFyZ2V0RmlsZSwgcmVhZEZpbGVTeW5jKHNvdXJjZSkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvcHlGb2xkZXJSZWN1cnNpdmVTeW5jID0gKHNvdXJjZTogc3RyaW5nLCB0YXJnZXQ6IHN0cmluZyk6IHZvaWQgPT4ge1xuICBsZXQgZmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgY29uc3QgdGFyZ2V0Rm9sZGVyOiBzdHJpbmcgPSBwYXRoSm9pbih0YXJnZXQsIHBhdGhCYXNlbmFtZShzb3VyY2UpKTtcblxuICBpZighZXhpc3RzU3luYyh0YXJnZXRGb2xkZXIpKSB7XG4gICAgbWtkaXJTeW5jKHRhcmdldEZvbGRlcik7XG4gIH1cblxuICBpZihsc3RhdFN5bmMoc291cmNlKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgZmlsZXMgPSByZWFkZGlyU3luYyhzb3VyY2UpO1xuICAgIGZpbGVzLmZvckVhY2goKGZpbGU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgY3VyU291cmNlOiBzdHJpbmcgPSBwYXRoSm9pbihzb3VyY2UsIGZpbGUpO1xuXG4gICAgICBpZihsc3RhdFN5bmMoY3VyU291cmNlKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgIGNvcHlGb2xkZXJSZWN1cnNpdmVTeW5jKGN1clNvdXJjZSwgdGFyZ2V0Rm9sZGVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvcHlGaWxlU3luYyhjdXJTb3VyY2UsIHRhcmdldEZvbGRlcik7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBnZXRQYWNrYWdlSnNvbiA9IChwYWNrYWdlUGF0aD86IHN0cmluZykgPT4ge1xuICBjb25zdCBmb3JtYXRQYXRoOiBzdHJpbmcgPSBwYWNrYWdlUGF0aCB8fCBgJHtwcm9jZXNzLmN3ZCgpfS9wYWNrYWdlLmpzb25gO1xuICBjb25zdCBwYWNrYWdlRGF0YTogc3RyaW5nID0gcmVhZEZpbGVTeW5jKGZvcm1hdFBhdGgpLnRvU3RyaW5nKCk7XG5cbiAgcmV0dXJuIEpTT04ucGFyc2UocGFja2FnZURhdGEpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEZpbGVzQnlFeHQgPSAoZXh0OiBzdHJpbmcsIGNvbmZpZzogTGV4Q29uZmlnVHlwZSk6IHN0cmluZ1tdID0+IHtcbiAgY29uc3Qge3NvdXJjZUZ1bGxQYXRofSA9IGNvbmZpZztcbiAgcmV0dXJuIGdsb2JTeW5jKGAqKi8qKiR7ZXh0fWAsIHtcbiAgICBhYnNvbHV0ZTogdHJ1ZSxcbiAgICBjd2Q6IHNvdXJjZUZ1bGxQYXRoLFxuICAgIG5vZGlyOiB0cnVlXG4gIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlbW92ZUNvbmZsaWN0TW9kdWxlcyA9IChtb2R1bGVMaXN0OiBvYmplY3QpID0+IHtcbiAgY29uc3QgdXBkYXRlZExpc3Q6IG9iamVjdCA9IHsuLi5tb2R1bGVMaXN0fTtcblxuICBPYmplY3Qua2V5cyh1cGRhdGVkTGlzdCkuZm9yRWFjaCgobW9kdWxlTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgcmVnZXg6IFJlZ0V4cCA9IG5ldyBSZWdFeHAoJ14oPyFAdHlwZXMvKS4qPyhqZXN0fHdlYnBhY2spLiokJywgJ2dpJyk7XG4gICAgaWYocmVnZXgudGVzdChtb2R1bGVOYW1lKSkge1xuICAgICAgZGVsZXRlIHVwZGF0ZWRMaXN0W21vZHVsZU5hbWVdO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIHVwZGF0ZWRMaXN0O1xufTtcblxuZXhwb3J0IGNvbnN0IHJlbW92ZUZpbGVzID0gKGZpbGVOYW1lOiBzdHJpbmcsIGlzUmVsYXRpdmU6IGJvb2xlYW4gPSBmYWxzZSkgPT4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICBjb25zdCBmaWxlUGF0aDogc3RyaW5nID0gaXNSZWxhdGl2ZSA/IHBhdGhSZXNvbHZlKGN3ZCwgZmlsZU5hbWUpIDogZmlsZU5hbWU7XG5cbiAgdHJ5IHtcbiAgICByaW1yYWZTeW5jKGZpbGVQYXRoKTtcbiAgICByZXR1cm4gcmVzb2x2ZShudWxsKTtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIHJldHVybiByZWplY3QoZXJyb3IpO1xuICB9XG59KTtcblxuZXhwb3J0IGNvbnN0IHJlbW92ZU1vZHVsZXMgPSAoKSA9PiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gIHRyeSB7XG4gICAgYXdhaXQgcmVtb3ZlRmlsZXMoJy4vbm9kZV9tb2R1bGVzJywgdHJ1ZSk7XG4gICAgYXdhaXQgcmVtb3ZlRmlsZXMoJy4veWFybi5sb2NrJywgdHJ1ZSk7XG4gICAgYXdhaXQgcmVtb3ZlRmlsZXMoJy4vcGFja2FnZS1sb2NrLmpzb24nLCB0cnVlKTtcblxuICAgIHJlc29sdmUobnVsbCk7XG4gIH0gY2F0Y2goZXJyb3IpIHtcbiAgICByZWplY3QoZXJyb3IpO1xuICB9XG59KTtcblxuZXhwb3J0IGNvbnN0IHNldFBhY2thZ2VKc29uID0gKGpzb24sIHBhY2thZ2VQYXRoPzogc3RyaW5nKSA9PiB7XG4gIGlmKCFqc29uKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgZm9ybWF0UGF0aDogc3RyaW5nID0gcGFja2FnZVBhdGggfHwgYCR7cHJvY2Vzcy5jd2QoKX0vcGFja2FnZS5qc29uYDtcblxuICB3cml0ZUZpbGVTeW5jKGZvcm1hdFBhdGgsIEpTT04uc3RyaW5naWZ5KGpzb24sIG51bGwsIDIpKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGlua2VkTW9kdWxlVHlwZSB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgcGF0aDogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgbGlua2VkTW9kdWxlcyA9IChzdGFydFBhdGg/OiBzdHJpbmcpOiBMaW5rZWRNb2R1bGVUeXBlW10gPT4ge1xuICBjb25zdCB3b3JraW5nUGF0aDogc3RyaW5nID0gc3RhcnRQYXRoIHx8IHByb2Nlc3MuY3dkKCk7XG4gIGxldCBtb2R1bGVQYXRoOiBzdHJpbmc7XG4gIGxldCBwcmVmaXg6IHN0cmluZztcblxuICBpZih3b3JraW5nUGF0aC5pbmNsdWRlcygnQCcpKSB7XG4gICAgcHJlZml4ID0gYEAke3dvcmtpbmdQYXRoLnNwbGl0KCdAJykucG9wKCl9YDtcbiAgICBtb2R1bGVQYXRoID0gd29ya2luZ1BhdGg7XG4gIH0gZWxzZSB7XG4gICAgbW9kdWxlUGF0aCA9IHBhdGhKb2luKHdvcmtpbmdQYXRoLCAnbm9kZV9tb2R1bGVzJyk7XG4gIH1cblxuICBjb25zdCBmb3VuZFBhdGhzOiBzdHJpbmdbXSA9IGdsb2JTeW5jKCcqJywge1xuICAgIGFic29sdXRlOiB0cnVlLFxuICAgIGN3ZDogbW9kdWxlUGF0aCxcbiAgICBub2RpcjogZmFsc2VcbiAgfSk7XG5cbiAgcmV0dXJuIGZvdW5kUGF0aHMucmVkdWNlKChsaXN0OiBMaW5rZWRNb2R1bGVUeXBlW10sIGZvdW5kUGF0aDogc3RyaW5nKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YXRzID0gbHN0YXRTeW5jKGZvdW5kUGF0aCk7XG5cbiAgICAgIGlmKHN0YXRzLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgY29uc3QgZGVlcExpc3Q6IExpbmtlZE1vZHVsZVR5cGVbXSA9IGxpbmtlZE1vZHVsZXMoZm91bmRQYXRoKTtcbiAgICAgICAgbGlzdC5wdXNoKC4uLmRlZXBMaXN0KTtcbiAgICAgIH0gZWxzZSBpZihzdGF0cy5pc1N5bWJvbGljTGluaygpKSB7XG4gICAgICAgIGNvbnN0IG1vZHVsZU5hbWVzOiBzdHJpbmdbXSA9IChbcHJlZml4LCBwYXRoQmFzZW5hbWUoZm91bmRQYXRoKV0pLmZpbHRlcigoaXRlbTogc3RyaW5nKSA9PiAhaXNFbXB0eShpdGVtKSk7XG4gICAgICAgIGxpc3QucHVzaCh7bmFtZTogYCR7bW9kdWxlTmFtZXMuam9pbignLycpfWAsIHBhdGg6IGZvdW5kUGF0aH0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbGlzdDtcbiAgICB9IGNhdGNoe1xuICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgfVxuICB9LCBbXSk7XG59O1xuXG5leHBvcnQgY29uc3QgY2hlY2tMaW5rZWRNb2R1bGVzID0gKCkgPT4ge1xuICBjb25zdCBsaW5rZWQgPSBsaW5rZWRNb2R1bGVzKCk7XG5cbiAgaWYobGlua2VkLmxlbmd0aCkge1xuICAgIGNvbnN0IG1zZ01vZHVsZTogc3RyaW5nID0gbGlua2VkLmxlbmd0aCA+IDEgPyAnTW9kdWxlcycgOiAnTW9kdWxlJztcbiAgICBjb25zdCBsaW5rZWRNc2c6IHN0cmluZyA9IGxpbmtlZC5yZWR1Y2UoXG4gICAgICAobXNnOiBzdHJpbmcsIGxpbmtlZE1vZHVsZTogTGlua2VkTW9kdWxlVHlwZSkgPT5cbiAgICAgICAgYCR7bXNnfVxcbiAqICR7bGlua2VkTW9kdWxlLm5hbWV9YCxcbiAgICAgIGBMaW5rZWQgJHttc2dNb2R1bGV9OmBcbiAgICApO1xuXG4gICAgbG9nKGJveGVuKGxpbmtlZE1zZywge2RpbUJvcmRlcjogdHJ1ZSwgcGFkZGluZzogMX0pLCAnd2FybicpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgdXBkYXRlVGVtcGxhdGVOYW1lID0gKGZpbGVQYXRoOiBzdHJpbmcsIHJlcGxhY2U6IHN0cmluZywgcmVwbGFjZUNhcHM6IHN0cmluZykgPT4ge1xuICBsZXQgZGF0YTogc3RyaW5nID0gcmVhZEZpbGVTeW5jKGZpbGVQYXRoLCAndXRmOCcpO1xuICBkYXRhID0gZGF0YS5yZXBsYWNlKC9zYW1wbGUvZywgcmVwbGFjZSk7XG4gIGRhdGEgPSBkYXRhLnJlcGxhY2UoL1NhbXBsZS9nLCByZXBsYWNlQ2Fwcyk7XG4gIHdyaXRlRmlsZVN5bmMoZmlsZVBhdGgsIGRhdGEsICd1dGY4Jyk7XG59OyJdLCJuYW1lcyI6WyJib3hlbiIsImNoYWxrIiwiY29weUZpbGUiLCJleGlzdHNTeW5jIiwibHN0YXRTeW5jIiwibWtkaXJTeW5jIiwicmVhZGRpclN5bmMiLCJyZWFkRmlsZVN5bmMiLCJ3cml0ZUZpbGVTeW5jIiwic3luYyIsImdsb2JTeW5jIiwiaXNFbXB0eSIsIm9yYSIsImJhc2VuYW1lIiwicGF0aEJhc2VuYW1lIiwiam9pbiIsInBhdGhKb2luIiwicmVsYXRpdmUiLCJwYXRoUmVsYXRpdmUiLCJyZXNvbHZlIiwicGF0aFJlc29sdmUiLCJyaW1yYWZTeW5jIiwibG9nIiwiY3dkIiwicHJvY2VzcyIsImdldEZpbGVuYW1lcyIsInByb3BzIiwiY2FsbGJhY2siLCJjbGlOYW1lIiwibmFtZSIsInF1aWV0IiwidHlwZSIsInVzZVR5cGVzY3JpcHQiLCJuYW1lQ2FwcyIsIml0ZW1UeXBlcyIsImluY2x1ZGVzIiwidW5kZWZpbmVkIiwiY2hhckF0IiwidG9VcHBlckNhc2UiLCJzdWJzdHIiLCJ0ZW1wbGF0ZVBhdGgiLCJ0ZW1wbGF0ZUV4dCIsInRlbXBsYXRlUmVhY3QiLCJjcmVhdGVTcGlubmVyIiwiZmFpbCIsInN0YXJ0Iiwic3VjY2VlZCIsImNvbG9yIiwiY3JlYXRlUHJvZ3Jlc3NCYXIiLCJwZXJjZW50YWdlIiwid2lkdGgiLCJmaWxsZWQiLCJNYXRoIiwicm91bmQiLCJlbXB0eSIsImZpbGxlZEJhciIsImN5YW4iLCJyZXBlYXQiLCJlbXB0eUJhciIsImdyYXkiLCJoYW5kbGVXZWJwYWNrUHJvZ3Jlc3MiLCJvdXRwdXQiLCJzcGlubmVyIiwiZW1vamkiLCJhY3Rpb24iLCJwcm9ncmVzc01hdGNoIiwibWF0Y2giLCJwcm9ncmVzcyIsInBhcnNlSW50IiwicHJvZ3Jlc3NCYXIiLCJ0ZXh0IiwiZ2VuZXJhbFByb2dyZXNzTWF0Y2giLCJjb3B5RmlsZXMiLCJmaWxlcyIsInR5cGVOYW1lIiwiY29uZmlnIiwib3V0cHV0RnVsbFBhdGgiLCJzb3VyY2VGdWxsUGF0aCIsIml0ZW1zIiwibWFwIiwiZmlsZU5hbWUiLCJmcm9tIiwidG8iLCJQcm9taXNlIiwiYWxsIiwicmVqZWN0IiwicmVjdXJzaXZlIiwiY29weUVycm9yIiwibGVuZ3RoIiwiZXJyb3IiLCJtZXNzYWdlIiwiY29weUNvbmZpZ3VyZWRGaWxlcyIsImNvcHlGaWxlc0NvbmZpZyIsInNvdXJjZVBhdGgiLCJ0b3RhbENvcGllZCIsImJhc2VEaXIiLCJhbGxDb3B5UHJvbWlzZXMiLCJwYXR0ZXJuIiwicmVzb2x2ZWRQYXR0ZXJuIiwibWF0Y2hpbmdGaWxlcyIsImFic29sdXRlIiwibm9kaXIiLCJjb3B5UHJvbWlzZXMiLCJzb3VyY2VGaWxlIiwicmVsYXRpdmVQYXRoIiwiZGVzdFBhdGgiLCJkZXN0RGlyIiwicHVzaCIsImNvcHlGaWxlU3luYyIsInNvdXJjZSIsInRhcmdldCIsInRhcmdldEZpbGUiLCJpc0RpcmVjdG9yeSIsImNvcHlGb2xkZXJSZWN1cnNpdmVTeW5jIiwidGFyZ2V0Rm9sZGVyIiwiZm9yRWFjaCIsImZpbGUiLCJjdXJTb3VyY2UiLCJnZXRQYWNrYWdlSnNvbiIsInBhY2thZ2VQYXRoIiwiZm9ybWF0UGF0aCIsInBhY2thZ2VEYXRhIiwidG9TdHJpbmciLCJKU09OIiwicGFyc2UiLCJnZXRGaWxlc0J5RXh0IiwiZXh0IiwicmVtb3ZlQ29uZmxpY3RNb2R1bGVzIiwibW9kdWxlTGlzdCIsInVwZGF0ZWRMaXN0IiwiT2JqZWN0Iiwia2V5cyIsIm1vZHVsZU5hbWUiLCJyZWdleCIsIlJlZ0V4cCIsInRlc3QiLCJyZW1vdmVGaWxlcyIsImlzUmVsYXRpdmUiLCJmaWxlUGF0aCIsInJlbW92ZU1vZHVsZXMiLCJzZXRQYWNrYWdlSnNvbiIsImpzb24iLCJzdHJpbmdpZnkiLCJsaW5rZWRNb2R1bGVzIiwic3RhcnRQYXRoIiwid29ya2luZ1BhdGgiLCJtb2R1bGVQYXRoIiwicHJlZml4Iiwic3BsaXQiLCJwb3AiLCJmb3VuZFBhdGhzIiwicmVkdWNlIiwibGlzdCIsImZvdW5kUGF0aCIsInN0YXRzIiwiZGVlcExpc3QiLCJpc1N5bWJvbGljTGluayIsIm1vZHVsZU5hbWVzIiwiZmlsdGVyIiwiaXRlbSIsInBhdGgiLCJjaGVja0xpbmtlZE1vZHVsZXMiLCJsaW5rZWQiLCJtc2dNb2R1bGUiLCJsaW5rZWRNc2ciLCJtc2ciLCJsaW5rZWRNb2R1bGUiLCJkaW1Cb3JkZXIiLCJwYWRkaW5nIiwidXBkYXRlVGVtcGxhdGVOYW1lIiwicmVwbGFjZSIsInJlcGxhY2VDYXBzIiwiZGF0YSJdLCJtYXBwaW5ncyI6IkFBQUE7OztDQUdDLEdBRUQsT0FBT0EsV0FBVyxRQUFRO0FBQzFCLE9BQU9DLFdBQVcsUUFBUTtBQUMxQixTQUFRQyxRQUFRLEVBQUVDLFVBQVUsRUFBRUMsU0FBUyxFQUFFQyxTQUFTLEVBQUVDLFdBQVcsRUFBRUMsWUFBWSxFQUFFQyxhQUFhLFFBQU8sS0FBSztBQUN4RyxTQUFRQyxRQUFRQyxRQUFRLFFBQU8sT0FBTztBQUN0QyxPQUFPQyxhQUFhLG9CQUFvQjtBQUN4QyxPQUFPQyxTQUFTLE1BQU07QUFDdEIsU0FBUUMs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