@nlabs/lex
Version:
297 lines (296 loc) • 32.9 kB
JavaScript
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";
const cwd = process.cwd();
const getFilenames = (props) => {
const { callback, cliName, name, quiet, type, useTypescript } = props;
let nameCaps;
const itemTypes = ["stores", "views"];
if (!name) {
if (itemTypes.includes(type)) {
log(`
${cliName} Error: ${type} name is required. Please use 'lex -h' for options.`, "error", quiet);
return callback?.(1);
}
} 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
};
};
const createSpinner = (quiet = false) => {
if (quiet) {
return {
fail: () => {
},
start: () => {
},
succeed: () => {
}
};
}
return ora({ color: "yellow" });
};
const createProgressBar = (percentage) => {
const width = 20;
const filled = Math.round(percentage / 100 * width);
const empty = width - filled;
const filledBar = chalk.cyan("\u2588").repeat(filled);
const emptyBar = chalk.gray("\u2591").repeat(empty);
return filledBar + emptyBar;
};
const handleWebpackProgress = (output, spinner, quiet, emoji, action) => {
if (quiet) {
return;
}
const progressMatch = output.match(/\[webpack\.Progress\] (\d+)%/);
if (progressMatch) {
const progress = parseInt(progressMatch[1], 10);
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], 10);
const progressBar = createProgressBar(progress);
spinner.text = `${emoji} ${action}: ${progressBar} ${progress}%`;
}
}
};
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");
}
};
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);
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;
}
for (const sourceFile of matchingFiles) {
const relativePath = pathRelative(baseDir, sourceFile);
const destPath = pathResolve(outputFullPath, relativePath);
const destDir = pathResolve(destPath, "..");
mkdirSync(destDir, { recursive: true });
await new Promise((resolve, reject) => {
copyFile(sourceFile, destPath, (copyError) => {
if (copyError) {
reject(copyError);
} else {
resolve(true);
}
});
});
totalCopied++;
}
}
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;
}
};
const copyFileSync = (source, target) => {
let targetFile = target;
if (existsSync(target)) {
if (lstatSync(target).isDirectory()) {
targetFile = pathJoin(target, pathBasename(source));
}
}
writeFileSync(targetFile, readFileSync(source));
};
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);
}
});
}
};
const getPackageJson = (packagePath) => {
const formatPath = packagePath || `${process.cwd()}/package.json`;
const packageData = readFileSync(formatPath).toString();
return JSON.parse(packageData);
};
const getFilesByExt = (ext, config) => {
const { sourceFullPath } = config;
return globSync(`${sourceFullPath}/**/**${ext}`);
};
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;
};
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);
}
});
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);
}
});
const setPackageJson = (json, packagePath) => {
if (!json) {
return;
}
const formatPath = packagePath || `${process.cwd()}/package.json`;
writeFileSync(formatPath, JSON.stringify(json, null, 2));
};
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(`${modulePath}/*`);
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;
}
}, []);
};
const checkLinkedModules = () => {
const linked = linkedModules();
if (linked.length) {
const msgModule = linked.length > 1 ? "Modules" : "Module";
const linkedMsg = linked.reduce(
(msg, linkedModule) => `${msg}
* ${linkedModule.name}`,
`Linked ${msgModule}:`
);
log(boxen(linkedMsg, { dimBorder: true, padding: 1 }), "warn");
}
};
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");
};
export {
checkLinkedModules,
copyConfiguredFiles,
copyFileSync,
copyFiles,
copyFolderRecursiveSync,
createProgressBar,
createSpinner,
cwd,
getFilenames,
getFilesByExt,
getPackageJson,
handleWebpackProgress,
linkedModules,
removeConflictModules,
removeFiles,
removeModules,
setPackageJson,
updateTemplateName
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL3V0aWxzL2FwcC50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cblxuaW1wb3J0IGJveGVuIGZyb20gJ2JveGVuJztcbmltcG9ydCBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQge2NvcHlGaWxlLCBleGlzdHNTeW5jLCBsc3RhdFN5bmMsIG1rZGlyU3luYywgcmVhZGRpclN5bmMsIHJlYWRGaWxlU3luYywgd3JpdGVGaWxlU3luY30gZnJvbSAnZnMnO1xuaW1wb3J0IHtzeW5jIGFzIGdsb2JTeW5jfSBmcm9tICdnbG9iJztcbmltcG9ydCBpc0VtcHR5IGZyb20gJ2xvZGFzaC9pc0VtcHR5LmpzJztcbmltcG9ydCBvcmEgZnJvbSAnb3JhJztcbmltcG9ydCB7YmFzZW5hbWUgYXMgcGF0aEJhc2VuYW1lLCBqb2luIGFzIHBhdGhKb2luLCByZWxhdGl2ZSBhcyBwYXRoUmVsYXRpdmUsIHJlc29sdmUgYXMgcGF0aFJlc29sdmV9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHtyaW1yYWZTeW5jfSBmcm9tICdyaW1yYWYnO1xuXG5cbmltcG9ydCB7bG9nfSBmcm9tICcuL2xvZy5qcyc7XG5cbmltcG9ydCB0eXBlIHtMZXhDb25maWdUeXBlfSBmcm9tICcuLi9MZXhDb25maWcuanMnO1xuXG5cbmV4cG9ydCBjb25zdCBjd2Q6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCk7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0RmlsZW5hbWVzUHJvcHMge1xuICByZWFkb25seSBjYWxsYmFjaz86IChzdGF0dXM6IG51bWJlcikgPT4gdm9pZDtcbiAgcmVhZG9ubHkgY2xpTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgbmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgcXVpZXQ/OiBib29sZWFuO1xuICByZWFkb25seSB0eXBlPzogc3RyaW5nO1xuICByZWFkb25seSB1c2VUeXBlc2NyaXB0PzogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIEZpbGVuYW1lc1Jlc3VsdCB7XG4gIG5hbWVDYXBzOiBzdHJpbmc7XG4gIHRlbXBsYXRlRXh0OiBzdHJpbmc7XG4gIHRlbXBsYXRlUGF0aDogc3RyaW5nO1xuICB0ZW1wbGF0ZVJlYWN0OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjb25zdCBnZXRGaWxlbmFtZXMgPSAocHJvcHM6IEdldEZpbGVuYW1lc1Byb3BzKTogRmlsZW5hbWVzUmVzdWx0IHwgdm9pZCA9PiB7XG4gIGNvbnN0IHtjYWxsYmFjaywgY2xpTmFtZSwgbmFtZSwgcXVpZXQsIHR5cGUsIHVzZVR5cGVzY3JpcHR9ID0gcHJvcHM7XG5cbiAgbGV0IG5hbWVDYXBzOiBzdHJpbmc7XG4gIGNvbnN0IGl0ZW1UeXBlczogc3RyaW5nW10gPSBbJ3N0b3JlcycsICd2aWV3cyddO1xuXG4gIGlmKCFuYW1lKSB7XG4gICAgaWYoaXRlbVR5cGVzLmluY2x1ZGVzKHR5cGUpKSB7XG4gICAgICBsb2coYFxcbiR7Y2xpTmFtZX0gRXJyb3I6ICR7dHlwZX0gbmFtZSBpcyByZXF1aXJlZC4gUGxlYXNlIHVzZSAnbGV4IC1oJyBmb3Igb3B0aW9ucy5gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICByZXR1cm4gY2FsbGJhY2s/LigxKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgbmFtZUNhcHMgPSBgJHtuYW1lLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpfSR7bmFtZS5zdWJzdHIoMSl9YDtcbiAgfVxuXG4gIGxvZyhgJHtjbGlOYW1lfSBhZGRpbmcgJHtuYW1lfSAke3R5cGV9Li4uYCwgJ2luZm8nLCBxdWlldCk7XG5cbiAgbGV0IHRlbXBsYXRlUGF0aDogc3RyaW5nO1xuICBsZXQgdGVtcGxhdGVFeHQ6IHN0cmluZztcbiAgbGV0IHRlbXBsYXRlUmVhY3Q6IHN0cmluZztcblxuICBpZih1c2VUeXBlc2NyaXB0KSB7XG4gICAgdGVtcGxhdGVQYXRoID0gJy4uLy4uL3RlbXBsYXRlcy90eXBlc2NyaXB0JztcbiAgICB0ZW1wbGF0ZUV4dCA9ICcudHMnO1xuICAgIHRlbXBsYXRlUmVhY3QgPSAnLnRzeCc7XG4gIH0gZWxzZSB7XG4gICAgdGVtcGxhdGVQYXRoID0gJy4uLy4uL3RlbXBsYXRlcy9mbG93JztcbiAgICB0ZW1wbGF0ZUV4dCA9ICcuanMnO1xuICAgIHRlbXBsYXRlUmVhY3QgPSAnLmpzJztcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgbmFtZUNhcHMsXG4gICAgdGVtcGxhdGVFeHQsXG4gICAgdGVtcGxhdGVQYXRoLFxuICAgIHRlbXBsYXRlUmVhY3RcbiAgfTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3Bpbm5lciB7XG4gIGZhaWw6ICh0ZXh0Pzogc3RyaW5nKSA9PiB2b2lkO1xuICBzdGFydDogKHRleHQ/OiBzdHJpbmcpID0+IHZvaWQ7XG4gIHN1Y2NlZWQ6ICh0ZXh0Pzogc3RyaW5nKSA9PiB2b2lkO1xuICB0ZXh0Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgY3JlYXRlU3Bpbm5lciA9IChxdWlldCA9IGZhbHNlKTogU3Bpbm5lciA9PiB7XG4gIGlmKHF1aWV0KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGZhaWw6ICgpID0+IHt9LFxuICAgICAgc3RhcnQ6ICgpID0+IHt9LFxuICAgICAgc3VjY2VlZDogKCkgPT4ge31cbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIG9yYSh7Y29sb3I6ICd5ZWxsb3cnfSk7XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlUHJvZ3Jlc3NCYXIgPSAocGVyY2VudGFnZTogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgY29uc3Qgd2lkdGggPSAyMDtcbiAgY29uc3QgZmlsbGVkID0gTWF0aC5yb3VuZCgocGVyY2VudGFnZSAvIDEwMCkgKiB3aWR0aCk7XG4gIGNvbnN0IGVtcHR5ID0gd2lkdGggLSBmaWxsZWQ7XG5cbiAgY29uc3QgZmlsbGVkQmFyID0gY2hhbGsuY3lhbignXHUyNTg4JykucmVwZWF0KGZpbGxlZCk7XG4gIGNvbnN0IGVtcHR5QmFyID0gY2hhbGsuZ3JheSgnXHUyNTkxJykucmVwZWF0KGVtcHR5KTtcblxuICByZXR1cm4gZmlsbGVkQmFyICsgZW1wdHlCYXI7XG59O1xuXG5leHBvcnQgY29uc3QgaGFuZGxlV2VicGFja1Byb2dyZXNzID0gKG91dHB1dDogc3RyaW5nLCBzcGlubmVyOiBTcGlubmVyLCBxdWlldDogYm9vbGVhbiwgZW1vamk6IHN0cmluZywgYWN0aW9uOiBzdHJpbmcpOiB2b2lkID0+IHtcbiAgaWYocXVpZXQpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBwcm9ncmVzc01hdGNoID0gb3V0cHV0Lm1hdGNoKC9cXFt3ZWJwYWNrXFwuUHJvZ3Jlc3NcXF0gKFxcZCspJS8pO1xuICBpZihwcm9ncmVzc01hdGNoKSB7XG4gICAgY29uc3QgcHJvZ3Jlc3MgPSBwYXJzZUludChwcm9ncmVzc01hdGNoWzFdLCAxMCk7XG4gICAgY29uc3QgcHJvZ3Jlc3NCYXIgPSBjcmVhdGVQcm9ncmVzc0Jhcihwcm9ncmVzcyk7XG4gICAgc3Bpbm5lci50ZXh0ID0gYCR7ZW1vaml9ICR7YWN0aW9ufTogJHtwcm9ncmVzc0Jhcn0gJHtwcm9ncmVzc30lYDtcbiAgfSBlbHNlIGlmKG91dHB1dC5pbmNsdWRlcygnW3dlYnBhY2suUHJvZ3Jlc3NdJykpIHtcbiAgICBjb25zdCBnZW5lcmFsUHJvZ3Jlc3NNYXRjaCA9IG91dHB1dC5tYXRjaCgvKFxcZCspJS8pO1xuICAgIGlmKGdlbmVyYWxQcm9ncmVzc01hdGNoKSB7XG4gICAgICBjb25zdCBwcm9ncmVzcyA9IHBhcnNlSW50KGdlbmVyYWxQcm9ncmVzc01hdGNoWzFdLCAxMCk7XG4gICAgICBjb25zdCBwcm9ncmVzc0JhciA9IGNyZWF0ZVByb2dyZXNzQmFyKHByb2dyZXNzKTtcbiAgICAgIHNwaW5uZXIudGV4dCA9IGAke2Vtb2ppfSAke2FjdGlvbn06ICR7cHJvZ3Jlc3NCYXJ9ICR7cHJvZ3Jlc3N9JWA7XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgY29uc3QgY29weUZpbGVzID0gYXN5bmMgKGZpbGVzOiBzdHJpbmdbXSwgdHlwZU5hbWU6IHN0cmluZywgc3Bpbm5lciwgY29uZmlnOiBMZXhDb25maWdUeXBlKSA9PiB7XG4gIGNvbnN0IHtvdXRwdXRGdWxsUGF0aCwgc291cmNlRnVsbFBhdGh9ID0gY29uZmlnO1xuICBjb25zdCBpdGVtcyA9IGZpbGVzLm1hcCgoZmlsZU5hbWU6IHN0cmluZykgPT4gKHtcbiAgICBmcm9tOiBmaWxlTmFtZSxcbiAgICB0bzogcGF0aFJlc29sdmUob3V0cHV0RnVsbFBhdGgsIHBhdGhSZWxhdGl2ZShzb3VyY2VGdWxsUGF0aCwgZmlsZU5hbWUpKVxuICB9KSk7XG5cbiAgdHJ5IHtcbiAgICBzcGlubmVyLnN0YXJ0KGBDb3B5aW5nICR7dHlwZU5hbWV9IGZpbGVzLi4uYCk7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoaXRlbXMubWFwKCh7ZnJvbSwgdG99KSA9PiBuZXcgUHJvbWlzZShcbiAgICAgIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgbWtkaXJTeW5jKHBhdGhSZXNvbHZlKHRvLCAnLi4nKSwge3JlY3Vyc2l2ZTogdHJ1ZX0pO1xuICAgICAgICByZXR1cm4gY29weUZpbGUoZnJvbSwgdG8sIChjb3B5RXJyb3IpID0+IHtcbiAgICAgICAgICBpZihjb3B5RXJyb3IpIHtcbiAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgKSkpO1xuICAgIHNwaW5uZXIuc3VjY2VlZChgU3VjY2Vzc2Z1bGx5IGNvcGllZCAke2ZpbGVzLmxlbmd0aH0gJHt0eXBlTmFtZX0gZmlsZXMhYCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKGBDb3B5aW5nIG9mICR7dHlwZU5hbWV9IGZpbGVzIGZhaWxlZC5gKTtcbiAgICBsb2coYEVycm9yOiAke2Vycm9yLm1lc3NhZ2V9YCwgJ2Vycm9yJyk7XG4gICAgbG9nKGVycm9yLCAnZXJyb3InKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGNvcHlDb25maWd1cmVkRmlsZXMgPSBhc3luYyAoc3Bpbm5lciwgY29uZmlnOiBMZXhDb25maWdUeXBlLCBxdWlldDogYm9vbGVhbikgPT4ge1xuICBjb25zdCB7Y29weUZpbGVzOiBjb3B5RmlsZXNDb25maWcsIG91dHB1dEZ1bGxQYXRoLCBzb3VyY2VGdWxsUGF0aCwgc291cmNlUGF0aH0gPSBjb25maWc7XG4gIGlmKCFjb3B5RmlsZXNDb25maWcgfHwgY29weUZpbGVzQ29uZmlnLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRyeSB7XG4gICAgc3Bpbm5lci5zdGFydCgnQ29weWluZyBjb25maWd1cmVkIGZpbGVzLi4uJyk7XG4gICAgbGV0IHRvdGFsQ29waWVkID0gMDtcblxuICAgIGNvbnN0IGJhc2VEaXIgPSBzb3VyY2VGdWxsUGF0aCB8fCAoc291cmNlUGF0aCA/IHBhdGhSZXNvbHZlKGN3ZCwgc291cmNlUGF0aCkgOiBjd2QpO1xuXG4gICAgZm9yKGNvbnN0IHBhdHRlcm4gb2YgY29weUZpbGVzQ29uZmlnKSB7XG4gICAgICBjb25zdCByZXNvbHZlZFBhdHRlcm4gPSBwYXRoUmVzb2x2ZShiYXNlRGlyLCBwYXR0ZXJuKTtcbiAgICAgIGNvbnN0IG1hdGNoaW5nRmlsZXMgPSBnbG9iU3luYyhyZXNvbHZlZFBhdHRlcm4sIHtcbiAgICAgICAgYWJzb2x1dGU6IHRydWUsXG4gICAgICAgIG5vZGlyOiB0cnVlXG4gICAgICB9KTtcbiAgICAgIGlmKG1hdGNoaW5nRmlsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGlmKCFxdWlldCkge1xuICAgICAgICAgIGxvZyhgV2FybmluZzogTm8gZmlsZXMgZm91bmQgbWF0Y2hpbmcgcGF0dGVybjogJHtwYXR0ZXJufWAsICd3YXJuJywgcXVpZXQpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBmb3IoY29uc3Qgc291cmNlRmlsZSBvZiBtYXRjaGluZ0ZpbGVzKSB7XG4gICAgICAgIC8vIENhbGN1bGF0ZSByZWxhdGl2ZSBwYXRoIGZyb20gc291cmNlIGRpcmVjdG9yeVxuICAgICAgICBjb25zdCByZWxhdGl2ZVBhdGggPSBwYXRoUmVsYXRpdmUoYmFzZURpciwgc291cmNlRmlsZSk7XG4gICAgICAgIC8vIERldGVybWluZSBkZXN0aW5hdGlvbiBwYXRoIGluIG91dHB1dCBkaXJlY3RvcnlcbiAgICAgICAgY29uc3QgZGVzdFBhdGggPSBwYXRoUmVzb2x2ZShvdXRwdXRGdWxsUGF0aCwgcmVsYXRpdmVQYXRoKTtcbiAgICAgICAgLy8gQ3JlYXRlIGRlc3RpbmF0aW9uIGRpcmVjdG9yeSBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgICAgIGNvbnN0IGRlc3REaXIgPSBwYXRoUmVzb2x2ZShkZXN0UGF0aCwgJy4uJyk7XG4gICAgICAgIG1rZGlyU3luYyhkZXN0RGlyLCB7cmVjdXJzaXZlOiB0cnVlfSk7XG5cbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgIGNvcHlGaWxlKHNvdXJjZUZpbGUsIGRlc3RQYXRoLCAoY29weUVycm9yKSA9PiB7XG4gICAgICAgICAgICBpZihjb3B5RXJyb3IpIHtcbiAgICAgICAgICAgICAgcmVqZWN0KGNvcHlFcnJvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXNvbHZlKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgdG90YWxDb3BpZWQrKztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYodG90YWxDb3BpZWQgPiAwKSB7XG4gICAgICBzcGlubmVyLnN1Y2NlZWQoYFN1Y2Nlc3NmdWxseSBjb3BpZWQgJHt0b3RhbENvcGllZH0gY29uZmlndXJlZCBmaWxlcyFgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3Bpbm5lci5zdWNjZWVkKCdObyBjb25maWd1cmVkIGZpbGVzIHRvIGNvcHknKTtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgc3Bpbm5lci5mYWlsKCdGYWlsZWQgdG8gY29weSBjb25maWd1cmVkIGZpbGVzJyk7XG4gICAgbG9nKGBFcnJvciBjb3B5aW5nIGNvbmZpZ3VyZWQgZmlsZXM6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgdGhyb3cgZXJyb3I7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBjb3B5RmlsZVN5bmMgPSAoc291cmNlOiBzdHJpbmcsIHRhcmdldDogc3RyaW5nKSA9PiB7XG4gIGxldCB0YXJnZXRGaWxlOiBzdHJpbmcgPSB0YXJnZXQ7XG5cbiAgaWYoZXhpc3RzU3luYyh0YXJnZXQpKSB7XG4gICAgaWYobHN0YXRTeW5jKHRhcmdldCkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgdGFyZ2V0RmlsZSA9IHBhdGhKb2luKHRhcmdldCwgcGF0aEJhc2VuYW1lKHNvdXJjZSkpO1xuICAgIH1cbiAgfVxuXG4gIHdyaXRlRmlsZVN5bmModGFyZ2V0RmlsZSwgcmVhZEZpbGVTeW5jKHNvdXJjZSkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGNvcHlGb2xkZXJSZWN1cnNpdmVTeW5jID0gKHNvdXJjZTogc3RyaW5nLCB0YXJnZXQ6IHN0cmluZyk6IHZvaWQgPT4ge1xuICBsZXQgZmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgY29uc3QgdGFyZ2V0Rm9sZGVyOiBzdHJpbmcgPSBwYXRoSm9pbih0YXJnZXQsIHBhdGhCYXNlbmFtZShzb3VyY2UpKTtcblxuICBpZighZXhpc3RzU3luYyh0YXJnZXRGb2xkZXIpKSB7XG4gICAgbWtkaXJTeW5jKHRhcmdldEZvbGRlcik7XG4gIH1cblxuICBpZihsc3RhdFN5bmMoc291cmNlKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgZmlsZXMgPSByZWFkZGlyU3luYyhzb3VyY2UpO1xuICAgIGZpbGVzLmZvckVhY2goKGZpbGU6IHN0cmluZykgPT4ge1xuICAgICAgY29uc3QgY3VyU291cmNlOiBzdHJpbmcgPSBwYXRoSm9pbihzb3VyY2UsIGZpbGUpO1xuXG4gICAgICBpZihsc3RhdFN5bmMoY3VyU291cmNlKS5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICAgIGNvcHlGb2xkZXJSZWN1cnNpdmVTeW5jKGN1clNvdXJjZSwgdGFyZ2V0Rm9sZGVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvcHlGaWxlU3luYyhjdXJTb3VyY2UsIHRhcmdldEZvbGRlcik7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBnZXRQYWNrYWdlSnNvbiA9IChwYWNrYWdlUGF0aD86IHN0cmluZykgPT4ge1xuICBjb25zdCBmb3JtYXRQYXRoOiBzdHJpbmcgPSBwYWNrYWdlUGF0aCB8fCBgJHtwcm9jZXNzLmN3ZCgpfS9wYWNrYWdlLmpzb25gO1xuXG4gIGNvbnN0IHBhY2thZ2VEYXRhOiBzdHJpbmcgPSByZWFkRmlsZVN5bmMoZm9ybWF0UGF0aCkudG9TdHJpbmcoKTtcbiAgcmV0dXJuIEpTT04ucGFyc2UocGFja2FnZURhdGEpO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldEZpbGVzQnlFeHQgPSAoZXh0OiBzdHJpbmcsIGNvbmZpZzogTGV4Q29uZmlnVHlwZSk6IHN0cmluZ1tdID0+IHtcbiAgY29uc3Qge3NvdXJjZUZ1bGxQYXRofSA9IGNvbmZpZztcbiAgcmV0dXJuIGdsb2JTeW5jKGAke3NvdXJjZUZ1bGxQYXRofS8qKi8qKiR7ZXh0fWApO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlbW92ZUNvbmZsaWN0TW9kdWxlcyA9IChtb2R1bGVMaXN0OiBvYmplY3QpID0+IHtcbiAgY29uc3QgdXBkYXRlZExpc3Q6IG9iamVjdCA9IHsuLi5tb2R1bGVMaXN0fTtcblxuICBPYmplY3Qua2V5cyh1cGRhdGVkTGlzdCkuZm9yRWFjaCgobW9kdWxlTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgY29uc3QgcmVnZXg6IFJlZ0V4cCA9IG5ldyBSZWdFeHAoJ14oPyFAdHlwZXMvKS4qPyhqZXN0fHdlYnBhY2spLiokJywgJ2dpJyk7XG4gICAgaWYocmVnZXgudGVzdChtb2R1bGVOYW1lKSkge1xuICAgICAgZGVsZXRlIHVwZGF0ZWRMaXN0W21vZHVsZU5hbWVdO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIHVwZGF0ZWRMaXN0O1xufTtcblxuZXhwb3J0IGNvbnN0IHJlbW92ZUZpbGVzID0gKGZpbGVOYW1lOiBzdHJpbmcsIGlzUmVsYXRpdmU6IGJvb2xlYW4gPSBmYWxzZSkgPT4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICBjb25zdCBmaWxlUGF0aDogc3RyaW5nID0gaXNSZWxhdGl2ZSA/IHBhdGhSZXNvbHZlKGN3ZCwgZmlsZU5hbWUpIDogZmlsZU5hbWU7XG4gIHRyeSB7XG4gICAgcmltcmFmU3luYyhmaWxlUGF0aCk7XG4gICAgcmV0dXJuIHJlc29sdmUobnVsbCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmV0dXJuIHJlamVjdChlcnJvcik7XG4gIH1cbn0pO1xuXG5leHBvcnQgY29uc3QgcmVtb3ZlTW9kdWxlcyA9ICgpID0+IG5ldyBQcm9taXNlKGFzeW5jIChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgdHJ5IHtcbiAgICAvLyBSZW1vdmUgbm9kZV9tb2R1bGVzXG4gICAgYXdhaXQgcmVtb3ZlRmlsZXMoJy4vbm9kZV9tb2R1bGVzJywgdHJ1ZSk7XG5cbiAgICAvLyBSZW1vdmUgeWFybiBsb2NrXG4gICAgYXdhaXQgcmVtb3ZlRmlsZXMoJy4veWFybi5sb2NrJywgdHJ1ZSk7XG5cbiAgICAvLyBSZW1vdmUgbnBtIGxvY2tcbiAgICBhd2FpdCByZW1vdmVGaWxlcygnLi9wYWNrYWdlLWxvY2suanNvbicsIHRydWUpO1xuXG4gICAgcmVzb2x2ZShudWxsKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICByZWplY3QoZXJyb3IpO1xuICB9XG59KTtcblxuZXhwb3J0IGNvbnN0IHNldFBhY2thZ2VKc29uID0gKGpzb24sIHBhY2thZ2VQYXRoPzogc3RyaW5nKSA9PiB7XG4gIGlmKCFqc29uKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgZm9ybWF0UGF0aDogc3RyaW5nID0gcGFja2FnZVBhdGggfHwgYCR7cHJvY2Vzcy5jd2QoKX0vcGFja2FnZS5qc29uYDtcblxuICB3cml0ZUZpbGVTeW5jKGZvcm1hdFBhdGgsIEpTT04uc3RyaW5naWZ5KGpzb24sIG51bGwsIDIpKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGlua2VkTW9kdWxlVHlwZSB7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgcGF0aDogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgbGlua2VkTW9kdWxlcyA9IChzdGFydFBhdGg/OiBzdHJpbmcpOiBMaW5rZWRNb2R1bGVUeXBlW10gPT4ge1xuICBjb25zdCB3b3JraW5nUGF0aDogc3RyaW5nID0gc3RhcnRQYXRoIHx8IHByb2Nlc3MuY3dkKCk7XG4gIGxldCBtb2R1bGVQYXRoOiBzdHJpbmc7XG4gIGxldCBwcmVmaXg6IHN0cmluZztcblxuICBpZih3b3JraW5nUGF0aC5pbmNsdWRlcygnQCcpKSB7XG4gICAgcHJlZml4ID0gYEAke3dvcmtpbmdQYXRoLnNwbGl0KCdAJykucG9wKCl9YDtcbiAgICBtb2R1bGVQYXRoID0gd29ya2luZ1BhdGg7XG4gIH0gZWxzZSB7XG4gICAgbW9kdWxlUGF0aCA9IHBhdGhKb2luKHdvcmtpbmdQYXRoLCAnbm9kZV9tb2R1bGVzJyk7XG4gIH1cblxuICBjb25zdCBmb3VuZFBhdGhzOiBzdHJpbmdbXSA9IGdsb2JTeW5jKGAke21vZHVsZVBhdGh9LypgKTtcbiAgcmV0dXJuIGZvdW5kUGF0aHMucmVkdWNlKChsaXN0OiBMaW5rZWRNb2R1bGVUeXBlW10sIGZvdW5kUGF0aDogc3RyaW5nKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN0YXRzID0gbHN0YXRTeW5jKGZvdW5kUGF0aCk7XG5cbiAgICAgIGlmKHN0YXRzLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgICAgY29uc3QgZGVlcExpc3Q6IExpbmtlZE1vZHVsZVR5cGVbXSA9IGxpbmtlZE1vZHVsZXMoZm91bmRQYXRoKTtcbiAgICAgICAgbGlzdC5wdXNoKC4uLmRlZXBMaXN0KTtcbiAgICAgIH0gZWxzZSBpZihzdGF0cy5pc1N5bWJvbGljTGluaygpKSB7XG4gICAgICAgIGNvbnN0IG1vZHVsZU5hbWVzOiBzdHJpbmdbXSA9IChbcHJlZml4LCBwYXRoQmFzZW5hbWUoZm91bmRQYXRoKV0pLmZpbHRlcigoaXRlbTogc3RyaW5nKSA9PiAhaXNFbXB0eShpdGVtKSk7XG4gICAgICAgIGxpc3QucHVzaCh7bmFtZTogYCR7bW9kdWxlTmFtZXMuam9pbignLycpfWAsIHBhdGg6IGZvdW5kUGF0aH0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbGlzdDtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFNraXAgZmlsZXMgdGhhdCBkb24ndCBleGlzdCBvciBjYW4ndCBiZSBhY2Nlc3NlZFxuICAgICAgcmV0dXJuIGxpc3Q7XG4gICAgfVxuICB9LCBbXSk7XG59O1xuXG5leHBvcnQgY29uc3QgY2hlY2tMaW5rZWRNb2R1bGVzID0gKCkgPT4ge1xuICBjb25zdCBsaW5rZWQgPSBsaW5rZWRNb2R1bGVzKCk7XG5cbiAgaWYobGlua2VkLmxlbmd0aCkge1xuICAgIGNvbnN0IG1zZ01vZHVsZTogc3RyaW5nID0gbGlua2VkLmxlbmd0aCA+IDEgPyAnTW9kdWxlcycgOiAnTW9kdWxlJztcbiAgICBjb25zdCBsaW5rZWRNc2c6IHN0cmluZyA9IGxpbmtlZC5yZWR1Y2UoXG4gICAgICAobXNnOiBzdHJpbmcsIGxpbmtlZE1vZHVsZTogTGlua2VkTW9kdWxlVHlwZSkgPT5cbiAgICAgICAgYCR7bXNnfVxcbiAqICR7bGlua2VkTW9kdWxlLm5hbWV9YCxcbiAgICAgIGBMaW5rZWQgJHttc2dNb2R1bGV9OmBcbiAgICApO1xuICAgIGxvZyhib3hlbihsaW5rZWRNc2csIHtkaW1Cb3JkZXI6IHRydWUsIHBhZGRpbmc6IDF9KSwgJ3dhcm4nKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHVwZGF0ZVRlbXBsYXRlTmFtZSA9IChmaWxlUGF0aDogc3RyaW5nLCByZXBsYWNlOiBzdHJpbmcsIHJlcGxhY2VDYXBzOiBzdHJpbmcpID0+IHtcbiAgbGV0IGRhdGE6IHN0cmluZyA9IHJlYWRGaWxlU3luYyhmaWxlUGF0aCwgJ3V0ZjgnKTtcbiAgZGF0YSA9IGRhdGEucmVwbGFjZSgvc2FtcGxlL2csIHJlcGxhY2UpO1xuICBkYXRhID0gZGF0YS5yZXBsYWNlKC9TYW1wbGUvZywgcmVwbGFjZUNhcHMpO1xuICB3cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCBkYXRhLCAndXRmOCcpO1xufTsiXSwKICAibWFwcGluZ3MiOiAiQUFLQSxPQUFPLFdBQVc7QUFDbEIsT0FBTyxXQUFXO0FBQ2xCLFNBQVEsVUFBVSxZQUFZLFdBQVcsV0FBVyxhQUFhLGNBQWMscUJBQW9CO0FBQ25HLFNBQVEsUUFBUSxnQkFBZTtBQUMvQixPQUFPLGFBQWE7QUFDcEIsT0FBTyxTQUFTO0FBQ2hCLFNBQVEsWUFBWSxjQUFjLFFBQVEsVUFBVSxZQUFZLGNBQWMsV0FBVyxtQkFBa0I7QUFDM0csU0FBUSxrQkFBaUI7QUFHekIsU0FBUSxXQUFVO0FBS1gsTUFBTSxNQUFjLFFBQVEsSUFBSTtBQWtCaEMsTUFBTSxlQUFlLENBQUMsVUFBcUQ7QUFDaEYsUUFBTSxFQUFDLFVBQVUsU0FBUyxNQUFNLE9BQU8sTUFBTSxjQUFhLElBQUk7QUFFOUQsTUFBSTtBQUNKLFFBQU0sWUFBc0IsQ0FBQyxVQUFVLE9BQU87QUFFOUMsTUFBRyxDQUFDLE1BQU07QUFDUixRQUFHLFVBQVUsU0FBUyxJQUFJLEdBQUc7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