UNPKG

@tylertech/forge-build-tools

Version:
213 lines 30.5 kB
import * as fs from 'fs'; import * as util from 'util'; import { rimrafSync } from 'rimraf'; import * as tmp from 'tmp'; import { glob, globSync } from 'glob'; import fsExtra from 'fs-extra'; import cpath from 'canonical-path'; import { isGlob, logError } from '../utils/index.js'; export const existsSync = (path) => fs.existsSync(path); // Export promisified fs functions here export const mkdirAsync = util.promisify(fs.mkdir); export const mkdirp = fsExtra.mkdirpSync; export const copy = fsExtra.copySync; export const copyAsync = util.promisify(fsExtra.copy); export const symlinkAsync = util.promisify(fs.symlink); export const readFileAsync = util.promisify(fs.readFile); export const writeFileAsync = util.promisify(fs.writeFile); export const existsAsync = util.promisify(fs.exists); export const readdirAsync = util.promisify(fs.readdir); export const statAsync = util.promisify(fs.stat); export const lstatAsync = util.promisify(fs.lstat); export const removeSync = fsExtra.removeSync; export const ensureDir = util.promisify(fsExtra.ensureDir); export const ensureDirSync = fsExtra.ensureDirSync; export const outputFileAsync = fsExtra.outputFile; export const globFiles = globSync; export const emptyDir = fsExtra.emptyDirSync; export const emptyDirAsync = fsExtra.emptyDir; export const deleteDir = rimrafSync; export const rename = util.promisify(fs.rename); export const deleteFile = util.promisify(fs.unlink); export const moveAsync = util.promisify(fsExtra.move); export function globFilesAsync(pattern, options) { return glob(pattern, options); } /** * Deletes the list of files. * @param files The files to delete. */ export async function deleteFiles(files) { if (typeof files === 'string') { files = isGlob(files) ? await globFilesAsync(files, {}) : [files]; } files.forEach(filename => deleteFile(cpath.resolve(filename))); } /** * Moves an array of files or a glob pattern of files to a directory. * @param {string[] | string} files The array of files or a glob pattern of files to search for. * @param {string} rootDir The common root directory in which to build the structure in the output directory. * @param {string} outputDir The output directory path. */ export async function moveFiles(files, rootDir, outputDir) { if (typeof files === 'string') { files = isGlob(files) ? await globFilesAsync(files, {}) : [files]; } if (rootDir) { rootDir = cpath.resolve(rootDir); } outputDir = cpath.resolve(outputDir); for (const filename of files) { const absoluteFilePath = cpath.resolve(filename); const filePath = rootDir ? absoluteFilePath.replace(rootDir, '').replace(/^\//, '') : cpath.basename(absoluteFilePath); const outputFilePath = cpath.join(outputDir, filePath); mkdirp(cpath.dirname(outputFilePath)); await rename(filename, outputFilePath); } } /** * * @param dirs The directory paths to move. * @param outputDir The new directory location. */ export async function moveDirectories(dirs, outputDir) { for (const dir of dirs) { const outputPath = cpath.join(outputDir, cpath.basename(dir)); if (existsSync(dir) && !existsSync(outputPath)) { await moveAsync(dir, outputPath); } } } /** * Copies an array of files or a glob pattern of files to a directory. * @param {string | string[]} files The array of files or a glob pattern of files to search for. * @param {string} rootDir The common root directory in which to build the structure in the output directory. * @param {string | string[]} outputDirs The output directory path. */ export async function copyFilesAsync(files, rootDir, outputDirs, ignoredFiles) { if (typeof files === 'string') { files = isGlob(files) ? await globFilesAsync(files, { ignore: ignoredFiles }) : [files]; } if (typeof outputDirs === 'string') { outputDirs = [outputDirs]; } if (!(outputDirs instanceof Array)) { throw new Error('outputDirs must be an array.'); } if (rootDir) { rootDir = cpath.resolve(rootDir); } outputDirs = outputDirs.map(dir => cpath.resolve(dir)); outputDirs.forEach(dir => mkdirp(dir)); for (const file of files) { const absoluteFilePath = cpath.resolve(file); const promises = []; for (const outputDir of outputDirs) { const relativePath = rootDir ? absoluteFilePath.replace(rootDir, '').replace(/^\//, '') : cpath.basename(absoluteFilePath); const outputFilePath = cpath.join(outputDir, relativePath); promises.push(copyAsync(file, outputFilePath)); } await Promise.all(promises); } } /** * Copies the provided files from one directory to another. * @param fileConfigs The file copy descriptors. */ export async function copyFilesMultiple(fileConfigs) { if (fileConfigs.some(config => !config.path || !config.outputPath)) { throw new Error('Every file config must specify valid path and outputPath properties.'); } for (const config of fileConfigs) { let files = []; if (typeof config.path === 'string') { files = isGlob(config.path) ? await globFilesAsync(config.path, {}) : [config.path]; } else if (config.path instanceof Array) { for (const filename of config.path) { files = files.concat(isGlob(filename) ? await globFilesAsync(filename, {}) : [filename]); } } else { throw new Error('Invalid filepath provided.'); } const outputPath = cpath.resolve(config.outputPath); mkdirp(outputPath); for (const file of files) { const absoluteFilePath = cpath.resolve(file); const outputFilePath = config.rootPath ? cpath.join(outputPath, absoluteFilePath.replace(cpath.resolve(config.rootPath), '').replace(/^\//, '')) : cpath.join(outputPath, cpath.basename(file)); await copy(file, outputFilePath); } } } /** * Reads in a JSON file and returns an instance of it. * @param filepath The path to the file to read. */ export async function readJsonFile(filepath) { let json; let contents; try { contents = await readFileAsync(filepath, 'utf-8'); } catch { return undefined; } if (contents) { try { json = JSON.parse(contents); } catch (e) { logError('Invalid JSON file: ' + filepath); } } return json; } /** * Writes an object to a JSON file. * Note: overwrites the file, does not merge the JSON contents. * @param filepath The file path to write to. * @param data The object to convert to JSON. */ export async function writeJsonFile(filepath, data) { const contents = JSON.stringify(data, null, ' '); await writeFileAsync(filepath, contents, 'utf8'); } /** * Creates a new temporary directory. * @param options The options to pass to `tmp`. */ export async function createTempDir(options) { const defaultOptions = { mode: 0o777, keep: false, unsafeCleanup: true }; const tmpOptions = Object.assign(defaultOptions, options); return new Promise((resolve, reject) => { tmp.setGracefulCleanup(); tmp.dir(tmpOptions, (err, path, cleanupCallback) => { if (err) { reject(err); } const result = { path, remove: cleanupCallback }; resolve(result); }); }); } /** * Replaces the extension in `inPath` with the extension specified in `extension`. * @param {string} inPath The path to replace the extension in. * @param {string} extension The new extension. */ export function replaceExtension(inPath, extension) { if (!inPath || typeof inPath !== 'string') { return inPath; } const newPath = cpath.basename(inPath, cpath.extname(inPath)) + extension.replace(/^\.?/, '.'); return cpath.join(cpath.dirname(inPath), newPath); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZnMvZnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNwQyxPQUFPLEtBQUssR0FBRyxNQUFNLEtBQUssQ0FBQztBQUMzQixPQUFPLEVBQUUsSUFBSSxFQUFpQyxRQUFRLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckUsT0FBTyxPQUFPLE1BQU0sVUFBVSxDQUFDO0FBQy9CLE9BQU8sS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBRW5DLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFckQsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHLENBQUMsSUFBWSxFQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBRXpFLHVDQUF1QztBQUN2QyxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDbkQsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7QUFDekMsTUFBTSxDQUFDLE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUM7QUFDckMsTUFBTSxDQUFDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3RELE1BQU0sQ0FBQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUN2RCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FB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R0FBRyxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRSxFQUFFO1lBQ2pELElBQUksR0FBRyxFQUFFLENBQUM7Z0JBQ1IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ2QsQ0FBQztZQUVELE1BQU0sTUFBTSxHQUFHO2dCQUNiLElBQUk7Z0JBQ0osTUFBTSxFQUFFLGVBQWU7YUFDeEIsQ0FBQztZQUNGLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNsQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsTUFBYyxFQUFFLFNBQWlCO0lBQ2hFLElBQUksQ0FBQyxNQUFNLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDMUMsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQztJQUMvRixPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztBQUNwRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgdXRpbCBmcm9tICd1dGlsJztcbmltcG9ydCB7IHJpbXJhZlN5bmMgfSBmcm9tICdyaW1yYWYnO1xuaW1wb3J0ICogYXMgdG1wIGZyb20gJ3RtcCc7XG5pbXBvcnQgeyBnbG9iLCBHbG9iT3B0aW9uc1dpdGhGaWxlVHlwZXNVbnNldCwgZ2xvYlN5bmMgfSBmcm9tICdnbG9iJztcbmltcG9ydCBmc0V4dHJhIGZyb20gJ2ZzLWV4dHJhJztcbmltcG9ydCBjcGF0aCBmcm9tICdjYW5vbmljYWwtcGF0aCc7XG5cbmltcG9ydCB7IGlzR2xvYiwgbG9nRXJyb3IgfSBmcm9tICcuLi91dGlscy9pbmRleC5qcyc7XG5cbmV4cG9ydCBjb25zdCBleGlzdHNTeW5jID0gKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4gPT4gZnMuZXhpc3RzU3luYyhwYXRoKTtcblxuLy8gRXhwb3J0IHByb21pc2lmaWVkIGZzIGZ1bmN0aW9ucyBoZXJlXG5leHBvcnQgY29uc3QgbWtkaXJBc3luYyA9IHV0aWwucHJvbWlzaWZ5KGZzLm1rZGlyKTtcbmV4cG9ydCBjb25zdCBta2RpcnAgPSBmc0V4dHJhLm1rZGlycFN5bmM7XG5leHBvcnQgY29uc3QgY29weSA9IGZzRXh0cmEuY29weVN5bmM7XG5leHBvcnQgY29uc3QgY29weUFzeW5jID0gdXRpbC5wcm9taXNpZnkoZnNFeHRyYS5jb3B5KTtcbmV4cG9ydCBjb25zdCBzeW1saW5rQXN5bmMgPSB1dGlsLnByb21pc2lmeShmcy5zeW1saW5rKTtcbmV4cG9ydCBjb25zdCByZWFkRmlsZUFzeW5jID0gdXRpbC5wcm9taXNpZnkoZnMucmVhZEZpbGUpO1xuZXhwb3J0IGNvbnN0IHdyaXRlRmlsZUFzeW5jID0gdXRpbC5wcm9taXNpZnkoZnMud3JpdGVGaWxlKTtcbmV4cG9ydCBjb25zdCBleGlzdHNBc3luYyA9IHV0aWwucHJvbWlzaWZ5KGZzLmV4aXN0cyk7XG5leHBvcnQgY29uc3QgcmVhZGRpckFzeW5jID0gdXRpbC5wcm9taXNpZnkoZnMucmVhZGRpcik7XG5leHBvcnQgY29uc3Qgc3RhdEFzeW5jID0gdXRpbC5wcm9taXNpZnkoZnMuc3RhdCk7XG5leHBvcnQgY29uc3QgbHN0YXRBc3luYyA9IHV0aWwucHJvbWlzaWZ5KGZzLmxzdGF0KTtcbmV4cG9ydCBjb25zdCByZW1vdmVTeW5jID0gZnNFeHRyYS5yZW1vdmVTeW5jO1xuZXhwb3J0IGNvbnN0IGVuc3VyZURpciA9IHV0aWwucHJvbWlzaWZ5KGZzRXh0cmEuZW5zdXJlRGlyKTtcbmV4cG9ydCBjb25zdCBlbnN1cmVEaXJTeW5jID0gZnNFeHRyYS5lbnN1cmVEaXJTeW5jO1xuZXhwb3J0IGNvbnN0IG91dHB1dEZpbGVBc3luYyA9IGZzRXh0cmEub3V0cHV0RmlsZTtcbmV4cG9ydCBjb25zdCBnbG9iRmlsZXMgPSBnbG9iU3luYztcbmV4cG9ydCBjb25zdCBlbXB0eURpciA9IGZzRXh0cmEuZW1wdHlEaXJTeW5jO1xuZXhwb3J0IGNvbnN0IGVtcHR5RGlyQXN5bmMgPSBmc0V4dHJhLmVtcHR5RGlyO1xuZXhwb3J0IGNvbnN0IGRlbGV0ZURpciA9IHJpbXJhZlN5bmM7XG5leHBvcnQgY29uc3QgcmVuYW1lID0gdXRpbC5wcm9taXNpZnkoZnMucmVuYW1lKTtcbmV4cG9ydCBjb25zdCBkZWxldGVGaWxlID0gdXRpbC5wcm9taXNpZnkoZnMudW5saW5rKTtcbmV4cG9ydCBjb25zdCBtb3ZlQXN5bmMgPSB1dGlsLnByb21pc2lmeShmc0V4dHJhLm1vdmUpO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2xvYkZpbGVzQXN5bmMocGF0dGVybjogc3RyaW5nIHwgc3RyaW5nW10sIG9wdGlvbnM/OiBHbG9iT3B0aW9uc1dpdGhGaWxlVHlwZXNVbnNldCB8IHVuZGVmaW5lZCk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgcmV0dXJuIGdsb2IocGF0dGVybiwgb3B0aW9ucyk7XG59XG5cbi8qKlxuICogRGVsZXRlcyB0aGUgbGlzdCBvZiBmaWxlcy5cbiAqIEBwYXJhbSBmaWxlcyBUaGUgZmlsZXMgdG8gZGVsZXRlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVsZXRlRmlsZXMoZmlsZXM6IHN0cmluZyB8IHN0cmluZ1tdKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmICh0eXBlb2YgZmlsZXMgPT09ICdzdHJpbmcnKSB7XG4gICAgZmlsZXMgPSBpc0dsb2IoZmlsZXMpID8gYXdhaXQgZ2xvYkZpbGVzQXN5bmMoZmlsZXMsIHt9KSBhcyBzdHJpbmdbXSA6IFtmaWxlc107XG4gIH1cblxuICBmaWxlcy5mb3JFYWNoKGZpbGVuYW1lID0+IGRlbGV0ZUZpbGUoY3BhdGgucmVzb2x2ZShmaWxlbmFtZSkpKTtcbn1cblxuLyoqXG4gKiBNb3ZlcyBhbiBhcnJheSBvZiBmaWxlcyBvciBhIGdsb2IgcGF0dGVybiBvZiBmaWxlcyB0byBhIGRpcmVjdG9yeS5cbiAqIEBwYXJhbSB7c3RyaW5nW10gfCBzdHJpbmd9IGZpbGVzIFRoZSBhcnJheSBvZiBmaWxlcyBvciBhIGdsb2IgcGF0dGVybiBvZiBmaWxlcyB0byBzZWFyY2ggZm9yLlxuICogQHBhcmFtIHtzdHJpbmd9IHJvb3REaXIgVGhlIGNvbW1vbiByb290IGRpcmVjdG9yeSBpbiB3aGljaCB0byBidWlsZCB0aGUgc3RydWN0dXJlIGluIHRoZSBvdXRwdXQgZGlyZWN0b3J5LlxuICogQHBhcmFtIHtzdHJpbmd9IG91dHB1dERpciBUaGUgb3V0cHV0IGRpcmVjdG9yeSBwYXRoLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbW92ZUZpbGVzKGZpbGVzOiBzdHJpbmdbXSB8IHN0cmluZywgcm9vdERpcjogc3RyaW5nIHwgbnVsbCwgb3V0cHV0RGlyOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKHR5cGVvZiBmaWxlcyA9PT0gJ3N0cmluZycpIHtcbiAgICBmaWxlcyA9IGlzR2xvYihmaWxlcykgPyBhd2FpdCBnbG9iRmlsZXNBc3luYyhmaWxlcywge30pIGFzIHN0cmluZ1tdIDogW2ZpbGVzXTtcbiAgfVxuXG4gIGlmIChyb290RGlyKSB7XG4gICAgcm9vdERpciA9IGNwYXRoLnJlc29sdmUocm9vdERpcik7XG4gIH1cbiAgb3V0cHV0RGlyID0gY3BhdGgucmVzb2x2ZShvdXRwdXREaXIpO1xuXG4gIGZvciAoY29uc3QgZmlsZW5hbWUgb2YgZmlsZXMpIHtcbiAgICBjb25zdCBhYnNvbHV0ZUZpbGVQYXRoID0gY3BhdGgucmVzb2x2ZShmaWxlbmFtZSk7XG4gICAgY29uc3QgZmlsZVBhdGggPSByb290RGlyID8gYWJzb2x1dGVGaWxlUGF0aC5yZXBsYWNlKHJvb3REaXIsICcnKS5yZXBsYWNlKC9eXFwvLywgJycpIDogY3BhdGguYmFzZW5hbWUoYWJzb2x1dGVGaWxlUGF0aCk7XG4gICAgY29uc3Qgb3V0cHV0RmlsZVBhdGggPSBjcGF0aC5qb2luKG91dHB1dERpciwgZmlsZVBhdGgpO1xuICAgIG1rZGlycChjcGF0aC5kaXJuYW1lKG91dHB1dEZpbGVQYXRoKSk7XG4gICAgYXdhaXQgcmVuYW1lKGZpbGVuYW1lLCBvdXRwdXRGaWxlUGF0aCk7XG4gIH1cbn1cblxuLyoqXG4gKlxuICogQHBhcmFtIGRpcnMgVGhlIGRpcmVjdG9yeSBwYXRocyB0byBtb3ZlLlxuICogQHBhcmFtIG91dHB1dERpciBUaGUgbmV3IGRpcmVjdG9yeSBsb2NhdGlvbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1vdmVEaXJlY3RvcmllcyhkaXJzOiBzdHJpbmdbXSwgb3V0cHV0RGlyOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yIChjb25zdCBkaXIgb2YgZGlycykge1xuICAgIGNvbnN0IG91dHB1dFBhdGggPSBjcGF0aC5qb2luKG91dHB1dERpciwgY3BhdGguYmFzZW5hbWUoZGlyKSk7XG4gICAgaWYgKGV4aXN0c1N5bmMoZGlyKSAmJiAhZXhpc3RzU3luYyhvdXRwdXRQYXRoKSkge1xuICAgICAgYXdhaXQgbW92ZUFzeW5jKGRpciwgb3V0cHV0UGF0aCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogQ29waWVzIGFuIGFycmF5IG9mIGZpbGVzIG9yIGEgZ2xvYiBwYXR0ZXJuIG9mIGZpbGVzIHRvIGEgZGlyZWN0b3J5LlxuICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0gZmlsZXMgVGhlIGFycmF5IG9mIGZpbGVzIG9yIGEgZ2xvYiBwYXR0ZXJuIG9mIGZpbGVzIHRvIHNlYXJjaCBmb3IuXG4gKiBAcGFyYW0ge3N0cmluZ30gcm9vdERpciBUaGUgY29tbW9uIHJvb3QgZGlyZWN0b3J5IGluIHdoaWNoIHRvIGJ1aWxkIHRoZSBzdHJ1Y3R1cmUgaW4gdGhlIG91dHB1dCBkaXJlY3RvcnkuXG4gKiBAcGFyYW0ge3N0cmluZyB8IHN0cmluZ1tdfSBvdXRwdXREaXJzIFRoZSBvdXRwdXQgZGlyZWN0b3J5IHBhdGguXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb3B5RmlsZXNBc3luYyhmaWxlczogc3RyaW5nIHwgc3RyaW5nW10sIHJvb3REaXI6IHN0cmluZyB8IG51bGwsIG91dHB1dERpcnM6IHN0cmluZyB8IHN0cmluZ1tdLCBpZ25vcmVkRmlsZXM/OiBzdHJpbmcgfCBzdHJpbmdbXSk6IFByb21pc2U8dm9pZD4ge1xuICBpZiAodHlwZW9mIGZpbGVzID09PSAnc3RyaW5nJykge1xuICAgIGZpbGVzID0gaXNHbG9iKGZpbGVzKSA/IGF3YWl0IGdsb2JGaWxlc0FzeW5jKGZpbGVzLCB7IGlnbm9yZTogaWdub3JlZEZpbGVzIH0pIGFzIHN0cmluZ1tdIDogW2ZpbGVzXTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb3V0cHV0RGlycyA9PT0gJ3N0cmluZycpIHtcbiAgICBvdXRwdXREaXJzID0gW291dHB1dERpcnNdO1xuICB9XG5cbiAgaWYgKCEob3V0cHV0RGlycyBpbnN0YW5jZW9mIEFycmF5KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignb3V0cHV0RGlycyBtdXN0IGJlIGFuIGFycmF5LicpO1xuICB9XG5cbiAgaWYgKHJvb3REaXIpIHtcbiAgICByb290RGlyID0gY3BhdGgucmVzb2x2ZShyb290RGlyKTtcbiAgfVxuXG4gIG91dHB1dERpcnMgPSBvdXRwdXREaXJzLm1hcChkaXIgPT4gY3BhdGgucmVzb2x2ZShkaXIpKTtcbiAgb3V0cHV0RGlycy5mb3JFYWNoKGRpciA9PiBta2RpcnAoZGlyKSk7XG5cbiAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgY29uc3QgYWJzb2x1dGVGaWxlUGF0aCA9IGNwYXRoLnJlc29sdmUoZmlsZSk7XG4gICAgY29uc3QgcHJvbWlzZXM6IEFycmF5PFByb21pc2U8dm9pZD4+ID0gW107XG5cbiAgICBmb3IgKGNvbnN0IG91dHB1dERpciBvZiBvdXRwdXREaXJzKSB7XG4gICAgICBjb25zdCByZWxhdGl2ZVBhdGggPSByb290RGlyID8gYWJzb2x1dGVGaWxlUGF0aC5yZXBsYWNlKHJvb3REaXIsICcnKS5yZXBsYWNlKC9eXFwvLywgJycpIDogY3BhdGguYmFzZW5hbWUoYWJzb2x1dGVGaWxlUGF0aCk7XG4gICAgICBjb25zdCBvdXRwdXRGaWxlUGF0aCA9IGNwYXRoLmpvaW4ob3V0cHV0RGlyLCByZWxhdGl2ZVBhdGgpO1xuICAgICAgcHJvbWlzZXMucHVzaChjb3B5QXN5bmMoZmlsZSwgb3V0cHV0RmlsZVBhdGgpKTtcbiAgICB9XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChwcm9taXNlcyk7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBJRmlsZUNvcHlDb25maWcge1xuICBwYXRoOiBzdHJpbmcgfCBzdHJpbmdbXTtcbiAgb3V0cHV0UGF0aDogc3RyaW5nO1xuICByb290UGF0aD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBDb3BpZXMgdGhlIHByb3ZpZGVkIGZpbGVzIGZyb20gb25lIGRpcmVjdG9yeSB0byBhbm90aGVyLlxuICogQHBhcmFtIGZpbGVDb25maWdzIFRoZSBmaWxlIGNvcHkgZGVzY3JpcHRvcnMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb3B5RmlsZXNNdWx0aXBsZShmaWxlQ29uZmlnczogSUZpbGVDb3B5Q29uZmlnW10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKGZpbGVDb25maWdzLnNvbWUoY29uZmlnID0+ICFjb25maWcucGF0aCB8fCAhY29uZmlnLm91dHB1dFBhdGgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdFdmVyeSBmaWxlIGNvbmZpZyBtdXN0IHNwZWNpZnkgdmFsaWQgcGF0aCBhbmQgb3V0cHV0UGF0aCBwcm9wZXJ0aWVzLicpO1xuICB9XG5cbiAgZm9yIChjb25zdCBjb25maWcgb2YgZmlsZUNvbmZpZ3MpIHtcbiAgICBsZXQgZmlsZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICBpZiAodHlwZW9mIGNvbmZpZy5wYXRoID09PSAnc3RyaW5nJykge1xuICAgICAgZmlsZXMgPSBpc0dsb2IoY29uZmlnLnBhdGgpID8gYXdhaXQgZ2xvYkZpbGVzQXN5bmMoY29uZmlnLnBhdGgsIHt9KSA6IFtjb25maWcucGF0aF07XG4gICAgfSBlbHNlIGlmIChjb25maWcucGF0aCBpbnN0YW5jZW9mIEFycmF5KSB7XG4gICAgICBmb3IgKGNvbnN0IGZpbGVuYW1lIG9mIGNvbmZpZy5wYXRoKSB7XG4gICAgICAgIGZpbGVzID0gZmlsZXMuY29uY2F0KGlzR2xvYihmaWxlbmFtZSkgPyBhd2FpdCBnbG9iRmlsZXNBc3luYyhmaWxlbmFtZSwge30pIDogW2ZpbGVuYW1lXSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBmaWxlcGF0aCBwcm92aWRlZC4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXRQYXRoID0gY3BhdGgucmVzb2x2ZShjb25maWcub3V0cHV0UGF0aCk7XG4gICAgbWtkaXJwKG91dHB1dFBhdGgpO1xuXG4gICAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgICBjb25zdCBhYnNvbHV0ZUZpbGVQYXRoID0gY3BhdGgucmVzb2x2ZShmaWxlKTtcbiAgICAgIGNvbnN0IG91dHB1dEZpbGVQYXRoID0gY29uZmlnLnJvb3RQYXRoID8gY3BhdGguam9pbihvdXRwdXRQYXRoLCBhYnNvbHV0ZUZpbGVQYXRoLnJlcGxhY2UoY3BhdGgucmVzb2x2ZShjb25maWcucm9vdFBhdGgpLCAnJykucmVwbGFjZSgvXlxcLy8sICcnKSkgOiBjcGF0aC5qb2luKG91dHB1dFBhdGgsIGNwYXRoLmJhc2VuYW1lKGZpbGUpKTtcbiAgICAgIGF3YWl0IGNvcHkoZmlsZSwgb3V0cHV0RmlsZVBhdGgpO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFJlYWRzIGluIGEgSlNPTiBmaWxlIGFuZCByZXR1cm5zIGFuIGluc3RhbmNlIG9mIGl0LlxuICogQHBhcmFtIGZpbGVwYXRoIFRoZSBwYXRoIHRvIHRoZSBmaWxlIHRvIHJlYWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkSnNvbkZpbGU8VD4oZmlsZXBhdGg6IHN0cmluZyk6IFByb21pc2U8VCB8IHVuZGVmaW5lZD4ge1xuICBsZXQganNvbjogVCB8IHVuZGVmaW5lZDtcbiAgbGV0IGNvbnRlbnRzOiBzdHJpbmc7XG5cbiAgdHJ5IHtcbiAgICBjb250ZW50cyA9IGF3YWl0IHJlYWRGaWxlQXN5bmMoZmlsZXBhdGgsICd1dGYtOCcpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgaWYgKGNvbnRlbnRzKSB7XG4gICAgdHJ5IHtcbiAgICAgIGpzb24gPSBKU09OLnBhcnNlKGNvbnRlbnRzKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsb2dFcnJvcignSW52YWxpZCBKU09OIGZpbGU6ICcgKyBmaWxlcGF0aCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGpzb247XG59XG5cbi8qKlxuICogV3JpdGVzIGFuIG9iamVjdCB0byBhIEpTT04gZmlsZS5cbiAqIE5vdGU6IG92ZXJ3cml0ZXMgdGhlIGZpbGUsIGRvZXMgbm90IG1lcmdlIHRoZSBKU09OIGNvbnRlbnRzLlxuICogQHBhcmFtIGZpbGVwYXRoIFRoZSBmaWxlIHBhdGggdG8gd3JpdGUgdG8uXG4gKiBAcGFyYW0gZGF0YSBUaGUgb2JqZWN0IHRvIGNvbnZlcnQgdG8gSlNPTi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlSnNvbkZpbGU8VD4oZmlsZXBhdGg6IHN0cmluZywgZGF0YTogVCk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBjb250ZW50cyA9IEpTT04uc3RyaW5naWZ5KGRhdGEsIG51bGwsICcgICcpO1xuICBhd2FpdCB3cml0ZUZpbGVBc3luYyhmaWxlcGF0aCwgY29udGVudHMsICd1dGY4Jyk7XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyB0ZW1wb3JhcnkgZGlyZWN0b3J5LlxuICogQHBhcmFtIG9wdGlvbnMgVGhlIG9wdGlvbnMgdG8gcGFzcyB0byBgdG1wYC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVRlbXBEaXIob3B0aW9ucz86IElUZW1wT3B0aW9ucyk6IFByb21pc2U8SVRlbXBEaXJSZXN1bHQ+IHtcbiAgY29uc3QgZGVmYXVsdE9wdGlvbnM6IHRtcC5EaXJPcHRpb25zID0ge1xuICAgIG1vZGU6IDBvNzc3LFxuICAgIGtlZXA6IGZhbHNlLFxuICAgIHVuc2FmZUNsZWFudXA6IHRydWVcbiAgfTtcbiAgY29uc3QgdG1wT3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdE9wdGlvbnMsIG9wdGlvbnMpIGFzIHRtcC5EaXJPcHRpb25zO1xuICByZXR1cm4gbmV3IFByb21pc2U8SVRlbXBEaXJSZXN1bHQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICB0bXAuc2V0R3JhY2VmdWxDbGVhbnVwKCk7XG4gICAgdG1wLmRpcih0bXBPcHRpb25zLCAoZXJyLCBwYXRoLCBjbGVhbnVwQ2FsbGJhY2spID0+IHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IHtcbiAgICAgICAgcGF0aCxcbiAgICAgICAgcmVtb3ZlOiBjbGVhbnVwQ2FsbGJhY2tcbiAgICAgIH07XG4gICAgICByZXNvbHZlKHJlc3VsdCk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFJlcGxhY2VzIHRoZSBleHRlbnNpb24gaW4gYGluUGF0aGAgd2l0aCB0aGUgZXh0ZW5zaW9uIHNwZWNpZmllZCBpbiBgZXh0ZW5zaW9uYC5cbiAqIEBwYXJhbSB7c3RyaW5nfSBpblBhdGggVGhlIHBhdGggdG8gcmVwbGFjZSB0aGUgZXh0ZW5zaW9uIGluLlxuICogQHBhcmFtIHtzdHJpbmd9IGV4dGVuc2lvbiBUaGUgbmV3IGV4dGVuc2lvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGxhY2VFeHRlbnNpb24oaW5QYXRoOiBzdHJpbmcsIGV4dGVuc2lvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKCFpblBhdGggfHwgdHlwZW9mIGluUGF0aCAhPT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gaW5QYXRoO1xuICB9XG4gIGNvbnN0IG5ld1BhdGggPSBjcGF0aC5iYXNlbmFtZShpblBhdGgsIGNwYXRoLmV4dG5hbWUoaW5QYXRoKSkgKyBleHRlbnNpb24ucmVwbGFjZSgvXlxcLj8vLCAnLicpO1xuICByZXR1cm4gY3BhdGguam9pbihjcGF0aC5kaXJuYW1lKGluUGF0aCksIG5ld1BhdGgpO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElUZW1wT3B0aW9ucyB7XG4gIG1vZGU/OiBudW1iZXI7XG4gIHByZWZpeD86IHN0cmluZztcbiAgcG9zdGZpeD86IHN0cmluZztcbiAga2VlcD86IGJvb2xlYW47XG4gIHJlY3Vyc2l2ZUNsZWFudXA/OiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIElUZW1wRGlyUmVzdWx0IHtcbiAgcGF0aDogc3RyaW5nO1xuICByZW1vdmU6ICgpID0+IHZvaWQ7XG59XG4iXX0=