UNPKG

astx

Version:

super powerful structural search and replace for JavaScript and TypeScript to automate your refactoring

365 lines (334 loc) 36.5 kB
import path from 'path' import chalk from 'chalk' import formatDiff from '../util/formatDiff.mjs' import { isEmpty, once } from 'lodash-es' import inquirer from 'inquirer' import fs from 'fs-extra' import dedent from 'dedent-js' import CodeFrameError from '../util/CodeFrameError.mjs' import { formatIpcMatches } from '../util/formatMatches.mjs' import { AstxWorkerPool, astxCosmiconfig, runTransform, } from '../node/index.mjs' import { invertIpcError, makeIpcTransformResult } from '../node/ipc.mjs' import ansiEscapes from 'ansi-escapes' import { spinner } from './spinner.mjs' import '../node/registerTsNode.mjs' import isInteractive from '../util/isInteractive.mjs' /* eslint-disable no-console */ const transform = { command: '$0 [filesAndDirectories..]', describe: 'apply a transform to the given files and directories', builder: (yargs) => yargs .positional('filesAndDirectories', { type: 'string', array: true, }) .option('transform', { alias: 't', describe: `path to the transform file. Can be either a local path or url. Defaults to ./astx.ts or ./astx.js if --find isn't given`, }) .options('parser', { describe: 'parser to use (options: babel, babel/auto, recast/babel, recast/babel/auto)', type: 'string', }) .options('parserOptions', { describe: 'options for parser', type: 'string', }) .option('find', { alias: 'f', describe: 'search pattern', type: 'string', }) .option('replace', { alias: 'r', describe: 'replace pattern', type: 'string', }) .option('yes', { alias: 'y', describe: `don't ask for confirmation before writing changes`, type: 'boolean', }) .option('gitignore', { type: 'boolean', describe: `ignore gitignored files`, default: true, }) .option('workers', { type: 'number', describe: 'number of worker threads to use', }) .option('debugConfig', { type: 'boolean', describe: 'print found config and location', }), handler: async (argv) => { var _ref, _argv$workers const startTime = Date.now() const configResult = await astxCosmiconfig.search() if (argv.debugConfig) { console.log(JSON.stringify(configResult, null, 2)) process.exit(0) } const config = configResult === null || configResult === void 0 ? void 0 : configResult.config const paths = (argv.filesAndDirectories || []).filter( (x) => typeof x === 'string' ) const { transform, transformFile } = await (async () => { if (argv.transform) { const transformFile = path.resolve(argv.transform) return { transformFile, transform: await import(transformFile), } } else if (argv.find) { const getOpt = (regex) => { const index = process.argv.findIndex((a) => regex.test(a)) return index >= 0 ? process.argv[index + 1] : undefined } // yargs Eats quotes, not cool... const find = getOpt(/^(-f|--find)$/) const replace = getOpt(/^(-r|--replace)$/) return { transform: { find, replace, }, } } else { const files = [path.resolve('astx.ts'), path.resolve('astx.js')] for (const transformFile of files) { if (await fs.pathExists(transformFile)) { return { transformFile, transform: await import(transformFile), } } } throw new Error(`missing transform file: ${files.join(' or ')}`) } })() const { parser, parserOptions, gitignore } = argv const results = {} let errorCount = 0 let changedCount = 0 let unchangedCount = 0 let progress = { type: 'progress', completed: 0, total: 0, globDone: false, } let progressDisplayed = false function clearProgress() { if (progressDisplayed) { process.stderr.write(ansiEscapes.cursorLeft + ansiEscapes.eraseLine) progressDisplayed = false } } function showProgress() { clearProgress() progressDisplayed = true const { completed, total, globDone } = progress process.stderr.write( chalk.magenta( `${spinner()} Running... ${completed}/${total}${ globDone && total ? ` (${((completed * 100) / total).toFixed(1)}%)` : '' } ${((Date.now() - startTime) / 1000).toFixed(2)}s` ) ) } let spinnerInterval const interactive = isInteractive() const workers = (_ref = (_argv$workers = argv.workers) !== null && _argv$workers !== void 0 ? _argv$workers : process.env.ASTX_WORKERS ? parseInt(process.env.ASTX_WORKERS) : undefined) !== null && _ref !== void 0 ? _ref : config === null || config === void 0 ? void 0 : config.workers const pool = workers === 0 ? null : new AstxWorkerPool({ capacity: workers, }) try { if (interactive) { spinnerInterval = setInterval(showProgress, 30) } const runTransformOptions = { gitignore: gitignore ? undefined : null, transform, transformFile, paths, config: { parser: parser, parserOptions: parserOptions ? JSON.parse(parserOptions) : undefined, }, } for await (const _event of pool ? pool.runTransform(runTransformOptions) : runTransform(runTransformOptions)) { const event = !pool && _event.type === 'result' ? { type: 'result', result: makeIpcTransformResult(_event), } : _event if (event.type === 'progress') { progress = event if (interactive) showProgress() continue } clearProgress() const { file, source, transformed, reports, matches, error: _error, } = event.result const error = _error ? invertIpcError(_error) : undefined const relpath = path.relative(process.cwd(), file) const logHeader = once((logFn) => logFn( chalk.blue(dedent` ${'='.repeat(relpath.length)} ${chalk.bold(relpath)} ${'='.repeat(relpath.length)} `) ) ) if (error) { errorCount++ logHeader(console.error) if (error instanceof CodeFrameError) { console.error( error.format({ highlightCode: true, forceColor: true, stack: true, }) ) } else { console.error(chalk.red(error.stack)) } } else if (source && transformed && source !== transformed) { changedCount++ results[file] = transformed if (!argv.yes) { logHeader(console.log) console.log(formatDiff(source, transformed)) } } else if ( matches !== null && matches !== void 0 && matches.length && source && transform.find && !transform.replace && !transform.astx ) { logHeader(console.log) console.log(formatIpcMatches(source, matches)) } else { unchangedCount++ } if ( reports !== null && reports !== void 0 && reports.length && !transform.onReport ) { logHeader(console.error) console.error( chalk.blue(dedent` Reports ------- `) ) reports === null || reports === void 0 ? void 0 : reports.forEach((r) => console.error(r)) } } } catch (error) { console.error( chalk.red(error instanceof Error ? error.stack : String(error)) ) process.exit(1) } finally { if (spinnerInterval != null) clearInterval(spinnerInterval) clearProgress() } if (transform.replace || transform.astx) { console.error( chalk.yellow( `${changedCount} file${changedCount === 1 ? '' : 's'} changed` ) ) console.error( chalk.green( `${unchangedCount} file${unchangedCount === 1 ? '' : 's'} unchanged` ) ) if (errorCount > 0) { console.error( chalk.red(`${errorCount} file${errorCount === 1 ? '' : 's'} errored`) ) } } else if (transform.find) { console.error( chalk.yellow( `\n${unchangedCount} file${ changedCount === 1 ? '' : 's' } had no matches` ) ) } if (!isEmpty(results)) { const apply = argv.yes ? true : ( await inquirer.prompt([ { type: 'confirm', name: 'apply', message: 'Apply changes', default: false, }, ]) ).apply if (apply) { for (const file in results) { await fs.writeFile(file, results[file], 'utf8') console.error(`Wrote ${file}`) } } if (process.send) process.send({ exit: 0, }) } await (pool === null || pool === void 0 ? void 0 : pool.end()) process.exit(0) }, } export default transform //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJwYXRoIiwiY2hhbGsiLCJmb3JtYXREaWZmIiwiaXNFbXB0eSIsIm9uY2UiLCJpbnF1aXJlciIsImZzIiwiZGVkZW50IiwiQ29kZUZyYW1lRXJyb3IiLCJmb3JtYXRJcGNNYXRjaGVzIiwiQXN0eFdvcmtlclBvb2wiLCJhc3R4Q29zbWljb25maWciLCJydW5UcmFuc2Zvcm0iLCJpbnZlcnRJcGNFcnJvciIsIm1ha2VJcGNUcmFuc2Zvcm1SZXN1bHQiLCJhbnNpRXNjYXBlcyIsInNwaW5uZXIiLCJpc0ludGVyYWN0aXZlIiwidHJhbnNmb3JtIiwiY29tbWFuZCIsImRlc2NyaWJlIiwiYnVpbGRlciIsInlhcmdzIiwicG9zaXRpb25hbCIsInR5cGUiLCJhcnJheSIsIm9wdGlvbiIsImFsaWFzIiwib3B0aW9ucyIsImRlZmF1bHQiLCJoYW5kbGVyIiwiYXJndiIsInN0YXJ0VGltZSIsIkRhdGUiLCJub3ciLCJjb25maWdSZXN1bHQiLCJzZWFyY2giLCJkZWJ1Z0NvbmZpZyIsImNvbnNvbGUiLCJsb2ciLCJKU09OIiwic3RyaW5naWZ5IiwicHJvY2VzcyIsImV4aXQiLCJjb25maWciLCJwYXRocyIsImZpbGVzQW5kRGlyZWN0b3JpZXMiLCJmaWx0ZXIiLCJ4IiwidHJhbnNmb3JtRmlsZSIsInJlc29sdmUiLCJmaW5kIiwiZ2V0T3B0IiwicmVnZXgiLCJpbmRleCIsImZpbmRJbmRleCIsImEiLCJ0ZXN0IiwidW5kZWZpbmVkIiwicmVwbGFjZSIsImZpbGVzIiwicGF0aEV4aXN0cyIsIkVycm9yIiwiam9pbiIsInBhcnNlciIsInBhcnNlck9wdGlvbnMiLCJnaXRpZ25vcmUiLCJyZXN1bHRzIiwiZXJyb3JDb3VudCIsImNoYW5nZWRDb3VudCIsInVuY2hhbmdlZENvdW50IiwicHJvZ3Jlc3MiLCJjb21wbGV0ZWQiLCJ0b3RhbCIsImdsb2JEb25lIiwicHJvZ3Jlc3NEaXNwbGF5ZWQiLCJjbGVhclByb2dyZXNzIiwic3RkZXJyIiwid3JpdGUiLCJjdXJzb3JMZWZ0IiwiZXJhc2VMaW5lIiwic2hvd1Byb2dyZXNzIiwibWFnZW50YSIsInRvRml4ZWQiLCJzcGlubmVySW50ZXJ2YWwiLCJpbnRlcmFjdGl2ZSIsIndvcmtlcnMiLCJlbnYiLCJBU1RYX1dPUktFUlMiLCJwYXJzZUludCIsInBvb2wiLCJjYXBhY2l0eSIsInNldEludGVydmFsIiwicnVuVHJhbnNmb3JtT3B0aW9ucyIsInBhcnNlIiwiX2V2ZW50IiwiZXZlbnQiLCJyZXN1bHQiLCJmaWxlIiwic291cmNlIiwidHJhbnNmb3JtZWQiLCJyZXBvcnRzIiwibWF0Y2hlcyIsImVycm9yIiwiX2Vycm9yIiwicmVscGF0aCIsInJlbGF0aXZlIiwiY3dkIiwibG9nSGVhZGVyIiwibG9nRm4iLCJibHVlIiwicmVwZWF0IiwibGVuZ3RoIiwiYm9sZCIsImZvcm1hdCIsImhpZ2hsaWdodENvZGUiLCJmb3JjZUNvbG9yIiwic3RhY2siLCJyZWQiLCJ5ZXMiLCJhc3R4Iiwib25SZXBvcnQiLCJmb3JFYWNoIiwiciIsIlN0cmluZyIsImNsZWFySW50ZXJ2YWwiLCJ5ZWxsb3ciLCJncmVlbiIsImFwcGx5IiwicHJvbXB0IiwibmFtZSIsIm1lc3NhZ2UiLCJ3cml0ZUZpbGUiLCJzZW5kIiwiZW5kIl0sInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaS90cmFuc2Zvcm0udHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQXJndW1lbnRzLCBBcmd2LCBDb21tYW5kTW9kdWxlIH0gZnJvbSAneWFyZ3MnXG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJ1xuaW1wb3J0IGNoYWxrIGZyb20gJ2NoYWxrJ1xuaW1wb3J0IGZvcm1hdERpZmYgZnJvbSAnLi4vdXRpbC9mb3JtYXREaWZmJ1xuaW1wb3J0IHsgaXNFbXB0eSwgb25jZSB9IGZyb20gJ2xvZGFzaCdcbmltcG9ydCBpbnF1aXJlciBmcm9tICdpbnF1aXJlcidcbmltcG9ydCBmcyBmcm9tICdmcy1leHRyYSdcbmltcG9ydCBkZWRlbnQgZnJvbSAnZGVkZW50LWpzJ1xuaW1wb3J0IENvZGVGcmFtZUVycm9yIGZyb20gJy4uL3V0aWwvQ29kZUZyYW1lRXJyb3InXG5pbXBvcnQgeyBmb3JtYXRJcGNNYXRjaGVzIH0gZnJvbSAnLi4vdXRpbC9mb3JtYXRNYXRjaGVzJ1xuaW1wb3J0IHtcbiAgQXN0eFdvcmtlclBvb2wsXG4gIGFzdHhDb3NtaWNvbmZpZyxcbiAgcnVuVHJhbnNmb3JtLFxuICBQcm9ncmVzcyxcbn0gZnJvbSAnLi4vbm9kZSdcbmltcG9ydCB7XG4gIGludmVydElwY0Vycm9yLFxuICBJcGNUcmFuc2Zvcm1SZXN1bHQsXG4gIG1ha2VJcGNUcmFuc2Zvcm1SZXN1bHQsXG59IGZyb20gJy4uL25vZGUvaXBjJ1xuaW1wb3J0IHsgVHJhbnNmb3JtIH0gZnJvbSAnLi4vQXN0eCdcbmltcG9ydCBhbnNpRXNjYXBlcyBmcm9tICdhbnNpLWVzY2FwZXMnXG5pbXBvcnQgeyBzcGlubmVyIH0gZnJvbSAnLi9zcGlubmVyJ1xuaW1wb3J0ICcuLi9ub2RlL3JlZ2lzdGVyVHNOb2RlJ1xuaW1wb3J0IGlzSW50ZXJhY3RpdmUgZnJvbSAnLi4vdXRpbC9pc0ludGVyYWN0aXZlJ1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1jb25zb2xlICovXG5cbnR5cGUgT3B0aW9ucyA9IHtcbiAgdHJhbnNmb3JtPzogc3RyaW5nXG4gIHBhcnNlcj86IHN0cmluZ1xuICBwYXJzZXJPcHRpb25zPzogc3RyaW5nXG4gIGZpbmQ/OiBzdHJpbmdcbiAgcmVwbGFjZT86IHN0cmluZ1xuICBmaWxlc0FuZERpcmVjdG9yaWVzPzogc3RyaW5nW11cbiAgeWVzPzogYm9vbGVhblxuICBnaXRpZ25vcmU/OiBib29sZWFuXG4gIHRocmVhZHM/OiBudW1iZXJcbiAgZGVidWdDb25maWc/OiBib29sZWFuXG59XG5cbmNvbnN0IHRyYW5zZm9ybTogQ29tbWFuZE1vZHVsZTxPcHRpb25zPiA9IHtcbiAgY29tbWFuZDogJyQwIFtmaWxlc0FuZERpcmVjdG9yaWVzLi5dJyxcbiAgZGVzY3JpYmU6ICdhcHBseSBhIHRyYW5zZm9ybSB0byB0aGUgZ2l2ZW4gZmlsZXMgYW5kIGRpcmVjdG9yaWVzJyxcbiAgYnVpbGRlcjogKHlhcmdzOiBBcmd2PE9wdGlvbnM+KSA9PlxuICAgIHlhcmdzXG4gICAgICAucG9zaXRpb25hbCgnZmlsZXNBbmREaXJlY3RvcmllcycsIHtcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgIGFycmF5OiB0cnVlLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb24oJ3RyYW5zZm9ybScsIHtcbiAgICAgICAgYWxpYXM6ICd0JyxcbiAgICAgICAgZGVzY3JpYmU6IGBwYXRoIHRvIHRoZSB0cmFuc2Zvcm0gZmlsZS4gQ2FuIGJlIGVpdGhlciBhIGxvY2FsIHBhdGggb3IgdXJsLiBEZWZhdWx0cyB0byAuL2FzdHgudHMgb3IgLi9hc3R4LmpzIGlmIC0tZmluZCBpc24ndCBnaXZlbmAsXG4gICAgICB9KVxuICAgICAgLm9wdGlvbnMoJ3BhcnNlcicsIHtcbiAgICAgICAgZGVzY3JpYmU6XG4gICAgICAgICAgJ3BhcnNlciB0byB1c2UgKG9wdGlvbnM6IGJhYmVsLCBiYWJlbC9hdXRvLCByZWNhc3QvYmFiZWwsIHJlY2FzdC9iYWJlbC9hdXRvKScsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb25zKCdwYXJzZXJPcHRpb25zJywge1xuICAgICAgICBkZXNjcmliZTogJ29wdGlvbnMgZm9yIHBhcnNlcicsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb24oJ2ZpbmQnLCB7XG4gICAgICAgIGFsaWFzOiAnZicsXG4gICAgICAgIGRlc2NyaWJlOiAnc2VhcmNoIHBhdHRlcm4nLFxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uKCdyZXBsYWNlJywge1xuICAgICAgICBhbGlhczogJ3InLFxuICAgICAgICBkZXNjcmliZTogJ3JlcGxhY2UgcGF0dGVybicsXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb24oJ3llcycsIHtcbiAgICAgICAgYWxpYXM6ICd5JyxcbiAgICAgICAgZGVzY3JpYmU6IGBkb24ndCBhc2sgZm9yIGNvbmZpcm1hdGlvbiBiZWZvcmUgd3JpdGluZyBjaGFuZ2VzYCxcbiAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgfSlcbiAgICAgIC5vcHRpb24oJ2dpdGlnbm9yZScsIHtcbiAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZXNjcmliZTogYGlnbm9yZSBnaXRpZ25vcmVkIGZpbGVzYCxcbiAgICAgICAgZGVmYXVsdDogdHJ1ZSxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uKCd3b3JrZXJzJywge1xuICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgZGVzY3JpYmU6ICdudW1iZXIgb2Ygd29ya2VyIHRocmVhZHMgdG8gdXNlJyxcbiAgICAgIH0pXG4gICAgICAub3B0aW9uKCdkZWJ1Z0NvbmZpZycsIHtcbiAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICBkZXNjcmliZTogJ3ByaW50IGZvdW5kIGNvbmZpZyBhbmQgbG9jYXRpb24nLFxuICAgICAgfSksXG5cbiAgaGFuZGxlcjogYXN5bmMgKGFyZ3Y6IEFyZ3VtZW50czxPcHRpb25zPikgPT4ge1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KClcblxuICAgIGNvbnN0IGNvbmZpZ1Jlc3VsdCA9IGF3YWl0IGFzdHhDb3NtaWNvbmZpZy5zZWFyY2goKVxuICAgIGlmIChhcmd2LmRlYnVnQ29uZmlnKSB7XG4gICAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeShjb25maWdSZXN1bHQsIG51bGwsIDIpKVxuICAgICAgcHJvY2Vzcy5leGl0KDApXG4gICAgfVxuICAgIGNvbnN0IGNvbmZpZyA9IGNvbmZpZ1Jlc3VsdD8uY29uZmlnXG5cbiAgICBjb25zdCBwYXRocyA9IChhcmd2LmZpbGVzQW5kRGlyZWN0b3JpZXMgfHwgW10pLmZpbHRlcihcbiAgICAgICh4KSA9PiB0eXBlb2YgeCA9PT0gJ3N0cmluZydcbiAgICApIGFzIHN0cmluZ1tdXG5cbiAgICBjb25zdCB7IHRyYW5zZm9ybSwgdHJhbnNmb3JtRmlsZSB9ID0gYXdhaXQgKGFzeW5jICgpOiBQcm9taXNlPHtcbiAgICAgIHRyYW5zZm9ybTogVHJhbnNmb3JtXG4gICAgICB0cmFuc2Zvcm1GaWxlPzogc3RyaW5nXG4gICAgfT4gPT4ge1xuICAgICAgaWYgKGFyZ3YudHJhbnNmb3JtKSB7XG4gICAgICAgIGNvbnN0IHRyYW5zZm9ybUZpbGUgPSBwYXRoLnJlc29sdmUoYXJndi50cmFuc2Zvcm0pXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHJhbnNmb3JtRmlsZSxcbiAgICAgICAgICB0cmFuc2Zvcm06IGF3YWl0IGltcG9ydCh0cmFuc2Zvcm1GaWxlKSxcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChhcmd2LmZpbmQpIHtcbiAgICAgICAgY29uc3QgZ2V0T3B0ID0gKHJlZ2V4OiBSZWdFeHApOiBzdHJpbmcgfCB1bmRlZmluZWQgPT4ge1xuICAgICAgICAgIGNvbnN0IGluZGV4ID0gcHJvY2Vzcy5hcmd2LmZpbmRJbmRleCgoYSkgPT4gcmVnZXgudGVzdChhKSlcbiAgICAgICAgICByZXR1cm4gaW5kZXggPj0gMCA/IHByb2Nlc3MuYXJndltpbmRleCArIDFdIDogdW5kZWZpbmVkXG4gICAgICAgIH1cbiAgICAgICAgLy8geWFyZ3MgRWF0cyBxdW90ZXMsIG5vdCBjb29sLi4uXG4gICAgICAgIGNvbnN0IGZpbmQgPSBnZXRPcHQoL14oLWZ8LS1maW5kKSQvKVxuICAgICAgICBjb25zdCByZXBsYWNlID0gZ2V0T3B0KC9eKC1yfC0tcmVwbGFjZSkkLylcbiAgICAgICAgcmV0dXJuIHsgdHJhbnNmb3JtOiB7IGZpbmQsIHJlcGxhY2UgfSB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBmaWxlcyA9IFtwYXRoLnJlc29sdmUoJ2FzdHgudHMnKSwgcGF0aC5yZXNvbHZlKCdhc3R4LmpzJyldXG4gICAgICAgIGZvciAoY29uc3QgdHJhbnNmb3JtRmlsZSBvZiBmaWxlcykge1xuICAgICAgICAgIGlmIChhd2FpdCBmcy5wYXRoRXhpc3RzKHRyYW5zZm9ybUZpbGUpKSB7XG4gICAgICAgICAgICByZXR1cm4geyB0cmFuc2Zvcm1GaWxlLCB0cmFuc2Zvcm06IGF3YWl0IGltcG9ydCh0cmFuc2Zvcm1GaWxlKSB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbWlzc2luZyB0cmFuc2Zvcm0gZmlsZTogJHtmaWxlcy5qb2luKCcgb3IgJyl9YClcbiAgICAgIH1cbiAgICB9KSgpXG4gICAgY29uc3QgeyBwYXJzZXIsIHBhcnNlck9wdGlvbnMsIGdpdGlnbm9yZSB9ID0gYXJndlxuXG4gICAgY29uc3QgcmVzdWx0czogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9XG4gICAgbGV0IGVycm9yQ291bnQgPSAwXG4gICAgbGV0IGNoYW5nZWRDb3VudCA9IDBcbiAgICBsZXQgdW5jaGFuZ2VkQ291bnQgPSAwXG5cbiAgICBsZXQgcHJvZ3Jlc3M6IFByb2dyZXNzID0ge1xuICAgICAgdHlwZTogJ3Byb2dyZXNzJyxcbiAgICAgIGNvbXBsZXRlZDogMCxcbiAgICAgIHRvdGFsOiAwLFxuICAgICAgZ2xvYkRvbmU6IGZhbHNlLFxuICAgIH1cblxuICAgIGxldCBwcm9ncmVzc0Rpc3BsYXllZCA9IGZhbHNlXG4gICAgZnVuY3Rpb24gY2xlYXJQcm9ncmVzcygpIHtcbiAgICAgIGlmIChwcm9ncmVzc0Rpc3BsYXllZCkge1xuICAgICAgICBwcm9jZXNzLnN0ZGVyci53cml0ZShhbnNpRXNjYXBlcy5jdXJzb3JMZWZ0ICsgYW5zaUVzY2FwZXMuZXJhc2VMaW5lKVxuICAgICAgICBwcm9ncmVzc0Rpc3BsYXllZCA9IGZhbHNlXG4gICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNob3dQcm9ncmVzcygpIHtcbiAgICAgIGNsZWFyUHJvZ3Jlc3MoKVxuICAgICAgcHJvZ3Jlc3NEaXNwbGF5ZWQgPSB0cnVlXG4gICAgICBjb25zdCB7IGNvbXBsZXRlZCwgdG90YWwsIGdsb2JEb25lIH0gPSBwcm9ncmVzc1xuICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUoXG4gICAgICAgIGNoYWxrLm1hZ2VudGEoXG4gICAgICAgICAgYCR7c3Bpbm5lcigpfSBSdW5uaW5nLi4uICR7Y29tcGxldGVkfS8ke3RvdGFsfSR7XG4gICAgICAgICAgICBnbG9iRG9uZSAmJiB0b3RhbFxuICAgICAgICAgICAgICA/IGAgKCR7KChjb21wbGV0ZWQgKiAxMDApIC8gdG90YWwpLnRvRml4ZWQoMSl9JSlgXG4gICAgICAgICAgICAgIDogJydcbiAgICAgICAgICB9ICR7KChEYXRlLm5vdygpIC0gc3RhcnRUaW1lKSAvIDEwMDApLnRvRml4ZWQoMil9c2BcbiAgICAgICAgKVxuICAgICAgKVxuICAgIH1cbiAgICBsZXQgc3Bpbm5lckludGVydmFsXG5cbiAgICBjb25zdCBpbnRlcmFjdGl2ZSA9IGlzSW50ZXJhY3RpdmUoKVxuICAgIGNvbnN0IHdvcmtlcnMgPVxuICAgICAgYXJndi53b3JrZXJzID8/XG4gICAgICAocHJvY2Vzcy5lbnYuQVNUWF9XT1JLRVJTXG4gICAgICAgID8gcGFyc2VJbnQocHJvY2Vzcy5lbnYuQVNUWF9XT1JLRVJTKVxuICAgICAgICA6IHVuZGVmaW5lZCkgPz9cbiAgICAgIGNvbmZpZz8ud29ya2Vyc1xuICAgIGNvbnN0IHBvb2wgPVxuICAgICAgd29ya2VycyA9PT0gMCA/IG51bGwgOiBuZXcgQXN0eFdvcmtlclBvb2woeyBjYXBhY2l0eTogd29ya2VycyB9KVxuICAgIHRyeSB7XG4gICAgICBpZiAoaW50ZXJhY3RpdmUpIHtcbiAgICAgICAgc3Bpbm5lckludGVydmFsID0gc2V0SW50ZXJ2YWwoc2hvd1Byb2dyZXNzLCAzMClcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJ1blRyYW5zZm9ybU9wdGlvbnMgPSB7XG4gICAgICAgIGdpdGlnbm9yZTogZ2l0aWdub3JlID8gdW5kZWZpbmVkIDogbnVsbCxcbiAgICAgICAgdHJhbnNmb3JtLFxuICAgICAgICB0cmFuc2Zvcm1GaWxlLFxuICAgICAgICBwYXRocyxcbiAgICAgICAgY29uZmlnOiB7XG4gICAgICAgICAgcGFyc2VyOiBwYXJzZXIgYXMgYW55LFxuICAgICAgICAgIHBhcnNlck9wdGlvbnM6IHBhcnNlck9wdGlvbnMgPyBKU09OLnBhcnNlKHBhcnNlck9wdGlvbnMpIDogdW5kZWZpbmVkLFxuICAgICAgICB9LFxuICAgICAgfVxuICAgICAgZm9yIGF3YWl0IChjb25zdCBfZXZlbnQgb2YgcG9vbFxuICAgICAgICA/IHBvb2wucnVuVHJhbnNmb3JtKHJ1blRyYW5zZm9ybU9wdGlvbnMpXG4gICAgICAgIDogcnVuVHJhbnNmb3JtKHJ1blRyYW5zZm9ybU9wdGlvbnMpKSB7XG4gICAgICAgIGNvbnN0IGV2ZW50OiB7IHR5cGU6ICdyZXN1bHQnOyByZXN1bHQ6IElwY1RyYW5zZm9ybVJlc3VsdCB9IHwgUHJvZ3Jlc3MgPVxuICAgICAgICAgICFwb29sICYmIF9ldmVudC50eXBlID09PSAncmVzdWx0J1xuICAgICAgICAgICAgPyB7IHR5cGU6ICdyZXN1bHQnLCByZXN1bHQ6IG1ha2VJcGNUcmFuc2Zvcm1SZXN1bHQoX2V2ZW50IGFzIGFueSkgfVxuICAgICAgICAgICAgOiAoX2V2ZW50IGFzIGFueSlcbiAgICAgICAgaWYgKGV2ZW50LnR5cGUgPT09ICdwcm9ncmVzcycpIHtcbiAgICAgICAgICBwcm9ncmVzcyA9IGV2ZW50XG4gICAgICAgICAgaWYgKGludGVyYWN0aXZlKSBzaG93UHJvZ3Jlc3MoKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cbiAgICAgICAgY2xlYXJQcm9ncmVzcygpXG4gICAgICAgIGNvbnN0IHtcbiAgICAgICAgICBmaWxlLFxuICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICB0cmFuc2Zvcm1lZCxcbiAgICAgICAgICByZXBvcnRzLFxuICAgICAgICAgIG1hdGNoZXMsXG4gICAgICAgICAgZXJyb3I6IF9lcnJvcixcbiAgICAgICAgfSA9IGV2ZW50LnJlc3VsdFxuICAgICAgICBjb25zdCBlcnJvciA9IF9lcnJvciA/IGludmVydElwY0Vycm9yKF9lcnJvcikgOiB1bmRlZmluZWRcbiAgICAgICAgY29uc3QgcmVscGF0aCA9IHBhdGgucmVsYXRpdmUocHJvY2Vzcy5jd2QoKSwgZmlsZSlcbiAgICAgICAgY29uc3QgbG9nSGVhZGVyID0gb25jZSgobG9nRm46ICh2YWx1ZTogc3RyaW5nKSA9PiBhbnkpID0+XG4gICAgICAgICAgbG9nRm4oXG4gICAgICAgICAgICBjaGFsay5ibHVlKGRlZGVudGBcbiAgICAgICAgICAgICR7Jz0nLnJlcGVhdChyZWxwYXRoLmxlbmd0aCl9XG4gICAgICAgICAgICAke2NoYWxrLmJvbGQocmVscGF0aCl9XG4gICAgICAgICAgICAkeyc9Jy5yZXBlYXQocmVscGF0aC5sZW5ndGgpfVxuICAgICAgICAgIGApXG4gICAgICAgICAgKVxuICAgICAgICApXG5cbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgZXJyb3JDb3VudCsrXG4gICAgICAgICAgbG9nSGVhZGVyKGNvbnNvbGUuZXJyb3IpXG4gICAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgQ29kZUZyYW1lRXJyb3IpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICAgIGVycm9yLmZvcm1hdCh7XG4gICAgICAgICAgICAgICAgaGlnaGxpZ2h0Q29kZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBmb3JjZUNvbG9yOiB0cnVlLFxuICAgICAgICAgICAgICAgIHN0YWNrOiB0cnVlLFxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGNoYWxrLnJlZChlcnJvci5zdGFjaykpXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHNvdXJjZSAmJiB0cmFuc2Zvcm1lZCAmJiBzb3VyY2UgIT09IHRyYW5zZm9ybWVkKSB7XG4gICAgICAgICAgY2hhbmdlZENvdW50KytcbiAgICAgICAgICByZXN1bHRzW2ZpbGVdID0gdHJhbnNmb3JtZWRcbiAgICAgICAgICBpZiAoIWFyZ3YueWVzKSB7XG4gICAgICAgICAgICBsb2dIZWFkZXIoY29uc29sZS5sb2cpXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhmb3JtYXREaWZmKHNvdXJjZSwgdHJhbnNmb3JtZWQpKVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICBtYXRjaGVzPy5sZW5ndGggJiZcbiAgICAgICAgICBzb3VyY2UgJiZcbiAgICAgICAgICB0cmFuc2Zvcm0uZmluZCAmJlxuICAgICAgICAgICF0cmFuc2Zvcm0ucmVwbGFjZSAmJlxuICAgICAgICAgICF0cmFuc2Zvcm0uYXN0eFxuICAgICAgICApIHtcbiAgICAgICAgICBsb2dIZWFkZXIoY29uc29sZS5sb2cpXG4gICAgICAgICAgY29uc29sZS5sb2coZm9ybWF0SXBjTWF0Y2hlcyhzb3VyY2UsIG1hdGNoZXMpKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHVuY2hhbmdlZENvdW50KytcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXBvcnRzPy5sZW5ndGggJiYgIXRyYW5zZm9ybS5vblJlcG9ydCkge1xuICAgICAgICAgIGxvZ0hlYWRlcihjb25zb2xlLmVycm9yKVxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICBjaGFsay5ibHVlKGRlZGVudGBcbiAgICAgICAgICAgIFJlcG9ydHNcbiAgICAgICAgICAgIC0tLS0tLS1cbiAgICAgICAgICBgKVxuICAgICAgICAgIClcbiAgICAgICAgICByZXBvcnRzPy5mb3JFYWNoKChyOiBhbnkpID0+IGNvbnNvbGUuZXJyb3IocikpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgY2hhbGsucmVkKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5zdGFjayA6IFN0cmluZyhlcnJvcikpXG4gICAgICApXG4gICAgICBwcm9jZXNzLmV4aXQoMSlcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKHNwaW5uZXJJbnRlcnZhbCAhPSBudWxsKSBjbGVhckludGVydmFsKHNwaW5uZXJJbnRlcnZhbClcbiAgICAgIGNsZWFyUHJvZ3Jlc3MoKVxuICAgIH1cblxuICAgIGlmICh0cmFuc2Zvcm0ucmVwbGFjZSB8fCB0cmFuc2Zvcm0uYXN0eCkge1xuICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgY2hhbGsueWVsbG93KFxuICAgICAgICAgIGAke2NoYW5nZWRDb3VudH0gZmlsZSR7Y2hhbmdlZENvdW50ID09PSAxID8gJycgOiAncyd9IGNoYW5nZWRgXG4gICAgICAgIClcbiAgICAgIClcbiAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgIGNoYWxrLmdyZWVuKFxuICAgICAgICAgIGAke3VuY2hhbmdlZENvdW50fSBmaWxlJHt1bmNoYW5nZWRDb3VudCA9PT0gMSA/ICcnIDogJ3MnfSB1bmNoYW5nZWRgXG4gICAgICAgIClcbiAgICAgIClcbiAgICAgIGlmIChlcnJvckNvdW50ID4gMCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgIGNoYWxrLnJlZChgJHtlcnJvckNvdW50fSBmaWxlJHtlcnJvckNvdW50ID09PSAxID8gJycgOiAncyd9IGVycm9yZWRgKVxuICAgICAgICApXG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0cmFuc2Zvcm0uZmluZCkge1xuICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgY2hhbGsueWVsbG93KFxuICAgICAgICAgIGBcXG4ke3VuY2hhbmdlZENvdW50fSBmaWxlJHtcbiAgICAgICAgICAgIGNoYW5nZWRDb3VudCA9PT0gMSA/ICcnIDogJ3MnXG4gICAgICAgICAgfSBoYWQgbm8gbWF0Y2hlc2BcbiAgICAgICAgKVxuICAgICAgKVxuICAgIH1cblxuICAgIGlmICghaXNFbXB0eShyZXN1bHRzKSkge1xuICAgICAgY29uc3QgYXBwbHkgPSBhcmd2Lnllc1xuICAgICAgICA/IHRydWVcbiAgICAgICAgOiAoXG4gICAgICAgICAgICBhd2FpdCBpbnF1aXJlci5wcm9tcHQoW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgdHlwZTogJ2NvbmZpcm0nLFxuICAgICAgICAgICAgICAgIG5hbWU6ICdhcHBseScsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogJ0FwcGx5IGNoYW5nZXMnLFxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IGZhbHNlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSlcbiAgICAgICAgICApLmFwcGx5XG4gICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgZm9yIChjb25zdCBmaWxlIGluIHJlc3VsdHMpIHtcbiAgICAgICAgICBhd2FpdCBmcy53cml0ZUZpbGUoZmlsZSwgcmVzdWx0c1tmaWxlXSwgJ3V0ZjgnKVxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYFdyb3RlICR7ZmlsZX1gKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAocHJvY2Vzcy5zZW5kKSBwcm9jZXNzLnNlbmQoeyBleGl0OiAwIH0pXG4gICAgfVxuICAgIGF3YWl0IHBvb2w/LmVuZCgpXG4gICAgcHJvY2Vzcy5leGl0KDApXG4gIH0sXG59XG5cbmV4cG9ydCBkZWZhdWx0IHRyYW5zZm9ybVxuIl0sIm1hcHBpbmdzIjoiO0FBQ0EsT0FBT0EsSUFBUCxNQUFpQixNQUFqQjtBQUNBLE9BQU9DLEtBQVAsTUFBa0IsT0FBbEI7QUFDQSxPQUFPQyxVQUFQLE1BQXVCLG9CQUF2QjtBQUNBLFNBQVNDLE9BQVQsRUFBa0JDLElBQWxCLFFBQThCLFFBQTlCO0FBQ0EsT0FBT0MsUUFBUCxNQUFxQixVQUFyQjtBQUNBLE9BQU9DLEVBQVAsTUFBZSxVQUFmO0FB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