@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.
303 lines • 42.1 kB
JavaScript
/**
* Phase 4: Integration Hooks for Unified Logging System.
*
* Maps native events from 10 monitoring/logging systems into UnifiedLogEntry
* objects and routes them through LogManager. Each source system exposes a
* lightweight `addLogListener` callback; the translation logic lives here so
* source files stay minimal and never import UnifiedLogEntry.
*
* Usage:
* const cleanups = wireLogHooks(logManager, container);
* // later …
* cleanups.forEach(fn => fn());
*/
import { SecurityMonitor } from '../security/securityMonitor.js';
import { DefaultElementProvider } from '../portfolio/DefaultElementProvider.js';
import { LRUCache } from '../cache/LRUCache.js';
// ---------------------------------------------------------------------------
// Severity → LogLevel helper (shared by SecurityMonitor, SecurityTelemetry,
// SecurityAuditor)
// ---------------------------------------------------------------------------
const SEVERITY_TO_LEVEL = {
CRITICAL: 'error',
HIGH: 'error',
MEDIUM: 'warn',
LOW: 'info',
critical: 'error',
high: 'error',
medium: 'warn',
low: 'info',
};
// ---------------------------------------------------------------------------
// Exported factory for TriggerMetricsTracker (created outside DI container)
// ---------------------------------------------------------------------------
export function getTriggerMetricsLogListener(logManager, contextTracker) {
return (level, message, data) => {
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'telemetry',
level,
source: 'TriggerMetricsTracker',
message,
data,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
};
}
// ---------------------------------------------------------------------------
// Exported factory for SecurityAuditor (created outside DI container)
// ---------------------------------------------------------------------------
export function getSecurityAuditorLogListener(logManager, contextTracker) {
return (level, message, data) => {
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'security',
level,
source: 'SecurityAuditor',
message,
data,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
};
}
// ---------------------------------------------------------------------------
// Main wiring function
// ---------------------------------------------------------------------------
/**
* Wire all monitoring systems into the unified logging pipeline.
*
* @param logManager The LogManager singleton from the DI container.
* @param container The DI container (used to resolve source services).
* @returns Array of unsubscribe functions — call them during shutdown.
*/
export function wireLogHooks(logManager, container) {
const cleanups = [];
// Resolve ContextTracker for correlationId injection
let contextTracker = null;
try {
contextTracker = container.resolve('ContextTracker');
}
catch { /* ContextTracker not registered */ }
// --- MCPLogger (application) -------------------------------------------
try {
const mcpLogger = container.resolve('MCPLogger');
const unsub = mcpLogger.addLogListener((logEntry) => {
const entry = {
id: logManager.generateId(),
timestamp: logEntry.timestamp.toISOString(),
category: 'application',
level: logEntry.level,
source: 'MCPLogger',
message: logEntry.message,
data: logEntry.data != null ? logEntry.data : undefined,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
});
cleanups.push(unsub);
}
catch { /* MCPLogger not registered */ }
// --- SecurityMonitor (security, static) ---------------------------------
{
const unsub = SecurityMonitor.addLogListener((logEntry) => {
const entry = {
id: logManager.generateId(),
timestamp: logEntry.timestamp,
category: 'security',
level: SEVERITY_TO_LEVEL[logEntry.severity] ?? 'info',
source: 'SecurityMonitor',
message: `[${logEntry.type}] ${logEntry.details}`,
data: {
...logEntry.additionalData,
eventType: logEntry.type,
severity: logEntry.severity,
sourceComponent: logEntry.source,
},
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
});
cleanups.push(unsub);
}
// --- SecurityTelemetry (security) ---------------------------------------
try {
const secTelemetry = container.resolve('SecurityTelemetry');
const unsub = secTelemetry.addLogListener((telEntry) => {
const entry = {
id: logManager.generateId(),
timestamp: telEntry.timestamp,
category: 'security',
level: SEVERITY_TO_LEVEL[telEntry.severity] ?? 'info',
source: 'SecurityTelemetry',
message: `Blocked ${telEntry.attackType}: ${telEntry.pattern}`,
data: telEntry.metadata,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
});
cleanups.push(unsub);
}
catch { /* SecurityTelemetry not registered */ }
// --- PerformanceMonitor (performance) -----------------------------------
try {
const perfMonitor = container.resolve('PerformanceMonitor');
const unsub = perfMonitor.addLogListener((level, message, data) => {
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'performance',
level: level,
source: 'PerformanceMonitor',
message,
data,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
});
cleanups.push(unsub);
}
catch { /* PerformanceMonitor not registered */ }
// --- ElementEventDispatcher (application) — already has on() -----------
try {
const dispatcher = container.resolve('ElementEventDispatcher');
const eventLevelMap = {
'element:load:error': 'error',
'element:save:error': 'error',
'element:delete:error': 'error',
'element:lock-timeout': 'warn',
'element:activate': 'info',
'element:deactivate': 'info',
'element:load:success': 'info',
'element:save:success': 'info',
'element:delete:success': 'info',
};
// Only log events that have a mapped level (errors, warnings, success, activate/deactivate).
// Skip start/cache/external-change events — they fire per-element and create noise
// without adding value beyond the completion/error logs.
const loggedEvents = Object.keys(eventLevelMap);
for (const eventName of loggedEvents) {
const unsub = dispatcher.on(eventName, (payload) => {
const level = eventLevelMap[eventName] ?? 'debug';
const requestCorrelationId = contextTracker?.getCorrelationId();
// Use elementId if available, fall back to filename from filePath
const elementName = payload.elementId
|| (payload.filePath ? payload.filePath.replace(/\.[^.]+$/, '') : '');
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'application',
level,
source: 'ElementEventDispatcher',
message: `${eventName} [${payload.elementType ?? 'unknown'}:${elementName}]`,
data: {
...payload.extra,
...(payload.correlationId ? { operationId: payload.correlationId } : {}),
...(payload.filePath ? { filePath: payload.filePath } : {}),
},
correlationId: requestCorrelationId ?? payload.correlationId,
};
logManager.log(entry);
});
cleanups.push(unsub);
}
}
catch { /* ElementEventDispatcher not registered */ }
// --- OperationalTelemetry (telemetry) -----------------------------------
try {
const opsTelemetry = container.resolve('OperationalTelemetry');
const unsub = opsTelemetry.addLogListener((level, message, data) => {
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'telemetry',
level: level,
source: 'OperationalTelemetry',
message,
data,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
});
cleanups.push(unsub);
}
catch { /* OperationalTelemetry not registered */ }
// --- FileLockManager (performance) --------------------------------------
try {
const lockManager = container.resolve('FileLockManager');
const unsub = lockManager.addLogListener((level, message, data) => {
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'performance',
level: level,
source: 'FileLockManager',
message,
data,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
});
cleanups.push(unsub);
}
catch { /* FileLockManager not registered */ }
// --- DefaultElementProvider (performance, static) -----------------------
{
const unsub = DefaultElementProvider.addLogListener((level, message, data) => {
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'performance',
level: level,
source: 'DefaultElementProvider',
message,
data,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
});
cleanups.push(unsub);
}
// --- LRUCache (performance, static) ------------------------------------
{
const unsub = LRUCache.addLogListener((level, message, data) => {
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'performance',
level: level,
source: 'LRUCache',
message,
data,
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
});
cleanups.push(unsub);
}
// --- StateChangeNotifier (application) — extends EventEmitter ----------
try {
const notifier = container.resolve('StateChangeNotifier');
const handler = (event) => {
const entry = {
id: logManager.generateId(),
timestamp: new Date().toISOString(),
category: 'application',
level: 'info',
source: 'StateChangeNotifier',
message: `State change: ${event.type}`,
data: { previousValue: event.previousValue, newValue: event.newValue },
correlationId: contextTracker?.getCorrelationId(),
};
logManager.log(entry);
};
notifier.on('state-change', handler);
cleanups.push(() => notifier.removeListener('state-change', handler));
}
catch { /* StateChangeNotifier not registered */ }
return cleanups;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTG9nSG9va3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbG9nZ2luZy9Mb2dIb29rcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7O0dBWUc7QUFJSCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDakUsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sd0NBQXdDLENBQUM7QUFDaEYsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRWhELDhFQUE4RTtBQUM5RSw0RUFBNEU7QUFDNUUsbUJBQW1CO0FBQ25CLDhFQUE4RTtBQUU5RSxNQUFNLGlCQUFpQixHQUE2QjtJQUNsRCxRQUFRLEVBQUUsT0FBTztJQUNqQixJQUFJLEVBQUUsT0FBTztJQUNiLE1BQU0sRUFBRSxNQUFNO0lBQ2QsR0FBRyxFQUFFLE1BQU07SUFDWCxRQUFRLEVBQUUsT0FBTztJQUNqQixJQUFJLEVBQUUsT0FBTztJQUNiLE1BQU0sRUFBRSxNQUFNO0lBQ2QsR0FBRyxFQUFFLE1BQU07Q0FDWixDQUFDO0FBUUYsOEVBQThFO0FBQzlFLDRFQUE0RTtBQUM1RSw4RUFBOEU7QUFFOUUsTUFBTSxVQUFVLDRCQUE0QixDQUMxQyxVQUFzQixFQUN0QixjQUFzQztJQUV0QyxPQUFPLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsRUFBRTtRQUM5QixNQUFNLEtBQUssR0FBb0I7WUFDN0IsRUFBRSxFQUFFLFVBQVUsQ0FBQyxVQUFVLEVBQUU7WUFDM0IsU0FBUyxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFO1lBQ25DLFFBQVEsRUFBRSxXQUFXO1lBQ3JCLEtBQUs7WUFDTCxNQUFNLEVBQUUsdUJBQXVCO1lBQy9CLE9BQU87WUFDUCxJQUFJO1lBQ0osYUFBYSxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRTtTQUNsRCxDQUFDO1FBQ0YsVUFBVSxDQUFDLEdBQUcs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QyxJQUFJLEVBQUUsRUFBRSxhQUFhLEVBQUUsS0FBSyxDQUFDLGFBQWEsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVEsRUFBRTtnQkFDdEUsYUFBYSxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRTthQUNsRCxDQUFDO1lBQ0YsVUFBVSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4QixDQUFDLENBQUM7UUFDRixRQUFRLENBQUMsRUFBRSxDQUFDLGNBQWMsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNyQyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDeEUsQ0FBQztJQUFDLE1BQU0sQ0FBQyxDQUFDLHdDQUF3QyxDQUFDLENBQUM7SUFFcEQsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUGhhc2UgNDogSW50ZWdyYXRpb24gSG9va3MgZm9yIFVuaWZpZWQgTG9nZ2luZyBTeXN0ZW0uXG4gKlxuICogTWFwcyBuYXRpdmUgZXZlbnRzIGZyb20gMTAgbW9uaXRvcmluZy9sb2dnaW5nIHN5c3RlbXMgaW50byBVbmlmaWVkTG9nRW50cnlcbiAqIG9iamVjdHMgYW5kIHJvdXRlcyB0aGVtIHRocm91Z2ggTG9nTWFuYWdlci4gIEVhY2ggc291cmNlIHN5c3RlbSBleHBvc2VzIGFcbiAqIGxpZ2h0d2VpZ2h0IGBhZGRMb2dMaXN0ZW5lcmAgY2FsbGJhY2s7IHRoZSB0cmFuc2xhdGlvbiBsb2dpYyBsaXZlcyBoZXJlIHNvXG4gKiBzb3VyY2UgZmlsZXMgc3RheSBtaW5pbWFsIGFuZCBuZXZlciBpbXBvcnQgVW5pZmllZExvZ0VudHJ5LlxuICpcbiAqIFVzYWdlOlxuICogICBjb25zdCBjbGVhbnVwcyA9IHdpcmVMb2dIb29rcyhsb2dNYW5hZ2VyLCBjb250YWluZXIpO1xuICogICAvLyBsYXRlciDigKZcbiAqICAgY2xlYW51cHMuZm9yRWFjaChmbiA9PiBmbigpKTtcbiAqL1xuXG5pbXBvcnQgdHlwZSB7IExvZ01hbmFnZXIgfSBmcm9tICcuL0xvZ01hbmFnZXIuanMnO1xuaW1wb3J0IHR5cGUgeyBMb2dMZXZlbCwgVW5pZmllZExvZ0VudHJ5IH0gZnJvbSAnLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBTZWN1cml0eU1vbml0b3IgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cml0eU1vbml0b3IuanMnO1xuaW1wb3J0IHsgRGVmYXVsdEVsZW1lbnRQcm92aWRlciB9IGZyb20gJy4uL3BvcnRmb2xpby9EZWZhdWx0RWxlbWVudFByb3ZpZGVyLmpzJztcbmltcG9ydCB7IExSVUNhY2hlIH0gZnJvbSAnLi4vY2FjaGUvTFJVQ2FjaGUuanMnO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFNldmVyaXR5IOKGkiBMb2dMZXZlbCBoZWxwZXIgKHNoYXJlZCBieSBTZWN1cml0eU1vbml0b3IsIFNlY3VyaXR5VGVsZW1ldHJ5LFxuLy8gU2VjdXJpdHlBdWRpdG9yKVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmNvbnN0IFNFVkVSSVRZX1RPX0xFVkVMOiBSZWNvcmQ8c3RyaW5nLCBMb2dMZXZlbD4gPSB7XG4gIENSSVRJQ0FMOiAnZXJyb3InLFxuICBISUdIOiAnZXJyb3InLFxuICBNRURJVU06ICd3YXJuJyxcbiAgTE9XOiAnaW5mbycsXG4gIGNyaXRpY2FsOiAnZXJyb3InLFxuICBoaWdoOiAnZXJyb3InLFxuICBtZWRpdW06ICd3YXJuJyxcbiAgbG93OiAnaW5mbycsXG59O1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENvcnJlbGF0aW9uSWQgcHJvdmlkZXIgaW50ZXJmYWNlIChzdWJzZXQgb2YgQ29udGV4dFRyYWNrZXIpXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxudHlwZSBDb3JyZWxhdGlvbklkUHJvdmlkZXIgPSB7IGdldENvcnJlbGF0aW9uSWQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIH07XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gRXhwb3J0ZWQgZmFjdG9yeSBmb3IgVHJpZ2dlck1ldHJpY3NUcmFja2VyIChjcmVhdGVkIG91dHNpZGUgREkgY29udGFpbmVyKVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUcmlnZ2VyTWV0cmljc0xvZ0xpc3RlbmVyKFxuICBsb2dNYW5hZ2VyOiBMb2dNYW5hZ2VyLFxuICBjb250ZXh0VHJhY2tlcj86IENvcnJlbGF0aW9uSWRQcm92aWRlcixcbik6IChsZXZlbDogJ2RlYnVnJyB8ICdpbmZvJyB8ICd3YXJuJyB8ICdlcnJvcicsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB2b2lkIHtcbiAgcmV0dXJuIChsZXZlbCwgbWVzc2FnZSwgZGF0YSkgPT4ge1xuICAgIGNvbnN0IGVudHJ5OiBVbmlmaWVkTG9nRW50cnkgPSB7XG4gICAgICBpZDogbG9nTWFuYWdlci5nZW5lcmF0ZUlkKCksXG4gICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGNhdGVnb3J5OiAndGVsZW1ldHJ5JyxcbiAgICAgIGxldmVsLFxuICAgICAgc291cmNlOiAnVHJpZ2dlck1ldHJpY3NUcmFja2VyJyxcbiAgICAgIG1lc3NhZ2UsXG4gICAgICBkYXRhLFxuICAgICAgY29ycmVsYXRpb25JZDogY29udGV4dFRyYWNrZXI/LmdldENvcnJlbGF0aW9uSWQoKSxcbiAgICB9O1xuICAgIGxvZ01hbmFnZXIubG9nKGVudHJ5KTtcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBFeHBvcnRlZCBmYWN0b3J5IGZvciBTZWN1cml0eUF1ZGl0b3IgKGNyZWF0ZWQgb3V0c2lkZSBESSBjb250YWluZXIpXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFNlY3VyaXR5QXVkaXRvckxvZ0xpc3RlbmVyKFxuICBsb2dNYW5hZ2VyOiBMb2dNYW5hZ2VyLFxuICBjb250ZXh0VHJhY2tlcj86IENvcnJlbGF0aW9uSWRQcm92aWRlcixcbik6IChsZXZlbDogJ2RlYnVnJyB8ICdpbmZvJyB8ICd3YXJuJyB8ICdlcnJvcicsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB2b2lkIHtcbiAgcmV0dXJuIChsZXZlbCwgbWVzc2FnZSwgZGF0YSkgPT4ge1xuICAgIGNvbnN0IGVudHJ5OiBVbmlmaWVkTG9nRW50cnkgPSB7XG4gICAgICBpZDogbG9nTWFuYWdlci5nZW5lcmF0ZUlkKCksXG4gICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGNhdGVnb3J5OiAnc2VjdXJpdHknLFxuICAgICAgbGV2ZWwsXG4gICAgICBzb3VyY2U6ICdTZWN1cml0eUF1ZGl0b3InLFxuICAgICAgbWVzc2FnZSxcbiAgICAgIGRhdGEsXG4gICAgICBjb3JyZWxhdGlvbklkOiBjb250ZXh0VHJhY2tlcj8uZ2V0Q29ycmVsYXRpb25JZCgpLFxuICAgIH07XG4gICAgbG9nTWFuYWdlci5sb2coZW50cnkpO1xuICB9O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIE1haW4gd2lyaW5nIGZ1bmN0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBXaXJlIGFsbCBtb25pdG9yaW5nIHN5c3RlbXMgaW50byB0aGUgdW5pZmllZCBsb2dnaW5nIHBpcGVsaW5lLlxuICpcbiAqIEBwYXJhbSBsb2dNYW5hZ2VyICBUaGUgTG9nTWFuYWdlciBzaW5nbGV0b24gZnJvbSB0aGUgREkgY29udGFpbmVyLlxuICogQHBhcmFtIGNvbnRhaW5lciAgIFRoZSBESSBjb250YWluZXIgKHVzZWQgdG8gcmVzb2x2ZSBzb3VyY2Ugc2VydmljZXMpLlxuICogQHJldHVybnMgQXJyYXkgb2YgdW5zdWJzY3JpYmUgZnVuY3Rpb25zIOKAlCBjYWxsIHRoZW0gZHVyaW5nIHNodXRkb3duLlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2lyZUxvZ0hvb2tzKFxuICBsb2dNYW5hZ2VyOiBMb2dNYW5hZ2VyLFxuICBjb250YWluZXI6IHsgcmVzb2x2ZTxUPihuYW1lOiBzdHJpbmcpOiBUIH0sXG4pOiAoKCkgPT4gdm9pZClbXSB7XG4gIGNvbnN0IGNsZWFudXBzOiAoKCkgPT4gdm9pZClbXSA9IFtdO1xuXG4gIC8vIFJlc29sdmUgQ29udGV4dFRyYWNrZXIgZm9yIGNvcnJlbGF0aW9uSWQgaW5qZWN0aW9uXG4gIGxldCBjb250ZXh0VHJhY2tlcjogQ29ycmVsYXRpb25JZFByb3ZpZGVyIHwgbnVsbCA9IG51bGw7XG4gIHRyeSB7XG4gICAgY29udGV4dFRyYWNrZXIgPSBjb250YWluZXIucmVzb2x2ZTxDb3JyZWxhdGlvbklkUHJvdmlkZXI+KCdDb250ZXh0VHJhY2tlcicpO1xuICB9IGNhdGNoIHsgLyogQ29udGV4dFRyYWNrZXIgbm90IHJlZ2lzdGVyZWQgKi8gfVxuXG4gIC8vIC0tLSBNQ1BMb2dnZXIgKGFwcGxpY2F0aW9uKSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIHRyeSB7XG4gICAgY29uc3QgbWNwTG9nZ2VyID0gY29udGFpbmVyLnJlc29sdmU8e1xuICAgICAgYWRkTG9nTGlzdGVuZXIoZm46IChlbnRyeTogeyB0aW1lc3RhbXA6IERhdGU7IGxldmVsOiBzdHJpbmc7IG1lc3NhZ2U6IHN0cmluZzsgZGF0YT86IGFueSB9KSA9PiB2b2lkKTogKCkgPT4gdm9pZDtcbiAgICB9PignTUNQTG9nZ2VyJyk7XG4gICAgY29uc3QgdW5zdWIgPSBtY3BMb2dnZXIuYWRkTG9nTGlzdGVuZXIoKGxvZ0VudHJ5KSA9PiB7XG4gICAgICBjb25zdCBlbnRyeTogVW5pZmllZExvZ0VudHJ5ID0ge1xuICAgICAgICBpZDogbG9nTWFuYWdlci5nZW5lcmF0ZUlkKCksXG4gICAgICAgIHRpbWVzdGFtcDogbG9nRW50cnkudGltZXN0YW1wLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIGNhdGVnb3J5OiAnYXBwbGljYXRpb24nLFxuICAgICAgICBsZXZlbDogbG9nRW50cnkubGV2ZWwgYXMgTG9nTGV2ZWwsXG4gICAgICAgIHNvdXJjZTogJ01DUExvZ2dlcicsXG4gICAgICAgIG1lc3NhZ2U6IGxvZ0VudHJ5Lm1lc3NhZ2UsXG4gICAgICAgIGRhdGE6IGxvZ0VudHJ5LmRhdGEgIT0gbnVsbCA/IGxvZ0VudHJ5LmRhdGEgOiB1bmRlZmluZWQsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IGNvbnRleHRUcmFja2VyPy5nZXRDb3JyZWxhdGlvbklkKCksXG4gICAgICB9O1xuICAgICAgbG9nTWFuYWdlci5sb2coZW50cnkpO1xuICAgIH0pO1xuICAgIGNsZWFudXBzLnB1c2godW5zdWIpO1xuICB9IGNhdGNoIHsgLyogTUNQTG9nZ2VyIG5vdCByZWdpc3RlcmVkICovIH1cblxuICAvLyAtLS0gU2VjdXJpdHlNb25pdG9yIChzZWN1cml0eSwgc3RhdGljKSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAge1xuICAgIGNvbnN0IHVuc3ViID0gU2VjdXJpdHlNb25pdG9yLmFkZExvZ0xpc3RlbmVyKChsb2dFbnRyeSkgPT4ge1xuICAgICAgY29uc3QgZW50cnk6IFVuaWZpZWRMb2dFbnRyeSA9IHtcbiAgICAgICAgaWQ6IGxvZ01hbmFnZXIuZ2VuZXJhdGVJZCgpLFxuICAgICAgICB0aW1lc3RhbXA6IGxvZ0VudHJ5LnRpbWVzdGFtcCxcbiAgICAgICAgY2F0ZWdvcnk6ICdzZWN1cml0eScsXG4gICAgICAgIGxldmVsOiBTRVZFUklUWV9UT19MRVZFTFtsb2dFbnRyeS5zZXZlcml0eV0gPz8gJ2luZm8nLFxuICAgICAgICBzb3VyY2U6ICdTZWN1cml0eU1vbml0b3InLFxuICAgICAgICBtZXNzYWdlOiBgWyR7bG9nRW50cnkudHlwZX1dICR7bG9nRW50cnkuZGV0YWlsc31gLFxuICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgLi4ubG9nRW50cnkuYWRkaXRpb25hbERhdGEsXG4gICAgICAgICAgZXZlbnRUeXBlOiBsb2dFbnRyeS50eXBlLFxuICAgICAgICAgIHNldmVyaXR5OiBsb2dFbnRyeS5zZXZlcml0eSxcbiAgICAgICAgICBzb3VyY2VDb21wb25lbnQ6IGxvZ0VudHJ5LnNvdXJjZSxcbiAgICAgICAgfSxcbiAgICAgICAgY29ycmVsYXRpb25JZDogY29udGV4dFRyYWNrZXI/LmdldENvcnJlbGF0aW9uSWQoKSxcbiAgICAgIH07XG4gICAgICBsb2dNYW5hZ2VyLmxvZyhlbnRyeSk7XG4gICAgfSk7XG4gICAgY2xlYW51cHMucHVzaCh1bnN1Yik7XG4gIH1cblxuICAvLyAtLS0gU2VjdXJpdHlUZWxlbWV0cnkgKHNlY3VyaXR5KSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgdHJ5IHtcbiAgICBjb25zdCBzZWNUZWxlbWV0cnkgPSBjb250YWluZXIucmVzb2x2ZTx7XG4gICAgICBhZGRMb2dMaXN0ZW5lcihmbjogKGVudHJ5OiB7XG4gICAgICAgIHRpbWVzdGFtcDogc3RyaW5nOyBhdHRhY2tUeXBlOiBzdHJpbmc7IHBhdHRlcm46IHN0cmluZztcbiAgICAgICAgc2V2ZXJpdHk6IHN0cmluZzsgc291cmNlOiBzdHJpbmc7IG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgYW55PjtcbiAgICAgIH0pID0+IHZvaWQpOiAoKSA9PiB2b2lkO1xuICAgIH0+KCdTZWN1cml0eVRlbGVtZXRyeScpO1xuICAgIGNvbnN0IHVuc3ViID0gc2VjVGVsZW1ldHJ5LmFkZExvZ0xpc3RlbmVyKCh0ZWxFbnRyeSkgPT4ge1xuICAgICAgY29uc3QgZW50cnk6IFVuaWZpZWRMb2dFbnRyeSA9IHtcbiAgICAgICAgaWQ6IGxvZ01hbmFnZXIuZ2VuZXJhdGVJZCgpLFxuICAgICAgICB0aW1lc3RhbXA6IHRlbEVudHJ5LnRpbWVzdGFtcCxcbiAgICAgICAgY2F0ZWdvcnk6ICdzZWN1cml0eScsXG4gICAgICAgIGxldmVsOiBTRVZFUklUWV9UT19MRVZFTFt0ZWxFbnRyeS5zZXZlcml0eV0gPz8gJ2luZm8nLFxuICAgICAgICBzb3VyY2U6ICdTZWN1cml0eVRlbGVtZXRyeScsXG4gICAgICAgIG1lc3NhZ2U6IGBCbG9ja2VkICR7dGVsRW50cnkuYXR0YWNrVHlwZX06ICR7dGVsRW50cnkucGF0dGVybn1gLFxuICAgICAgICBkYXRhOiB0ZWxFbnRyeS5tZXRhZGF0YSxcbiAgICAgICAgY29ycmVsYXRpb25JZDogY29udGV4dFRyYWNrZXI/LmdldENvcnJlbGF0aW9uSWQoKSxcbiAgICAgIH07XG4gICAgICBsb2dNYW5hZ2VyLmxvZyhlbnRyeSk7XG4gICAgfSk7XG4gICAgY2xlYW51cHMucHVzaCh1bnN1Yik7XG4gIH0gY2F0Y2ggeyAvKiBTZWN1cml0eVRlbGVtZXRyeSBub3QgcmVnaXN0ZXJlZCAqLyB9XG5cbiAgLy8gLS0tIFBlcmZvcm1hbmNlTW9uaXRvciAocGVyZm9ybWFuY2UpIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIHRyeSB7XG4gICAgY29uc3QgcGVyZk1vbml0b3IgPSBjb250YWluZXIucmVzb2x2ZTx7XG4gICAgICBhZGRMb2dMaXN0ZW5lcihmbjogKGxldmVsOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB2b2lkKTogKCkgPT4gdm9pZDtcbiAgICB9PignUGVyZm9ybWFuY2VNb25pdG9yJyk7XG4gICAgY29uc3QgdW5zdWIgPSBwZXJmTW9uaXRvci5hZGRMb2dMaXN0ZW5lcigobGV2ZWwsIG1lc3NhZ2UsIGRhdGEpID0+IHtcbiAgICAgIGNvbnN0IGVudHJ5OiBVbmlmaWVkTG9nRW50cnkgPSB7XG4gICAgICAgIGlkOiBsb2dNYW5hZ2VyLmdlbmVyYXRlSWQoKSxcbiAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIGNhdGVnb3J5OiAncGVyZm9ybWFuY2UnLFxuICAgICAgICBsZXZlbDogbGV2ZWwgYXMgTG9nTGV2ZWwsXG4gICAgICAgIHNvdXJjZTogJ1BlcmZvcm1hbmNlTW9uaXRvcicsXG4gICAgICAgIG1lc3NhZ2UsXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IGNvbnRleHRUcmFja2VyPy5nZXRDb3JyZWxhdGlvbklkKCksXG4gICAgICB9O1xuICAgICAgbG9nTWFuYWdlci5sb2coZW50cnkpO1xuICAgIH0pO1xuICAgIGNsZWFudXBzLnB1c2godW5zdWIpO1xuICB9IGNhdGNoIHsgLyogUGVyZm9ybWFuY2VNb25pdG9yIG5vdCByZWdpc3RlcmVkICovIH1cblxuICAvLyAtLS0gRWxlbWVudEV2ZW50RGlzcGF0Y2hlciAoYXBwbGljYXRpb24pIOKAlCBhbHJlYWR5IGhhcyBvbigpIC0tLS0tLS0tLS0tXG4gIHRyeSB7XG4gICAgY29uc3QgZGlzcGF0Y2hlciA9IGNvbnRhaW5lci5yZXNvbHZlPHtcbiAgICAgIG9uKGV2ZW50OiBzdHJpbmcsIGhhbmRsZXI6IChwYXlsb2FkOiBhbnkpID0+IHZvaWQpOiAoKSA9PiB2b2lkO1xuICAgIH0+KCdFbGVtZW50RXZlbnREaXNwYXRjaGVyJyk7XG5cbiAgICBjb25zdCBldmVudExldmVsTWFwOiBSZWNvcmQ8c3RyaW5nLCBMb2dMZXZlbD4gPSB7XG4gICAgICAnZWxlbWVudDpsb2FkOmVycm9yJzogJ2Vycm9yJyxcbiAgICAgICdlbGVtZW50OnNhdmU6ZXJyb3InOiAnZXJyb3InLFxuICAgICAgJ2VsZW1lbnQ6ZGVsZXRlOmVycm9yJzogJ2Vycm9yJyxcbiAgICAgICdlbGVtZW50OmxvY2stdGltZW91dCc6ICd3YXJuJyxcbiAgICAgICdlbGVtZW50OmFjdGl2YXRlJzogJ2luZm8nLFxuICAgICAgJ2VsZW1lbnQ6ZGVhY3RpdmF0ZSc6ICdpbmZvJyxcbiAgICAgICdlbGVtZW50OmxvYWQ6c3VjY2Vzcyc6ICdpbmZvJyxcbiAgICAgICdlbGVtZW50OnNhdmU6c3VjY2Vzcyc6ICdpbmZvJyxcbiAgICAgICdlbGVtZW50OmRlbGV0ZTpzdWNjZXNzJzogJ2luZm8nLFxuICAgIH07XG5cbiAgICAvLyBPbmx5IGxvZyBldmVudHMgdGhhdCBoYXZlIGEgbWFwcGVkIGxldmVsIChlcnJvcnMsIHdhcm5pbmdzLCBzdWNjZXNzLCBhY3RpdmF0ZS9kZWFjdGl2YXRlKS5cbiAgICAvLyBTa2lwIHN0YXJ0L2NhY2hlL2V4dGVybmFsLWNoYW5nZSBldmVudHMg4oCUIHRoZXkgZmlyZSBwZXItZWxlbWVudCBhbmQgY3JlYXRlIG5vaXNlXG4gICAgLy8gd2l0aG91dCBhZGRpbmcgdmFsdWUgYmV5b25kIHRoZSBjb21wbGV0aW9uL2Vycm9yIGxvZ3MuXG4gICAgY29uc3QgbG9nZ2VkRXZlbnRzID0gT2JqZWN0LmtleXMoZXZlbnRMZXZlbE1hcCk7XG5cbiAgICBmb3IgKGNvbnN0IGV2ZW50TmFtZSBvZiBsb2dnZWRFdmVudHMpIHtcbiAgICAgIGNvbnN0IHVuc3ViID0gZGlzcGF0Y2hlci5vbihldmVudE5hbWUsIChwYXlsb2FkOiBhbnkpID0+IHtcbiAgICAgICAgY29uc3QgbGV2ZWwgPSBldmVudExldmVsTWFwW2V2ZW50TmFtZV0gPz8gJ2RlYnVnJztcbiAgICAgICAgY29uc3QgcmVxdWVzdENvcnJlbGF0aW9uSWQgPSBjb250ZXh0VHJhY2tlcj8uZ2V0Q29ycmVsYXRpb25JZCgpO1xuICAgICAgICAvLyBVc2UgZWxlbWVudElkIGlmIGF2YWlsYWJsZSwgZmFsbCBiYWNrIHRvIGZpbGVuYW1lIGZyb20gZmlsZVBhdGhcbiAgICAgICAgY29uc3QgZWxlbWVudE5hbWUgPSBwYXlsb2FkLmVsZW1lbnRJZFxuICAgICAgICAgIHx8IChwYXlsb2FkLmZpbGVQYXRoID8gcGF5bG9hZC5maWxlUGF0aC5yZXBsYWNlKC9cXC5bXi5dKyQvLCAnJykgOiAnJyk7XG4gICAgICAgIGNvbnN0IGVudHJ5OiBVbmlmaWVkTG9nRW50cnkgPSB7XG4gICAgICAgICAgaWQ6IGxvZ01hbmFnZXIuZ2VuZXJhdGVJZCgpLFxuICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgIGNhdGVnb3J5OiAnYXBwbGljYXRpb24nLFxuICAgICAgICAgIGxldmVsLFxuICAgICAgICAgIHNvdXJjZTogJ0VsZW1lbnRFdmVudERpc3BhdGNoZXInLFxuICAgICAgICAgIG1lc3NhZ2U6IGAke2V2ZW50TmFtZX0gWyR7cGF5bG9hZC5lbGVtZW50VHlwZSA/PyAndW5rbm93bid9OiR7ZWxlbWVudE5hbWV9XWAsXG4gICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgLi4ucGF5bG9hZC5leHRyYSxcbiAgICAgICAgICAgIC4uLihwYXlsb2FkLmNvcnJlbGF0aW9uSWQgPyB7IG9wZXJhdGlvbklkOiBwYXlsb2FkLmNvcnJlbGF0aW9uSWQgfSA6IHt9KSxcbiAgICAgICAgICAgIC4uLihwYXlsb2FkLmZpbGVQYXRoID8geyBmaWxlUGF0aDogcGF5bG9hZC5maWxlUGF0aCB9IDoge30pLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgY29ycmVsYXRpb25JZDogcmVxdWVzdENvcnJlbGF0aW9uSWQgPz8gcGF5bG9hZC5jb3JyZWxhdGlvbklkLFxuICAgICAgICB9O1xuICAgICAgICBsb2dNYW5hZ2VyLmxvZyhlbnRyeSk7XG4gICAgICB9KTtcbiAgICAgIGNsZWFudXBzLnB1c2godW5zdWIpO1xuICAgIH1cbiAgfSBjYXRjaCB7IC8qIEVsZW1lbnRFdmVudERpc3BhdGNoZXIgbm90IHJlZ2lzdGVyZWQgKi8gfVxuXG4gIC8vIC0tLSBPcGVyYXRpb25hbFRlbGVtZXRyeSAodGVsZW1ldHJ5KSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICB0cnkge1xuICAgIGNvbnN0IG9wc1RlbGVtZXRyeSA9IGNvbnRhaW5lci5yZXNvbHZlPHtcbiAgICAgIGFkZExvZ0xpc3RlbmVyKGZuOiAobGV2ZWw6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nLCBkYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pID0+IHZvaWQpOiAoKSA9PiB2b2lkO1xuICAgIH0+KCdPcGVyYXRpb25hbFRlbGVtZXRyeScpO1xuICAgIGNvbnN0IHVuc3ViID0gb3BzVGVsZW1ldHJ5LmFkZExvZ0xpc3RlbmVyKChsZXZlbCwgbWVzc2FnZSwgZGF0YSkgPT4ge1xuICAgICAgY29uc3QgZW50cnk6IFVuaWZpZWRMb2dFbnRyeSA9IHtcbiAgICAgICAgaWQ6IGxvZ01hbmFnZXIuZ2VuZXJhdGVJZCgpLFxuICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgY2F0ZWdvcnk6ICd0ZWxlbWV0cnknLFxuICAgICAgICBsZXZlbDogbGV2ZWwgYXMgTG9nTGV2ZWwsXG4gICAgICAgIHNvdXJjZTogJ09wZXJhdGlvbmFsVGVsZW1ldHJ5JyxcbiAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgZGF0YSxcbiAgICAgICAgY29ycmVsYXRpb25JZDogY29udGV4dFRyYWNrZXI/LmdldENvcnJlbGF0aW9uSWQoKSxcbiAgICAgIH07XG4gICAgICBsb2dNYW5hZ2VyLmxvZyhlbnRyeSk7XG4gICAgfSk7XG4gICAgY2xlYW51cHMucHVzaCh1bnN1Yik7XG4gIH0gY2F0Y2ggeyAvKiBPcGVyYXRpb25hbFRlbGVtZXRyeSBub3QgcmVnaXN0ZXJlZCAqLyB9XG5cbiAgLy8gLS0tIEZpbGVMb2NrTWFuYWdlciAocGVyZm9ybWFuY2UpIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIHRyeSB7XG4gICAgY29uc3QgbG9ja01hbmFnZXIgPSBjb250YWluZXIucmVzb2x2ZTx7XG4gICAgICBhZGRMb2dMaXN0ZW5lcihmbjogKGxldmVsOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSA9PiB2b2lkKTogKCkgPT4gdm9pZDtcbiAgICB9PignRmlsZUxvY2tNYW5hZ2VyJyk7XG4gICAgY29uc3QgdW5zdWIgPSBsb2NrTWFuYWdlci5hZGRMb2dMaXN0ZW5lcigobGV2ZWwsIG1lc3NhZ2UsIGRhdGEpID0+IHtcbiAgICAgIGNvbnN0IGVudHJ5OiBVbmlmaWVkTG9nRW50cnkgPSB7XG4gICAgICAgIGlkOiBsb2dNYW5hZ2VyLmdlbmVyYXRlSWQoKSxcbiAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIGNhdGVnb3J5OiAncGVyZm9ybWFuY2UnLFxuICAgICAgICBsZXZlbDogbGV2ZWwgYXMgTG9nTGV2ZWwsXG4gICAgICAgIHNvdXJjZTogJ0ZpbGVMb2NrTWFuYWdlcicsXG4gICAgICAgIG1lc3NhZ2UsXG4gICAgICAgIGRhdGEsXG4gICAgICAgIGNvcnJlbGF0aW9uSWQ6IGNvbnRleHRUcmFja2VyPy5nZXRDb3JyZWxhdGlvbklkKCksXG4gICAgICB9O1xuICAgICAgbG9nTWFuYWdlci5sb2coZW50cnkpO1xuICAgIH0pO1xuICAgIGNsZWFudXBzLnB1c2godW5zdWIpO1xuICB9IGNhdGNoIHsgLyogRmlsZUxvY2tNYW5hZ2VyIG5vdCByZWdpc3RlcmVkICovIH1cblxuICAvLyAtLS0gRGVmYXVsdEVsZW1lbnRQcm92aWRlciAocGVyZm9ybWFuY2UsIHN0YXRpYykgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAge1xuICAgIGNvbnN0IHVuc3ViID0gRGVmYXVsdEVsZW1lbnRQcm92aWRlci5hZGRMb2dMaXN0ZW5lcigobGV2ZWwsIG1lc3NhZ2UsIGRhdGEpID0+IHtcbiAgICAgIGNvbnN0IGVudHJ5OiBVbmlmaWVkTG9nRW50cnkgPSB7XG4gICAgICAgIGlkOiBsb2dNYW5hZ2VyLmdlbmVyYXRlSWQoKSxcbiAgICAgICAgdGltZXN0YW1wOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgIGNhdGVnb3J5OiAncGVyZm9ybWFuY2UnLFxuICAgICAgICBsZXZlbDogbGV2ZWwgYXMgTG9nTGV2ZWwsXG4gICAgICAgIHNvdXJjZTogJ0RlZmF1bHRFbGVtZW50UHJvdmlkZXInLFxuICAgICAgICBtZXNzYWdlLFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBjb250ZXh0VHJhY2tlcj8uZ2V0Q29ycmVsYXRpb25JZCgpLFxuICAgICAgfTtcbiAgICAgIGxvZ01hbmFnZXIubG9nKGVudHJ5KTtcbiAgICB9KTtcbiAgICBjbGVhbnVwcy5wdXNoKHVuc3ViKTtcbiAgfVxuXG4gIC8vIC0tLSBMUlVDYWNoZSAocGVyZm9ybWFuY2UsIHN0YXRpYykgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIHtcbiAgICBjb25zdCB1bnN1YiA9IExSVUNhY2hlLmFkZExvZ0xpc3RlbmVyKChsZXZlbCwgbWVzc2FnZSwgZGF0YSkgPT4ge1xuICAgICAgY29uc3QgZW50cnk6IFVuaWZpZWRMb2dFbnRyeSA9IHtcbiAgICAgICAgaWQ6IGxvZ01hbmFnZXIuZ2VuZXJhdGVJZCgpLFxuICAgICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgY2F0ZWdvcnk6ICdwZXJmb3JtYW5jZScsXG4gICAgICAgIGxldmVsOiBsZXZlbCBhcyBMb2dMZXZlbCxcbiAgICAgICAgc291cmNlOiAnTFJVQ2FjaGUnLFxuICAgICAgICBtZXNzYWdlLFxuICAgICAgICBkYXRhLFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBjb250ZXh0VHJhY2tlcj8uZ2V0Q29ycmVsYXRpb25JZCgpLFxuICAgICAgfTtcbiAgICAgIGxvZ01hbmFnZXIubG9nKGVudHJ5KTtcbiAgICB9KTtcbiAgICBjbGVhbnVwcy5wdXNoKHVuc3ViKTtcbiAgfVxuXG4gIC8vIC0tLSBTdGF0ZUNoYW5nZU5vdGlmaWVyIChhcHBsaWNhdGlvbikg4oCUIGV4dGVuZHMgRXZlbnRFbWl0dGVyIC0tLS0tLS0tLS1cbiAgdHJ5IHtcbiAgICBjb25zdCBub3RpZmllciA9IGNvbnRhaW5lci5yZXNvbHZlPHtcbiAgICAgIG9uKGV2ZW50OiBzdHJpbmcsIGhhbmRsZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IGFueTtcbiAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50OiBzdHJpbmcsIGhhbmRsZXI6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IGFueTtcbiAgICB9PignU3RhdGVDaGFuZ2VOb3RpZmllcicpO1xuICAgIGNvbnN0IGhhbmRsZXIgPSAoZXZlbnQ6IHsgdHlwZTogc3RyaW5nOyBwcmV2aW91c1ZhbHVlOiBzdHJpbmcgfCBudWxsOyBuZXdWYWx1ZTogc3RyaW5nIHwgbnVsbCB9KSA9PiB7XG4gICAgICBjb25zdCBlbnRyeTogVW5pZmllZExvZ0VudHJ5ID0ge1xuICAgICAgICBpZDogbG9nTWFuYWdlci5nZW5lcmF0ZUlkKCksXG4gICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICBjYXRlZ29yeTogJ2FwcGxpY2F0aW9uJyxcbiAgICAgICAgbGV2ZWw6ICdpbmZvJyxcbiAgICAgICAgc291cmNlOiAnU3RhdGVDaGFuZ2VOb3RpZmllcicsXG4gICAgICAgIG1lc3NhZ2U6IGBTdGF0ZSBjaGFuZ2U6ICR7ZXZlbnQudHlwZX1gLFxuICAgICAgICBkYXRhOiB7IHByZXZpb3VzVmFsdWU6IGV2ZW50LnByZXZpb3VzVmFsdWUsIG5ld1ZhbHVlOiBldmVudC5uZXdWYWx1ZSB9LFxuICAgICAgICBjb3JyZWxhdGlvbklkOiBjb250ZXh0VHJhY2tlcj8uZ2V0Q29ycmVsYXRpb25JZCgpLFxuICAgICAgfTtcbiAgICAgIGxvZ01hbmFnZXIubG9nKGVudHJ5KTtcbiAgICB9O1xuICAgIG5vdGlmaWVyLm9uKCdzdGF0ZS1jaGFuZ2UnLCBoYW5kbGVyKTtcbiAgICBjbGVhbnVwcy5wdXNoKCgpID0+IG5vdGlmaWVyLnJlbW92ZUxpc3RlbmVyKCdzdGF0ZS1jaGFuZ2UnLCBoYW5kbGVyKSk7XG4gIH0gY2F0Y2ggeyAvKiBTdGF0ZUNoYW5nZU5vdGlmaWVyIG5vdCByZWdpc3RlcmVkICovIH1cblxuICByZXR1cm4gY2xlYW51cHM7XG59XG4iXX0=