@nlabs/lex
Version:
269 lines (268 loc) • 33.1 kB
JavaScript
import { existsSync, readFileSync, writeFileSync } from "fs";
import { dirname, extname as pathExtname, resolve as pathResolve } from "path";
import { URL } from "url";
import { getDirName, getLexPackageJsonPath, relativeFilePath } from "./utils/file.js";
import { log } from "./utils/log.js";
const cwd = process.cwd();
const defaultConfigValues = {
ai: {
maxTokens: 4e3,
model: "gpt-4o",
provider: "none",
temperature: 0.1
},
configFiles: [],
copyFiles: [],
entryHTML: "index.html",
entryJs: "index.js",
env: null,
esbuild: {
drop: ["console", "debugger"],
legalComments: "none",
metafile: false,
minify: true,
pure: ["console.log", "console.warn", "console.error"],
sourcemap: false,
splitting: true,
treeShaking: true
},
eslint: {},
jest: {},
outputFullPath: pathResolve(cwd, "./lib"),
outputHash: false,
outputPath: "./lib",
packageManager: "npm",
preset: "web",
sourceFullPath: pathResolve(cwd, "./src"),
sourcePath: "./src",
targetEnvironment: "web",
useGraphQl: false,
useTypescript: false,
webpack: {
publicPath: "./src/static"
}
};
const getTypeScriptConfigPath = (configName) => {
const cwd2 = process.cwd();
if (configName === "tsconfig.build.json") {
const projectBuildConfig = pathResolve(cwd2, "tsconfig.build.json");
if (existsSync(projectBuildConfig)) {
return projectBuildConfig;
}
}
if (configName === "tsconfig.lint.json") {
const projectLintConfig = pathResolve(cwd2, "tsconfig.eslint.json");
if (existsSync(projectLintConfig)) {
return projectLintConfig;
}
}
if (configName === "tsconfig.test.json") {
const projectTestConfig = pathResolve(cwd2, "tsconfig.test.json");
if (existsSync(projectTestConfig)) {
return projectTestConfig;
}
}
const projectConfigPath = pathResolve(cwd2, configName);
if (existsSync(projectConfigPath)) {
return projectConfigPath;
}
const lexDir = LexConfig.getLexDir();
return pathResolve(lexDir, configName);
};
class LexConfig {
static config = {
...defaultConfigValues
};
static set useTypescript(value) {
LexConfig.config.useTypescript = value;
const { sourceFullPath } = LexConfig.config;
const { entryJs } = LexConfig.config;
if (entryJs === "index.js" && value) {
const indexPath = pathResolve(cwd, sourceFullPath, "index.tsx");
const hasIndexTsx = existsSync(indexPath);
if (hasIndexTsx) {
LexConfig.config.entryJs = "index.tsx";
} else {
LexConfig.config.entryJs = "index.ts";
}
}
}
static getLexDir() {
return dirname(getLexPackageJsonPath());
}
static updateConfig(updatedConfig) {
const { outputFullPath, outputPath, sourcePath, sourceFullPath, useTypescript, ai } = updatedConfig;
const cwd2 = process.cwd();
if (useTypescript !== void 0) {
LexConfig.useTypescript = useTypescript;
}
if (outputPath !== void 0 && outputFullPath === void 0) {
updatedConfig.outputFullPath = pathResolve(cwd2, outputPath);
}
if (sourcePath !== void 0 && sourceFullPath === void 0) {
updatedConfig.sourceFullPath = pathResolve(cwd2, sourcePath);
}
if (ai) {
LexConfig.config.ai = { ...LexConfig.config.ai, ...ai };
if (process.env.CURSOR_IDE === "true" && LexConfig.config.ai.provider === "none") {
LexConfig.config.ai.provider = "cursor";
}
}
LexConfig.config = { ...LexConfig.config, ...updatedConfig };
return LexConfig.config;
}
static addConfigParams(cmd, params) {
const nameProperty = "_name";
const { environment, outputPath, sourcePath, typescript } = cmd;
if (outputPath !== void 0) {
params.outputPath = outputPath;
params.outputFullPath = pathResolve(cwd, outputPath);
}
if (sourcePath !== void 0) {
params.sourcePath = sourcePath;
params.sourceFullPath = pathResolve(cwd, sourcePath);
}
if (typescript !== void 0) {
params.useTypescript = true;
}
if (environment !== void 0) {
params.targetEnvironment = environment === "web" ? "web" : "node";
}
process.env.LEX_CONFIG = JSON.stringify(
{
...LexConfig.updateConfig(params),
commandName: cmd[nameProperty],
isStatic: cmd.static
},
null,
0
);
}
static async parseConfig(cmd, isRoot = true) {
const { cliName = "Lex", lexConfig, lexConfigName, quiet, typescript, debug = false } = cmd;
const configFormats = ["js", "mjs", "cjs", "ts", "json"];
const configBaseName = lexConfigName || "lex.config";
let configPath = lexConfig || "";
let configExists = lexConfig ? existsSync(configPath) : false;
if (!configPath || !configExists) {
if (debug) {
log(`Searching for config files with base name: ${configBaseName}`, "info", quiet);
}
for (const format of configFormats) {
const potentialPath = isRoot ? pathResolve(cwd, `./${configBaseName}.${format}`) : relativeFilePath(`${configBaseName}.${format}`, cwd);
if (debug) {
log(`Checking for config file: ${potentialPath}`, "info", quiet);
}
if (existsSync(potentialPath)) {
configPath = potentialPath;
configExists = true;
break;
}
}
}
if (configExists) {
log(`Using ${cliName} configuration file: ${configPath}`, "note", quiet);
const ext = pathExtname(configPath);
if (ext === ".json") {
const configContent = readFileSync(configPath, "utf8");
if (configContent) {
let configJson;
try {
configJson = JSON.parse(configContent)?.default || {};
} catch (error) {
log(`
${cliName} Error: Failed to parse JSON config: ${error.message}`, "error", quiet);
configJson = {};
}
LexConfig.addConfigParams(cmd, configJson);
} else {
log(`
${cliName} Error: Config file malformed, ${configPath}`, "error", quiet);
}
} else if ([".js", ".mjs", ".cjs", ".ts"].includes(ext)) {
try {
let lexCustomConfig;
if (ext === ".cjs") {
const fileUrl = new URL(`file:///${pathResolve(configPath)}`).href;
if (debug) {
log(`Loading CommonJS config from: ${fileUrl}`, "info", quiet);
}
lexCustomConfig = await import(fileUrl);
} else {
if (debug) {
log(`Loading ESM/TS config from: ${configPath}`, "info", quiet);
}
lexCustomConfig = await import(configPath);
}
const config = lexCustomConfig.default || lexCustomConfig;
if (debug) {
log(`Loaded config: ${JSON.stringify(config, null, 2)}`, "info", quiet);
}
if (!config) {
log(`
${cliName} Warning: Config file loaded but no configuration found`, "warn", quiet);
}
LexConfig.addConfigParams(cmd, config || {});
} catch (error) {
log(`
${cliName} Error: Failed to load config file: ${error.message}`, "error", quiet);
if (debug) {
console.error(error);
}
}
} else {
log(`
${cliName} Error: Config file must be a JS, CJS, MJS, TS, or JSON file.`, "error", quiet);
}
} else {
if (debug) {
log("No config file found. Using default configuration.", "info", quiet);
}
LexConfig.useTypescript = !!typescript;
LexConfig.addConfigParams(cmd, LexConfig.config);
}
}
static checkTypescriptConfig() {
const tsconfigPath = pathResolve(cwd, "./tsconfig.json");
if (!existsSync(tsconfigPath)) {
const dirName = getDirName();
writeFileSync(tsconfigPath, readFileSync(pathResolve(dirName, "../../../tsconfig.base.json")));
}
}
static checkCompileTypescriptConfig() {
const lexDir = LexConfig.getLexDir();
const tsconfigCompilePath = pathResolve(lexDir, "./tsconfig.build.json");
if (!existsSync(tsconfigCompilePath)) {
const templatePath = pathResolve(lexDir, "tsconfig.build.json");
if (existsSync(templatePath)) {
writeFileSync(tsconfigCompilePath, readFileSync(templatePath));
}
}
}
static checkLintTypescriptConfig() {
const lexDir = LexConfig.getLexDir();
const tsconfigLintPath = pathResolve(lexDir, "./tsconfig.lint.json");
if (!existsSync(tsconfigLintPath)) {
const templatePath = pathResolve(lexDir, "tsconfig.lint.json");
if (existsSync(templatePath)) {
writeFileSync(tsconfigLintPath, readFileSync(templatePath));
}
}
}
static checkTestTypescriptConfig() {
const lexDir = LexConfig.getLexDir();
const tsconfigTestPath = pathResolve(lexDir, "./tsconfig.test.json");
if (!existsSync(tsconfigTestPath)) {
const templatePath = pathResolve(lexDir, "tsconfig.test.json");
if (existsSync(templatePath)) {
writeFileSync(tsconfigTestPath, readFileSync(templatePath));
}
}
}
}
export {
LexConfig,
defaultConfigValues,
getTypeScriptConfigPath
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL0xleENvbmZpZy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCB7ZXhpc3RzU3luYywgcmVhZEZpbGVTeW5jLCB3cml0ZUZpbGVTeW5jfSBmcm9tICdmcyc7XG5pbXBvcnQge2Rpcm5hbWUsIGV4dG5hbWUgYXMgcGF0aEV4dG5hbWUsIHJlc29sdmUgYXMgcGF0aFJlc29sdmV9IGZyb20gJ3BhdGgnO1xuaW1wb3J0IHtVUkx9IGZyb20gJ3VybCc7XG5cbmltcG9ydCB7Z2V0RGlyTmFtZSwgZ2V0TGV4UGFja2FnZUpzb25QYXRoLCByZWxhdGl2ZUZpbGVQYXRofSBmcm9tICcuL3V0aWxzL2ZpbGUuanMnO1xuaW1wb3J0IHtsb2d9IGZyb20gJy4vdXRpbHMvbG9nLmpzJztcblxuaW1wb3J0IHR5cGUge0xpbnRlcn0gZnJvbSAnZXNsaW50JztcblxuY29uc3QgY3dkOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpO1xuXG5leHBvcnQgaW50ZXJmYWNlIEVzYnVpbGRDb25maWcge1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICBlbnRyeVBvaW50cz86IHN0cmluZ1tdO1xuICBvdXRkaXI/OiBzdHJpbmc7XG4gIHBsYXRmb3JtPzogJ25vZGUnIHwgJ2Jyb3dzZXInO1xuICB0YXJnZXQ/OiBzdHJpbmc7XG4gIGZvcm1hdD86ICdjanMnIHwgJ2VzbSc7XG4gIG1pbmlmeT86IGJvb2xlYW47XG4gIHRyZWVTaGFraW5nPzogYm9vbGVhbjtcbiAgZHJvcD86IHN0cmluZ1tdO1xuICBwdXJlPzogc3RyaW5nW107XG4gIGV4dGVybmFsPzogc3RyaW5nW107XG4gIHNwbGl0dGluZz86IGJvb2xlYW47XG4gIG1ldGFmaWxlPzogYm9vbGVhbjtcbiAgc291cmNlbWFwPzogYm9vbGVhbiB8ICdpbmxpbmUnIHwgJ2V4dGVybmFsJztcbiAgbGVnYWxDb21tZW50cz86ICdub25lJyB8ICdpbmxpbmUnIHwgJ2VvZicgfCAnbGlua2VkJyB8ICdzZXBhcmF0ZSc7XG4gIGJhbm5lcj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGZvb3Rlcj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGRlZmluZT86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgSmVzdENvbmZpZyB7XG4gIFtrZXk6IHN0cmluZ106IHVua25vd247XG4gIHJvb3RzPzogc3RyaW5nW107XG4gIHRlc3RFbnZpcm9ubWVudD86IHN0cmluZztcbiAgdHJhbnNmb3JtPzogUmVjb3JkPHN0cmluZywgW3N0cmluZywgUmVjb3JkPHN0cmluZywgdW5rbm93bj5dPjtcbiAgdHJhbnNmb3JtSWdub3JlUGF0dGVybnM/OiBzdHJpbmdbXTtcbiAgbW9kdWxlTmFtZU1hcHBlcj86IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIGV4dGVuc2lvbnNUb1RyZWF0QXNFc20/OiBzdHJpbmdbXTtcbiAgcHJlc2V0Pzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFdlYnBhY2tDb25maWcge1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICBlbnRyeT86IHN0cmluZyB8IHN0cmluZ1tdO1xuICBvdXRwdXQ/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgbW9kdWxlPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHBsdWdpbnM/OiB1bmtub3duW107XG4gIHB1YmxpY1BhdGg/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQUlDb25maWcge1xuICBwcm92aWRlcj86ICdjdXJzb3InIHwgJ2NvcGlsb3QnIHwgJ29wZW5haScgfCAnYW50aHJvcGljJyB8ICdub25lJztcbiAgYXBpS2V5Pzogc3RyaW5nO1xuICBtb2RlbD86IHN0cmluZztcbiAgbWF4VG9rZW5zPzogbnVtYmVyO1xuICB0ZW1wZXJhdHVyZT86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFU0xpbnRDb25maWcge1xuICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICBleHRlbmRzPzogc3RyaW5nW107XG4gIHJ1bGVzPzogTGludGVyLlJ1bGVzUmVjb3JkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExleENvbmZpZ1R5cGUge1xuICBhaT86IEFJQ29uZmlnO1xuICBjb25maWdGaWxlcz86IHN0cmluZ1tdO1xuICBjb3B5RmlsZXM/OiBzdHJpbmdbXTtcbiAgZW50cnlIVE1MPzogc3RyaW5nO1xuICBlbnRyeUpzPzogc3RyaW5nO1xuICBlbnY/OiBvYmplY3Q7XG4gIGVzYnVpbGQ/OiBFc2J1aWxkQ29uZmlnO1xuICBlc2xpbnQ/OiBFU0xpbnRDb25maWc7XG4gIGdpdFVybD86IHN0cmluZztcbiAgamVzdD86IEplc3RDb25maWc7XG4gIGxpYnJhcnlOYW1lPzogc3RyaW5nO1xuICBsaWJyYXJ5VGFyZ2V0Pzogc3RyaW5nO1xuICBvdXRwdXRGaWxlPzogc3RyaW5nO1xuICBvdXRwdXRGdWxsUGF0aD86IHN0cmluZztcbiAgb3V0cHV0SGFzaD86IGJvb2xlYW47XG4gIG91dHB1dFBhdGg/OiBzdHJpbmc7XG4gIHBhY2thZ2VNYW5hZ2VyPzogJ25wbScgfCAneWFybic7XG4gIHByZXNldD86ICd3ZWInIHwgJ25vZGUnIHwgJ2xhbWJkYScgfCAnbW9iaWxlJztcbiAgc291cmNlRnVsbFBhdGg/OiBzdHJpbmc7XG4gIHNvdXJjZVBhdGg/OiBzdHJpbmc7XG4gIHRhcmdldEVudmlyb25tZW50PzogJ25vZGUnIHwgJ3dlYic7XG4gIHVzZUdyYXBoUWw/OiBib29sZWFuO1xuICB1c2VUeXBlc2NyaXB0PzogYm9vbGVhbjtcbiAgd2VicGFjaz86IFdlYnBhY2tDb25maWc7XG59XG5cbmV4cG9ydCB0eXBlIENvbmZpZyA9IExleENvbmZpZ1R5cGU7XG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0Q29uZmlnVmFsdWVzOiBMZXhDb25maWdUeXBlID0ge1xuICBhaToge1xuICAgIG1heFRva2VuczogNDAwMCxcbiAgICBtb2RlbDogJ2dwdC00bycsXG4gICAgcHJvdmlkZXI6ICdub25lJyxcbiAgICB0ZW1wZXJhdHVyZTogMC4xXG4gIH0sXG4gIGNvbmZpZ0ZpbGVzOiBbXSxcbiAgY29weUZpbGVzOiBbXSxcbiAgZW50cnlIVE1MOiAnaW5kZXguaHRtbCcsXG4gIGVudHJ5SnM6ICdpbmRleC5qcycsXG4gIGVudjogbnVsbCxcbiAgZXNidWlsZDoge1xuICAgIGRyb3A6IFsnY29uc29sZScsICdkZWJ1Z2dlciddLFxuICAgIGxlZ2FsQ29tbWVudHM6ICdub25lJyxcbiAgICBtZXRhZmlsZTogZmFsc2UsXG4gICAgbWluaWZ5OiB0cnVlLFxuICAgIHB1cmU6IFsnY29uc29sZS5sb2cnLCAnY29uc29sZS53YXJuJywgJ2NvbnNvbGUuZXJyb3InXSxcbiAgICBzb3VyY2VtYXA6IGZhbHNlLFxuICAgIHNwbGl0dGluZzogdHJ1ZSxcbiAgICB0cmVlU2hha2luZzogdHJ1ZVxuICB9LFxuICBlc2xpbnQ6IHt9LFxuICBqZXN0OiB7fSxcbiAgb3V0cHV0RnVsbFBhdGg6IHBhdGhSZXNvbHZlKGN3ZCwgJy4vbGliJyksXG4gIG91dHB1dEhhc2g6IGZhbHNlLFxuICBvdXRwdXRQYXRoOiAnLi9saWInLFxuICBwYWNrYWdlTWFuYWdlcjogJ25wbScsXG4gIHByZXNldDogJ3dlYicsXG4gIHNvdXJjZUZ1bGxQYXRoOiBwYXRoUmVzb2x2ZShjd2QsICcuL3NyYycpLFxuICBzb3VyY2VQYXRoOiAnLi9zcmMnLFxuICB0YXJnZXRFbnZpcm9ubWVudDogJ3dlYicsXG4gIHVzZUdyYXBoUWw6IGZhbHNlLFxuICB1c2VUeXBlc2NyaXB0OiBmYWxzZSxcbiAgd2VicGFjazoge1xuICAgIHB1YmxpY1BhdGg6ICcuL3NyYy9zdGF0aWMnXG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBnZXRUeXBlU2NyaXB0Q29uZmlnUGF0aCA9IChjb25maWdOYW1lOiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xuICBjb25zdCBjd2QgPSBwcm9jZXNzLmN3ZCgpO1xuXG4gIGlmKGNvbmZpZ05hbWUgPT09ICd0c2NvbmZpZy5idWlsZC5qc29uJykge1xuICAgIGNvbnN0IHByb2plY3RCdWlsZENvbmZpZyA9IHBhdGhSZXNvbHZlKGN3ZCwgJ3RzY29uZmlnLmJ1aWxkLmpzb24nKTtcbiAgICBpZihleGlzdHNTeW5jKHByb2plY3RCdWlsZENvbmZpZykpIHtcbiAgICAgIHJldHVybiBwcm9qZWN0QnVpbGRDb25maWc7XG4gICAgfVxuICB9XG5cbiAgaWYoY29uZmlnTmFtZSA9PT0gJ3RzY29uZmlnLmxpbnQuanNvbicpIHtcbiAgICBjb25zdCBwcm9qZWN0TGludENvbmZpZyA9IHBhdGhSZXNvbHZlKGN3ZCwgJ3RzY29uZmlnLmVzbGludC5qc29uJyk7XG4gICAgaWYoZXhpc3RzU3luYyhwcm9qZWN0TGludENvbmZpZykpIHtcbiAgICAgIHJldHVybiBwcm9qZWN0TGludENvbmZpZztcbiAgICB9XG4gIH1cblxuICBpZihjb25maWdOYW1lID09PSAndHNjb25maWcudGVzdC5qc29uJykge1xuICAgIGNvbnN0IHByb2plY3RUZXN0Q29uZmlnID0gcGF0aFJlc29sdmUoY3dkLCAndHNjb25maWcudGVzdC5qc29uJyk7XG4gICAgaWYoZXhpc3RzU3luYyhwcm9qZWN0VGVzdENvbmZpZykpIHtcbiAgICAgIHJldHVybiBwcm9qZWN0VGVzdENvbmZpZztcbiAgICB9XG4gIH1cblxuICBjb25zdCBwcm9qZWN0Q29uZmlnUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgY29uZmlnTmFtZSk7XG4gIGlmKGV4aXN0c1N5bmMocHJvamVjdENvbmZpZ1BhdGgpKSB7XG4gICAgcmV0dXJuIHByb2plY3RDb25maWdQYXRoO1xuICB9XG5cbiAgY29uc3QgbGV4RGlyID0gTGV4Q29uZmlnLmdldExleERpcigpO1xuICByZXR1cm4gcGF0aFJlc29sdmUobGV4RGlyLCBjb25maWdOYW1lKTtcbn07XG5cbmV4cG9ydCBjbGFzcyBMZXhDb25maWcge1xuICBzdGF0aWMgY29uZmlnOiBMZXhDb25maWdUeXBlID0ge1xuICAgIC4uLmRlZmF1bHRDb25maWdWYWx1ZXNcbiAgfTtcblxuICBzdGF0aWMgc2V0IHVzZVR5cGVzY3JpcHQodmFsdWU6IGJvb2xlYW4pIHtcbiAgICBMZXhDb25maWcuY29uZmlnLnVzZVR5cGVzY3JpcHQgPSB2YWx1ZTtcbiAgICBjb25zdCB7c291cmNlRnVsbFBhdGh9ID0gTGV4Q29uZmlnLmNvbmZpZztcblxuICAgIGNvbnN0IHtlbnRyeUpzfSA9IExleENvbmZpZy5jb25maWc7XG5cbiAgICBpZihlbnRyeUpzID09PSAnaW5kZXguanMnICYmIHZhbHVlKSB7XG4gICAgICBjb25zdCBpbmRleFBhdGg6IHN0cmluZyA9IHBhdGhSZXNvbHZlKGN3ZCwgc291cmNlRnVsbFBhdGgsICdpbmRleC50c3gnKTtcbiAgICAgIGNvbnN0IGhhc0luZGV4VHN4OiBib29sZWFuID0gZXhpc3RzU3luYyhpbmRleFBhdGgpO1xuXG4gICAgICBpZihoYXNJbmRleFRzeCkge1xuICAgICAgICBMZXhDb25maWcuY29uZmlnLmVudHJ5SnMgPSAnaW5kZXgudHN4JztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIExleENvbmZpZy5jb25maWcuZW50cnlKcyA9ICdpbmRleC50cyc7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgc3RhdGljIGdldExleERpcigpOiBzdHJpbmcge1xuICAgIHJldHVybiBkaXJuYW1lKGdldExleFBhY2thZ2VKc29uUGF0aCgpKTtcbiAgfVxuXG4gIHN0YXRpYyB1cGRhdGVDb25maWcodXBkYXRlZENvbmZpZzogTGV4Q29uZmlnVHlwZSk6IExleENvbmZpZ1R5cGUge1xuICAgIGNvbnN0IHtvdXRwdXRGdWxsUGF0aCwgb3V0cHV0UGF0aCwgc291cmNlUGF0aCwgc291cmNlRnVsbFBhdGgsIHVzZVR5cGVzY3JpcHQsIGFpfSA9IHVwZGF0ZWRDb25maWc7XG4gICAgY29uc3QgY3dkOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpO1xuXG4gICAgaWYodXNlVHlwZXNjcmlwdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBMZXhDb25maWcudXNlVHlwZXNjcmlwdCA9IHVzZVR5cGVzY3JpcHQ7XG4gICAgfVxuXG4gICAgaWYob3V0cHV0UGF0aCAhPT0gdW5kZWZpbmVkICYmIG91dHB1dEZ1bGxQYXRoID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHVwZGF0ZWRDb25maWcub3V0cHV0RnVsbFBhdGggPSBwYXRoUmVzb2x2ZShjd2QsIG91dHB1dFBhdGgpO1xuICAgIH1cblxuICAgIGlmKHNvdXJjZVBhdGggIT09IHVuZGVmaW5lZCAmJiBzb3VyY2VGdWxsUGF0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB1cGRhdGVkQ29uZmlnLnNvdXJjZUZ1bGxQYXRoID0gcGF0aFJlc29sdmUoY3dkLCBzb3VyY2VQYXRoKTtcbiAgICB9XG5cbiAgICBpZihhaSkge1xuICAgICAgTGV4Q29uZmlnLmNvbmZpZy5haSA9IHsuLi5MZXhDb25maWcuY29uZmlnLmFpLCAuLi5haX07XG5cbiAgICAgIGlmKHByb2Nlc3MuZW52LkNVUlNPUl9JREUgPT09ICd0cnVlJyAmJiBMZXhDb25maWcuY29uZmlnLmFpLnByb3ZpZGVyID09PSAnbm9uZScpIHtcbiAgICAgICAgTGV4Q29uZmlnLmNvbmZpZy5haS5wcm92aWRlciA9ICdjdXJzb3InO1xuICAgICAgfVxuICAgIH1cblxuICAgIExleENvbmZpZy5jb25maWcgPSB7Li4uTGV4Q29uZmlnLmNvbmZpZywgLi4udXBkYXRlZENvbmZpZ307XG5cbiAgICByZXR1cm4gTGV4Q29uZmlnLmNvbmZpZztcbiAgfVxuXG4gIHN0YXRpYyBhZGRDb25maWdQYXJhbXMoY21kLCBwYXJhbXM6IExleENvbmZpZ1R5cGUpIHtcbiAgICBjb25zdCBuYW1lUHJvcGVydHk6IHN0cmluZyA9ICdfbmFtZSc7XG4gICAgY29uc3Qge2Vudmlyb25tZW50LCBvdXRwdXRQYXRoLCBzb3VyY2VQYXRoLCB0eXBlc2NyaXB0fSA9IGNtZDtcblxuICAgIGlmKG91dHB1dFBhdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgcGFyYW1zLm91dHB1dFBhdGggPSBvdXRwdXRQYXRoO1xuICAgICAgcGFyYW1zLm91dHB1dEZ1bGxQYXRoID0gcGF0aFJlc29sdmUoY3dkLCBvdXRwdXRQYXRoKTtcbiAgICB9XG5cbiAgICBpZihzb3VyY2VQYXRoICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHBhcmFtcy5zb3VyY2VQYXRoID0gc291cmNlUGF0aDtcbiAgICAgIHBhcmFtcy5zb3VyY2VGdWxsUGF0aCA9IHBhdGhSZXNvbHZlKGN3ZCwgc291cmNlUGF0aCk7XG4gICAgfVxuXG4gICAgaWYodHlwZXNjcmlwdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwYXJhbXMudXNlVHlwZXNjcmlwdCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYoZW52aXJvbm1lbnQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcGFyYW1zLnRhcmdldEVudmlyb25tZW50ID0gZW52aXJvbm1lbnQgPT09ICd3ZWInID8gJ3dlYicgOiAnbm9kZSc7XG4gICAgfVxuXG4gICAgcHJvY2Vzcy5lbnYuTEVYX0NPTkZJRyA9IEpTT04uc3RyaW5naWZ5KFxuICAgICAge1xuICAgICAgICAuLi5MZXhDb25maWcudXBkYXRlQ29uZmlnKHBhcmFtcyksXG4gICAgICAgIGNvbW1hbmROYW1lOiBjbWRbbmFtZVByb3BlcnR5XSxcbiAgICAgICAgaXNTdGF0aWM6IGNtZC5zdGF0aWNcbiAgICAgIH0sIG51bGwsIDBcbiAgICApO1xuICB9XG5cbiAgc3RhdGljIGFzeW5jIHBhcnNlQ29uZmlnKGNtZCwgaXNSb290OiBib29sZWFuID0gdHJ1ZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHtjbGlOYW1lID0gJ0xleCcsIGxleENvbmZpZywgbGV4Q29uZmlnTmFtZSwgcXVpZXQsIHR5cGVzY3JpcHQsIGRlYnVnID0gZmFsc2V9ID0gY21kO1xuICAgIGNvbnN0IGNvbmZpZ0Zvcm1hdHMgPSBbJ2pzJywgJ21qcycsICdjanMnLCAndHMnLCAnanNvbiddO1xuICAgIGNvbnN0IGNvbmZpZ0Jhc2VOYW1lOiBzdHJpbmcgPSBsZXhDb25maWdOYW1lIHx8ICdsZXguY29uZmlnJztcbiAgICBsZXQgY29uZmlnUGF0aDogc3RyaW5nID0gbGV4Q29uZmlnIHx8ICcnO1xuICAgIGxldCBjb25maWdFeGlzdHM6IGJvb2xlYW4gPSBsZXhDb25maWcgPyBleGlzdHNTeW5jKGNvbmZpZ1BhdGgpIDogZmFsc2U7XG5cbiAgICBpZighY29uZmlnUGF0aCB8fCAhY29uZmlnRXhpc3RzKSB7XG4gICAgICBpZihkZWJ1Zykge1xuICAgICAgICBsb2coYFNlYXJjaGluZyBmb3IgY29uZmlnIGZpbGVzIHdpdGggYmFzZSBuYW1lOiAke2NvbmZpZ0Jhc2VOYW1lfWAsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfVxuXG4gICAgICBmb3IoY29uc3QgZm9ybWF0IG9mIGNvbmZpZ0Zvcm1hdHMpIHtcbiAgICAgICAgY29uc3QgcG90ZW50aWFsUGF0aCA9IGlzUm9vdFxuICAgICAgICAgID8gcGF0aFJlc29sdmUoY3dkLCBgLi8ke2NvbmZpZ0Jhc2VOYW1lfS4ke2Zvcm1hdH1gKVxuICAgICAgICAgIDogcmVsYXRpdmVGaWxlUGF0aChgJHtjb25maWdCYXNlTmFtZX0uJHtmb3JtYXR9YCwgY3dkKTtcblxuICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgIGxvZyhgQ2hlY2tpbmcgZm9yIGNvbmZpZyBmaWxlOiAke3BvdGVudGlhbFBhdGh9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZihleGlzdHNTeW5jKHBvdGVudGlhbFBhdGgpKSB7XG4gICAgICAgICAgY29uZmlnUGF0aCA9IHBvdGVudGlhbFBhdGg7XG4gICAgICAgICAgY29uZmlnRXhpc3RzID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmKGNvbmZpZ0V4aXN0cykge1xuICAgICAgbG9nKGBVc2luZyAke2NsaU5hbWV9IGNvbmZpZ3VyYXRpb24gZmlsZTogJHtjb25maWdQYXRofWAsICdub3RlJywgcXVpZXQpO1xuICAgICAgY29uc3QgZXh0OiBzdHJpbmcgPSBwYXRoRXh0bmFtZShjb25maWdQYXRoKTtcblxuICAgICAgaWYoZXh0ID09PSAnLmpzb24nKSB7XG4gICAgICAgIGNvbnN0IGNvbmZpZ0NvbnRlbnQ6IHN0cmluZyA9IHJlYWRGaWxlU3luYyhjb25maWdQYXRoLCAndXRmOCcpO1xuXG4gICAgICAgIGlmKGNvbmZpZ0NvbnRlbnQpIHtcbiAgICAgICAgICBsZXQgY29uZmlnSnNvbjogTGV4Q29uZmlnVHlwZTtcblxuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25maWdKc29uID0gSlNPTi5wYXJzZShjb25maWdDb250ZW50KT8uZGVmYXVsdCB8fCB7fTtcbiAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBGYWlsZWQgdG8gcGFyc2UgSlNPTiBjb25maWc6ICR7ZXJyb3IubWVzc2FnZX1gLCAnZXJyb3InLCBxdWlldCk7XG4gICAgICAgICAgICBjb25maWdKc29uID0ge307XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgTGV4Q29uZmlnLmFkZENvbmZpZ1BhcmFtcyhjbWQsIGNvbmZpZ0pzb24pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGxvZyhgXFxuJHtjbGlOYW1lfSBFcnJvcjogQ29uZmlnIGZpbGUgbWFsZm9ybWVkLCAke2NvbmZpZ1BhdGh9YCwgJ2Vycm9yJywgcXVpZXQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYoWycuanMnLCAnLm1qcycsICcuY2pzJywgJy50cyddLmluY2x1ZGVzKGV4dCkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBsZXQgbGV4Q3VzdG9tQ29uZmlnO1xuXG4gICAgICAgICAgaWYoZXh0ID09PSAnLmNqcycpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpbGVVcmwgPSBuZXcgVVJMKGBmaWxlOi8vLyR7cGF0aFJlc29sdmUoY29uZmlnUGF0aCl9YCkuaHJlZjtcblxuICAgICAgICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgICAgICAgbG9nKGBMb2FkaW5nIENvbW1vbkpTIGNvbmZpZyBmcm9tOiAke2ZpbGVVcmx9YCwgJ2luZm8nLCBxdWlldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXhDdXN0b21Db25maWcgPSBhd2FpdCBpbXBvcnQoZmlsZVVybCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgICAgIGxvZyhgTG9hZGluZyBFU00vVFMgY29uZmlnIGZyb206ICR7Y29uZmlnUGF0aH1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV4Q3VzdG9tQ29uZmlnID0gYXdhaXQgaW1wb3J0KGNvbmZpZ1BhdGgpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGNvbnN0IGNvbmZpZyA9IGxleEN1c3RvbUNvbmZpZy5kZWZhdWx0IHx8IGxleEN1c3RvbUNvbmZpZztcblxuICAgICAgICAgIGlmKGRlYnVnKSB7XG4gICAgICAgICAgICBsb2coYExvYWRlZCBjb25maWc6ICR7SlNPTi5zdHJpbmdpZnkoY29uZmlnLCBudWxsLCAyKX1gLCAnaW5mbycsIHF1aWV0KTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZighY29uZmlnKSB7XG4gICAgICAgICAgICBsb2coYFxcbiR7Y2xpTmFtZX0gV2FybmluZzogQ29uZmlnIGZpbGUgbG9hZGVkIGJ1dCBubyBjb25maWd1cmF0aW9uIGZvdW5kYCwgJ3dhcm4nLCBxdWlldCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgTGV4Q29uZmlnLmFkZENvbmZpZ1BhcmFtcyhjbWQsIGNvbmZpZyB8fCB7fSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBGYWlsZWQgdG8gbG9hZCBjb25maWcgZmlsZTogJHtlcnJvci5tZXNzYWdlfWAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgICAgICBpZihkZWJ1Zykge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyb3IpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nKGBcXG4ke2NsaU5hbWV9IEVycm9yOiBDb25maWcgZmlsZSBtdXN0IGJlIGEgSlMsIENKUywgTUpTLCBUUywgb3IgSlNPTiBmaWxlLmAsICdlcnJvcicsIHF1aWV0KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYoZGVidWcpIHtcbiAgICAgICAgbG9nKCdObyBjb25maWcgZmlsZSBmb3VuZC4gVXNpbmcgZGVmYXVsdCBjb25maWd1cmF0aW9uLicsICdpbmZvJywgcXVpZXQpO1xuICAgICAgfVxuXG4gICAgICBMZXhDb25maWcudXNlVHlwZXNjcmlwdCA9ICEhdHlwZXNjcmlwdDtcbiAgICAgIExleENvbmZpZy5hZGRDb25maWdQYXJhbXMoY21kLCBMZXhDb25maWcuY29uZmlnKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgY2hlY2tUeXBlc2NyaXB0Q29uZmlnKCkge1xuICAgIGNvbnN0IHRzY29uZmlnUGF0aDogc3RyaW5nID0gcGF0aFJlc29sdmUoY3dkLCAnLi90c2NvbmZpZy5qc29uJyk7XG5cbiAgICBpZighZXhpc3RzU3luYyh0c2NvbmZpZ1BhdGgpKSB7XG4gICAgICBjb25zdCBkaXJOYW1lID0gZ2V0RGlyTmFtZSgpO1xuICAgICAgd3JpdGVGaWxlU3luYyh0c2NvbmZpZ1BhdGgsIHJlYWRGaWxlU3luYyhwYXRoUmVzb2x2ZShkaXJOYW1lLCAnLi4vLi4vLi4vdHNjb25maWcuYmFzZS5qc29uJykpKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgY2hlY2tDb21waWxlVHlwZXNjcmlwdENvbmZpZygpIHtcbiAgICBjb25zdCBsZXhEaXIgPSBMZXhDb25maWcuZ2V0TGV4RGlyKCk7XG4gICAgY29uc3QgdHNjb25maWdDb21waWxlUGF0aDogc3RyaW5nID0gcGF0aFJlc29sdmUobGV4RGlyLCAnLi90c2NvbmZpZy5idWlsZC5qc29uJyk7XG5cbiAgICBpZighZXhpc3RzU3luYyh0c2NvbmZpZ0NvbXBpbGVQYXRoKSkge1xuICAgICAgY29uc3QgdGVtcGxhdGVQYXRoID0gcGF0aFJlc29sdmUobGV4RGlyLCAndHNjb25maWcuYnVpbGQuanNvbicpO1xuICAgICAgaWYoZXhpc3RzU3luYyh0ZW1wbGF0ZVBhdGgpKSB7XG4gICAgICAgIHdyaXRlRmlsZVN5bmModHNjb25maWdDb21waWxlUGF0aCwgcmVhZEZpbGVTeW5jKHRlbXBsYXRlUGF0aCkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBjaGVja0xpbnRUeXBlc2NyaXB0Q29uZmlnKCkge1xuICAgIGNvbnN0IGxleERpciA9IExleENvbmZpZy5nZXRMZXhEaXIoKTtcbiAgICBjb25zdCB0c2NvbmZpZ0xpbnRQYXRoOiBzdHJpbmcgPSBwYXRoUmVzb2x2ZShsZXhEaXIsICcuL3RzY29uZmlnLmxpbnQuanNvbicpO1xuXG4gICAgaWYoIWV4aXN0c1N5bmModHNjb25maWdMaW50UGF0aCkpIHtcbiAgICAgIGNvbnN0IHRlbXBsYXRlUGF0aCA9IHBhdGhSZXNvbHZlKGxleERpciwgJ3RzY29uZmlnLmxpbnQuanNvbicpO1xuICAgICAgaWYoZXhpc3RzU3luYyh0ZW1wbGF0ZVBhdGgpKSB7XG4gICAgICAgIHdyaXRlRmlsZVN5bmModHNjb25maWdMaW50UGF0aCwgcmVhZEZpbGVTeW5jKHRlbXBsYXRlUGF0aCkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyBjaGVja1Rlc3RUeXBlc2NyaXB0Q29uZmlnKCkge1xuICAgIGNvbnN0IGxleERpciA9IExleENvbmZpZy5nZXRMZXhEaXIoKTtcbiAgICBjb25zdCB0c2NvbmZpZ1Rlc3RQYXRoOiBzdHJpbmcgPSBwYXRoUmVzb2x2ZShsZXhEaXIsICcuL3RzY29uZmlnLnRlc3QuanNvbicpO1xuXG4gICAgaWYoIWV4aXN0c1N5bmModHNjb25maWdUZXN0UGF0aCkpIHtcbiAgICAgIGNvbnN0IHRlbXBsYXRlUGF0aCA9IHBhdGhSZXNvbHZlKGxleERpciwgJ3RzY29uZmlnLnRlc3QuanNvbicpO1xuICAgICAgaWYoZXhpc3RzU3luYyh0ZW1wbGF0ZVBhdGgpKSB7XG4gICAgICAgIHdyaXRlRmlsZVN5bmModHNjb25maWdUZXN0UGF0aCwgcmVhZEZpbGVTeW5jKHRlbXBsYXRlUGF0aCkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxufSJdLAogICJtYXBwaW5ncyI6ICJBQUlBLFNBQVEsWUFBWSxjQUFjLHFCQUFvQjtBQUN0RCxTQUFRLFNBQVMsV0FBVyxhQUFhLFdBQVcsbUJBQWtCO0FBQ3RFLFNBQVEsV0FBVTtBQUVsQixTQUFRLFlBQVksdUJBQXVCLHdCQUF1QjtBQUNsRSxTQUFRLFdBQVU7QUFJbEIsTUFBTSxNQUFjLFFBQVEsSUFBSTtBQXNGekIsTUFBTSxzQkFBcUM7QUFBQSxFQUNoRCxJQUFJO0FBQUEsSUFDRixXQUFXO0FBQUEsSUFDWCxPQUFPO0FBQUEsSUFDUCxVQUFVO0FBQUEsSUFDVixhQUFhO0FBQUEsRUFDZjtBQUFBLEVBQ0EsYUFBYSxDQUFDO0FBQUEsRUFDZCxXQUFXLENBQUM7QUFBQSxFQUNaLFdBQVc7QUFBQSxFQUNYLFNBQVM7QUFBQSxFQUNULEtBQUs7QUFBQSxFQUNMLFNBQVM7QUFBQSxJQUNQLE1BQU0sQ0FBQyxXQUFXLFVBQVU7QUFBQSxJQUM1QixlQUFlO0FBQUEsSUFDZixVQUFVO0FBQUEsSUFDVixRQUFRO0FB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