@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.
181 lines • 24.9 kB
JavaScript
/**
* Version management and comparison utilities
*/
import * as fs from 'fs/promises';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { logger } from '../utils/logger.js';
import { InstallationDetector } from '../utils/installation.js';
export class VersionManager {
/**
* Get current version from package.json or embedded version
*/
async getCurrentVersion() {
// First, try to import the generated version file
try {
const { PACKAGE_VERSION } = await import('../generated/version.js');
if (PACKAGE_VERSION) {
logger.debug(`[VersionManager] Using embedded version: ${PACKAGE_VERSION}`);
return PACKAGE_VERSION;
}
}
catch (error) {
logger.debug('[VersionManager] No embedded version found, will search for package.json');
}
// Determine installation type
const installationType = InstallationDetector.getInstallationType();
// For npm installations, look relative to the module location
if (installationType === 'npm') {
const npmPath = InstallationDetector.getNpmGlobalPath();
if (npmPath) {
const packageJsonPath = path.join(npmPath, 'package.json');
try {
const packageContent = await fs.readFile(packageJsonPath, 'utf-8');
const packageData = JSON.parse(packageContent);
return packageData.version;
}
catch (error) {
logger.error('[VersionManager] Error reading package.json from npm path:', error);
}
}
}
// For git installations, search from current file location
if (installationType === 'git') {
const currentFileUrl = import.meta.url;
const currentFilePath = fileURLToPath(currentFileUrl);
let currentDir = path.dirname(currentFilePath);
// Search upward for package.json
for (let i = 0; i < 5; i++) {
const candidatePath = path.join(currentDir, 'package.json');
try {
await fs.access(candidatePath);
const packageContent = await fs.readFile(candidatePath, 'utf-8');
const packageData = JSON.parse(packageContent);
return packageData.version;
}
catch {
// File doesn't exist, try parent directory
const parentDir = path.dirname(currentDir);
if (parentDir === currentDir) {
break;
}
currentDir = parentDir;
}
}
}
// Last resort: try process.cwd() (original behavior)
let currentDir = process.cwd();
for (let i = 0; i < 5; i++) {
const candidatePath = path.join(currentDir, 'package.json');
try {
await fs.access(candidatePath);
const packageContent = await fs.readFile(candidatePath, 'utf-8');
const packageData = JSON.parse(packageContent);
return packageData.version;
}
catch {
const parentDir = path.dirname(currentDir);
if (parentDir === currentDir) {
break;
}
currentDir = parentDir;
}
}
throw new Error('Could not determine version. Please ensure you have a valid installation.');
}
/**
* Enhanced semantic version comparison supporting pre-release versions
* Returns: -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2
*/
compareVersions(version1, version2) {
// Normalize versions by removing 'v' prefix
const v1 = version1.replace(/^v/, '');
const v2 = version2.replace(/^v/, '');
// Split version and pre-release parts
const [v1main, v1pre] = v1.split('-');
const [v2main, v2pre] = v2.split('-');
// Compare main version parts (x.y.z)
const v1parts = v1main.split('.').map(part => parseInt(part) || 0);
const v2parts = v2main.split('.').map(part => parseInt(part) || 0);
const maxLength = Math.max(v1parts.length, v2parts.length);
for (let i = 0; i < maxLength; i++) {
const v1part = v1parts[i] || 0;
const v2part = v2parts[i] || 0;
if (v1part < v2part)
return -1;
if (v1part > v2part)
return 1;
}
// If main versions are equal, compare pre-release versions
// Version without pre-release is greater than version with pre-release
if (!v1pre && v2pre)
return 1; // 1.0.0 > 1.0.0-beta
if (v1pre && !v2pre)
return -1; // 1.0.0-beta < 1.0.0
if (!v1pre && !v2pre)
return 0; // 1.0.0 == 1.0.0
// Both have pre-release, compare lexicographically
return v1pre.localeCompare(v2pre);
}
/**
* Parse version from dependency output
*/
parseVersionFromOutput(output, tool) {
// Git version output: "git version 2.39.2"
// npm version output: "8.19.2" or JSON with version info
if (tool === 'git') {
const match = output.match(/git version (\d+\.\d+\.\d+)/);
return match ? match[1] : null;
}
else if (tool === 'npm') {
// npm might return just the version number or JSON
const cleanOutput = output.trim();
if (cleanOutput.match(/^\d+\.\d+\.\d+/)) {
return cleanOutput.split('\n')[0]; // First line if multiple lines
}
// Try to parse as JSON if it looks like JSON
try {
const parsed = JSON.parse(cleanOutput);
return parsed.npm || parsed.version || null;
}
catch {
// If not JSON, try to extract version pattern
const match = cleanOutput.match(/(\d+\.\d+\.\d+)/);
return match ? match[1] : null;
}
}
return null;
}
/**
* Validate that a dependency version meets requirements
*/
validateDependencyVersion(actualVersion, requirements, toolName) {
const minComparison = this.compareVersions(actualVersion, requirements.minimum);
const maxComparison = this.compareVersions(actualVersion, requirements.maximum);
// Check if version is below minimum
if (minComparison < 0) {
return {
valid: false,
error: `${toolName} version ${actualVersion} is below minimum required version ${requirements.minimum}. Please upgrade ${toolName}.`
};
}
// Check if version is above maximum tested
if (maxComparison > 0) {
return {
valid: true,
warning: `${toolName} version ${actualVersion} is above maximum tested version ${requirements.maximum}. Some features may not work as expected.`
};
}
// Check if not at recommended version
const recComparison = this.compareVersions(actualVersion, requirements.recommended);
if (recComparison !== 0) {
return {
valid: true,
warning: `${toolName} version ${actualVersion} works but ${requirements.recommended} is recommended for optimal stability.`
};
}
// Version is perfect
return { valid: true };
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiVmVyc2lvbk1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXBkYXRlL1ZlcnNpb25NYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsT0FBTyxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUNwQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDNUMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFFaEUsTUFBTSxPQUFPLGNBQWM7SUFDekI7O09BRUc7SUFDSCxLQUFLLENBQUMsaUJBQWlCO1FBQ3JCLGtEQUFrRDtRQUNsRCxJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsZUFBZSxFQUFFLEdBQUcsTUFBTSxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQztZQUNwRSxJQUFJLGVBQWUsRUFBRSxDQUFDO2dCQUNwQixNQUFNLENBQUMsS0FBSyxDQUFDLDRDQUE0QyxlQUFlLEVBQUUsQ0FBQyxDQUFDO2dCQUM1RSxPQUFPLGVBQWUsQ0FBQztZQUN6QixDQUFDO1FBQ0gsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLDBFQUEwRSxDQUFDLENBQUM7UUFDM0YsQ0FBQztRQUVELDhCQUE4QjtRQUM5QixNQUFNLGdCQUFnQixHQUFHLG9CQUFvQixDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFcEUsOERBQThEO1FBQzlELElBQUksZ0JBQWdCLEtBQUssS0FBSyxFQUFFLENBQUM7WUFDL0IsTUFBTSxPQUFPLEdBQUcsb0JBQW9CLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUN4RCxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLE1BQU0sZUFBZSxHQUFHLElB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QztRQUNKLENBQUM7UUFFRCxzQ0FBc0M7UUFDdEMsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxhQUFhLEVBQUUsWUFBWSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ3BGLElBQUksYUFBYSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3hCLE9BQU87Z0JBQ0wsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsT0FBTyxFQUFFLEdBQUcsUUFBUSxZQUFZLGFBQWEsY0FBYyxZQUFZLENBQUMsV0FBVyx3Q0FBd0M7YUFDNUgsQ0FBQztRQUNKLENBQUM7UUFFRCxxQkFBcUI7UUFDckIsT0FBTyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUN6QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFZlcnNpb24gbWFuYWdlbWVudCBhbmQgY29tcGFyaXNvbiB1dGlsaXRpZXNcbiAqL1xuXG5pbXBvcnQgKiBhcyBmcyBmcm9tICdmcy9wcm9taXNlcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ3VybCc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgSW5zdGFsbGF0aW9uRGV0ZWN0b3IgfSBmcm9tICcuLi91dGlscy9pbnN0YWxsYXRpb24uanMnO1xuXG5leHBvcnQgY2xhc3MgVmVyc2lvbk1hbmFnZXIge1xuICAvKipcbiAgICogR2V0IGN1cnJlbnQgdmVyc2lvbiBmcm9tIHBhY2thZ2UuanNvbiBvciBlbWJlZGRlZCB2ZXJzaW9uXG4gICAqL1xuICBhc3luYyBnZXRDdXJyZW50VmVyc2lvbigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIC8vIEZpcnN0LCB0cnkgdG8gaW1wb3J0IHRoZSBnZW5lcmF0ZWQgdmVyc2lvbiBmaWxlXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHsgUEFDS0FHRV9WRVJTSU9OIH0gPSBhd2FpdCBpbXBvcnQoJy4uL2dlbmVyYXRlZC92ZXJzaW9uLmpzJyk7XG4gICAgICBpZiAoUEFDS0FHRV9WRVJTSU9OKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgW1ZlcnNpb25NYW5hZ2VyXSBVc2luZyBlbWJlZGRlZCB2ZXJzaW9uOiAke1BBQ0tBR0VfVkVSU0lPTn1gKTtcbiAgICAgICAgcmV0dXJuIFBBQ0tBR0VfVkVSU0lPTjtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdbVmVyc2lvbk1hbmFnZXJdIE5vIGVtYmVkZGVkIHZlcnNpb24gZm91bmQsIHdpbGwgc2VhcmNoIGZvciBwYWNrYWdlLmpzb24nKTtcbiAgICB9XG4gICAgXG4gICAgLy8gRGV0ZXJtaW5lIGluc3RhbGxhdGlvbiB0eXBlXG4gICAgY29uc3QgaW5zdGFsbGF0aW9uVHlwZSA9IEluc3RhbGxhdGlvbkRldGVjdG9yLmdldEluc3RhbGxhdGlvblR5cGUoKTtcbiAgICBcbiAgICAvLyBGb3IgbnBtIGluc3RhbGxhdGlvbnMsIGxvb2sgcmVsYXRpdmUgdG8gdGhlIG1vZHVsZSBsb2NhdGlvblxuICAgIGlmIChpbnN0YWxsYXRpb25UeXBlID09PSAnbnBtJykge1xuICAgICAgY29uc3QgbnBtUGF0aCA9IEluc3RhbGxhdGlvbkRldGVjdG9yLmdldE5wbUdsb2JhbFBhdGgoKTtcbiAgICAgIGlmIChucG1QYXRoKSB7XG4gICAgICAgIGNvbnN0IHBhY2thZ2VKc29uUGF0aCA9IHBhdGguam9pbihucG1QYXRoLCAncGFja2FnZS5qc29uJyk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgcGFja2FnZUNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShwYWNrYWdlSnNvblBhdGgsICd1dGYtOCcpO1xuICAgICAgICAgIGNvbnN0IHBhY2thZ2VEYXRhID0gSlNPTi5wYXJzZShwYWNrYWdlQ29udGVudCk7XG4gICAgICAgICAgcmV0dXJuIHBhY2thZ2VEYXRhLnZlcnNpb247XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgbG9nZ2VyLmVycm9yKCdbVmVyc2lvbk1hbmFnZXJdIEVycm9yIHJlYWRpbmcgcGFja2FnZS5qc29uIGZyb20gbnBtIHBhdGg6JywgZXJyb3IpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIC8vIEZvciBnaXQgaW5zdGFsbGF0aW9ucywgc2VhcmNoIGZyb20gY3VycmVudCBmaWxlIGxvY2F0aW9uXG4gICAgaWYgKGluc3RhbGxhdGlvblR5cGUgPT09ICdnaXQnKSB7XG4gICAgICBjb25zdCBjdXJyZW50RmlsZVVybCA9IGltcG9ydC5tZXRhLnVybDtcbiAgICAgIGNvbnN0IGN1cnJlbnRGaWxlUGF0aCA9IGZpbGVVUkxUb1BhdGgoY3VycmVudEZpbGVVcmwpO1xuICAgICAgbGV0IGN1cnJlbnREaXIgPSBwYXRoLmRpcm5hbWUoY3VycmVudEZpbGVQYXRoKTtcbiAgICAgIFxuICAgICAgLy8gU2VhcmNoIHVwd2FyZCBmb3IgcGFja2FnZS5qc29uXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDU7IGkrKykge1xuICAgICAgICBjb25zdCBjYW5kaWRhdGVQYXRoID0gcGF0aC5qb2luKGN1cnJlbnREaXIsICdwYWNrYWdlLmpzb24nKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBmcy5hY2Nlc3MoY2FuZGlkYXRlUGF0aCk7XG4gICAgICAgICAgY29uc3QgcGFja2FnZUNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShjYW5kaWRhdGVQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgICBjb25zdCBwYWNrYWdlRGF0YSA9IEpTT04ucGFyc2UocGFja2FnZUNvbnRlbnQpO1xuICAgICAgICAgIHJldHVybiBwYWNrYWdlRGF0YS52ZXJzaW9uO1xuICAgICAgICB9IGNhdGNoIHtcbiAgICAgICAgICAvLyBGaWxlIGRvZXNuJ3QgZXhpc3QsIHRyeSBwYXJlbnQgZGlyZWN0b3J5XG4gICAgICAgICAgY29uc3QgcGFyZW50RGlyID0gcGF0aC5kaXJuYW1lKGN1cnJlbnREaXIpO1xuICAgICAgICAgIGlmIChwYXJlbnREaXIgPT09IGN1cnJlbnREaXIpIHtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjdXJyZW50RGlyID0gcGFyZW50RGlyO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIC8vIExhc3QgcmVzb3J0OiB0cnkgcHJvY2Vzcy5jd2QoKSAob3JpZ2luYWwgYmVoYXZpb3IpXG4gICAgbGV0IGN1cnJlbnREaXIgPSBwcm9jZXNzLmN3ZCgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNTsgaSsrKSB7XG4gICAgICBjb25zdCBjYW5kaWRhdGVQYXRoID0gcGF0aC5qb2luKGN1cnJlbnREaXIsICdwYWNrYWdlLmpzb24nKTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IGZzLmFjY2VzcyhjYW5kaWRhdGVQYXRoKTtcbiAgICAgICAgY29uc3QgcGFja2FnZUNvbnRlbnQgPSBhd2FpdCBmcy5yZWFkRmlsZShjYW5kaWRhdGVQYXRoLCAndXRmLTgnKTtcbiAgICAgICAgY29uc3QgcGFja2FnZURhdGEgPSBKU09OLnBhcnNlKHBhY2thZ2VDb250ZW50KTtcbiAgICAgICAgcmV0dXJuIHBhY2thZ2VEYXRhLnZlcnNpb247XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgY29uc3QgcGFyZW50RGlyID0gcGF0aC5kaXJuYW1lKGN1cnJlbnREaXIpO1xuICAgICAgICBpZiAocGFyZW50RGlyID09PSBjdXJyZW50RGlyKSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudERpciA9IHBhcmVudERpcjtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb3VsZCBub3QgZGV0ZXJtaW5lIHZlcnNpb24uIFBsZWFzZSBlbnN1cmUgeW91IGhhdmUgYSB2YWxpZCBpbnN0YWxsYXRpb24uJyk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBFbmhhbmNlZCBzZW1hbnRpYyB2ZXJzaW9uIGNvbXBhcmlzb24gc3VwcG9ydGluZyBwcmUtcmVsZWFzZSB2ZXJzaW9uc1xuICAgKiBSZXR1cm5zOiAtMSBpZiB2MSA8IHYyLCAwIGlmIHYxID09IHYyLCAxIGlmIHYxID4gdjJcbiAgICovXG4gIGNvbXBhcmVWZXJzaW9ucyh2ZXJzaW9uMTogc3RyaW5nLCB2ZXJzaW9uMjogc3RyaW5nKTogbnVtYmVyIHtcbiAgICAvLyBOb3JtYWxpemUgdmVyc2lvbnMgYnkgcmVtb3ZpbmcgJ3YnIHByZWZpeFxuICAgIGNvbnN0IHYxID0gdmVyc2lvbjEucmVwbGFjZSgvXnYvLCAnJyk7XG4gICAgY29uc3QgdjIgPSB2ZXJzaW9uMi5yZXBsYWNlKC9edi8sICcnKTtcbiAgICBcbiAgICAvLyBTcGxpdCB2ZXJzaW9uIGFuZCBwcmUtcmVsZWFzZSBwYXJ0c1xuICAgIGNvbnN0IFt2MW1haW4sIHYxcHJlXSA9IHYxLnNwbGl0KCctJyk7XG4gICAgY29uc3QgW3YybWFpbiwgdjJwcmVdID0gdjIuc3BsaXQoJy0nKTtcbiAgICBcbiAgICAvLyBDb21wYXJlIG1haW4gdmVyc2lvbiBwYXJ0cyAoeC55LnopXG4gICAgY29uc3QgdjFwYXJ0cyA9IHYxbWFpbi5zcGxpdCgnLicpLm1hcChwYXJ0ID0+IHBhcnNlSW50KHBhcnQpIHx8IDApO1xuICAgIGNvbnN0IHYycGFydHMgPSB2Mm1haW4uc3BsaXQoJy4nKS5tYXAocGFydCA9PiBwYXJzZUludChwYXJ0KSB8fCAwKTtcbiAgICBcbiAgICBjb25zdCBtYXhMZW5ndGggPSBNYXRoLm1heCh2MXBhcnRzLmxlbmd0aCwgdjJwYXJ0cy5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWF4TGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHYxcGFydCA9IHYxcGFydHNbaV0gfHwgMDtcbiAgICAgIGNvbnN0IHYycGFydCA9IHYycGFydHNbaV0gfHwgMDtcbiAgICAgIFxuICAgICAgaWYgKHYxcGFydCA8IHYycGFydCkgcmV0dXJuIC0xO1xuICAgICAgaWYgKHYxcGFydCA+IHYycGFydCkgcmV0dXJuIDE7XG4gICAgfVxuICAgIFxuICAgIC8vIElmIG1haW4gdmVyc2lvbnMgYXJlIGVxdWFsLCBjb21wYXJlIHByZS1yZWxlYXNlIHZlcnNpb25zXG4gICAgLy8gVmVyc2lvbiB3aXRob3V0IHByZS1yZWxlYXNlIGlzIGdyZWF0ZXIgdGhhbiB2ZXJzaW9uIHdpdGggcHJlLXJlbGVhc2VcbiAgICBpZiAoIXYxcHJlICYmIHYycHJlKSByZXR1cm4gMTsgICAvLyAxLjAuMCA+IDEuMC4wLWJldGFcbiAgICBpZiAodjFwcmUgJiYgIXYycHJlKSByZXR1cm4gLTE7ICAvLyAxLjAuMC1iZXRhIDwgMS4wLjBcbiAgICBpZiAoIXYxcHJlICYmICF2MnByZSkgcmV0dXJuIDA7ICAvLyAxLjAuMCA9PSAxLjAuMFxuICAgIFxuICAgIC8vIEJvdGggaGF2ZSBwcmUtcmVsZWFzZSwgY29tcGFyZSBsZXhpY29ncmFwaGljYWxseVxuICAgIHJldHVybiB2MXByZS5sb2NhbGVDb21wYXJlKHYycHJlKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIFBhcnNlIHZlcnNpb24gZnJvbSBkZXBlbmRlbmN5IG91dHB1dFxuICAgKi9cbiAgcGFyc2VWZXJzaW9uRnJvbU91dHB1dChvdXRwdXQ6IHN0cmluZywgdG9vbDogc3RyaW5nKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgLy8gR2l0IHZlcnNpb24gb3V0cHV0OiBcImdpdCB2ZXJzaW9uIDIuMzkuMlwiXG4gICAgLy8gbnBtIHZlcnNpb24gb3V0cHV0OiBcIjguMTkuMlwiIG9yIEpTT04gd2l0aCB2ZXJzaW9uIGluZm9cbiAgICBcbiAgICBpZiAodG9vbCA9PT0gJ2dpdCcpIHtcbiAgICAgIGNvbnN0IG1hdGNoID0gb3V0cHV0Lm1hdGNoKC9naXQgdmVyc2lvbiAoXFxkK1xcLlxcZCtcXC5cXGQrKS8pO1xuICAgICAgcmV0dXJuIG1hdGNoID8gbWF0Y2hbMV0gOiBudWxsO1xuICAgIH0gZWxzZSBpZiAodG9vbCA9PT0gJ25wbScpIHtcbiAgICAgIC8vIG5wbSBtaWdodCByZXR1cm4ganVzdCB0aGUgdmVyc2lvbiBudW1iZXIgb3IgSlNPTlxuICAgICAgY29uc3QgY2xlYW5PdXRwdXQgPSBvdXRwdXQudHJpbSgpO1xuICAgICAgaWYgKGNsZWFuT3V0cHV0Lm1hdGNoKC9eXFxkK1xcLlxcZCtcXC5cXGQrLykpIHtcbiAgICAgICAgcmV0dXJuIGNsZWFuT3V0cHV0LnNwbGl0KCdcXG4nKVswXTsgLy8gRmlyc3QgbGluZSBpZiBtdWx0aXBsZSBsaW5lc1xuICAgICAgfVxuICAgICAgLy8gVHJ5IHRvIHBhcnNlIGFzIEpTT04gaWYgaXQgbG9va3MgbGlrZSBKU09OXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGNsZWFuT3V0cHV0KTtcbiAgICAgICAgcmV0dXJuIHBhcnNlZC5ucG0gfHwgcGFyc2VkLnZlcnNpb24gfHwgbnVsbDtcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICAvLyBJZiBub3QgSlNPTiwgdHJ5IHRvIGV4dHJhY3QgdmVyc2lvbiBwYXR0ZXJuXG4gICAgICAgIGNvbnN0IG1hdGNoID0gY2xlYW5PdXRwdXQubWF0Y2goLyhcXGQrXFwuXFxkK1xcLlxcZCspLyk7XG4gICAgICAgIHJldHVybiBtYXRjaCA/IG1hdGNoWzFdIDogbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGF0IGEgZGVwZW5kZW5jeSB2ZXJzaW9uIG1lZXRzIHJlcXVpcmVtZW50c1xuICAgKi9cbiAgdmFsaWRhdGVEZXBlbmRlbmN5VmVyc2lvbihcbiAgICBhY3R1YWxWZXJzaW9uOiBzdHJpbmcsIFxuICAgIHJlcXVpcmVtZW50czogeyBtaW5pbXVtOiBzdHJpbmc7IG1heGltdW06IHN0cmluZzsgcmVjb21tZW5kZWQ6IHN0cmluZyB9LFxuICAgIHRvb2xOYW1lOiBzdHJpbmdcbiAgKTogeyB2YWxpZDogYm9vbGVhbjsgd2FybmluZz86IHN0cmluZzsgZXJyb3I/OiBzdHJpbmcgfSB7XG4gICAgY29uc3QgbWluQ29tcGFyaXNvbiA9IHRoaXMuY29tcGFyZVZlcnNpb25zKGFjdHVhbFZlcnNpb24sIHJlcXVpcmVtZW50cy5taW5pbXVtKTtcbiAgICBjb25zdCBtYXhDb21wYXJpc29uID0gdGhpcy5jb21wYXJlVmVyc2lvbnMoYWN0dWFsVmVyc2lvbiwgcmVxdWlyZW1lbnRzLm1heGltdW0pO1xuICAgIFxuICAgIC8vIENoZWNrIGlmIHZlcnNpb24gaXMgYmVsb3cgbWluaW11bVxuICAgIGlmIChtaW5Db21wYXJpc29uIDwgMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsaWQ6IGZhbHNlLFxuICAgICAgICBlcnJvcjogYCR7dG9vbE5hbWV9IHZlcnNpb24gJHthY3R1YWxWZXJzaW9ufSBpcyBiZWxvdyBtaW5pbXVtIHJlcXVpcmVkIHZlcnNpb24gJHtyZXF1aXJlbWVudHMubWluaW11bX0uIFBsZWFzZSB1cGdyYWRlICR7dG9vbE5hbWV9LmBcbiAgICAgIH07XG4gICAgfVxuICAgIFxuICAgIC8vIENoZWNrIGlmIHZlcnNpb24gaXMgYWJvdmUgbWF4aW11bSB0ZXN0ZWRcbiAgICBpZiAobWF4Q29tcGFyaXNvbiA+IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbGlkOiB0cnVlLFxuICAgICAgICB3YXJuaW5nOiBgJHt0b29sTmFtZX0gdmVyc2lvbiAke2FjdHVhbFZlcnNpb259IGlzIGFib3ZlIG1heGltdW0gdGVzdGVkIHZlcnNpb24gJHtyZXF1aXJlbWVudHMubWF4aW11bX0uIFNvbWUgZmVhdHVyZXMgbWF5IG5vdCB3b3JrIGFzIGV4cGVjdGVkLmBcbiAgICAgIH07XG4gICAgfVxuICAgIFxuICAgIC8vIENoZWNrIGlmIG5vdCBhdCByZWNvbW1lbmRlZCB2ZXJzaW9uXG4gICAgY29uc3QgcmVjQ29tcGFyaXNvbiA9IHRoaXMuY29tcGFyZVZlcnNpb25zKGFjdHVhbFZlcnNpb24sIHJlcXVpcmVtZW50cy5yZWNvbW1lbmRlZCk7XG4gICAgaWYgKHJlY0NvbXBhcmlzb24gIT09IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbGlkOiB0cnVlLFxuICAgICAgICB3YXJuaW5nOiBgJHt0b29sTmFtZX0gdmVyc2lvbiAke2FjdHVhbFZlcnNpb259IHdvcmtzIGJ1dCAke3JlcXVpcmVtZW50cy5yZWNvbW1lbmRlZH0gaXMgcmVjb21tZW5kZWQgZm9yIG9wdGltYWwgc3RhYmlsaXR5LmBcbiAgICAgIH07XG4gICAgfVxuICAgIFxuICAgIC8vIFZlcnNpb24gaXMgcGVyZmVjdFxuICAgIHJldHVybiB7IHZhbGlkOiB0cnVlIH07XG4gIH1cbn0iXX0=