UNPKG

@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 28.7 kB
/** * Centralized error handling utilities for consistent error processing * Preserves stack traces and provides user-friendly messages */ import { logger } from './logger.js'; /** * Error categories for better error handling */ export var ErrorCategory; (function (ErrorCategory) { ErrorCategory["USER_ERROR"] = "USER_ERROR"; ErrorCategory["SYSTEM_ERROR"] = "SYSTEM_ERROR"; ErrorCategory["NETWORK_ERROR"] = "NETWORK_ERROR"; ErrorCategory["AUTH_ERROR"] = "AUTH_ERROR"; ErrorCategory["VALIDATION_ERROR"] = "VALIDATION_ERROR"; // Validation failures })(ErrorCategory || (ErrorCategory = {})); /** * Custom error class with additional context */ export class ApplicationError extends Error { category; code; details; originalError; constructor(message, category = ErrorCategory.SYSTEM_ERROR, code, details, originalError) { super(message); this.name = 'ApplicationError'; this.category = category; this.code = code; this.details = details; this.originalError = originalError; // Maintain proper stack trace with truncation to prevent memory issues if (originalError?.stack) { const truncatedOriginalStack = ErrorHandler.truncateStack(originalError.stack); this.stack = `${this.stack}\nCaused by: ${truncatedOriginalStack}`; } } } /** * Error thrown when an element is not found. * * Used by strategies and handlers when a requested element does not exist. * This error is caught by MCPAQLHandler and converted to a proper failure response. * * @see Issue #275 - Handlers return success=true for missing elements */ export class ElementNotFoundError extends ApplicationError { elementType; elementName; constructor(elementType, elementName) { super(`${elementType} '${elementName}' not found`, ErrorCategory.USER_ERROR, 'ELEMENT_NOT_FOUND', { elementType, elementName }); this.name = 'ElementNotFoundError'; this.elementType = elementType; this.elementName = elementName; } } /** * Error thrown when a required parameter is missing. * * Used by handlers when an operation requires a parameter that was not provided. * * @see Issue #275 - Handlers return success=true for missing elements */ export class MissingParameterError extends ApplicationError { parameterName; operation; constructor(parameterName, operation) { super(`Missing required parameter '${parameterName}' for operation '${operation}'`, ErrorCategory.USER_ERROR, 'MISSING_PARAMETER', { parameterName, operation }); this.name = 'MissingParameterError'; this.parameterName = parameterName; this.operation = operation; } } /** * Utility class for consistent error handling */ export class ErrorHandler { /** * Maximum stack trace depth to prevent memory issues */ static MAX_STACK_DEPTH = 10; /** * Maximum length for stack trace strings */ static MAX_STACK_LENGTH = 5000; /** * Truncate stack trace to prevent memory issues */ static truncateStack(stack) { if (!stack) return undefined; // Limit total length if (stack.length > this.MAX_STACK_LENGTH) { stack = stack.substring(0, this.MAX_STACK_LENGTH) + '\n... (truncated)'; } // Limit number of stack frames const lines = stack.split('\n'); if (lines.length > this.MAX_STACK_DEPTH) { return lines.slice(0, this.MAX_STACK_DEPTH).join('\n') + '\n... (truncated)'; } return stack; } /** * Extract error information while preserving context */ static extractErrorInfo(error) { // Handle ApplicationError if (error instanceof ApplicationError) { return { message: error.message, category: error.category, code: error.code, details: error.details, stack: this.truncateStack(error.stack), originalError: error.originalError }; } // Handle standard Error if (error instanceof Error) { return { message: error.message, category: ErrorCategory.SYSTEM_ERROR, stack: this.truncateStack(error.stack), originalError: error }; } // Handle string errors if (typeof error === 'string') { return { message: error, category: ErrorCategory.SYSTEM_ERROR }; } // Handle unknown errors return { message: 'An unknown error occurred', category: ErrorCategory.SYSTEM_ERROR, details: error }; } /** * Get user-friendly error message */ static getUserMessage(error) { const errorInfo = this.extractErrorInfo(error); // Provide user-friendly messages based on category switch (errorInfo.category) { case ErrorCategory.AUTH_ERROR: return `Authentication error: ${errorInfo.message}`; case ErrorCategory.VALIDATION_ERROR: return `Validation error: ${errorInfo.message}`; case ErrorCategory.NETWORK_ERROR: return `Network error: ${errorInfo.message}. Please check your connection and try again.`; case ErrorCategory.USER_ERROR: return errorInfo.message; // User errors should already be user-friendly default: // For system errors, provide a generic message return 'An unexpected error occurred. Please try again later.'; } } /** * Log error with appropriate level and context */ static logError(context, error, additionalInfo) { const errorInfo = this.extractErrorInfo(error); const logData = { context, category: errorInfo.category, code: errorInfo.code, message: errorInfo.message, ...additionalInfo }; // Log based on category switch (errorInfo.category) { case ErrorCategory.USER_ERROR: case ErrorCategory.VALIDATION_ERROR: logger.warn(`${context}: ${errorInfo.message}`, logData); break; case ErrorCategory.AUTH_ERROR: logger.warn(`${context}: Authentication error`, logData); break; case ErrorCategory.NETWORK_ERROR: logger.error(`${context}: Network error`, { ...logData, stack: errorInfo.stack }); break; default: logger.error(`${context}: System error`, { ...logData, stack: errorInfo.stack, details: errorInfo.details }); } // Log stack trace in debug mode for all errors (already truncated) if (errorInfo.stack) { logger.debug(`${context} - Stack trace:`, { stack: errorInfo.stack }); } } /** * Create an error with context preservation */ static createError(message, category = ErrorCategory.SYSTEM_ERROR, code, originalError) { const original = originalError instanceof Error ? originalError : undefined; return new ApplicationError(message, category, code, undefined, original); } /** * Wrap an error with additional context */ static wrapError(error, context, category) { const errorInfo = this.extractErrorInfo(error); return new ApplicationError(`${context}: ${errorInfo.message}`, category || errorInfo.category, errorInfo.code, errorInfo.details, errorInfo.originalError); } /** * Check if error is of a specific category */ static isErrorCategory(error, category) { const errorInfo = this.extractErrorInfo(error); return errorInfo.category === category; } /** * Format error for API response */ static formatForResponse(error) { const errorInfo = this.extractErrorInfo(error); const userMessage = this.getUserMessage(error); return { success: false, message: userMessage, error: errorInfo.code || errorInfo.category, // Only include details in development details: process.env.NODE_ENV === 'development' ? errorInfo.details : undefined }; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRXJyb3JIYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL0Vycm9ySGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXJDOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksYUFNWDtBQU5ELFdBQVksYUFBYTtJQUN2QiwwQ0FBeUIsQ0FBQTtJQUN6Qiw4Q0FBNkIsQ0FBQTtJQUM3QixnREFBK0IsQ0FBQTtJQUMvQiwwQ0FBeUIsQ0FBQTtJQUN6QixzREFBcUMsQ0FBQSxDQUFDLHNCQUFzQjtBQUM5RCxDQUFDLEVBTlcsYUFBYSxLQUFiLGFBQWEsUUFNeEI7QUFjRDs7R0FFRztBQUNILE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxLQUFLO0lBQ3pCLFFBQVEsQ0FBZ0I7SUFDeEIsSUFBSSxDQUFVO0lBQ2QsT0FBTyxDQUEyQjtJQUNsQyxhQUFhLENBQVM7SUFFdEMsWUFDRSxPQUFlLEVBQ2YsV0FBMEIsYUFBYSxDQUFDLFlBQVksRUFDcEQsSUFBYSxFQUNiLE9BQWlDLEVBQ2pDLGFBQXFCO1FBRXJCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsa0JBQWtCLENBQUM7UUFDL0IsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFFbkMsdUVBQXVFO1FBQ3ZFLElBQUksYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDO1lBQ3pCLE1BQU0sc0JBQXNCLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0UsSUFBSSxDQUFDLEtBQUss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O0lBQ3pDLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxLQUFjO1FBTXJDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvQyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRS9DLE9BQU87WUFDTCxPQUFPLEVBQUUsS0FBSztZQUNkLE9BQU8sRUFBRSxXQUFXO1lBQ3BCLEtBQUssRUFBRSxTQUFTLENBQUMsSUFBSSxJQUFJLFNBQVMsQ0FBQyxRQUFRO1lBQzNDLHNDQUFzQztZQUN0QyxPQUFPLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEtBQUssYUFBYSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTO1NBQ2hGLENBQUM7SUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDZW50cmFsaXplZCBlcnJvciBoYW5kbGluZyB1dGlsaXRpZXMgZm9yIGNvbnNpc3RlbnQgZXJyb3IgcHJvY2Vzc2luZ1xuICogUHJlc2VydmVzIHN0YWNrIHRyYWNlcyBhbmQgcHJvdmlkZXMgdXNlci1mcmllbmRseSBtZXNzYWdlc1xuICovXG5cbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyLmpzJztcblxuLyoqXG4gKiBFcnJvciBjYXRlZ29yaWVzIGZvciBiZXR0ZXIgZXJyb3IgaGFuZGxpbmdcbiAqL1xuZXhwb3J0IGVudW0gRXJyb3JDYXRlZ29yeSB7XG4gIFVTRVJfRVJST1IgPSAnVVNFUl9FUlJPUicsICAgICAgICAvLyBVc2VyIGlucHV0IGlzc3Vlc1xuICBTWVNURU1fRVJST1IgPSAnU1lTVEVNX0VSUk9SJywgICAgLy8gSW50ZXJuYWwgc3lzdGVtIGZhaWx1cmVzXG4gIE5FVFdPUktfRVJST1IgPSAnTkVUV09SS19FUlJPUicsICAvLyBBUEkvbmV0d29yayBpc3N1ZXNcbiAgQVVUSF9FUlJPUiA9ICdBVVRIX0VSUk9SJywgICAgICAgIC8vIEF1dGhlbnRpY2F0aW9uL2F1dGhvcml6YXRpb25cbiAgVkFMSURBVElPTl9FUlJPUiA9ICdWQUxJREFUSU9OX0VSUk9SJyAvLyBWYWxpZGF0aW9uIGZhaWx1cmVzXG59XG5cbi8qKlxuICogU3RydWN0dXJlZCBlcnJvciBpbmZvcm1hdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIEVycm9ySW5mbyB7XG4gIG1lc3NhZ2U6IHN0cmluZztcbiAgY2F0ZWdvcnk6IEVycm9yQ2F0ZWdvcnk7XG4gIGNvZGU/OiBzdHJpbmc7XG4gIGRldGFpbHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgc3RhY2s/OiBzdHJpbmc7XG4gIG9yaWdpbmFsRXJyb3I/OiBFcnJvcjtcbn1cblxuLyoqXG4gKiBDdXN0b20gZXJyb3IgY2xhc3Mgd2l0aCBhZGRpdGlvbmFsIGNvbnRleHRcbiAqL1xuZXhwb3J0IGNsYXNzIEFwcGxpY2F0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIHB1YmxpYyByZWFkb25seSBjYXRlZ29yeTogRXJyb3JDYXRlZ29yeTtcbiAgcHVibGljIHJlYWRvbmx5IGNvZGU/OiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSBkZXRhaWxzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHB1YmxpYyByZWFkb25seSBvcmlnaW5hbEVycm9yPzogRXJyb3I7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgbWVzc2FnZTogc3RyaW5nLFxuICAgIGNhdGVnb3J5OiBFcnJvckNhdGVnb3J5ID0gRXJyb3JDYXRlZ29yeS5TWVNURU1fRVJST1IsXG4gICAgY29kZT86IHN0cmluZyxcbiAgICBkZXRhaWxzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gICAgb3JpZ2luYWxFcnJvcj86IEVycm9yXG4gICkge1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgIHRoaXMubmFtZSA9ICdBcHBsaWNhdGlvbkVycm9yJztcbiAgICB0aGlzLmNhdGVnb3J5ID0gY2F0ZWdvcnk7XG4gICAgdGhpcy5jb2RlID0gY29kZTtcbiAgICB0aGlzLmRldGFpbHMgPSBkZXRhaWxzO1xuICAgIHRoaXMub3JpZ2luYWxFcnJvciA9IG9yaWdpbmFsRXJyb3I7XG5cbiAgICAvLyBNYWludGFpbiBwcm9wZXIgc3RhY2sgdHJhY2Ugd2l0aCB0cnVuY2F0aW9uIHRvIHByZXZlbnQgbWVtb3J5IGlzc3Vlc1xuICAgIGlmIChvcmlnaW5hbEVycm9yPy5zdGFjaykge1xuICAgICAgY29uc3QgdHJ1bmNhdGVkT3JpZ2luYWxTdGFjayA9IEVycm9ySGFuZGxlci50cnVuY2F0ZVN0YWNrKG9yaWdpbmFsRXJyb3Iuc3RhY2spO1xuICAgICAgdGhpcy5zdGFjayA9IGAke3RoaXMuc3RhY2t9XFxuQ2F1c2VkIGJ5OiAke3RydW5jYXRlZE9yaWdpbmFsU3RhY2t9YDtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBFcnJvciB0aHJvd24gd2hlbiBhbiBlbGVtZW50IGlzIG5vdCBmb3VuZC5cbiAqXG4gKiBVc2VkIGJ5IHN0cmF0ZWdpZXMgYW5kIGhhbmRsZXJzIHdoZW4gYSByZXF1ZXN0ZWQgZWxlbWVudCBkb2VzIG5vdCBleGlzdC5cbiAqIFRoaXMgZXJyb3IgaXMgY2F1Z2h0IGJ5IE1DUEFRTEhhbmRsZXIgYW5kIGNvbnZlcnRlZCB0byBhIHByb3BlciBmYWlsdXJlIHJlc3BvbnNlLlxuICpcbiAqIEBzZWUgSXNzdWUgIzI3NSAtIEhhbmRsZXJzIHJldHVybiBzdWNjZXNzPXRydWUgZm9yIG1pc3NpbmcgZWxlbWVudHNcbiAqL1xuZXhwb3J0IGNsYXNzIEVsZW1lbnROb3RGb3VuZEVycm9yIGV4dGVuZHMgQXBwbGljYXRpb25FcnJvciB7XG4gIHB1YmxpYyByZWFkb25seSBlbGVtZW50VHlwZTogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgZWxlbWVudE5hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihlbGVtZW50VHlwZTogc3RyaW5nLCBlbGVtZW50TmFtZTogc3RyaW5nKSB7XG4gICAgc3VwZXIoXG4gICAgICBgJHtlbGVtZW50VHlwZX0gJyR7ZWxlbWVudE5hbWV9JyBub3QgZm91bmRgLFxuICAgICAgRXJyb3JDYXRlZ29yeS5VU0VSX0VSUk9SLFxuICAgICAgJ0VMRU1FTlRfTk9UX0ZPVU5EJyxcbiAgICAgIHsgZWxlbWVudFR5cGUsIGVsZW1lbnROYW1lIH1cbiAgICApO1xuICAgIHRoaXMubmFtZSA9ICdFbGVtZW50Tm90Rm91bmRFcnJvcic7XG4gICAgdGhpcy5lbGVtZW50VHlwZSA9IGVsZW1lbnRUeXBlO1xuICAgIHRoaXMuZWxlbWVudE5hbWUgPSBlbGVtZW50TmFtZTtcbiAgfVxufVxuXG4vKipcbiAqIEVycm9yIHRocm93biB3aGVuIGEgcmVxdWlyZWQgcGFyYW1ldGVyIGlzIG1pc3NpbmcuXG4gKlxuICogVXNlZCBieSBoYW5kbGVycyB3aGVuIGFuIG9wZXJhdGlvbiByZXF1aXJlcyBhIHBhcmFtZXRlciB0aGF0IHdhcyBub3QgcHJvdmlkZWQuXG4gKlxuICogQHNlZSBJc3N1ZSAjMjc1IC0gSGFuZGxlcnMgcmV0dXJuIHN1Y2Nlc3M9dHJ1ZSBmb3IgbWlzc2luZyBlbGVtZW50c1xuICovXG5leHBvcnQgY2xhc3MgTWlzc2luZ1BhcmFtZXRlckVycm9yIGV4dGVuZHMgQXBwbGljYXRpb25FcnJvciB7XG4gIHB1YmxpYyByZWFkb25seSBwYXJhbWV0ZXJOYW1lOiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSBvcGVyYXRpb246IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihwYXJhbWV0ZXJOYW1lOiBzdHJpbmcsIG9wZXJhdGlvbjogc3RyaW5nKSB7XG4gICAgc3VwZXIoXG4gICAgICBgTWlzc2luZyByZXF1aXJlZCBwYXJhbWV0ZXIgJyR7cGFyYW1ldGVyTmFtZX0nIGZvciBvcGVyYXRpb24gJyR7b3BlcmF0aW9ufSdgLFxuICAgICAgRXJyb3JDYXRlZ29yeS5VU0VSX0VSUk9SLFxuICAgICAgJ01JU1NJTkdfUEFSQU1FVEVSJyxcbiAgICAgIHsgcGFyYW1ldGVyTmFtZSwgb3BlcmF0aW9uIH1cbiAgICApO1xuICAgIHRoaXMubmFtZSA9ICdNaXNzaW5nUGFyYW1ldGVyRXJyb3InO1xuICAgIHRoaXMucGFyYW1ldGVyTmFtZSA9IHBhcmFtZXRlck5hbWU7XG4gICAgdGhpcy5vcGVyYXRpb24gPSBvcGVyYXRpb247XG4gIH1cbn1cblxuLyoqXG4gKiBVdGlsaXR5IGNsYXNzIGZvciBjb25zaXN0ZW50IGVycm9yIGhhbmRsaW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBFcnJvckhhbmRsZXIge1xuICAvKipcbiAgICogTWF4aW11bSBzdGFjayB0cmFjZSBkZXB0aCB0byBwcmV2ZW50IG1lbW9yeSBpc3N1ZXNcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IE1BWF9TVEFDS19ERVBUSCA9IDEwO1xuICBcbiAgLyoqXG4gICAqIE1heGltdW0gbGVuZ3RoIGZvciBzdGFjayB0cmFjZSBzdHJpbmdzXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBNQVhfU1RBQ0tfTEVOR1RIID0gNTAwMDtcbiAgXG4gIC8qKlxuICAgKiBUcnVuY2F0ZSBzdGFjayB0cmFjZSB0byBwcmV2ZW50IG1lbW9yeSBpc3N1ZXNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgdHJ1bmNhdGVTdGFjayhzdGFjaz86IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFzdGFjaykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBcbiAgICAvLyBMaW1pdCB0b3RhbCBsZW5ndGhcbiAgICBpZiAoc3RhY2subGVuZ3RoID4gdGhpcy5NQVhfU1RBQ0tfTEVOR1RIKSB7XG4gICAgICBzdGFjayA9IHN0YWNrLnN1YnN0cmluZygwLCB0aGlzLk1BWF9TVEFDS19MRU5HVEgpICsgJ1xcbi4uLiAodHJ1bmNhdGVkKSc7XG4gICAgfVxuICAgIFxuICAgIC8vIExpbWl0IG51bWJlciBvZiBzdGFjayBmcmFtZXNcbiAgICBjb25zdCBsaW5lcyA9IHN0YWNrLnNwbGl0KCdcXG4nKTtcbiAgICBpZiAobGluZXMubGVuZ3RoID4gdGhpcy5NQVhfU1RBQ0tfREVQVEgpIHtcbiAgICAgIHJldHVybiBsaW5lcy5zbGljZSgwLCB0aGlzLk1BWF9TVEFDS19ERVBUSCkuam9pbignXFxuJykgKyAnXFxuLi4uICh0cnVuY2F0ZWQpJztcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHN0YWNrO1xuICB9XG4gIFxuICAvKipcbiAgICogRXh0cmFjdCBlcnJvciBpbmZvcm1hdGlvbiB3aGlsZSBwcmVzZXJ2aW5nIGNvbnRleHRcbiAgICovXG4gIHN0YXRpYyBleHRyYWN0RXJyb3JJbmZvKGVycm9yOiB1bmtub3duKTogRXJyb3JJbmZvIHtcbiAgICAvLyBIYW5kbGUgQXBwbGljYXRpb25FcnJvclxuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEFwcGxpY2F0aW9uRXJyb3IpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UsXG4gICAgICAgIGNhdGVnb3J5OiBlcnJvci5jYXRlZ29yeSxcbiAgICAgICAgY29kZTogZXJyb3IuY29kZSxcbiAgICAgICAgZGV0YWlsczogZXJyb3IuZGV0YWlscyxcbiAgICAgICAgc3RhY2s6IHRoaXMudHJ1bmNhdGVTdGFjayhlcnJvci5zdGFjayksXG4gICAgICAgIG9yaWdpbmFsRXJyb3I6IGVycm9yLm9yaWdpbmFsRXJyb3JcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHN0YW5kYXJkIEVycm9yXG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UsXG4gICAgICAgIGNhdGVnb3J5OiBFcnJvckNhdGVnb3J5LlNZU1RFTV9FUlJPUixcbiAgICAgICAgc3RhY2s6IHRoaXMudHJ1bmNhdGVTdGFjayhlcnJvci5zdGFjayksXG4gICAgICAgIG9yaWdpbmFsRXJyb3I6IGVycm9yXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSBzdHJpbmcgZXJyb3JzXG4gICAgaWYgKHR5cGVvZiBlcnJvciA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1lc3NhZ2U6IGVycm9yLFxuICAgICAgICBjYXRlZ29yeTogRXJyb3JDYXRlZ29yeS5TWVNURU1fRVJST1JcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIHVua25vd24gZXJyb3JzXG4gICAgcmV0dXJuIHtcbiAgICAgIG1lc3NhZ2U6ICdBbiB1bmtub3duIGVycm9yIG9jY3VycmVkJyxcbiAgICAgIGNhdGVnb3J5OiBFcnJvckNhdGVnb3J5LlNZU1RFTV9FUlJPUixcbiAgICAgIGRldGFpbHM6IGVycm9yIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdXNlci1mcmllbmRseSBlcnJvciBtZXNzYWdlXG4gICAqL1xuICBzdGF0aWMgZ2V0VXNlck1lc3NhZ2UoZXJyb3I6IHVua25vd24pOiBzdHJpbmcge1xuICAgIGNvbnN0IGVycm9ySW5mbyA9IHRoaXMuZXh0cmFjdEVycm9ySW5mbyhlcnJvcik7XG4gICAgXG4gICAgLy8gUHJvdmlkZSB1c2VyLWZyaWVuZGx5IG1lc3NhZ2VzIGJhc2VkIG9uIGNhdGVnb3J5XG4gICAgc3dpdGNoIChlcnJvckluZm8uY2F0ZWdvcnkpIHtcbiAgICAgIGNhc2UgRXJyb3JDYXRlZ29yeS5BVVRIX0VSUk9SOlxuICAgICAgICByZXR1cm4gYEF1dGhlbnRpY2F0aW9uIGVycm9yOiAke2Vycm9ySW5mby5tZXNzYWdlfWA7XG4gICAgICBjYXNlIEVycm9yQ2F0ZWdvcnkuVkFMSURBVElPTl9FUlJPUjpcbiAgICAgICAgcmV0dXJuIGBWYWxpZGF0aW9uIGVycm9yOiAke2Vycm9ySW5mby5tZXNzYWdlfWA7XG4gICAgICBjYXNlIEVycm9yQ2F0ZWdvcnkuTkVUV09SS19FUlJPUjpcbiAgICAgICAgcmV0dXJuIGBOZXR3b3JrIGVycm9yOiAke2Vycm9ySW5mby5tZXNzYWdlfS4gUGxlYXNlIGNoZWNrIHlvdXIgY29ubmVjdGlvbiBhbmQgdHJ5IGFnYWluLmA7XG4gICAgICBjYXNlIEVycm9yQ2F0ZWdvcnkuVVNFUl9FUlJPUjpcbiAgICAgICAgcmV0dXJuIGVycm9ySW5mby5tZXNzYWdlOyAvLyBVc2VyIGVycm9ycyBzaG91bGQgYWxyZWFkeSBiZSB1c2VyLWZyaWVuZGx5XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyBGb3Igc3lzdGVtIGVycm9ycywgcHJvdmlkZSBhIGdlbmVyaWMgbWVzc2FnZVxuICAgICAgICByZXR1cm4gJ0FuIHVuZXhwZWN0ZWQgZXJyb3Igb2NjdXJyZWQuIFBsZWFzZSB0cnkgYWdhaW4gbGF0ZXIuJztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTG9nIGVycm9yIHdpdGggYXBwcm9wcmlhdGUgbGV2ZWwgYW5kIGNvbnRleHRcbiAgICovXG4gIHN0YXRpYyBsb2dFcnJvcihcbiAgICBjb250ZXh0OiBzdHJpbmcsXG4gICAgZXJyb3I6IHVua25vd24sXG4gICAgYWRkaXRpb25hbEluZm8/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlxuICApOiB2b2lkIHtcbiAgICBjb25zdCBlcnJvckluZm8gPSB0aGlzLmV4dHJhY3RFcnJvckluZm8oZXJyb3IpO1xuICAgIFxuICAgIGNvbnN0IGxvZ0RhdGEgPSB7XG4gICAgICBjb250ZXh0LFxuICAgICAgY2F0ZWdvcnk6IGVycm9ySW5mby5jYXRlZ29yeSxcbiAgICAgIGNvZGU6IGVycm9ySW5mby5jb2RlLFxuICAgICAgbWVzc2FnZTogZXJyb3JJbmZvLm1lc3NhZ2UsXG4gICAgICAuLi5hZGRpdGlvbmFsSW5mb1xuICAgIH07XG5cbiAgICAvLyBMb2cgYmFzZWQgb24gY2F0ZWdvcnlcbiAgICBzd2l0Y2ggKGVycm9ySW5mby5jYXRlZ29yeSkge1xuICAgICAgY2FzZSBFcnJvckNhdGVnb3J5LlVTRVJfRVJST1I6XG4gICAgICBjYXNlIEVycm9yQ2F0ZWdvcnkuVkFMSURBVElPTl9FUlJPUjpcbiAgICAgICAgbG9nZ2VyLndhcm4oYCR7Y29udGV4dH06ICR7ZXJyb3JJbmZvLm1lc3NhZ2V9YCwgbG9nRGF0YSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBFcnJvckNhdGVnb3J5LkFVVEhfRVJST1I6XG4gICAgICAgIGxvZ2dlci53YXJuKGAke2NvbnRleHR9OiBBdXRoZW50aWNhdGlvbiBlcnJvcmAsIGxvZ0RhdGEpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgRXJyb3JDYXRlZ29yeS5ORVRXT1JLX0VSUk9SOlxuICAgICAgICBsb2dnZXIuZXJyb3IoYCR7Y29udGV4dH06IE5ldHdvcmsgZXJyb3JgLCB7XG4gICAgICAgICAgLi4ubG9nRGF0YSxcbiAgICAgICAgICBzdGFjazogZXJyb3JJbmZvLnN0YWNrXG4gICAgICAgIH0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGxvZ2dlci5lcnJvcihgJHtjb250ZXh0fTogU3lzdGVtIGVycm9yYCwge1xuICAgICAgICAgIC4uLmxvZ0RhdGEsXG4gICAgICAgICAgc3RhY2s6IGVycm9ySW5mby5zdGFjayxcbiAgICAgICAgICBkZXRhaWxzOiBlcnJvckluZm8uZGV0YWlsc1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBMb2cgc3RhY2sgdHJhY2UgaW4gZGVidWcgbW9kZSBmb3IgYWxsIGVycm9ycyAoYWxyZWFkeSB0cnVuY2F0ZWQpXG4gICAgaWYgKGVycm9ySW5mby5zdGFjaykge1xuICAgICAgbG9nZ2VyLmRlYnVnKGAke2NvbnRleHR9IC0gU3RhY2sgdHJhY2U6YCwgeyBzdGFjazogZXJyb3JJbmZvLnN0YWNrIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW4gZXJyb3Igd2l0aCBjb250ZXh0IHByZXNlcnZhdGlvblxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZUVycm9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyxcbiAgICBjYXRlZ29yeTogRXJyb3JDYXRlZ29yeSA9IEVycm9yQ2F0ZWdvcnkuU1lTVEVNX0VSUk9SLFxuICAgIGNvZGU/OiBzdHJpbmcsXG4gICAgb3JpZ2luYWxFcnJvcj86IHVua25vd25cbiAgKTogQXBwbGljYXRpb25FcnJvciB7XG4gICAgY29uc3Qgb3JpZ2luYWwgPSBvcmlnaW5hbEVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBvcmlnaW5hbEVycm9yIDogdW5kZWZpbmVkO1xuICAgIHJldHVybiBuZXcgQXBwbGljYXRpb25FcnJvcihtZXNzYWdlLCBjYXRlZ29yeSwgY29kZSwgdW5kZWZpbmVkLCBvcmlnaW5hbCk7XG4gIH1cblxuICAvKipcbiAgICogV3JhcCBhbiBlcnJvciB3aXRoIGFkZGl0aW9uYWwgY29udGV4dFxuICAgKi9cbiAgc3RhdGljIHdyYXBFcnJvcihcbiAgICBlcnJvcjogdW5rbm93bixcbiAgICBjb250ZXh0OiBzdHJpbmcsXG4gICAgY2F0ZWdvcnk/OiBFcnJvckNhdGVnb3J5XG4gICk6IEFwcGxpY2F0aW9uRXJyb3Ige1xuICAgIGNvbnN0IGVycm9ySW5mbyA9IHRoaXMuZXh0cmFjdEVycm9ySW5mbyhlcnJvcik7XG4gICAgcmV0dXJuIG5ldyBBcHBsaWNhdGlvbkVycm9yKFxuICAgICAgYCR7Y29udGV4dH06ICR7ZXJyb3JJbmZvLm1lc3NhZ2V9YCxcbiAgICAgIGNhdGVnb3J5IHx8IGVycm9ySW5mby5jYXRlZ29yeSxcbiAgICAgIGVycm9ySW5mby5jb2RlLFxuICAgICAgZXJyb3JJbmZvLmRldGFpbHMsXG4gICAgICBlcnJvckluZm8ub3JpZ2luYWxFcnJvclxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgZXJyb3IgaXMgb2YgYSBzcGVjaWZpYyBjYXRlZ29yeVxuICAgKi9cbiAgc3RhdGljIGlzRXJyb3JDYXRlZ29yeShlcnJvcjogdW5rbm93biwgY2F0ZWdvcnk6IEVycm9yQ2F0ZWdvcnkpOiBib29sZWFuIHtcbiAgICBjb25zdCBlcnJvckluZm8gPSB0aGlzLmV4dHJhY3RFcnJvckluZm8oZXJyb3IpO1xuICAgIHJldHVybiBlcnJvckluZm8uY2F0ZWdvcnkgPT09IGNhdGVnb3J5O1xuICB9XG5cbiAgLyoqXG4gICAqIEZvcm1hdCBlcnJvciBmb3IgQVBJIHJlc3BvbnNlXG4gICAqL1xuICBzdGF0aWMgZm9ybWF0Rm9yUmVzcG9uc2UoZXJyb3I6IHVua25vd24pOiB7XG4gICAgc3VjY2VzczogZmFsc2U7XG4gICAgbWVzc2FnZTogc3RyaW5nO1xuICAgIGVycm9yOiBzdHJpbmc7XG4gICAgZGV0YWlscz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICB9IHtcbiAgICBjb25zdCBlcnJvckluZm8gPSB0aGlzLmV4dHJhY3RFcnJvckluZm8oZXJyb3IpO1xuICAgIGNvbnN0IHVzZXJNZXNzYWdlID0gdGhpcy5nZXRVc2VyTWVzc2FnZShlcnJvcik7XG4gICAgXG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgbWVzc2FnZTogdXNlck1lc3NhZ2UsXG4gICAgICBlcnJvcjogZXJyb3JJbmZvLmNvZGUgfHwgZXJyb3JJbmZvLmNhdGVnb3J5LFxuICAgICAgLy8gT25seSBpbmNsdWRlIGRldGFpbHMgaW4gZGV2ZWxvcG1lbnRcbiAgICAgIGRldGFpbHM6IHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAnZGV2ZWxvcG1lbnQnID8gZXJyb3JJbmZvLmRldGFpbHMgOiB1bmRlZmluZWRcbiAgICB9O1xuICB9XG59Il19