@dollhousemcp/mcp-server
Version:
DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.
267 lines • 33 kB
JavaScript
/**
* CLI command for formatting/cleaning DollhouseMCP elements
*
* Usage:
* npx dollhouse format-element <file>
* npx dollhouse format-element --type memories
* npx dollhouse format-element --all
*
* Options:
* --in-place Format files in place (default: create .formatted files)
* --no-backup Don't create backup files when using --in-place
* --output-dir Directory to write formatted files
* --type Element type to format (personas, skills, etc.)
* --all Format all elements in portfolio
*/
import * as path from 'node:path';
import { Command } from 'commander';
import chalk from 'chalk';
import { ElementFormatter } from '../utils/ElementFormatter.js';
import { ElementType } from '../portfolio/types.js';
import { PortfolioManager } from '../portfolio/PortfolioManager.js';
import { SecurityMonitor } from '../security/securityMonitor.js';
import { FileOperationsService } from '../services/FileOperationsService.js';
import { FileLockManager } from '../security/fileLockManager.js';
const program = new Command();
program
.name('format-element')
.description('Format and clean malformed DollhouseMCP elements')
.argument('[files...]', 'Element files to format')
.option('-i, --in-place', 'Format files in place', false)
.option('-b, --backup', 'Create backup files when using --in-place', true)
.option('-o, --output-dir <dir>', 'Directory for formatted files')
.option('-t, --type <type>', 'Format all elements of this type')
.option('-a, --all', 'Format all elements in portfolio', false)
.option('-v, --validate', 'Validate YAML after formatting', true)
.option('--dry-run', 'Show what would be formatted without changes', false)
.action(async (files, options) => {
try {
logCliOperation(files, options);
const formatter = createFormatter(options);
const results = await processFormatOperation(files, options, formatter);
displayResults(results, options.dryRun);
exitWithCode(results);
}
catch (error) {
console.error(chalk.red('Failed to format elements:'), error);
process.exit(1);
}
});
/**
* Log CLI operation for audit
*/
function logCliOperation(files, options) {
SecurityMonitor.logSecurityEvent({
type: 'FILE_COPIED',
severity: 'LOW',
source: 'format-element CLI',
details: `Starting format operation: ${options.all ? 'all elements' : files.length + ' files'}`
});
}
/**
* Create formatter with options
*/
function createFormatter(options) {
const fileLockManager = new FileLockManager();
const fileOperations = new FileOperationsService(fileLockManager);
return new ElementFormatter({
backup: options.backup,
inPlace: options.inPlace,
validate: options.validate,
outputDir: options.outputDir
}, fileOperations);
}
/**
* Process format operation based on options
*/
async function processFormatOperation(files, options, formatter) {
if (options.all) {
return formatAllElements(formatter);
}
else if (options.type) {
return formatElementType(options.type, formatter);
}
else if (files.length > 0) {
return formatSpecificFiles(files, options, formatter);
}
else {
console.error(chalk.red('No files specified. Use --help for usage.'));
process.exit(1);
}
}
/**
* Format all elements in portfolio
*/
async function formatAllElements(formatter) {
console.log(chalk.blue('Formatting all portfolio elements...'));
const fileLockManager = new FileLockManager();
const fileOperations = new FileOperationsService(fileLockManager);
const portfolioManager = new PortfolioManager(fileOperations);
const results = [];
for (const elementType of Object.values(ElementType)) {
console.log(chalk.gray(`\nFormatting ${elementType}...`));
const elementDir = portfolioManager.getElementDir(elementType);
const parentDir = path.dirname(elementDir);
const typeResults = await formatter.formatElementType(elementType, parentDir);
results.push(...typeResults);
}
return results;
}
/**
* Format specific element type
*/
async function formatElementType(type, formatter) {
const elementType = type;
if (!Object.values(ElementType).includes(elementType)) {
console.error(chalk.red(`Invalid element type: ${type}`));
console.log('Valid types:', Object.values(ElementType).join(', '));
process.exit(1);
}
console.log(chalk.blue(`Formatting all ${elementType} elements...`));
const fileLockManager = new FileLockManager();
const fileOperations = new FileOperationsService(fileLockManager);
const portfolioManager = new PortfolioManager(fileOperations);
const elementDir = portfolioManager.getElementDir(elementType);
const parentDir = path.dirname(elementDir);
return formatter.formatElementType(elementType, parentDir);
}
/**
* Format specific files
*/
async function formatSpecificFiles(files, options, formatter) {
console.log(chalk.blue(`Formatting ${files.length} file(s)...`));
if (options.dryRun) {
for (const file of files) {
console.log(chalk.gray(`Would format: ${file}`));
}
return [];
}
return formatter.formatFiles(files);
}
/**
* Exit with appropriate code based on results
* Exit codes:
* 0 - All successful
* 1 - Total failure (all files failed)
* 2 - Partial failure (some files failed)
*/
function exitWithCode(results) {
const failed = results.filter(r => !r.success).length;
const total = results.length;
if (failed === 0) {
process.exit(0); // All successful
}
else if (failed === total) {
process.exit(1); // Total failure
}
else {
process.exit(2); // Partial failure
}
}
/**
* Display formatting results
* Refactored to reduce cognitive complexity
*/
function displayResults(results, dryRun) {
const { successful, failed } = categorizeResults(results);
displayResultsSummary(successful, failed);
displayResultsDetails(results, failed.length);
displayStatsSummary(results, dryRun);
}
/**
* Categorize results into successful and failed
*/
function categorizeResults(results) {
const successful = results.filter(r => r.success);
const failed = results.filter(r => !r.success);
return { successful, failed };
}
/**
* Display results summary
*/
function displayResultsSummary(successful, failed) {
console.log('\n' + chalk.bold('Formatting Results:'));
console.log(chalk.green(`✓ ${successful.length} file(s) formatted successfully`));
if (failed.length > 0) {
console.log(chalk.red(`✗ ${failed.length} file(s) failed`));
}
}
/**
* Display detailed results
*/
function displayResultsDetails(results, failedCount) {
if (results.length > 10 && failedCount === 0) {
return; // Skip details for large successful batches
}
console.log('\n' + chalk.bold('Details:'));
for (const result of results) {
displaySingleResult(result);
}
}
/**
* Display a single result
*/
function displaySingleResult(result) {
const icon = result.success ? chalk.green('✓') : chalk.red('✗');
const fileName = path.basename(result.filePath);
console.log(`\n${icon} ${chalk.cyan(fileName)}`);
displayResultIssues(result);
displayResultFixes(result);
displayResultError(result);
displayResultBackup(result);
}
/**
* Display result issues
*/
function displayResultIssues(result) {
if (result.issues.length === 0)
return;
console.log(chalk.yellow(' Issues found:'));
for (const issue of result.issues) {
console.log(chalk.yellow(` - ${issue}`));
}
}
/**
* Display result fixes
*/
function displayResultFixes(result) {
if (result.fixed.length === 0)
return;
console.log(chalk.green(' Fixed:'));
for (const fix of result.fixed) {
console.log(chalk.green(` - ${fix}`));
}
}
/**
* Display result error
*/
function displayResultError(result) {
if (result.error) {
console.log(chalk.red(` Error: ${result.error}`));
}
}
/**
* Display result backup path
*/
function displayResultBackup(result) {
if (result.backupPath) {
console.log(chalk.gray(` Backup: ${result.backupPath}`));
}
}
/**
* Display statistics summary
*/
function displayStatsSummary(results, dryRun) {
console.log('\n' + chalk.bold('Summary:'));
const totalIssues = results.reduce((sum, r) => sum + r.issues.length, 0);
const totalFixes = results.reduce((sum, r) => sum + r.fixed.length, 0);
console.log(` Total issues found: ${totalIssues}`);
console.log(` Total fixes applied: ${totalFixes}`);
if (dryRun) {
console.log(chalk.yellow('\n(Dry run - no changes were made)'));
}
}
// Parse command line arguments
program.parse(process.argv);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybWF0LWVsZW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2xpL2Zvcm1hdC1lbGVtZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFFQTs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUVILE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDcEMsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBQzFCLE9BQU8sRUFBRSxnQkFBZ0IsRUFBbUIsTUFBTSw4QkFBOEIsQ0FBQztBQUNqRixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDcEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDcEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUVqRSxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0FBRTlCLE9BQU87S0FDSixJQUFJLENBQUMsZ0JBQWdCLENBQUM7S0FDdEIsV0FBVyxDQUFDLGtEQUFrRCxDQUFDO0tBQy9ELFFBQVEsQ0FBQyxZQUFZLEVBQUUseUJBQXlCLENBQUM7S0FDakQsTUFBTSxDQUFDLGdCQUFnQixFQUFFLHVCQUF1QixFQUFFLEtBQUssQ0FBQztLQUN4RCxNQUFNLENBQUMsY0FBYyxFQUFFLDJDQUEyQyxFQUFFLElBQUksQ0FBQztLQUN6RSxNQUFNLENBQUMsd0JBQXdCLEVBQUUsK0JBQStCLENBQUM7S0FDakUsTUFBTSxDQUFDLG1CQUFtQixFQUFFLGtDQUFrQyxDQUFDO0tBQy9ELE1BQU0sQ0FBQyxXQUFXLEVBQUUsa0NBQWtDLEVBQUUsS0FBSyxDQUFDO0tBQzlELE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxnQ0FBZ0MsRUFBRSxJQUFJLENBQUM7S0FDaEUsTUFBTSxDQUFDLFdBQVcsRUFBRSw4Q0FBOEMsRUFBRSxLQUFLLENBQUM7S0FDMUUsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFlLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDekMsSUFBSSxDQUFDO1FBQ0gsZUFBZSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNoQyxNQUFNLFNBQVMsR0FBRyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0MsTUFBTSxPQUFPLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQ3hFLGNBQWMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3hDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyw0QkFBNEIsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzlELE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbEIsQ0FBQztBQUNILENBQUMsQ0FBQyxDQUFDO0FBRUw7O0dBRUc7QUFDSCxTQUFTLGVBQWUsQ0FBQyxLQUFlLEVBQUUsT0FBWTtJQUNwRCxlQUFlLENBQUMsZ0JBQWdCLENBQUM7UUFDL0IsSUFBSSxFQUFFLGFBQWE7UUFDbkIsUUFBUSxFQUFFLEtBQUs7UUFDZixNQUFNLEVBQUUsb0JBQW9CO1FBQzVCLE9BQU8sRUFBRSw4QkFBOEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLFFBQVEsRUFBRTtLQUNoRyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGVBQWUsQ0FBQyxPQUFZO0lBQ25DLE1BQU0sZUFBZSxHQUFHLElBQUksZUFBZSxFQUFFLENBQUM7SUFDOUMsTUFBTSxjQUFjLEdBQUcsSUFBSSxxQkFBcUIsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUNsRSxPQUFPLElBQUksZ0JBQWdCLENBQUM7UUFDMUIsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1FBQ3RCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztRQUN4QixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7UUFDMUIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO0tBQzdCLEVBQUUsY0FBYyxDQUFDLENBQUM7QUFDckIsQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLHNCQUFzQixDQUNuQyxLQUFlLEVBQ2YsT0FBWSxFQUNaLFNBQTJCO0lBRTNCLElBQUksT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLE9BQU8saUJBQWlCLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdEMsQ0FBQztTQUFNLElBQUksT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3hCLE9BQU8saUJBQWlCLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztJQUNwRCxDQUFDO1NBQU0sSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzVCLE9BQU8sbUJBQW1CLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztJQUN4RCxDQUFDO1NBQU0sQ0FBQztRQUNOLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQywyQ0FBMkMsQ0FBQyxDQUFDLENBQUM7UUFDdEUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNsQixDQUFDO0FBQ0gsQ0FBQztBQUVEOztHQUVHO0FBQ0gsS0FBSyxVQUFVLGlCQUFpQixDQUFDLFNBQTJCO0lBQzFELE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDLENBQUM7SUFDaEUsTUFBTSxlQUFlLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztJQUM5QyxNQUFNLGNBQWMsR0FBRyxJQUFJLHFCQUFxQixDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ2xFLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM5RCxNQUFNLE9BQU8sR0FBc0IsRUFBRSxDQUFDO0lBRXRDLEtBQUssTUFBTSxXQUFXLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1FBQ3JELE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsV0FBVyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzFELE1BQU0sVUFBVSxHQUFHLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMvRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzNDLE1BQU0sV0FBVyxHQUFHLE1BQU0sU0FBUyxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUM5RSxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsV0FBVyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxpQkFBaUIsQ0FDOUIsSUFBWSxFQUNaLFNBQTJCO0lBRTNCLE1BQU0sV0FBVyxHQUFHLElBQW1CLENBQUM7SUFDeEMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7UUFDdEQsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLHlCQUF5QixJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDMUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNuRSxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ2xCLENBQUM7SUFFRCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsa0JBQWtCLFdBQVcsY0FBYyxDQUFDLENBQUMsQ0FBQztJQUNyRSxNQUFNLGVBQWUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO0lBQzlDLE1BQU0sY0FBYyxHQUFHLElBQUkscUJBQXFCLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDbEUsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLGdCQUFnQixDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQzlELE1BQU0sVUFBVSxHQUFHLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUMvRCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzNDLE9BQU8sU0FBUyxDQUFDLGlCQUFpQixDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsQ0FBQztBQUM3RCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxLQUFLLFVBQVUsbUJBQW1CLENBQ2hDLEtBQWUsRUFDZixPQUFZLEVBQ1osU0FBMkI7SUFFM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLGNBQWMsS0FBSyxDQUFDLE1BQU0sYUFBYSxDQUFDLENBQUMsQ0FBQztJQUVqRSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNuQixLQUFLLE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3pCLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ25ELENBQUM7UUFDRCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCxPQUFPLFNBQVMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdEMsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsWUFBWSxDQUFDLE9BQTBCO0lBQzlDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDdEQsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUU3QixJQUFJLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUNqQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUUsaUJBQWlCO0lBQ3JDLENBQUM7U0FBTSxJQUFJLE1BQU0sS0FBSyxLQUFLLEVBQUUsQ0FBQztRQUM1QixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUUsZ0JBQWdCO0lBQ3BDLENBQUM7U0FBTSxDQUFDO1FBQ04sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFFLGtCQUFrQjtJQUN0QyxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsY0FBYyxDQUFDLE9BQTBCLEVBQUUsTUFBZTtJQUNqRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRTFELHFCQUFxQixDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUMxQyxxQkFBcUIsQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlDLG1CQUFtQixDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztBQUN2QyxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGlCQUFpQixDQUFDLE9BQTBCO0lBQ25ELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbEQsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLENBQUM7QUFDaEMsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxxQkFBcUIsQ0FBQyxVQUE2QixFQUFFLE1BQXlCO0lBQ3JGLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsQ0FBQyxDQUFDO0lBQ3RELE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLFVBQVUsQ0FBQyxNQUFNLGlDQUFpQyxDQUFDLENBQUMsQ0FBQztJQUVsRixJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDdEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssTUFBTSxDQUFDLE1BQU0saUJBQWlCLENBQUMsQ0FBQyxDQUFDO0lBQzlELENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLHFCQUFxQixDQUFDLE9BQTBCLEVBQUUsV0FBbUI7SUFDNUUsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLEVBQUUsSUFBSSxXQUFXLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDN0MsT0FBTyxDQUFDLDRDQUE0QztJQUN0RCxDQUFDO0lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQzNDLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFLENBQUM7UUFDN0IsbUJBQW1CLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUIsQ0FBQztBQUNILENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQUMsTUFBdUI7SUFDbEQsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNoRSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUVoRCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssSUFBSSxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBRWpELG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzVCLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzNCLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzNCLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzlCLENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQUMsTUFBdUI7SUFDbEQsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTztJQUV2QyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDO0lBQzdDLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2xDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5QyxDQUFDO0FBQ0gsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxNQUF1QjtJQUNqRCxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUM7UUFBRSxPQUFPO0lBRXRDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBQ3JDLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMzQyxDQUFDO0FBQ0gsQ0FBQztBQUVEOztHQUVHO0FBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxNQUF1QjtJQUNqRCxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNqQixPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsWUFBWSxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3JELENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLG1CQUFtQixDQUFDLE1BQXVCO0lBQ2xELElBQUksTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3RCLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDNUQsQ0FBQztBQUNILENBQUM7QUFFRDs7R0FFRztBQUNILFNBQVMsbUJBQW1CLENBQUMsT0FBMEIsRUFBRSxNQUFlO0lBQ3RFLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztJQUMzQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3pFLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFdkUsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUNwRCxPQUFPLENBQUMsR0FBRyxDQUFDLDBCQUEwQixVQUFVLEVBQUUsQ0FBQyxDQUFDO0lBRXBELElBQUksTUFBTSxFQUFFLENBQUM7UUFDWCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsb0NBQW9DLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7QUFDSCxDQUFDO0FBRUQsK0JBQStCO0FBQy9CLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiIyEvdXNyL2Jpbi9lbnYgbm9kZVxuXG4vKipcbiAqIENMSSBjb21tYW5kIGZvciBmb3JtYXR0aW5nL2NsZWFuaW5nIERvbGxob3VzZU1DUCBlbGVtZW50c1xuICpcbiAqIFVzYWdlOlxuICogICBucHggZG9sbGhvdXNlIGZvcm1hdC1lbGVtZW50IDxmaWxlPlxuICogICBucHggZG9sbGhvdXNlIGZvcm1hdC1lbGVtZW50IC0tdHlwZSBtZW1vcmllc1xuICogICBucHggZG9sbGhvdXNlIGZvcm1hdC1lbGVtZW50IC0tYWxsXG4gKlxuICogT3B0aW9uczpcbiAqICAgLS1pbi1wbGFjZSAgICBGb3JtYXQgZmlsZXMgaW4gcGxhY2UgKGRlZmF1bHQ6IGNyZWF0ZSAuZm9ybWF0dGVkIGZpbGVzKVxuICogICAtLW5vLWJhY2t1cCAgIERvbid0IGNyZWF0ZSBiYWNrdXAgZmlsZXMgd2hlbiB1c2luZyAtLWluLXBsYWNlXG4gKiAgIC0tb3V0cHV0LWRpciAgRGlyZWN0b3J5IHRvIHdyaXRlIGZvcm1hdHRlZCBmaWxlc1xuICogICAtLXR5cGUgICAgICAgIEVsZW1lbnQgdHlwZSB0byBmb3JtYXQgKHBlcnNvbmFzLCBza2lsbHMsIGV0Yy4pXG4gKiAgIC0tYWxsICAgICAgICAgRm9ybWF0IGFsbCBlbGVtZW50cyBpbiBwb3J0Zm9saW9cbiAqL1xuXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSAnY29tbWFuZGVyJztcbmltcG9ydCBjaGFsayBmcm9tICdjaGFsayc7XG5pbXBvcnQgeyBFbGVtZW50Rm9ybWF0dGVyLCBGb3JtYXR0ZXJSZXN1bHQgfSBmcm9tICcuLi91dGlscy9FbGVtZW50Rm9ybWF0dGVyLmpzJztcbmltcG9ydCB7IEVsZW1lbnRUeXBlIH0gZnJvbSAnLi4vcG9ydGZvbGlvL3R5cGVzLmpzJztcbmltcG9ydCB7IFBvcnRmb2xpb01hbmFnZXIgfSBmcm9tICcuLi9wb3J0Zm9saW8vUG9ydGZvbGlvTWFuYWdlci5qcyc7XG5pbXBvcnQgeyBTZWN1cml0eU1vbml0b3IgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cml0eU1vbml0b3IuanMnO1xuaW1wb3J0IHsgRmlsZU9wZXJhdGlvbnNTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvRmlsZU9wZXJhdGlvbnNTZXJ2aWNlLmpzJztcbmltcG9ydCB7IEZpbGVMb2NrTWFuYWdlciB9IGZyb20gJy4uL3NlY3VyaXR5L2ZpbGVMb2NrTWFuYWdlci5qcyc7XG5cbmNvbnN0IHByb2dyYW0gPSBuZXcgQ29tbWFuZCgpO1xuXG5wcm9ncmFtXG4gIC5uYW1lKCdmb3JtYXQtZWxlbWVudCcpXG4gIC5kZXNjcmlwdGlvbignRm9ybWF0IGFuZCBjbGVhbiBtYWxmb3JtZWQgRG9sbGhvdXNlTUNQIGVsZW1lbnRzJylcbiAgLmFyZ3VtZW50KCdbZmlsZXMuLi5dJywgJ0VsZW1lbnQgZmlsZXMgdG8gZm9ybWF0JylcbiAgLm9wdGlvbignLWksIC0taW4tcGxhY2UnLCAnRm9ybWF0IGZpbGVzIGluIHBsYWNlJywgZmFsc2UpXG4gIC5vcHRpb24oJy1iLCAtLWJhY2t1cCcsICdDcmVhdGUgYmFja3VwIGZpbGVzIHdoZW4gdXNpbmcgLS1pbi1wbGFjZScsIHRydWUpXG4gIC5vcHRpb24oJy1vLCAtLW91dHB1dC1kaXIgPGRpcj4nLCAnRGlyZWN0b3J5IGZvciBmb3JtYXR0ZWQgZmlsZXMnKVxuICAub3B0aW9uKCctdCwgLS10eXBlIDx0eXBlPicsICdGb3JtYXQgYWxsIGVsZW1lbnRzIG9mIHRoaXMgdHlwZScpXG4gIC5vcHRpb24oJy1hLCAtLWFsbCcsICdGb3JtYXQgYWxsIGVsZW1lbnRzIGluIHBvcnRmb2xpbycsIGZhbHNlKVxuICAub3B0aW9uKCctdiwgLS12YWxpZGF0ZScsICdWYWxpZGF0ZSBZQU1MIGFmdGVyIGZvcm1hdHRpbmcnLCB0cnVlKVxuICAub3B0aW9uKCctLWRyeS1ydW4nLCAnU2hvdyB3aGF0IHdvdWxkIGJlIGZvcm1hdHRlZCB3aXRob3V0IGNoYW5nZXMnLCBmYWxzZSlcbiAgLmFjdGlvbihhc3luYyAoZmlsZXM6IHN0cmluZ1tdLCBvcHRpb25zKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGxvZ0NsaU9wZXJhdGlvbihmaWxlcywgb3B0aW9ucyk7XG4gICAgICBjb25zdCBmb3JtYXR0ZXIgPSBjcmVhdGVGb3JtYXR0ZXIob3B0aW9ucyk7XG4gICAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgcHJvY2Vzc0Zvcm1hdE9wZXJhdGlvbihmaWxlcywgb3B0aW9ucywgZm9ybWF0dGVyKTtcbiAgICAgIGRpc3BsYXlSZXN1bHRzKHJlc3VsdHMsIG9wdGlvbnMuZHJ5UnVuKTtcbiAgICAgIGV4aXRXaXRoQ29kZShyZXN1bHRzKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoJ0ZhaWxlZCB0byBmb3JtYXQgZWxlbWVudHM6JyksIGVycm9yKTtcbiAgICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgICB9XG4gIH0pO1xuXG4vKipcbiAqIExvZyBDTEkgb3BlcmF0aW9uIGZvciBhdWRpdFxuICovXG5mdW5jdGlvbiBsb2dDbGlPcGVyYXRpb24oZmlsZXM6IHN0cmluZ1tdLCBvcHRpb25zOiBhbnkpOiB2b2lkIHtcbiAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgIHR5cGU6ICdGSUxFX0NPUElFRCcsXG4gICAgc2V2ZXJpdHk6ICdMT1cnLFxuICAgIHNvdXJjZTogJ2Zvcm1hdC1lbGVtZW50IENMSScsXG4gICAgZGV0YWlsczogYFN0YXJ0aW5nIGZvcm1hdCBvcGVyYXRpb246ICR7b3B0aW9ucy5hbGwgPyAnYWxsIGVsZW1lbnRzJyA6IGZpbGVzLmxlbmd0aCArICcgZmlsZXMnfWBcbiAgfSk7XG59XG5cbi8qKlxuICogQ3JlYXRlIGZvcm1hdHRlciB3aXRoIG9wdGlvbnNcbiAqL1xuZnVuY3Rpb24gY3JlYXRlRm9ybWF0dGVyKG9wdGlvbnM6IGFueSk6IEVsZW1lbnRGb3JtYXR0ZXIge1xuICBjb25zdCBmaWxlTG9ja01hbmFnZXIgPSBuZXcgRmlsZUxvY2tNYW5hZ2VyKCk7XG4gIGNvbnN0IGZpbGVPcGVyYXRpb25zID0gbmV3IEZpbGVPcGVyYXRpb25zU2VydmljZShmaWxlTG9ja01hbmFnZXIpO1xuICByZXR1cm4gbmV3IEVsZW1lbnRGb3JtYXR0ZXIoe1xuICAgIGJhY2t1cDogb3B0aW9ucy5iYWNrdXAsXG4gICAgaW5QbGFjZTogb3B0aW9ucy5pblBsYWNlLFxuICAgIHZhbGlkYXRlOiBvcHRpb25zLnZhbGlkYXRlLFxuICAgIG91dHB1dERpcjogb3B0aW9ucy5vdXRwdXREaXJcbiAgfSwgZmlsZU9wZXJhdGlvbnMpO1xufVxuXG4vKipcbiAqIFByb2Nlc3MgZm9ybWF0IG9wZXJhdGlvbiBiYXNlZCBvbiBvcHRpb25zXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NGb3JtYXRPcGVyYXRpb24oXG4gIGZpbGVzOiBzdHJpbmdbXSxcbiAgb3B0aW9uczogYW55LFxuICBmb3JtYXR0ZXI6IEVsZW1lbnRGb3JtYXR0ZXJcbik6IFByb21pc2U8Rm9ybWF0dGVyUmVzdWx0W10+IHtcbiAgaWYgKG9wdGlvbnMuYWxsKSB7XG4gICAgcmV0dXJuIGZvcm1hdEFsbEVsZW1lbnRzKGZvcm1hdHRlcik7XG4gIH0gZWxzZSBpZiAob3B0aW9ucy50eXBlKSB7XG4gICAgcmV0dXJuIGZvcm1hdEVsZW1lbnRUeXBlKG9wdGlvbnMudHlwZSwgZm9ybWF0dGVyKTtcbiAgfSBlbHNlIGlmIChmaWxlcy5sZW5ndGggPiAwKSB7XG4gICAgcmV0dXJuIGZvcm1hdFNwZWNpZmljRmlsZXMoZmlsZXMsIG9wdGlvbnMsIGZvcm1hdHRlcik7XG4gIH0gZWxzZSB7XG4gICAgY29uc29sZS5lcnJvcihjaGFsay5yZWQoJ05vIGZpbGVzIHNwZWNpZmllZC4gVXNlIC0taGVscCBmb3IgdXNhZ2UuJykpO1xuICAgIHByb2Nlc3MuZXhpdCgxKTtcbiAgfVxufVxuXG4vKipcbiAqIEZvcm1hdCBhbGwgZWxlbWVudHMgaW4gcG9ydGZvbGlvXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZvcm1hdEFsbEVsZW1lbnRzKGZvcm1hdHRlcjogRWxlbWVudEZvcm1hdHRlcik6IFByb21pc2U8Rm9ybWF0dGVyUmVzdWx0W10+IHtcbiAgY29uc29sZS5sb2coY2hhbGsuYmx1ZSgnRm9ybWF0dGluZyBhbGwgcG9ydGZvbGlvIGVsZW1lbnRzLi4uJykpO1xuICBjb25zdCBmaWxlTG9ja01hbmFnZXIgPSBuZXcgRmlsZUxvY2tNYW5hZ2VyKCk7XG4gIGNvbnN0IGZpbGVPcGVyYXRpb25zID0gbmV3IEZpbGVPcGVyYXRpb25zU2VydmljZShmaWxlTG9ja01hbmFnZXIpO1xuICBjb25zdCBwb3J0Zm9saW9NYW5hZ2VyID0gbmV3IFBvcnRmb2xpb01hbmFnZXIoZmlsZU9wZXJhdGlvbnMpO1xuICBjb25zdCByZXN1bHRzOiBGb3JtYXR0ZXJSZXN1bHRbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZWxlbWVudFR5cGUgb2YgT2JqZWN0LnZhbHVlcyhFbGVtZW50VHlwZSkpIHtcbiAgICBjb25zb2xlLmxvZyhjaGFsay5ncmF5KGBcXG5Gb3JtYXR0aW5nICR7ZWxlbWVudFR5cGV9Li4uYCkpO1xuICAgIGNvbnN0IGVsZW1lbnREaXIgPSBwb3J0Zm9saW9NYW5hZ2VyLmdldEVsZW1lbnREaXIoZWxlbWVudFR5cGUpO1xuICAgIGNvbnN0IHBhcmVudERpciA9IHBhdGguZGlybmFtZShlbGVtZW50RGlyKTtcbiAgICBjb25zdCB0eXBlUmVzdWx0cyA9IGF3YWl0IGZvcm1hdHRlci5mb3JtYXRFbGVtZW50VHlwZShlbGVtZW50VHlwZSwgcGFyZW50RGlyKTtcbiAgICByZXN1bHRzLnB1c2goLi4udHlwZVJlc3VsdHMpO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdHM7XG59XG5cbi8qKlxuICogRm9ybWF0IHNwZWNpZmljIGVsZW1lbnQgdHlwZVxuICovXG5hc3luYyBmdW5jdGlvbiBmb3JtYXRFbGVtZW50VHlwZShcbiAgdHlwZTogc3RyaW5nLFxuICBmb3JtYXR0ZXI6IEVsZW1lbnRGb3JtYXR0ZXJcbik6IFByb21pc2U8Rm9ybWF0dGVyUmVzdWx0W10+IHtcbiAgY29uc3QgZWxlbWVudFR5cGUgPSB0eXBlIGFzIEVsZW1lbnRUeXBlO1xuICBpZiAoIU9iamVjdC52YWx1ZXMoRWxlbWVudFR5cGUpLmluY2x1ZGVzKGVsZW1lbnRUeXBlKSkge1xuICAgIGNvbnNvbGUuZXJyb3IoY2hhbGsucmVkKGBJbnZhbGlkIGVsZW1lbnQgdHlwZTogJHt0eXBlfWApKTtcbiAgICBjb25zb2xlLmxvZygnVmFsaWQgdHlwZXM6JywgT2JqZWN0LnZhbHVlcyhFbGVtZW50VHlwZSkuam9pbignLCAnKSk7XG4gICAgcHJvY2Vzcy5leGl0KDEpO1xuICB9XG5cbiAgY29uc29sZS5sb2coY2hhbGsuYmx1ZShgRm9ybWF0dGluZyBhbGwgJHtlbGVtZW50VHlwZX0gZWxlbWVudHMuLi5gKSk7XG4gIGNvbnN0IGZpbGVMb2NrTWFuYWdlciA9IG5ldyBGaWxlTG9ja01hbmFnZXIoKTtcbiAgY29uc3QgZmlsZU9wZXJhdGlvbnMgPSBuZXcgRmlsZU9wZXJhdGlvbnNTZXJ2aWNlKGZpbGVMb2NrTWFuYWdlcik7XG4gIGNvbnN0IHBvcnRmb2xpb01hbmFnZXIgPSBuZXcgUG9ydGZvbGlvTWFuYWdlcihmaWxlT3BlcmF0aW9ucyk7XG4gIGNvbnN0IGVsZW1lbnREaXIgPSBwb3J0Zm9saW9NYW5hZ2VyLmdldEVsZW1lbnREaXIoZWxlbWVudFR5cGUpO1xuICBjb25zdCBwYXJlbnREaXIgPSBwYXRoLmRpcm5hbWUoZWxlbWVudERpcik7XG4gIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0RWxlbWVudFR5cGUoZWxlbWVudFR5cGUsIHBhcmVudERpcik7XG59XG5cbi8qKlxuICogRm9ybWF0IHNwZWNpZmljIGZpbGVzXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZvcm1hdFNwZWNpZmljRmlsZXMoXG4gIGZpbGVzOiBzdHJpbmdbXSxcbiAgb3B0aW9uczogYW55LFxuICBmb3JtYXR0ZXI6IEVsZW1lbnRGb3JtYXR0ZXJcbik6IFByb21pc2U8Rm9ybWF0dGVyUmVzdWx0W10+IHtcbiAgY29uc29sZS5sb2coY2hhbGsuYmx1ZShgRm9ybWF0dGluZyAke2ZpbGVzLmxlbmd0aH0gZmlsZShzKS4uLmApKTtcblxuICBpZiAob3B0aW9ucy5kcnlSdW4pIHtcbiAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZmlsZXMpIHtcbiAgICAgIGNvbnNvbGUubG9nKGNoYWxrLmdyYXkoYFdvdWxkIGZvcm1hdDogJHtmaWxlfWApKTtcbiAgICB9XG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcmV0dXJuIGZvcm1hdHRlci5mb3JtYXRGaWxlcyhmaWxlcyk7XG59XG5cbi8qKlxuICogRXhpdCB3aXRoIGFwcHJvcHJpYXRlIGNvZGUgYmFzZWQgb24gcmVzdWx0c1xuICogRXhpdCBjb2RlczpcbiAqIDAgLSBBbGwgc3VjY2Vzc2Z1bFxuICogMSAtIFRvdGFsIGZhaWx1cmUgKGFsbCBmaWxlcyBmYWlsZWQpXG4gKiAyIC0gUGFydGlhbCBmYWlsdXJlIChzb21lIGZpbGVzIGZhaWxlZClcbiAqL1xuZnVuY3Rpb24gZXhpdFdpdGhDb2RlKHJlc3VsdHM6IEZvcm1hdHRlclJlc3VsdFtdKTogdm9pZCB7XG4gIGNvbnN0IGZhaWxlZCA9IHJlc3VsdHMuZmlsdGVyKHIgPT4gIXIuc3VjY2VzcykubGVuZ3RoO1xuICBjb25zdCB0b3RhbCA9IHJlc3VsdHMubGVuZ3RoO1xuXG4gIGlmIChmYWlsZWQgPT09IDApIHtcbiAgICBwcm9jZXNzLmV4aXQoMCk7ICAvLyBBbGwgc3VjY2Vzc2Z1bFxuICB9IGVsc2UgaWYgKGZhaWxlZCA9PT0gdG90YWwpIHtcbiAgICBwcm9jZXNzLmV4aXQoMSk7ICAvLyBUb3RhbCBmYWlsdXJlXG4gIH0gZWxzZSB7XG4gICAgcHJvY2Vzcy5leGl0KDIpOyAgLy8gUGFydGlhbCBmYWlsdXJlXG4gIH1cbn1cblxuLyoqXG4gKiBEaXNwbGF5IGZvcm1hdHRpbmcgcmVzdWx0c1xuICogUmVmYWN0b3JlZCB0byByZWR1Y2UgY29nbml0aXZlIGNvbXBsZXhpdHlcbiAqL1xuZnVuY3Rpb24gZGlzcGxheVJlc3VsdHMocmVzdWx0czogRm9ybWF0dGVyUmVzdWx0W10sIGRyeVJ1bjogYm9vbGVhbik6IHZvaWQge1xuICBjb25zdCB7IHN1Y2Nlc3NmdWwsIGZhaWxlZCB9ID0gY2F0ZWdvcml6ZVJlc3VsdHMocmVzdWx0cyk7XG5cbiAgZGlzcGxheVJlc3VsdHNTdW1tYXJ5KHN1Y2Nlc3NmdWwsIGZhaWxlZCk7XG4gIGRpc3BsYXlSZXN1bHRzRGV0YWlscyhyZXN1bHRzLCBmYWlsZWQubGVuZ3RoKTtcbiAgZGlzcGxheVN0YXRzU3VtbWFyeShyZXN1bHRzLCBkcnlSdW4pO1xufVxuXG4vKipcbiAqIENhdGVnb3JpemUgcmVzdWx0cyBpbnRvIHN1Y2Nlc3NmdWwgYW5kIGZhaWxlZFxuICovXG5mdW5jdGlvbiBjYXRlZ29yaXplUmVzdWx0cyhyZXN1bHRzOiBGb3JtYXR0ZXJSZXN1bHRbXSk6IHsgc3VjY2Vzc2Z1bDogRm9ybWF0dGVyUmVzdWx0W107IGZhaWxlZDogRm9ybWF0dGVyUmVzdWx0W10gfSB7XG4gIGNvbnN0IHN1Y2Nlc3NmdWwgPSByZXN1bHRzLmZpbHRlcihyID0+IHIuc3VjY2Vzcyk7XG4gIGNvbnN0IGZhaWxlZCA9IHJlc3VsdHMuZmlsdGVyKHIgPT4gIXIuc3VjY2Vzcyk7XG4gIHJldHVybiB7IHN1Y2Nlc3NmdWwsIGZhaWxlZCB9O1xufVxuXG4vKipcbiAqIERpc3BsYXkgcmVzdWx0cyBzdW1tYXJ5XG4gKi9cbmZ1bmN0aW9uIGRpc3BsYXlSZXN1bHRzU3VtbWFyeShzdWNjZXNzZnVsOiBGb3JtYXR0ZXJSZXN1bHRbXSwgZmFpbGVkOiBGb3JtYXR0ZXJSZXN1bHRbXSk6IHZvaWQge1xuICBjb25zb2xlLmxvZygnXFxuJyArIGNoYWxrLmJvbGQoJ0Zvcm1hdHRpbmcgUmVzdWx0czonKSk7XG4gIGNvbnNvbGUubG9nKGNoYWxrLmdyZWVuKGDinJMgJHtzdWNjZXNzZnVsLmxlbmd0aH0gZmlsZShzKSBmb3JtYXR0ZWQgc3VjY2Vzc2Z1bGx5YCkpO1xuXG4gIGlmIChmYWlsZWQubGVuZ3RoID4gMCkge1xuICAgIGNvbnNvbGUubG9nKGNoYWxrLnJlZChg4pyXICR7ZmFpbGVkLmxlbmd0aH0gZmlsZShzKSBmYWlsZWRgKSk7XG4gIH1cbn1cblxuLyoqXG4gKiBEaXNwbGF5IGRldGFpbGVkIHJlc3VsdHNcbiAqL1xuZnVuY3Rpb24gZGlzcGxheVJlc3VsdHNEZXRhaWxzKHJlc3VsdHM6IEZvcm1hdHRlclJlc3VsdFtdLCBmYWlsZWRDb3VudDogbnVtYmVyKTogdm9pZCB7XG4gIGlmIChyZXN1bHRzLmxlbmd0aCA+IDEwICYmIGZhaWxlZENvdW50ID09PSAwKSB7XG4gICAgcmV0dXJuOyAvLyBTa2lwIGRldGFpbHMgZm9yIGxhcmdlIHN1Y2Nlc3NmdWwgYmF0Y2hlc1xuICB9XG5cbiAgY29uc29sZS5sb2coJ1xcbicgKyBjaGFsay5ib2xkKCdEZXRhaWxzOicpKTtcbiAgZm9yIChjb25zdCByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgIGRpc3BsYXlTaW5nbGVSZXN1bHQocmVzdWx0KTtcbiAgfVxufVxuXG4vKipcbiAqIERpc3BsYXkgYSBzaW5nbGUgcmVzdWx0XG4gKi9cbmZ1bmN0aW9uIGRpc3BsYXlTaW5nbGVSZXN1bHQocmVzdWx0OiBGb3JtYXR0ZXJSZXN1bHQpOiB2b2lkIHtcbiAgY29uc3QgaWNvbiA9IHJlc3VsdC5zdWNjZXNzID8gY2hhbGsuZ3JlZW4oJ+KckycpIDogY2hhbGsucmVkKCfinJcnKTtcbiAgY29uc3QgZmlsZU5hbWUgPSBwYXRoLmJhc2VuYW1lKHJlc3VsdC5maWxlUGF0aCk7XG5cbiAgY29uc29sZS5sb2coYFxcbiR7aWNvbn0gJHtjaGFsay5jeWFuKGZpbGVOYW1lKX1gKTtcblxuICBkaXNwbGF5UmVzdWx0SXNzdWVzKHJlc3VsdCk7XG4gIGRpc3BsYXlSZXN1bHRGaXhlcyhyZXN1bHQpO1xuICBkaXNwbGF5UmVzdWx0RXJyb3IocmVzdWx0KTtcbiAgZGlzcGxheVJlc3VsdEJhY2t1cChyZXN1bHQpO1xufVxuXG4vKipcbiAqIERpc3BsYXkgcmVzdWx0IGlzc3Vlc1xuICovXG5mdW5jdGlvbiBkaXNwbGF5UmVzdWx0SXNzdWVzKHJlc3VsdDogRm9ybWF0dGVyUmVzdWx0KTogdm9pZCB7XG4gIGlmIChyZXN1bHQuaXNzdWVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuXG4gIGNvbnNvbGUubG9nKGNoYWxrLnllbGxvdygnICBJc3N1ZXMgZm91bmQ6JykpO1xuICBmb3IgKGNvbnN0IGlzc3VlIG9mIHJlc3VsdC5pc3N1ZXMpIHtcbiAgICBjb25zb2xlLmxvZyhjaGFsay55ZWxsb3coYCAgICAtICR7aXNzdWV9YCkpO1xuICB9XG59XG5cbi8qKlxuICogRGlzcGxheSByZXN1bHQgZml4ZXNcbiAqL1xuZnVuY3Rpb24gZGlzcGxheVJlc3VsdEZpeGVzKHJlc3VsdDogRm9ybWF0dGVyUmVzdWx0KTogdm9pZCB7XG4gIGlmIChyZXN1bHQuZml4ZWQubGVuZ3RoID09PSAwKSByZXR1cm47XG5cbiAgY29uc29sZS5sb2coY2hhbGsuZ3JlZW4oJyAgRml4ZWQ6JykpO1xuICBmb3IgKGNvbnN0IGZpeCBvZiByZXN1bHQuZml4ZWQpIHtcbiAgICBjb25zb2xlLmxvZyhjaGFsay5ncmVlbihgICAgIC0gJHtmaXh9YCkpO1xuICB9XG59XG5cbi8qKlxuICogRGlzcGxheSByZXN1bHQgZXJyb3JcbiAqL1xuZnVuY3Rpb24gZGlzcGxheVJlc3VsdEVycm9yKHJlc3VsdDogRm9ybWF0dGVyUmVzdWx0KTogdm9pZCB7XG4gIGlmIChyZXN1bHQuZXJyb3IpIHtcbiAgICBjb25zb2xlLmxvZyhjaGFsay5yZWQoYCAgRXJyb3I6ICR7cmVzdWx0LmVycm9yfWApKTtcbiAgfVxufVxuXG4vKipcbiAqIERpc3BsYXkgcmVzdWx0IGJhY2t1cCBwYXRoXG4gKi9cbmZ1bmN0aW9uIGRpc3BsYXlSZXN1bHRCYWNrdXAocmVzdWx0OiBGb3JtYXR0ZXJSZXN1bHQpOiB2b2lkIHtcbiAgaWYgKHJlc3VsdC5iYWNrdXBQYXRoKSB7XG4gICAgY29uc29sZS5sb2coY2hhbGsuZ3JheShgICBCYWNrdXA6ICR7cmVzdWx0LmJhY2t1cFBhdGh9YCkpO1xuICB9XG59XG5cbi8qKlxuICogRGlzcGxheSBzdGF0aXN0aWNzIHN1bW1hcnlcbiAqL1xuZnVuY3Rpb24gZGlzcGxheVN0YXRzU3VtbWFyeShyZXN1bHRzOiBGb3JtYXR0ZXJSZXN1bHRbXSwgZHJ5UnVuOiBib29sZWFuKTogdm9pZCB7XG4gIGNvbnNvbGUubG9nKCdcXG4nICsgY2hhbGsuYm9sZCgnU3VtbWFyeTonKSk7XG4gIGNvbnN0IHRvdGFsSXNzdWVzID0gcmVzdWx0cy5yZWR1Y2UoKHN1bSwgcikgPT4gc3VtICsgci5pc3N1ZXMubGVuZ3RoLCAwKTtcbiAgY29uc3QgdG90YWxGaXhlcyA9IHJlc3VsdHMucmVkdWNlKChzdW0sIHIpID0+IHN1bSArIHIuZml4ZWQubGVuZ3RoLCAwKTtcblxuICBjb25zb2xlLmxvZyhgICBUb3RhbCBpc3N1ZXMgZm91bmQ6ICR7dG90YWxJc3N1ZXN9YCk7XG4gIGNvbnNvbGUubG9nKGAgIFRvdGFsIGZpeGVzIGFwcGxpZWQ6ICR7dG90YWxGaXhlc31gKTtcblxuICBpZiAoZHJ5UnVuKSB7XG4gICAgY29uc29sZS5sb2coY2hhbGsueWVsbG93KCdcXG4oRHJ5IHJ1biAtIG5vIGNoYW5nZXMgd2VyZSBtYWRlKScpKTtcbiAgfVxufVxuXG4vLyBQYXJzZSBjb21tYW5kIGxpbmUgYXJndW1lbnRzXG5wcm9ncmFtLnBhcnNlKHByb2Nlc3MuYXJndik7Il19