@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.
236 lines • 30.9 kB
JavaScript
/**
* Portfolio sync handler for the sync_portfolio MCP tool
* Manages bi-directional synchronization between local portfolio and GitHub
*
* Uses dependency injection for all services:
* - PortfolioSyncManager for sync operations
* - ConfigManager for configuration
* - PersonaIndicatorService for persona indicator formatting
*/
import { SecureErrorHandler } from '../security/errorHandler.js';
export class SyncHandler {
syncManager;
configManager;
indicatorService;
constructor(syncManager, configManager, indicatorService) {
this.syncManager = syncManager;
this.configManager = configManager;
this.indicatorService = indicatorService;
}
/**
* Handle portfolio sync operations
*/
async handleSyncOperation(options) {
const indicator = this.indicatorService.getPersonaIndicator();
try {
await this.configManager.initialize();
// Check if sync is enabled (allow list-remote and compare even when disabled)
const syncEnabled = this.configManager.getSetting('sync.enabled');
const readOnlyOperations = ['list-remote', 'compare'];
if (!syncEnabled && !readOnlyOperations.includes(options.operation)) {
return {
content: [{
type: "text",
text: `${indicator}⚠️ **Sync is Disabled**\n\n` +
`Portfolio sync is currently disabled for privacy.\n\n` +
`To enable sync:\n` +
`\`dollhouse_config action: "set", setting: "sync.enabled", value: true\`\n\n` +
`You can still use \`list-remote\` and \`compare\` to view differences.`
}]
};
}
// Map our operation to PortfolioSyncManager's SyncOperation format
const syncOp = {
operation: this.mapOperation(options.operation),
element_name: options.element_name,
element_type: options.element_type || options.filter?.type, // Use filter.type if element_type not provided
bulk: options.operation.includes('bulk'),
show_diff: options.operation === 'compare',
force: options.options?.force,
confirm: options.options?.force || options.options?.dry_run === false // force implies confirm, dry_run=false means confirm
};
// Call the unified handleSyncOperation method
const result = await this.syncManager.handleSyncOperation(syncOp);
// Format the result based on the operation type
return this.formatResult(result, options, indicator);
}
catch (error) {
const sanitizedError = SecureErrorHandler.sanitizeError(error);
return {
content: [{
type: "text",
text: `${indicator}❌ Sync operation failed: ${sanitizedError.message}`
}]
};
}
}
mapOperation(operation) {
switch (operation) {
case 'list-remote':
return 'list-remote';
case 'download':
case 'bulk-download':
return 'download';
case 'upload':
case 'bulk-upload':
return 'upload';
case 'compare':
return 'compare';
default:
return 'list-remote';
}
}
formatResult(result, options, indicator) {
if (!result.success) {
return {
content: [{
type: "text",
text: `${indicator}❌ ${result.message}`
}]
};
}
switch (options.operation) {
case 'list-remote':
return this.formatListResult(result, indicator);
case 'download':
case 'bulk-download':
return this.formatDownloadResult(result, options, indicator);
case 'upload':
case 'bulk-upload':
return this.formatUploadResult(result, options, indicator);
case 'compare':
return this.formatCompareResult(result, options, indicator);
default:
return {
content: [{
type: "text",
text: `${indicator}✅ ${result.message}`
}]
};
}
}
formatListResult(result, indicator) {
if (!result.elements || result.elements.length === 0) {
return {
content: [{
type: "text",
text: `${indicator}📋 **GitHub Portfolio is Empty**\n\n` +
`No elements found in your GitHub portfolio.\n\n` +
`Upload elements using:\n` +
`\`sync_portfolio operation: "upload", element_name: "name", element_type: "type"\``
}]
};
}
let text = `${indicator}📋 **GitHub Portfolio Contents**\n\n`;
text += `Found ${result.elements.length} elements:\n\n`;
// Group by type
const byType = {};
for (const element of result.elements) {
if (!byType[element.type]) {
byType[element.type] = [];
}
byType[element.type].push(element);
}
for (const [type, elements] of Object.entries(byType)) {
text += `**${type}** (${elements.length}):\n`;
for (const element of elements) {
text += ` • ${element.name}`;
if (element.remoteVersion) {
text += ` v${element.remoteVersion}`;
}
if (element.status) {
text += ` (${element.status})`;
}
text += '\n';
}
text += '\n';
}
return {
content: [{
type: "text",
text
}]
};
}
formatDownloadResult(result, options, indicator) {
if (options.operation === 'bulk-download') {
const elements = result.elements || [];
const downloaded = elements.filter(e => e.action === 'download').length;
const skipped = elements.filter(e => e.action === 'skip').length;
return {
content: [{
type: "text",
text: `${indicator}✅ **Bulk Download Complete**\n\n` +
`Downloaded: ${downloaded} elements\n` +
`Skipped: ${skipped} elements\n\n` +
result.message
}]
};
}
return {
content: [{
type: "text",
text: `${indicator}✅ **Element Downloaded**\n\n` +
`Element: ${options.element_name} (${options.element_type})\n\n` +
result.message
}]
};
}
formatUploadResult(result, options, indicator) {
if (options.operation === 'bulk-upload') {
const elements = result.elements || [];
const uploaded = elements.filter(e => e.action === 'upload').length;
const skipped = elements.filter(e => e.action === 'skip').length;
return {
content: [{
type: "text",
text: `${indicator}✅ **Bulk Upload Complete**\n\n` +
`Uploaded: ${uploaded} elements\n` +
`Skipped: ${skipped} elements\n\n` +
result.message
}]
};
}
return {
content: [{
type: "text",
text: `${indicator}✅ **Element Uploaded**\n\n` +
`Element: ${options.element_name} (${options.element_type})\n\n` +
result.message
}]
};
}
formatCompareResult(result, options, indicator) {
let text = `${indicator}🔍 **Version Comparison**\n\n`;
text += `Element: ${options.element_name} (${options.element_type})\n\n`;
if (result.data) {
// If we have detailed comparison data
const data = result.data;
if (data.local) {
text += `**Local Version**: ${data.local.version}\n`;
text += ` Modified: ${new Date(data.local.timestamp).toLocaleString()}\n`;
}
else {
text += `**Local Version**: Not found\n`;
}
if (data.remote) {
text += `\n**Remote Version**: ${data.remote.version}\n`;
text += ` Modified: ${new Date(data.remote.timestamp).toLocaleString()}\n`;
}
else {
text += `\n**Remote Version**: Not found\n`;
}
if (data.diff) {
text += `\n**Differences**:\n${data.diff}`;
}
}
text += `\n\n${result.message}`;
return {
content: [{
type: "text",
text
}]
};
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU3luY0hhbmRsZXJWMi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9oYW5kbGVycy9TeW5jSGFuZGxlclYyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBSUgsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFvQmpFLE1BQU0sT0FBTyxXQUFXO0lBRUg7SUFDQTtJQUNBO0lBSG5CLFlBQ21CLFdBQWlDLEVBQ2pDLGFBQTRCLEVBQzVCLGdCQUF5QztRQUZ6QyxnQkFBVyxHQUFYLFdBQVcsQ0FBc0I7UUFDakMsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFDNUIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUF5QjtJQUN6RCxDQUFDO0lBRUo7O09BRUc7SUFDSCxLQUFLLENBQUMsbUJBQW1CLENBQUMsT0FBNkI7UUFDckQsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFFOUQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBRXRDLDhFQUE4RTtZQUM5RSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUNsRSxNQUFNLGtCQUFrQixHQUFHLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3RELElBQUksQ0FBQyxXQUFXLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7Z0JBQ3BFLE9BQU87b0JBQ0wsT0FBTyxFQUFFLENBQUM7NEJBQ1IsSUFBSSxFQUFFLE1BQU07NEJBQ1osSUFBSSxFQUFFLEdBQUcsU0FBUyw2QkFBNkI7Z0NBQ3pDLHVEQUF1RDtnQ0FDdkQsbUJBQW1CO2dDQUNuQiw4RUFBOEU7Z0NBQzlFLHdFQUF3RTt5QkFDL0UsQ0FB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SUFBSSxFQUFFLENBQUM7Z0JBQ2QsSUFBSSxJQUFJLHVCQUF1QixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDN0MsQ0FBQztRQUNILENBQUM7UUFFRCxJQUFJLElBQUksT0FBTyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFaEMsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDO29CQUNSLElBQUksRUFBRSxNQUFNO29CQUNaLElBQUk7aUJBQ0wsQ0FBQztTQUNILENBQUM7SUFDSixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBvcnRmb2xpbyBzeW5jIGhhbmRsZXIgZm9yIHRoZSBzeW5jX3BvcnRmb2xpbyBNQ1AgdG9vbFxuICogTWFuYWdlcyBiaS1kaXJlY3Rpb25hbCBzeW5jaHJvbml6YXRpb24gYmV0d2VlbiBsb2NhbCBwb3J0Zm9saW8gYW5kIEdpdEh1YlxuICpcbiAqIFVzZXMgZGVwZW5kZW5jeSBpbmplY3Rpb24gZm9yIGFsbCBzZXJ2aWNlczpcbiAqIC0gUG9ydGZvbGlvU3luY01hbmFnZXIgZm9yIHN5bmMgb3BlcmF0aW9uc1xuICogLSBDb25maWdNYW5hZ2VyIGZvciBjb25maWd1cmF0aW9uXG4gKiAtIFBlcnNvbmFJbmRpY2F0b3JTZXJ2aWNlIGZvciBwZXJzb25hIGluZGljYXRvciBmb3JtYXR0aW5nXG4gKi9cblxuaW1wb3J0IHsgUG9ydGZvbGlvU3luY01hbmFnZXIsIFN5bmNPcGVyYXRpb24sIFN5bmNSZXN1bHQgfSBmcm9tICcuLi9wb3J0Zm9saW8vUG9ydGZvbGlvU3luY01hbmFnZXIuanMnO1xuaW1wb3J0IHsgQ29uZmlnTWFuYWdlciB9IGZyb20gJy4uL2NvbmZpZy9Db25maWdNYW5hZ2VyLmpzJztcbmltcG9ydCB7IFNlY3VyZUVycm9ySGFuZGxlciB9IGZyb20gJy4uL3NlY3VyaXR5L2Vycm9ySGFuZGxlci5qcyc7XG5pbXBvcnQgeyBFbGVtZW50VHlwZSB9IGZyb20gJy4uL3BvcnRmb2xpby9Qb3J0Zm9saW9NYW5hZ2VyLmpzJztcbmltcG9ydCB7IFBlcnNvbmFJbmRpY2F0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvUGVyc29uYUluZGljYXRvclNlcnZpY2UuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN5bmNPcGVyYXRpb25PcHRpb25zIHtcbiAgb3BlcmF0aW9uOiAnbGlzdC1yZW1vdGUnIHwgJ2Rvd25sb2FkJyB8ICd1cGxvYWQnIHwgJ2NvbXBhcmUnIHwgJ2J1bGstZG93bmxvYWQnIHwgJ2J1bGstdXBsb2FkJztcbiAgZWxlbWVudF9uYW1lPzogc3RyaW5nO1xuICBlbGVtZW50X3R5cGU/OiBFbGVtZW50VHlwZTtcbiAgZmlsdGVyPzoge1xuICAgIHR5cGU/OiBFbGVtZW50VHlwZTtcbiAgICBhdXRob3I/OiBzdHJpbmc7XG4gICAgdXBkYXRlZF9hZnRlcj86IHN0cmluZztcbiAgfTtcbiAgb3B0aW9ucz86IHtcbiAgICBmb3JjZT86IGJvb2xlYW47XG4gICAgZHJ5X3J1bj86IGJvb2xlYW47XG4gICAgaW5jbHVkZV9wcml2YXRlPzogYm9vbGVhbjtcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIFN5bmNIYW5kbGVyIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBzeW5jTWFuYWdlcjogUG9ydGZvbGlvU3luY01hbmFnZXIsXG4gICAgcHJpdmF0ZSByZWFkb25seSBjb25maWdNYW5hZ2VyOiBDb25maWdNYW5hZ2VyLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgaW5kaWNhdG9yU2VydmljZTogUGVyc29uYUluZGljYXRvclNlcnZpY2VcbiAgKSB7fVxuICBcbiAgLyoqXG4gICAqIEhhbmRsZSBwb3J0Zm9saW8gc3luYyBvcGVyYXRpb25zXG4gICAqL1xuICBhc3luYyBoYW5kbGVTeW5jT3BlcmF0aW9uKG9wdGlvbnM6IFN5bmNPcGVyYXRpb25PcHRpb25zKSB7XG4gICAgY29uc3QgaW5kaWNhdG9yID0gdGhpcy5pbmRpY2F0b3JTZXJ2aWNlLmdldFBlcnNvbmFJbmRpY2F0b3IoKTtcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmNvbmZpZ01hbmFnZXIuaW5pdGlhbGl6ZSgpO1xuXG4gICAgICAvLyBDaGVjayBpZiBzeW5jIGlzIGVuYWJsZWQgKGFsbG93IGxpc3QtcmVtb3RlIGFuZCBjb21wYXJlIGV2ZW4gd2hlbiBkaXNhYmxlZClcbiAgICAgIGNvbnN0IHN5bmNFbmFibGVkID0gdGhpcy5jb25maWdNYW5hZ2VyLmdldFNldHRpbmcoJ3N5bmMuZW5hYmxlZCcpO1xuICAgICAgY29uc3QgcmVhZE9ubHlPcGVyYXRpb25zID0gWydsaXN0LXJlbW90ZScsICdjb21wYXJlJ107XG4gICAgICBpZiAoIXN5bmNFbmFibGVkICYmICFyZWFkT25seU9wZXJhdGlvbnMuaW5jbHVkZXMob3B0aW9ucy5vcGVyYXRpb24pKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7aW5kaWNhdG9yfeKaoO+4jyAqKlN5bmMgaXMgRGlzYWJsZWQqKlxcblxcbmAgK1xuICAgICAgICAgICAgICAgICAgYFBvcnRmb2xpbyBzeW5jIGlzIGN1cnJlbnRseSBkaXNhYmxlZCBmb3IgcHJpdmFjeS5cXG5cXG5gICtcbiAgICAgICAgICAgICAgICAgIGBUbyBlbmFibGUgc3luYzpcXG5gICtcbiAgICAgICAgICAgICAgICAgIGBcXGBkb2xsaG91c2VfY29uZmlnIGFjdGlvbjogXCJzZXRcIiwgc2V0dGluZzogXCJzeW5jLmVuYWJsZWRcIiwgdmFsdWU6IHRydWVcXGBcXG5cXG5gICtcbiAgICAgICAgICAgICAgICAgIGBZb3UgY2FuIHN0aWxsIHVzZSBcXGBsaXN0LXJlbW90ZVxcYCBhbmQgXFxgY29tcGFyZVxcYCB0byB2aWV3IGRpZmZlcmVuY2VzLmBcbiAgICAgICAgICB9XVxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBNYXAgb3VyIG9wZXJhdGlvbiB0byBQb3J0Zm9saW9TeW5jTWFuYWdlcidzIFN5bmNPcGVyYXRpb24gZm9ybWF0XG4gICAgICBjb25zdCBzeW5jT3A6IFN5bmNPcGVyYXRpb24gPSB7XG4gICAgICAgIG9wZXJhdGlvbjogdGhpcy5tYXBPcGVyYXRpb24ob3B0aW9ucy5vcGVyYXRpb24pLFxuICAgICAgICBlbGVtZW50X25hbWU6IG9wdGlvbnMuZWxlbWVudF9uYW1lLFxuICAgICAgICBlbGVtZW50X3R5cGU6IG9wdGlvbnMuZWxlbWVudF90eXBlIHx8IG9wdGlvbnMuZmlsdGVyPy50eXBlLCAvLyBVc2UgZmlsdGVyLnR5cGUgaWYgZWxlbWVudF90eXBlIG5vdCBwcm92aWRlZFxuICAgICAgICBidWxrOiBvcHRpb25zLm9wZXJhdGlvbi5pbmNsdWRlcygnYnVsaycpLFxuICAgICAgICBzaG93X2RpZmY6IG9wdGlvbnMub3BlcmF0aW9uID09PSAnY29tcGFyZScsXG4gICAgICAgIGZvcmNlOiBvcHRpb25zLm9wdGlvbnM/LmZvcmNlLFxuICAgICAgICBjb25maXJtOiBvcHRpb25zLm9wdGlvbnM/LmZvcmNlIHx8IG9wdGlvbnMub3B0aW9ucz8uZHJ5X3J1biA9PT0gZmFsc2UgLy8gZm9yY2UgaW1wbGllcyBjb25maXJtLCBkcnlfcnVuPWZhbHNlIG1lYW5zIGNvbmZpcm1cbiAgICAgIH07XG4gICAgICBcbiAgICAgIC8vIENhbGwgdGhlIHVuaWZpZWQgaGFuZGxlU3luY09wZXJhdGlvbiBtZXRob2RcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuc3luY01hbmFnZXIuaGFuZGxlU3luY09wZXJhdGlvbihzeW5jT3ApO1xuICAgICAgXG4gICAgICAvLyBGb3JtYXQgdGhlIHJlc3VsdCBiYXNlZCBvbiB0aGUgb3BlcmF0aW9uIHR5cGVcbiAgICAgIHJldHVybiB0aGlzLmZvcm1hdFJlc3VsdChyZXN1bHQsIG9wdGlvbnMsIGluZGljYXRvcik7XG4gICAgICBcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc3Qgc2FuaXRpemVkRXJyb3IgPSBTZWN1cmVFcnJvckhhbmRsZXIuc2FuaXRpemVFcnJvcihlcnJvcik7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3inYwgU3luYyBvcGVyYXRpb24gZmFpbGVkOiAke3Nhbml0aXplZEVycm9yLm1lc3NhZ2V9YFxuICAgICAgICB9XVxuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgXG4gIHByaXZhdGUgbWFwT3BlcmF0aW9uKG9wZXJhdGlvbjogc3RyaW5nKTogJ2Rvd25sb2FkJyB8ICd1cGxvYWQnIHwgJ2NvbXBhcmUnIHwgJ2xpc3QtcmVtb3RlJyB7XG4gICAgc3dpdGNoIChvcGVyYXRpb24pIHtcbiAgICAgIGNhc2UgJ2xpc3QtcmVtb3RlJzpcbiAgICAgICAgcmV0dXJuICdsaXN0LXJlbW90ZSc7XG4gICAgICBjYXNlICdkb3dubG9hZCc6XG4gICAgICBjYXNlICdidWxrLWRvd25sb2FkJzpcbiAgICAgICAgcmV0dXJuICdkb3dubG9hZCc7XG4gICAgICBjYXNlICd1cGxvYWQnOlxuICAgICAgY2FzZSAnYnVsay11cGxvYWQnOlxuICAgICAgICByZXR1cm4gJ3VwbG9hZCc7XG4gICAgICBjYXNlICdjb21wYXJlJzpcbiAgICAgICAgcmV0dXJuICdjb21wYXJlJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiAnbGlzdC1yZW1vdGUnO1xuICAgIH1cbiAgfVxuICBcbiAgcHJpdmF0ZSBmb3JtYXRSZXN1bHQocmVzdWx0OiBTeW5jUmVzdWx0LCBvcHRpb25zOiBTeW5jT3BlcmF0aW9uT3B0aW9ucywgaW5kaWNhdG9yOiBzdHJpbmcpIHtcbiAgICBpZiAoIXJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3inYwgJHtyZXN1bHQubWVzc2FnZX1gXG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH1cbiAgICBcbiAgICBzd2l0Y2ggKG9wdGlvbnMub3BlcmF0aW9uKSB7XG4gICAgICBjYXNlICdsaXN0LXJlbW90ZSc6XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdExpc3RSZXN1bHQocmVzdWx0LCBpbmRpY2F0b3IpO1xuICAgICAgXG4gICAgICBjYXNlICdkb3dubG9hZCc6XG4gICAgICBjYXNlICdidWxrLWRvd25sb2FkJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0RG93bmxvYWRSZXN1bHQocmVzdWx0LCBvcHRpb25zLCBpbmRpY2F0b3IpO1xuICAgICAgXG4gICAgICBjYXNlICd1cGxvYWQnOlxuICAgICAgY2FzZSAnYnVsay11cGxvYWQnOlxuICAgICAgICByZXR1cm4gdGhpcy5mb3JtYXRVcGxvYWRSZXN1bHQocmVzdWx0LCBvcHRpb25zLCBpbmRpY2F0b3IpO1xuICAgICAgXG4gICAgICBjYXNlICdjb21wYXJlJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0Q29tcGFyZVJlc3VsdChyZXN1bHQsIG9wdGlvbnMsIGluZGljYXRvcik7XG4gICAgICBcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29udGVudDogW3tcbiAgICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgICAgdGV4dDogYCR7aW5kaWNhdG9yfeKchSAke3Jlc3VsdC5tZXNzYWdlfWBcbiAgICAgICAgICB9XVxuICAgICAgICB9O1xuICAgIH1cbiAgfVxuICBcbiAgcHJpdmF0ZSBmb3JtYXRMaXN0UmVzdWx0KHJlc3VsdDogU3luY1Jlc3VsdCwgaW5kaWNhdG9yOiBzdHJpbmcpIHtcbiAgICBpZiAoIXJlc3VsdC5lbGVtZW50cyB8fCByZXN1bHQuZWxlbWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3wn5OLICoqR2l0SHViIFBvcnRmb2xpbyBpcyBFbXB0eSoqXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgYE5vIGVsZW1lbnRzIGZvdW5kIGluIHlvdXIgR2l0SHViIHBvcnRmb2xpby5cXG5cXG5gICtcbiAgICAgICAgICAgICAgICBgVXBsb2FkIGVsZW1lbnRzIHVzaW5nOlxcbmAgK1xuICAgICAgICAgICAgICAgIGBcXGBzeW5jX3BvcnRmb2xpbyBvcGVyYXRpb246IFwidXBsb2FkXCIsIGVsZW1lbnRfbmFtZTogXCJuYW1lXCIsIGVsZW1lbnRfdHlwZTogXCJ0eXBlXCJcXGBgXG4gICAgICAgIH1dXG4gICAgICB9O1xuICAgIH1cbiAgICBcbiAgICBsZXQgdGV4dCA9IGAke2luZGljYXRvcn3wn5OLICoqR2l0SHViIFBvcnRmb2xpbyBDb250ZW50cyoqXFxuXFxuYDtcbiAgICB0ZXh0ICs9IGBGb3VuZCAke3Jlc3VsdC5lbGVtZW50cy5sZW5ndGh9IGVsZW1lbnRzOlxcblxcbmA7XG4gICAgXG4gICAgLy8gR3JvdXAgYnkgdHlwZVxuICAgIGNvbnN0IGJ5VHlwZTogUmVjb3JkPHN0cmluZywgYW55W10+ID0ge307XG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHJlc3VsdC5lbGVtZW50cykge1xuICAgICAgaWYgKCFieVR5cGVbZWxlbWVudC50eXBlXSkge1xuICAgICAgICBieVR5cGVbZWxlbWVudC50eXBlXSA9IFtdO1xuICAgICAgfVxuICAgICAgYnlUeXBlW2VsZW1lbnQudHlwZV0ucHVzaChlbGVtZW50KTtcbiAgICB9XG4gICAgXG4gICAgZm9yIChjb25zdCBbdHlwZSwgZWxlbWVudHNdIG9mIE9iamVjdC5lbnRyaWVzKGJ5VHlwZSkpIHtcbiAgICAgIHRleHQgKz0gYCoqJHt0eXBlfSoqICgke2VsZW1lbnRzLmxlbmd0aH0pOlxcbmA7XG4gICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHtcbiAgICAgICAgdGV4dCArPSBgICDigKIgJHtlbGVtZW50Lm5hbWV9YDtcbiAgICAgICAgaWYgKGVsZW1lbnQucmVtb3RlVmVyc2lvbikge1xuICAgICAgICAgIHRleHQgKz0gYCB2JHtlbGVtZW50LnJlbW90ZVZlcnNpb259YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZWxlbWVudC5zdGF0dXMpIHtcbiAgICAgICAgICB0ZXh0ICs9IGAgKCR7ZWxlbWVudC5zdGF0dXN9KWA7XG4gICAgICAgIH1cbiAgICAgICAgdGV4dCArPSAnXFxuJztcbiAgICAgIH1cbiAgICAgIHRleHQgKz0gJ1xcbic7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbe1xuICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgdGV4dFxuICAgICAgfV1cbiAgICB9O1xuICB9XG4gIFxuICBwcml2YXRlIGZvcm1hdERvd25sb2FkUmVzdWx0KHJlc3VsdDogU3luY1Jlc3VsdCwgb3B0aW9uczogU3luY09wZXJhdGlvbk9wdGlvbnMsIGluZGljYXRvcjogc3RyaW5nKSB7XG4gICAgaWYgKG9wdGlvbnMub3BlcmF0aW9uID09PSAnYnVsay1kb3dubG9hZCcpIHtcbiAgICAgIGNvbnN0IGVsZW1lbnRzID0gcmVzdWx0LmVsZW1lbnRzIHx8IFtdO1xuICAgICAgY29uc3QgZG93bmxvYWRlZCA9IGVsZW1lbnRzLmZpbHRlcihlID0+IGUuYWN0aW9uID09PSAnZG93bmxvYWQnKS5sZW5ndGg7XG4gICAgICBjb25zdCBza2lwcGVkID0gZWxlbWVudHMuZmlsdGVyKGUgPT4gZS5hY3Rpb24gPT09ICdza2lwJykubGVuZ3RoO1xuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3inIUgKipCdWxrIERvd25sb2FkIENvbXBsZXRlKipcXG5cXG5gICtcbiAgICAgICAgICAgICAgICBgRG93bmxvYWRlZDogJHtkb3dubG9hZGVkfSBlbGVtZW50c1xcbmAgK1xuICAgICAgICAgICAgICAgIGBTa2lwcGVkOiAke3NraXBwZWR9IGVsZW1lbnRzXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgcmVzdWx0Lm1lc3NhZ2VcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbe1xuICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgdGV4dDogYCR7aW5kaWNhdG9yfeKchSAqKkVsZW1lbnQgRG93bmxvYWRlZCoqXFxuXFxuYCArXG4gICAgICAgICAgICAgIGBFbGVtZW50OiAke29wdGlvbnMuZWxlbWVudF9uYW1lfSAoJHtvcHRpb25zLmVsZW1lbnRfdHlwZX0pXFxuXFxuYCArXG4gICAgICAgICAgICAgIHJlc3VsdC5tZXNzYWdlXG4gICAgICB9XVxuICAgIH07XG4gIH1cbiAgXG4gIHByaXZhdGUgZm9ybWF0VXBsb2FkUmVzdWx0KHJlc3VsdDogU3luY1Jlc3VsdCwgb3B0aW9uczogU3luY09wZXJhdGlvbk9wdGlvbnMsIGluZGljYXRvcjogc3RyaW5nKSB7XG4gICAgaWYgKG9wdGlvbnMub3BlcmF0aW9uID09PSAnYnVsay11cGxvYWQnKSB7XG4gICAgICBjb25zdCBlbGVtZW50cyA9IHJlc3VsdC5lbGVtZW50cyB8fCBbXTtcbiAgICAgIGNvbnN0IHVwbG9hZGVkID0gZWxlbWVudHMuZmlsdGVyKGUgPT4gZS5hY3Rpb24gPT09ICd1cGxvYWQnKS5sZW5ndGg7XG4gICAgICBjb25zdCBza2lwcGVkID0gZWxlbWVudHMuZmlsdGVyKGUgPT4gZS5hY3Rpb24gPT09ICdza2lwJykubGVuZ3RoO1xuICAgICAgXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb250ZW50OiBbe1xuICAgICAgICAgIHR5cGU6IFwidGV4dFwiLFxuICAgICAgICAgIHRleHQ6IGAke2luZGljYXRvcn3inIUgKipCdWxrIFVwbG9hZCBDb21wbGV0ZSoqXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgYFVwbG9hZGVkOiAke3VwbG9hZGVkfSBlbGVtZW50c1xcbmAgK1xuICAgICAgICAgICAgICAgIGBTa2lwcGVkOiAke3NraXBwZWR9IGVsZW1lbnRzXFxuXFxuYCArXG4gICAgICAgICAgICAgICAgcmVzdWx0Lm1lc3NhZ2VcbiAgICAgICAgfV1cbiAgICAgIH07XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB7XG4gICAgICBjb250ZW50OiBbe1xuICAgICAgICB0eXBlOiBcInRleHRcIixcbiAgICAgICAgdGV4dDogYCR7aW5kaWNhdG9yfeKchSAqKkVsZW1lbnQgVXBsb2FkZWQqKlxcblxcbmAgK1xuICAgICAgICAgICAgICBgRWxlbWVudDogJHtvcHRpb25zLmVsZW1lbnRfbmFtZX0gKCR7b3B0aW9ucy5lbGVtZW50X3R5cGV9KVxcblxcbmAgK1xuICAgICAgICAgICAgICByZXN1bHQubWVzc2FnZVxuICAgICAgfV1cbiAgICB9O1xuICB9XG4gIFxuICBwcml2YXRlIGZvcm1hdENvbXBhcmVSZXN1bHQocmVzdWx0OiBTeW5jUmVzdWx0LCBvcHRpb25zOiBTeW5jT3BlcmF0aW9uT3B0aW9ucywgaW5kaWNhdG9yOiBzdHJpbmcpIHtcbiAgICBsZXQgdGV4dCA9IGAke2luZGljYXRvcn3wn5SNICoqVmVyc2lvbiBDb21wYXJpc29uKipcXG5cXG5gO1xuICAgIHRleHQgKz0gYEVsZW1lbnQ6ICR7b3B0aW9ucy5lbGVtZW50X25hbWV9ICgke29wdGlvbnMuZWxlbWVudF90eXBlfSlcXG5cXG5gO1xuICAgIFxuICAgIGlmIChyZXN1bHQuZGF0YSkge1xuICAgICAgLy8gSWYgd2UgaGF2ZSBkZXRhaWxlZCBjb21wYXJpc29uIGRhdGFcbiAgICAgIGNvbnN0IGRhdGEgPSByZXN1bHQuZGF0YTtcbiAgICAgIGlmIChkYXRhLmxvY2FsKSB7XG4gICAgICAgIHRleHQgKz0gYCoqTG9jYWwgVmVyc2lvbioqOiAke2RhdGEubG9jYWwudmVyc2lvbn1cXG5gO1xuICAgICAgICB0ZXh0ICs9IGAgIE1vZGlmaWVkOiAke25ldyBEYXRlKGRhdGEubG9jYWwudGltZXN0YW1wKS50b0xvY2FsZVN0cmluZygpfVxcbmA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0ZXh0ICs9IGAqKkxvY2FsIFZlcnNpb24qKjogTm90IGZvdW5kXFxuYDtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKGRhdGEucmVtb3RlKSB7XG4gICAgICAgIHRleHQgKz0gYFxcbioqUmVtb3RlIFZlcnNpb24qKjogJHtkYXRhLnJlbW90ZS52ZXJzaW9ufVxcbmA7XG4gICAgICAgIHRleHQgKz0gYCAgTW9kaWZpZWQ6ICR7bmV3IERhdGUoZGF0YS5yZW1vdGUudGltZXN0YW1wKS50b0xvY2FsZVN0cmluZygpfVxcbmA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0ZXh0ICs9IGBcXG4qKlJlbW90ZSBWZXJzaW9uKio6IE5vdCBmb3VuZFxcbmA7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGlmIChkYXRhLmRpZmYpIHtcbiAgICAgICAgdGV4dCArPSBgXFxuKipEaWZmZXJlbmNlcyoqOlxcbiR7ZGF0YS5kaWZmfWA7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIHRleHQgKz0gYFxcblxcbiR7cmVzdWx0Lm1lc3NhZ2V9YDtcbiAgICBcbiAgICByZXR1cm4ge1xuICAgICAgY29udGVudDogW3tcbiAgICAgICAgdHlwZTogXCJ0ZXh0XCIsXG4gICAgICAgIHRleHRcbiAgICAgIH1dXG4gICAgfTtcbiAgfVxufVxuIl19