@dollhousemcp/mcp-server 1.5.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +494 -111
- package/data/agents/code-reviewer.md +8 -1
- package/data/agents/research-assistant.md +8 -1
- package/data/agents/task-manager.md +8 -1
- package/data/ensembles/business-advisor.md +8 -1
- package/data/ensembles/creative-studio.md +8 -1
- package/data/ensembles/development-team.md +8 -1
- package/data/ensembles/security-analysis-team.md +8 -1
- package/data/memories/conversation-history.md +8 -1
- package/data/memories/learning-progress.md +8 -1
- package/data/memories/project-context.md +8 -1
- package/data/personas/business-consultant.md +8 -1
- package/data/personas/creative-writer.md +8 -1
- package/data/personas/debug-detective.md +8 -1
- package/data/personas/eli5-explainer.md +8 -1
- package/data/personas/security-analyst.md +8 -1
- package/data/personas/technical-analyst.md +8 -1
- package/data/skills/code-review.md +8 -1
- package/data/skills/creative-writing.md +8 -1
- package/data/skills/data-analysis.md +8 -1
- package/data/skills/penetration-testing.md +8 -1
- package/data/skills/research.md +8 -1
- package/data/skills/threat-modeling.md +8 -1
- package/data/skills/translation.md +8 -1
- package/data/templates/code-documentation.md +8 -1
- package/data/templates/email-professional.md +8 -1
- package/data/templates/meeting-notes.md +8 -1
- package/data/templates/penetration-test-report.md +8 -1
- package/data/templates/project-brief.md +8 -1
- package/data/templates/report-executive.md +8 -1
- package/data/templates/security-vulnerability-report.md +8 -1
- package/data/templates/threat-assessment-report.md +8 -1
- package/dist/auth/GitHubAuthManager.d.ts +6 -1
- package/dist/auth/GitHubAuthManager.d.ts.map +1 -1
- package/dist/auth/GitHubAuthManager.js +45 -18
- package/dist/benchmarks/IndexPerformanceBenchmark.d.ts +98 -0
- package/dist/benchmarks/IndexPerformanceBenchmark.d.ts.map +1 -0
- package/dist/benchmarks/IndexPerformanceBenchmark.js +531 -0
- package/dist/cache/CollectionCache.d.ts.map +1 -1
- package/dist/cache/CollectionCache.js +13 -3
- package/dist/cache/CollectionIndexCache.d.ts +77 -0
- package/dist/cache/CollectionIndexCache.d.ts.map +1 -0
- package/dist/cache/CollectionIndexCache.js +349 -0
- package/dist/cache/LRUCache.d.ts +93 -0
- package/dist/cache/LRUCache.d.ts.map +1 -0
- package/dist/cache/LRUCache.js +299 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +2 -1
- package/dist/collection/CollectionBrowser.d.ts +21 -1
- package/dist/collection/CollectionBrowser.d.ts.map +1 -1
- package/dist/collection/CollectionBrowser.js +130 -10
- package/dist/collection/CollectionIndexManager.d.ts +151 -0
- package/dist/collection/CollectionIndexManager.d.ts.map +1 -0
- package/dist/collection/CollectionIndexManager.js +499 -0
- package/dist/collection/CollectionSearch.d.ts +55 -0
- package/dist/collection/CollectionSearch.d.ts.map +1 -1
- package/dist/collection/CollectionSearch.js +338 -13
- package/dist/collection/CollectionSeeder.d.ts.map +1 -1
- package/dist/collection/CollectionSeeder.js +38 -1
- package/dist/collection/ElementInstaller.d.ts +31 -0
- package/dist/collection/ElementInstaller.d.ts.map +1 -1
- package/dist/collection/ElementInstaller.js +77 -15
- package/dist/collection/PersonaSubmitter.d.ts +1 -1
- package/dist/collection/PersonaSubmitter.d.ts.map +1 -1
- package/dist/collection/PersonaSubmitter.js +2 -2
- package/dist/collection/index.d.ts +1 -0
- package/dist/collection/index.d.ts.map +1 -1
- package/dist/collection/index.js +2 -1
- package/dist/config/ConfigManager.d.ts +78 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +216 -0
- package/dist/config/element-types.d.ts +135 -0
- package/dist/config/element-types.d.ts.map +1 -0
- package/dist/config/element-types.js +108 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/portfolio-constants.d.ts +83 -0
- package/dist/config/portfolio-constants.d.ts.map +1 -0
- package/dist/config/portfolio-constants.js +99 -0
- package/dist/elements/BaseElement.d.ts +14 -2
- package/dist/elements/BaseElement.d.ts.map +1 -1
- package/dist/elements/BaseElement.js +88 -6
- package/dist/elements/agents/Agent.d.ts +10 -1
- package/dist/elements/agents/Agent.d.ts.map +1 -1
- package/dist/elements/agents/Agent.js +66 -19
- package/dist/elements/agents/AgentManager.d.ts +2 -0
- package/dist/elements/agents/AgentManager.d.ts.map +1 -1
- package/dist/elements/agents/AgentManager.js +12 -10
- package/dist/elements/skills/Skill.d.ts +10 -1
- package/dist/elements/skills/Skill.d.ts.map +1 -1
- package/dist/elements/skills/Skill.js +40 -3
- package/dist/elements/skills/SkillManager.d.ts +1 -0
- package/dist/elements/skills/SkillManager.d.ts.map +1 -1
- package/dist/elements/skills/SkillManager.js +10 -4
- package/dist/elements/templates/Template.d.ts +10 -1
- package/dist/elements/templates/Template.d.ts.map +1 -1
- package/dist/elements/templates/Template.js +35 -18
- package/dist/elements/templates/TemplateManager.d.ts +1 -1
- package/dist/elements/templates/TemplateManager.d.ts.map +1 -1
- package/dist/elements/templates/TemplateManager.js +6 -5
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +3 -3
- package/dist/index.barrel.d.ts +1 -2
- package/dist/index.barrel.d.ts.map +1 -1
- package/dist/index.barrel.js +2 -4
- package/dist/index.d.ts +143 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1883 -310
- package/dist/persona/PersonaElement.d.ts +10 -0
- package/dist/persona/PersonaElement.d.ts.map +1 -1
- package/dist/persona/PersonaElement.js +55 -32
- package/dist/persona/PersonaElementManager.d.ts.map +1 -1
- package/dist/persona/PersonaElementManager.js +13 -11
- package/dist/persona/PersonaLoader.d.ts.map +1 -1
- package/dist/persona/PersonaLoader.js +8 -2
- package/dist/persona/export-import/PersonaImporter.d.ts.map +1 -1
- package/dist/persona/export-import/PersonaImporter.js +24 -5
- package/dist/persona/export-import/PersonaSharer.d.ts +21 -0
- package/dist/persona/export-import/PersonaSharer.d.ts.map +1 -1
- package/dist/persona/export-import/PersonaSharer.js +198 -22
- package/dist/portfolio/DefaultElementProvider.d.ts +90 -0
- package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
- package/dist/portfolio/DefaultElementProvider.js +499 -7
- package/dist/portfolio/GitHubPortfolioIndexer.d.ts +129 -0
- package/dist/portfolio/GitHubPortfolioIndexer.d.ts.map +1 -0
- package/dist/portfolio/GitHubPortfolioIndexer.js +475 -0
- package/dist/portfolio/MigrationManager.d.ts.map +1 -1
- package/dist/portfolio/MigrationManager.js +136 -3
- package/dist/portfolio/PortfolioIndexManager.d.ts +130 -0
- package/dist/portfolio/PortfolioIndexManager.d.ts.map +1 -0
- package/dist/portfolio/PortfolioIndexManager.js +478 -0
- package/dist/portfolio/PortfolioManager.d.ts +5 -0
- package/dist/portfolio/PortfolioManager.d.ts.map +1 -1
- package/dist/portfolio/PortfolioManager.js +61 -20
- package/dist/portfolio/PortfolioRepoManager.d.ts +75 -0
- package/dist/portfolio/PortfolioRepoManager.d.ts.map +1 -0
- package/dist/portfolio/PortfolioRepoManager.js +337 -0
- package/dist/portfolio/UnifiedIndexManager.d.ts +388 -0
- package/dist/portfolio/UnifiedIndexManager.d.ts.map +1 -0
- package/dist/portfolio/UnifiedIndexManager.js +1434 -0
- package/dist/portfolio/index.d.ts +15 -0
- package/dist/portfolio/index.d.ts.map +1 -0
- package/dist/portfolio/index.js +15 -0
- package/dist/portfolio/types.d.ts +7 -0
- package/dist/portfolio/types.d.ts.map +1 -1
- package/dist/portfolio/types.js +6 -1
- package/dist/security/InputValidator.d.ts.map +1 -1
- package/dist/security/InputValidator.js +50 -48
- package/dist/security/audit/SecurityAuditor.d.ts.map +1 -1
- package/dist/security/audit/SecurityAuditor.js +17 -9
- package/dist/security/audit/config/suppressions.d.ts.map +1 -1
- package/dist/security/audit/config/suppressions.js +19 -3
- package/dist/security/contentValidator.d.ts +2 -0
- package/dist/security/contentValidator.d.ts.map +1 -1
- package/dist/security/contentValidator.js +115 -4
- package/dist/security/secureYamlParser.d.ts +1 -0
- package/dist/security/secureYamlParser.d.ts.map +1 -1
- package/dist/security/secureYamlParser.js +29 -7
- package/dist/security/securityMonitor.d.ts +1 -1
- package/dist/security/securityMonitor.d.ts.map +1 -1
- package/dist/security/securityMonitor.js +1 -1
- package/dist/security/tokenManager.d.ts +1 -1
- package/dist/security/tokenManager.d.ts.map +1 -1
- package/dist/security/tokenManager.js +30 -10
- package/dist/server/ServerSetup.d.ts +22 -2
- package/dist/server/ServerSetup.d.ts.map +1 -1
- package/dist/server/ServerSetup.js +77 -12
- package/dist/server/tools/AuthTools.d.ts.map +1 -1
- package/dist/server/tools/AuthTools.js +33 -1
- package/dist/server/tools/BuildInfoTools.d.ts +25 -0
- package/dist/server/tools/BuildInfoTools.d.ts.map +1 -0
- package/dist/server/tools/BuildInfoTools.js +36 -0
- package/dist/server/tools/CollectionTools.d.ts.map +1 -1
- package/dist/server/tools/CollectionTools.js +55 -46
- package/dist/server/tools/ConfigTools.d.ts.map +1 -1
- package/dist/server/tools/ConfigTools.js +29 -1
- package/dist/server/tools/PersonaTools.d.ts +4 -2
- package/dist/server/tools/PersonaTools.d.ts.map +1 -1
- package/dist/server/tools/PersonaTools.js +5 -152
- package/dist/server/tools/PortfolioTools.d.ts +12 -0
- package/dist/server/tools/PortfolioTools.d.ts.map +1 -0
- package/dist/server/tools/PortfolioTools.js +221 -0
- package/dist/server/tools/index.d.ts +3 -1
- package/dist/server/tools/index.d.ts.map +1 -1
- package/dist/server/tools/index.js +4 -2
- package/dist/server/types.d.ts +40 -5
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +1 -1
- package/dist/services/BuildInfoService.d.ts +84 -0
- package/dist/services/BuildInfoService.d.ts.map +1 -0
- package/dist/services/BuildInfoService.js +271 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.d.ts +54 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.d.ts.map +1 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.js +229 -0
- package/dist/tools/portfolio/submitToPortfolioTool.d.ts +164 -0
- package/dist/tools/portfolio/submitToPortfolioTool.d.ts.map +1 -0
- package/dist/tools/portfolio/submitToPortfolioTool.js +1523 -0
- package/dist/tools/portfolio/types.d.ts +41 -0
- package/dist/tools/portfolio/types.d.ts.map +1 -0
- package/dist/tools/portfolio/types.js +15 -0
- package/dist/types/collection.d.ts +51 -0
- package/dist/types/collection.d.ts.map +1 -1
- package/dist/types/collection.js +1 -1
- package/dist/utils/EarlyTerminationSearch.d.ts +41 -0
- package/dist/utils/EarlyTerminationSearch.d.ts.map +1 -0
- package/dist/utils/EarlyTerminationSearch.js +164 -0
- package/dist/utils/ErrorHandler.d.ts +86 -0
- package/dist/utils/ErrorHandler.d.ts.map +1 -0
- package/dist/utils/ErrorHandler.js +201 -0
- package/dist/utils/FileDiscoveryUtil.d.ts +53 -0
- package/dist/utils/FileDiscoveryUtil.d.ts.map +1 -0
- package/dist/utils/FileDiscoveryUtil.js +169 -0
- package/dist/utils/GitHubRateLimiter.d.ts +88 -0
- package/dist/utils/GitHubRateLimiter.d.ts.map +1 -0
- package/dist/utils/GitHubRateLimiter.js +315 -0
- package/dist/utils/PerformanceMonitor.d.ts +134 -0
- package/dist/utils/PerformanceMonitor.d.ts.map +1 -0
- package/dist/utils/PerformanceMonitor.js +347 -0
- package/dist/utils/RateLimiter.d.ts.map +1 -0
- package/dist/utils/RateLimiter.js +172 -0
- package/dist/utils/SecureDownloader.d.ts +241 -0
- package/dist/utils/SecureDownloader.d.ts.map +1 -0
- package/dist/utils/SecureDownloader.js +759 -0
- package/dist/utils/ToolCache.d.ts +82 -0
- package/dist/utils/ToolCache.d.ts.map +1 -0
- package/dist/utils/ToolCache.js +196 -0
- package/dist/utils/errorCodes.d.ts +136 -0
- package/dist/utils/errorCodes.d.ts.map +1 -0
- package/dist/utils/errorCodes.js +87 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -1
- package/dist/utils/installation.d.ts +1 -1
- package/dist/utils/installation.d.ts.map +1 -1
- package/dist/utils/installation.js +9 -8
- package/dist/utils/searchUtils.d.ts +31 -0
- package/dist/utils/searchUtils.d.ts.map +1 -1
- package/dist/utils/searchUtils.js +62 -1
- package/package.json +17 -7
- package/dist/config/updateConfig.d.ts +0 -84
- package/dist/config/updateConfig.d.ts.map +0 -1
- package/dist/config/updateConfig.js +0 -148
- package/dist/server/tools/UpdateTools.d.ts +0 -10
- package/dist/server/tools/UpdateTools.d.ts.map +0 -1
- package/dist/server/tools/UpdateTools.js +0 -85
- package/dist/update/BackupManager.d.ts +0 -63
- package/dist/update/BackupManager.d.ts.map +0 -1
- package/dist/update/BackupManager.js +0 -370
- package/dist/update/DependencyChecker.d.ts +0 -41
- package/dist/update/DependencyChecker.d.ts.map +0 -1
- package/dist/update/DependencyChecker.js +0 -132
- package/dist/update/RateLimiter.d.ts.map +0 -1
- package/dist/update/RateLimiter.js +0 -172
- package/dist/update/SignatureVerifier.d.ts +0 -71
- package/dist/update/SignatureVerifier.d.ts.map +0 -1
- package/dist/update/SignatureVerifier.js +0 -214
- package/dist/update/UpdateChecker.d.ts +0 -132
- package/dist/update/UpdateChecker.d.ts.map +0 -1
- package/dist/update/UpdateChecker.js +0 -506
- package/dist/update/UpdateManager.d.ts +0 -60
- package/dist/update/UpdateManager.d.ts.map +0 -1
- package/dist/update/UpdateManager.js +0 -730
- package/dist/update/VersionManager.d.ts +0 -31
- package/dist/update/VersionManager.d.ts.map +0 -1
- package/dist/update/VersionManager.js +0 -181
- package/dist/update/index.d.ts +0 -9
- package/dist/update/index.d.ts.map +0 -1
- package/dist/update/index.js +0 -9
- /package/dist/{update → utils}/RateLimiter.d.ts +0 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comprehensive Performance Benchmarking Suite for DollhouseMCP Indexing System
|
|
3
|
+
*
|
|
4
|
+
* Benchmarks:
|
|
5
|
+
* - Search response times under various loads
|
|
6
|
+
* - Memory usage patterns with large datasets
|
|
7
|
+
* - Cache performance and hit rates
|
|
8
|
+
* - Concurrent operation performance
|
|
9
|
+
* - Index building and rebuilding times
|
|
10
|
+
*/
|
|
11
|
+
import { UnifiedIndexManager } from '../portfolio/UnifiedIndexManager.js';
|
|
12
|
+
import { PortfolioIndexManager } from '../portfolio/PortfolioIndexManager.js';
|
|
13
|
+
import { PerformanceMonitor } from '../utils/PerformanceMonitor.js';
|
|
14
|
+
import { logger } from '../utils/logger.js';
|
|
15
|
+
import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
|
|
16
|
+
export class IndexPerformanceBenchmark {
|
|
17
|
+
unifiedIndexManager;
|
|
18
|
+
performanceMonitor;
|
|
19
|
+
benchmarkResults = [];
|
|
20
|
+
constructor() {
|
|
21
|
+
this.unifiedIndexManager = UnifiedIndexManager.getInstance();
|
|
22
|
+
this.performanceMonitor = PerformanceMonitor.getInstance();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Run comprehensive performance benchmark suite
|
|
26
|
+
*/
|
|
27
|
+
async runFullBenchmarkSuite() {
|
|
28
|
+
logger.info('Starting comprehensive performance benchmark suite');
|
|
29
|
+
const suiteStartTime = Date.now();
|
|
30
|
+
// Clear caches and reset state
|
|
31
|
+
await this.resetBenchmarkEnvironment();
|
|
32
|
+
const benchmarks = [
|
|
33
|
+
() => this.benchmarkSearchPerformance(),
|
|
34
|
+
() => this.benchmarkMemoryUsage(),
|
|
35
|
+
() => this.benchmarkCachePerformance(),
|
|
36
|
+
() => this.benchmarkConcurrentOperations(),
|
|
37
|
+
() => this.benchmarkLargeDatasetHandling(),
|
|
38
|
+
() => this.benchmarkIndexBuilding(),
|
|
39
|
+
() => this.benchmarkStreamingSearch(),
|
|
40
|
+
() => this.benchmarkLazyLoading()
|
|
41
|
+
];
|
|
42
|
+
// Run each benchmark
|
|
43
|
+
for (const benchmark of benchmarks) {
|
|
44
|
+
try {
|
|
45
|
+
const result = await benchmark();
|
|
46
|
+
this.benchmarkResults.push(result);
|
|
47
|
+
// Allow garbage collection between benchmarks
|
|
48
|
+
await this.waitForGC();
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
logger.error('Benchmark failed', {
|
|
52
|
+
error: error instanceof Error ? error.message : String(error)
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const suite = {
|
|
57
|
+
name: 'DollhouseMCP Index Performance Suite',
|
|
58
|
+
results: this.benchmarkResults,
|
|
59
|
+
summary: this.generateSummary(Date.now() - suiteStartTime)
|
|
60
|
+
};
|
|
61
|
+
logger.info('Benchmark suite completed', {
|
|
62
|
+
totalBenchmarks: suite.results.length,
|
|
63
|
+
totalDuration: suite.summary.totalDuration,
|
|
64
|
+
recommendations: suite.summary.recommendations.length
|
|
65
|
+
});
|
|
66
|
+
return suite;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Benchmark search performance with various query patterns
|
|
70
|
+
*/
|
|
71
|
+
async benchmarkSearchPerformance() {
|
|
72
|
+
const testQueries = [
|
|
73
|
+
'creative',
|
|
74
|
+
'professional assistant',
|
|
75
|
+
'development tools',
|
|
76
|
+
'data analysis',
|
|
77
|
+
'machine learning expert',
|
|
78
|
+
'a very long and complex query that might stress the search system with multiple terms and complex patterns',
|
|
79
|
+
'specific_exact_match',
|
|
80
|
+
'' // Empty query test
|
|
81
|
+
];
|
|
82
|
+
const memoryBefore = process.memoryUsage().heapUsed;
|
|
83
|
+
let peakMemory = memoryBefore;
|
|
84
|
+
const startTime = Date.now();
|
|
85
|
+
let totalOperations = 0;
|
|
86
|
+
let cacheHits = 0;
|
|
87
|
+
for (const query of testQueries) {
|
|
88
|
+
for (let i = 0; i < 10; i++) { // 10 iterations per query
|
|
89
|
+
const options = {
|
|
90
|
+
query,
|
|
91
|
+
includeLocal: true,
|
|
92
|
+
includeGitHub: true,
|
|
93
|
+
includeCollection: false,
|
|
94
|
+
pageSize: 20
|
|
95
|
+
};
|
|
96
|
+
await this.unifiedIndexManager.search(options);
|
|
97
|
+
totalOperations++;
|
|
98
|
+
// Track peak memory
|
|
99
|
+
const currentMemory = process.memoryUsage().heapUsed;
|
|
100
|
+
if (currentMemory > peakMemory) {
|
|
101
|
+
peakMemory = currentMemory;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const endTime = Date.now();
|
|
106
|
+
const memoryAfter = process.memoryUsage().heapUsed;
|
|
107
|
+
const duration = endTime - startTime;
|
|
108
|
+
const performanceStats = this.unifiedIndexManager.getPerformanceStats();
|
|
109
|
+
const searchStats = performanceStats.searchStats;
|
|
110
|
+
return {
|
|
111
|
+
name: 'Search Performance',
|
|
112
|
+
duration,
|
|
113
|
+
memoryUsage: {
|
|
114
|
+
before: memoryBefore / (1024 * 1024),
|
|
115
|
+
after: memoryAfter / (1024 * 1024),
|
|
116
|
+
peak: peakMemory / (1024 * 1024)
|
|
117
|
+
},
|
|
118
|
+
throughput: totalOperations / (duration / 1000),
|
|
119
|
+
cacheStats: {
|
|
120
|
+
hitRate: searchStats.cacheHitRate || 0,
|
|
121
|
+
totalOperations
|
|
122
|
+
},
|
|
123
|
+
metadata: {
|
|
124
|
+
avgSearchTime: searchStats.averageTime || 0,
|
|
125
|
+
p95SearchTime: searchStats.p95Time || 0,
|
|
126
|
+
slowQueries: searchStats.slowQueries || 0
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Benchmark memory usage with large result sets
|
|
132
|
+
*/
|
|
133
|
+
async benchmarkMemoryUsage() {
|
|
134
|
+
const memoryBefore = process.memoryUsage().heapUsed;
|
|
135
|
+
let peakMemory = memoryBefore;
|
|
136
|
+
const startTime = Date.now();
|
|
137
|
+
// Create increasingly large search operations
|
|
138
|
+
const largeBatches = [100, 500, 1000, 2000];
|
|
139
|
+
for (const batchSize of largeBatches) {
|
|
140
|
+
const options = {
|
|
141
|
+
query: '', // Empty query to get all results
|
|
142
|
+
includeLocal: true,
|
|
143
|
+
includeGitHub: true,
|
|
144
|
+
includeCollection: true,
|
|
145
|
+
pageSize: batchSize,
|
|
146
|
+
maxResults: batchSize
|
|
147
|
+
};
|
|
148
|
+
await this.unifiedIndexManager.search(options);
|
|
149
|
+
const currentMemory = process.memoryUsage().heapUsed;
|
|
150
|
+
if (currentMemory > peakMemory) {
|
|
151
|
+
peakMemory = currentMemory;
|
|
152
|
+
}
|
|
153
|
+
// Check for memory leaks
|
|
154
|
+
if (currentMemory > memoryBefore * 2) {
|
|
155
|
+
logger.warn('Potential memory leak detected', {
|
|
156
|
+
beforeMB: memoryBefore / (1024 * 1024),
|
|
157
|
+
currentMB: currentMemory / (1024 * 1024),
|
|
158
|
+
batchSize
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const endTime = Date.now();
|
|
163
|
+
const memoryAfter = process.memoryUsage().heapUsed;
|
|
164
|
+
return {
|
|
165
|
+
name: 'Memory Usage',
|
|
166
|
+
duration: endTime - startTime,
|
|
167
|
+
memoryUsage: {
|
|
168
|
+
before: memoryBefore / (1024 * 1024),
|
|
169
|
+
after: memoryAfter / (1024 * 1024),
|
|
170
|
+
peak: peakMemory / (1024 * 1024)
|
|
171
|
+
},
|
|
172
|
+
metadata: {
|
|
173
|
+
memoryGrowthMB: (memoryAfter - memoryBefore) / (1024 * 1024),
|
|
174
|
+
peakGrowthMB: (peakMemory - memoryBefore) / (1024 * 1024),
|
|
175
|
+
testedBatchSizes: largeBatches
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Benchmark cache performance and hit rates
|
|
181
|
+
*/
|
|
182
|
+
async benchmarkCachePerformance() {
|
|
183
|
+
const memoryBefore = process.memoryUsage().heapUsed;
|
|
184
|
+
const startTime = Date.now();
|
|
185
|
+
// Test cache warming and hit rate optimization
|
|
186
|
+
const rawQueries = ['test', 'performance', 'benchmark', 'cache'];
|
|
187
|
+
// DMCP-SEC-004 FIX: Normalize Unicode in all user input
|
|
188
|
+
const testQueries = rawQueries.map(q => {
|
|
189
|
+
const normalized = UnicodeValidator.normalize(q);
|
|
190
|
+
return normalized.isValid ? normalized.normalizedContent : q;
|
|
191
|
+
});
|
|
192
|
+
let totalOperations = 0;
|
|
193
|
+
let cacheHitsBefore = 0;
|
|
194
|
+
// First pass - cache misses expected
|
|
195
|
+
for (const query of testQueries) {
|
|
196
|
+
for (let i = 0; i < 5; i++) {
|
|
197
|
+
await this.unifiedIndexManager.search({ query, pageSize: 10 });
|
|
198
|
+
totalOperations++;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const statsAfterFirstPass = this.unifiedIndexManager.getPerformanceStats();
|
|
202
|
+
cacheHitsBefore = statsAfterFirstPass.cacheStats.searchResults.hitCount;
|
|
203
|
+
// Second pass - cache hits expected
|
|
204
|
+
for (const query of testQueries) {
|
|
205
|
+
for (let i = 0; i < 5; i++) {
|
|
206
|
+
await this.unifiedIndexManager.search({ query, pageSize: 10 });
|
|
207
|
+
totalOperations++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const endTime = Date.now();
|
|
211
|
+
const memoryAfter = process.memoryUsage().heapUsed;
|
|
212
|
+
const finalStats = this.unifiedIndexManager.getPerformanceStats();
|
|
213
|
+
const cacheStats = finalStats.cacheStats.searchResults;
|
|
214
|
+
return {
|
|
215
|
+
name: 'Cache Performance',
|
|
216
|
+
duration: endTime - startTime,
|
|
217
|
+
memoryUsage: {
|
|
218
|
+
before: memoryBefore / (1024 * 1024),
|
|
219
|
+
after: memoryAfter / (1024 * 1024),
|
|
220
|
+
peak: memoryAfter / (1024 * 1024)
|
|
221
|
+
},
|
|
222
|
+
cacheStats: {
|
|
223
|
+
hitRate: cacheStats.hitRate,
|
|
224
|
+
totalOperations
|
|
225
|
+
},
|
|
226
|
+
metadata: {
|
|
227
|
+
cacheSize: cacheStats.size,
|
|
228
|
+
evictions: cacheStats.evictionCount,
|
|
229
|
+
hitRateImprovement: cacheStats.hitRate
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Benchmark concurrent search operations
|
|
235
|
+
*/
|
|
236
|
+
async benchmarkConcurrentOperations() {
|
|
237
|
+
const memoryBefore = process.memoryUsage().heapUsed;
|
|
238
|
+
let peakMemory = memoryBefore;
|
|
239
|
+
const startTime = Date.now();
|
|
240
|
+
const concurrencyLevels = [5, 10, 20, 50];
|
|
241
|
+
let totalOperations = 0;
|
|
242
|
+
for (const concurrency of concurrencyLevels) {
|
|
243
|
+
const promises = [];
|
|
244
|
+
for (let i = 0; i < concurrency; i++) {
|
|
245
|
+
const searchPromise = this.unifiedIndexManager.search({
|
|
246
|
+
query: `concurrent_test_${i}`,
|
|
247
|
+
pageSize: 20
|
|
248
|
+
});
|
|
249
|
+
promises.push(searchPromise);
|
|
250
|
+
totalOperations++;
|
|
251
|
+
}
|
|
252
|
+
await Promise.all(promises);
|
|
253
|
+
const currentMemory = process.memoryUsage().heapUsed;
|
|
254
|
+
if (currentMemory > peakMemory) {
|
|
255
|
+
peakMemory = currentMemory;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const endTime = Date.now();
|
|
259
|
+
const memoryAfter = process.memoryUsage().heapUsed;
|
|
260
|
+
const duration = endTime - startTime;
|
|
261
|
+
return {
|
|
262
|
+
name: 'Concurrent Operations',
|
|
263
|
+
duration,
|
|
264
|
+
memoryUsage: {
|
|
265
|
+
before: memoryBefore / (1024 * 1024),
|
|
266
|
+
after: memoryAfter / (1024 * 1024),
|
|
267
|
+
peak: peakMemory / (1024 * 1024)
|
|
268
|
+
},
|
|
269
|
+
throughput: totalOperations / (duration / 1000),
|
|
270
|
+
metadata: {
|
|
271
|
+
testedConcurrencyLevels: concurrencyLevels,
|
|
272
|
+
totalConcurrentOps: totalOperations
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Benchmark large dataset handling (simulated)
|
|
278
|
+
*/
|
|
279
|
+
async benchmarkLargeDatasetHandling() {
|
|
280
|
+
const memoryBefore = process.memoryUsage().heapUsed;
|
|
281
|
+
let peakMemory = memoryBefore;
|
|
282
|
+
const startTime = Date.now();
|
|
283
|
+
// Simulate searches that would stress a large dataset
|
|
284
|
+
const stressTestQueries = [
|
|
285
|
+
{ query: '', pageSize: 1000 }, // Get all results
|
|
286
|
+
{ query: 'common_term', pageSize: 500 }, // High result count
|
|
287
|
+
{ query: 'very_specific_unique_term', pageSize: 100 }, // Low result count
|
|
288
|
+
{ query: 'partial_match_test', pageSize: 200 } // Medium result count
|
|
289
|
+
];
|
|
290
|
+
let totalResults = 0;
|
|
291
|
+
for (const testCase of stressTestQueries) {
|
|
292
|
+
const results = await this.unifiedIndexManager.search({
|
|
293
|
+
query: testCase.query,
|
|
294
|
+
pageSize: testCase.pageSize,
|
|
295
|
+
includeLocal: true,
|
|
296
|
+
includeGitHub: true,
|
|
297
|
+
includeCollection: true
|
|
298
|
+
});
|
|
299
|
+
totalResults += results.length;
|
|
300
|
+
const currentMemory = process.memoryUsage().heapUsed;
|
|
301
|
+
if (currentMemory > peakMemory) {
|
|
302
|
+
peakMemory = currentMemory;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
const endTime = Date.now();
|
|
306
|
+
const memoryAfter = process.memoryUsage().heapUsed;
|
|
307
|
+
return {
|
|
308
|
+
name: 'Large Dataset Handling',
|
|
309
|
+
duration: endTime - startTime,
|
|
310
|
+
memoryUsage: {
|
|
311
|
+
before: memoryBefore / (1024 * 1024),
|
|
312
|
+
after: memoryAfter / (1024 * 1024),
|
|
313
|
+
peak: peakMemory / (1024 * 1024)
|
|
314
|
+
},
|
|
315
|
+
metadata: {
|
|
316
|
+
totalResultsProcessed: totalResults,
|
|
317
|
+
averageResultsPerQuery: totalResults / stressTestQueries.length,
|
|
318
|
+
memoryPerResult: (peakMemory - memoryBefore) / totalResults
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Benchmark index building performance
|
|
324
|
+
*/
|
|
325
|
+
async benchmarkIndexBuilding() {
|
|
326
|
+
const memoryBefore = process.memoryUsage().heapUsed;
|
|
327
|
+
const startTime = Date.now();
|
|
328
|
+
// Force rebuild of all indexes
|
|
329
|
+
await this.unifiedIndexManager.rebuildAll();
|
|
330
|
+
const endTime = Date.now();
|
|
331
|
+
const memoryAfter = process.memoryUsage().heapUsed;
|
|
332
|
+
const localStats = await PortfolioIndexManager.getInstance().getStats();
|
|
333
|
+
return {
|
|
334
|
+
name: 'Index Building',
|
|
335
|
+
duration: endTime - startTime,
|
|
336
|
+
memoryUsage: {
|
|
337
|
+
before: memoryBefore / (1024 * 1024),
|
|
338
|
+
after: memoryAfter / (1024 * 1024),
|
|
339
|
+
peak: memoryAfter / (1024 * 1024)
|
|
340
|
+
},
|
|
341
|
+
metadata: {
|
|
342
|
+
totalElementsIndexed: localStats.totalElements,
|
|
343
|
+
indexingRate: localStats.totalElements / ((endTime - startTime) / 1000),
|
|
344
|
+
isStale: localStats.isStale
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Benchmark streaming search performance
|
|
350
|
+
*/
|
|
351
|
+
async benchmarkStreamingSearch() {
|
|
352
|
+
const memoryBefore = process.memoryUsage().heapUsed;
|
|
353
|
+
let peakMemory = memoryBefore;
|
|
354
|
+
const startTime = Date.now();
|
|
355
|
+
const streamingQueries = [
|
|
356
|
+
{ query: 'test', maxResults: 100 },
|
|
357
|
+
{ query: 'assistant', maxResults: 200 },
|
|
358
|
+
{ query: 'creative', maxResults: 150 }
|
|
359
|
+
];
|
|
360
|
+
let totalResults = 0;
|
|
361
|
+
for (const testCase of streamingQueries) {
|
|
362
|
+
const results = await this.unifiedIndexManager.search({
|
|
363
|
+
query: testCase.query,
|
|
364
|
+
streamResults: true,
|
|
365
|
+
maxResults: testCase.maxResults,
|
|
366
|
+
includeLocal: true,
|
|
367
|
+
includeGitHub: true
|
|
368
|
+
});
|
|
369
|
+
totalResults += results.length;
|
|
370
|
+
const currentMemory = process.memoryUsage().heapUsed;
|
|
371
|
+
if (currentMemory > peakMemory) {
|
|
372
|
+
peakMemory = currentMemory;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const endTime = Date.now();
|
|
376
|
+
const memoryAfter = process.memoryUsage().heapUsed;
|
|
377
|
+
return {
|
|
378
|
+
name: 'Streaming Search',
|
|
379
|
+
duration: endTime - startTime,
|
|
380
|
+
memoryUsage: {
|
|
381
|
+
before: memoryBefore / (1024 * 1024),
|
|
382
|
+
after: memoryAfter / (1024 * 1024),
|
|
383
|
+
peak: peakMemory / (1024 * 1024)
|
|
384
|
+
},
|
|
385
|
+
throughput: totalResults / ((endTime - startTime) / 1000),
|
|
386
|
+
metadata: {
|
|
387
|
+
totalStreamedResults: totalResults,
|
|
388
|
+
averageMemoryPerResult: (peakMemory - memoryBefore) / totalResults
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Benchmark lazy loading performance
|
|
394
|
+
*/
|
|
395
|
+
async benchmarkLazyLoading() {
|
|
396
|
+
const memoryBefore = process.memoryUsage().heapUsed;
|
|
397
|
+
const startTime = Date.now();
|
|
398
|
+
// Test lazy loading with different configurations
|
|
399
|
+
const lazyLoadTests = [
|
|
400
|
+
{ query: 'lazy_test_1', lazyLoad: true, includeLocal: true, includeGitHub: false, includeCollection: false },
|
|
401
|
+
{ query: 'lazy_test_2', lazyLoad: true, includeLocal: false, includeGitHub: true, includeCollection: false },
|
|
402
|
+
{ query: 'lazy_test_3', lazyLoad: true, includeLocal: true, includeGitHub: true, includeCollection: true },
|
|
403
|
+
{ query: 'lazy_test_4', lazyLoad: false, includeLocal: true, includeGitHub: true, includeCollection: true }
|
|
404
|
+
];
|
|
405
|
+
let totalOperations = 0;
|
|
406
|
+
for (const testCase of lazyLoadTests) {
|
|
407
|
+
await this.unifiedIndexManager.search(testCase);
|
|
408
|
+
totalOperations++;
|
|
409
|
+
}
|
|
410
|
+
const endTime = Date.now();
|
|
411
|
+
const memoryAfter = process.memoryUsage().heapUsed;
|
|
412
|
+
return {
|
|
413
|
+
name: 'Lazy Loading',
|
|
414
|
+
duration: endTime - startTime,
|
|
415
|
+
memoryUsage: {
|
|
416
|
+
before: memoryBefore / (1024 * 1024),
|
|
417
|
+
after: memoryAfter / (1024 * 1024),
|
|
418
|
+
peak: memoryAfter / (1024 * 1024)
|
|
419
|
+
},
|
|
420
|
+
throughput: totalOperations / ((endTime - startTime) / 1000),
|
|
421
|
+
metadata: {
|
|
422
|
+
totalLazyOperations: totalOperations,
|
|
423
|
+
averageOperationTime: (endTime - startTime) / totalOperations
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Reset benchmark environment
|
|
429
|
+
*/
|
|
430
|
+
async resetBenchmarkEnvironment() {
|
|
431
|
+
await this.unifiedIndexManager.rebuildAll();
|
|
432
|
+
this.performanceMonitor.reset();
|
|
433
|
+
this.benchmarkResults = [];
|
|
434
|
+
// Force garbage collection if available
|
|
435
|
+
if (global.gc) {
|
|
436
|
+
global.gc();
|
|
437
|
+
}
|
|
438
|
+
await this.waitForGC();
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Wait for garbage collection to complete
|
|
442
|
+
*/
|
|
443
|
+
async waitForGC() {
|
|
444
|
+
return new Promise(resolve => {
|
|
445
|
+
setImmediate(() => {
|
|
446
|
+
if (global.gc) {
|
|
447
|
+
global.gc();
|
|
448
|
+
}
|
|
449
|
+
setTimeout(resolve, 100); // Wait 100ms for GC to complete
|
|
450
|
+
});
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Generate benchmark summary and recommendations
|
|
455
|
+
*/
|
|
456
|
+
generateSummary(totalDuration) {
|
|
457
|
+
const recommendations = [];
|
|
458
|
+
let totalMemoryUsage = 0;
|
|
459
|
+
let peakMemoryUsage = 0;
|
|
460
|
+
// Analyze results and generate recommendations
|
|
461
|
+
for (const result of this.benchmarkResults) {
|
|
462
|
+
totalMemoryUsage += result.memoryUsage.after - result.memoryUsage.before;
|
|
463
|
+
peakMemoryUsage = Math.max(peakMemoryUsage, result.memoryUsage.peak);
|
|
464
|
+
// Check for performance issues
|
|
465
|
+
if (result.name === 'Search Performance' && result.metadata?.avgSearchTime > 100) {
|
|
466
|
+
recommendations.push('Average search time exceeds 100ms. Consider query optimization or increased caching.');
|
|
467
|
+
}
|
|
468
|
+
if (result.memoryUsage.peak > 200) {
|
|
469
|
+
recommendations.push(`High memory usage detected in ${result.name} (${result.memoryUsage.peak.toFixed(1)}MB). Consider memory optimization.`);
|
|
470
|
+
}
|
|
471
|
+
if (result.cacheStats?.hitRate && result.cacheStats.hitRate < 0.5) {
|
|
472
|
+
recommendations.push(`Low cache hit rate in ${result.name} (${result.cacheStats.hitRate.toFixed(2)}). Consider cache size increase or TTL adjustment.`);
|
|
473
|
+
}
|
|
474
|
+
if (result.throughput && result.throughput < 10) {
|
|
475
|
+
recommendations.push(`Low throughput in ${result.name} (${result.throughput.toFixed(1)} ops/sec). Consider performance optimization.`);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
// General recommendations
|
|
479
|
+
if (peakMemoryUsage > 50) {
|
|
480
|
+
recommendations.push('Peak memory usage exceeds 50MB. Consider implementing more aggressive memory cleanup.');
|
|
481
|
+
}
|
|
482
|
+
if (totalDuration > 30000) {
|
|
483
|
+
recommendations.push('Total benchmark duration exceeds 30 seconds. Consider performance optimizations.');
|
|
484
|
+
}
|
|
485
|
+
return {
|
|
486
|
+
totalDuration,
|
|
487
|
+
averageMemoryUsage: totalMemoryUsage / this.benchmarkResults.length,
|
|
488
|
+
peakMemoryUsage,
|
|
489
|
+
recommendations
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Export benchmark results to JSON
|
|
494
|
+
*/
|
|
495
|
+
exportResults(suite) {
|
|
496
|
+
return JSON.stringify(suite, null, 2);
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Generate benchmark report
|
|
500
|
+
*/
|
|
501
|
+
generateReport(suite) {
|
|
502
|
+
let report = `# DollhouseMCP Index Performance Benchmark Report\n\n`;
|
|
503
|
+
report += `**Generated:** ${new Date().toISOString()}\n`;
|
|
504
|
+
report += `**Total Duration:** ${suite.summary.totalDuration}ms\n`;
|
|
505
|
+
report += `**Peak Memory Usage:** ${suite.summary.peakMemoryUsage.toFixed(1)}MB\n\n`;
|
|
506
|
+
report += `## Benchmark Results\n\n`;
|
|
507
|
+
for (const result of suite.results) {
|
|
508
|
+
report += `### ${result.name}\n`;
|
|
509
|
+
report += `- **Duration:** ${result.duration}ms\n`;
|
|
510
|
+
report += `- **Memory Usage:** ${result.memoryUsage.before.toFixed(1)}MB → ${result.memoryUsage.after.toFixed(1)}MB (Peak: ${result.memoryUsage.peak.toFixed(1)}MB)\n`;
|
|
511
|
+
if (result.throughput) {
|
|
512
|
+
report += `- **Throughput:** ${result.throughput.toFixed(1)} ops/sec\n`;
|
|
513
|
+
}
|
|
514
|
+
if (result.cacheStats) {
|
|
515
|
+
report += `- **Cache Hit Rate:** ${result.cacheStats.hitRate.toFixed(2)}\n`;
|
|
516
|
+
}
|
|
517
|
+
report += `\n`;
|
|
518
|
+
}
|
|
519
|
+
report += `## Recommendations\n\n`;
|
|
520
|
+
if (suite.summary.recommendations.length === 0) {
|
|
521
|
+
report += `No performance issues detected. System is performing within acceptable parameters.\n`;
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
for (const recommendation of suite.summary.recommendations) {
|
|
525
|
+
report += `- ${recommendation}\n`;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return report;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSW5kZXhQZXJmb3JtYW5jZUJlbmNobWFyay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iZW5jaG1hcmtzL0luZGV4UGVyZm9ybWFuY2VCZW5jaG1hcmsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7OztHQVNHO0FBRUgsT0FBTyxFQUFFLG1CQUFtQixFQUF3QixNQUFNLHFDQUFxQyxDQUFDO0FBQ2hHLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBRTlFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBR3BFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQTZCOUUsTUFBTSxPQUFPLHlCQUF5QjtJQUM1QixtQkFBbUIsQ0FBc0I7SUFDekMsa0JBQWtCLENBQXFCO0lBQ3ZDLGdCQUFnQixHQUFzQixFQUFFLENBQUM7SUFFakQ7UUFDRSxJQUFJLENBQUMsbUJBQW1CLEdBQUcsbUJBQW1CLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDN0QsSUFBSSxDQUFDLGtCQUFrQixHQUFHLGtCQUFrQixDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzdELENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxxQkFBcUI7UUFDekIsTUFBTSxDQUFDLElBQUksQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUVsQywrQkFBK0I7UUFDL0IsTUFBTSxJQUFJLENBQUMseUJBQXlCLEVBQUUsQ0FBQztRQUV2QyxNQUFNLFVBQVUsR0FBRztZQUNqQixHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsMEJBQTBCLEVBQUU7WUFDdkMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLG9CQUFvQixFQUFFO1lBQ2pDLEdB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Q0FBQzthQUFNLENBQUM7WUFDTixLQUFLLE1BQU0sY0FBYyxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQzNELE1BQU0sSUFBSSxLQUFLLGNBQWMsSUFBSSxDQUFDO1lBQ3BDLENBQUM7UUFDSCxDQUFDO1FBRUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb21wcmVoZW5zaXZlIFBlcmZvcm1hbmNlIEJlbmNobWFya2luZyBTdWl0ZSBmb3IgRG9sbGhvdXNlTUNQIEluZGV4aW5nIFN5c3RlbVxuICogXG4gKiBCZW5jaG1hcmtzOlxuICogLSBTZWFyY2ggcmVzcG9uc2UgdGltZXMgdW5kZXIgdmFyaW91cyBsb2Fkc1xuICogLSBNZW1vcnkgdXNhZ2UgcGF0dGVybnMgd2l0aCBsYXJnZSBkYXRhc2V0c1xuICogLSBDYWNoZSBwZXJmb3JtYW5jZSBhbmQgaGl0IHJhdGVzXG4gKiAtIENvbmN1cnJlbnQgb3BlcmF0aW9uIHBlcmZvcm1hbmNlXG4gKiAtIEluZGV4IGJ1aWxkaW5nIGFuZCByZWJ1aWxkaW5nIHRpbWVzXG4gKi9cblxuaW1wb3J0IHsgVW5pZmllZEluZGV4TWFuYWdlciwgVW5pZmllZFNlYXJjaE9wdGlvbnMgfSBmcm9tICcuLi9wb3J0Zm9saW8vVW5pZmllZEluZGV4TWFuYWdlci5qcyc7XG5pbXBvcnQgeyBQb3J0Zm9saW9JbmRleE1hbmFnZXIgfSBmcm9tICcuLi9wb3J0Zm9saW8vUG9ydGZvbGlvSW5kZXhNYW5hZ2VyLmpzJztcbmltcG9ydCB7IENvbGxlY3Rpb25JbmRleENhY2hlIH0gZnJvbSAnLi4vY2FjaGUvQ29sbGVjdGlvbkluZGV4Q2FjaGUuanMnO1xuaW1wb3J0IHsgUGVyZm9ybWFuY2VNb25pdG9yIH0gZnJvbSAnLi4vdXRpbHMvUGVyZm9ybWFuY2VNb25pdG9yLmpzJztcbmltcG9ydCB7IEdpdEh1YkNsaWVudCB9IGZyb20gJy4uL2NvbGxlY3Rpb24vR2l0SHViQ2xpZW50LmpzJztcbmltcG9ydCB7IEFQSUNhY2hlIH0gZnJvbSAnLi4vY2FjaGUvQVBJQ2FjaGUuanMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IFVuaWNvZGVWYWxpZGF0b3IgfSBmcm9tICcuLi9zZWN1cml0eS92YWxpZGF0b3JzL3VuaWNvZGVWYWxpZGF0b3IuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJlbmNobWFya1Jlc3VsdCB7XG4gIG5hbWU6IHN0cmluZztcbiAgZHVyYXRpb246IG51bWJlcjtcbiAgbWVtb3J5VXNhZ2U6IHtcbiAgICBiZWZvcmU6IG51bWJlcjtcbiAgICBhZnRlcjogbnVtYmVyO1xuICAgIHBlYWs6IG51bWJlcjtcbiAgfTtcbiAgdGhyb3VnaHB1dD86IG51bWJlcjsgLy8gb3BlcmF0aW9ucyBwZXIgc2Vjb25kXG4gIGNhY2hlU3RhdHM/OiB7XG4gICAgaGl0UmF0ZTogbnVtYmVyO1xuICAgIHRvdGFsT3BlcmF0aW9uczogbnVtYmVyO1xuICB9O1xuICBtZXRhZGF0YT86IGFueTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCZW5jaG1hcmtTdWl0ZSB7XG4gIG5hbWU6IHN0cmluZztcbiAgcmVzdWx0czogQmVuY2htYXJrUmVzdWx0W107XG4gIHN1bW1hcnk6IHtcbiAgICB0b3RhbER1cmF0aW9uOiBudW1iZXI7XG4gICAgYXZlcmFnZU1lbW9yeVVzYWdlOiBudW1iZXI7XG4gICAgcGVha01lbW9yeVVzYWdlOiBudW1iZXI7XG4gICAgcmVjb21tZW5kYXRpb25zOiBzdHJpbmdbXTtcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIEluZGV4UGVyZm9ybWFuY2VCZW5jaG1hcmsge1xuICBwcml2YXRlIHVuaWZpZWRJbmRleE1hbmFnZXI6IFVuaWZpZWRJbmRleE1hbmFnZXI7XG4gIHByaXZhdGUgcGVyZm9ybWFuY2VNb25pdG9yOiBQZXJmb3JtYW5jZU1vbml0b3I7XG4gIHByaXZhdGUgYmVuY2htYXJrUmVzdWx0czogQmVuY2htYXJrUmVzdWx0W10gPSBbXTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnVuaWZpZWRJbmRleE1hbmFnZXIgPSBVbmlmaWVkSW5kZXhNYW5hZ2VyLmdldEluc3RhbmNlKCk7XG4gICAgdGhpcy5wZXJmb3JtYW5jZU1vbml0b3IgPSBQZXJmb3JtYW5jZU1vbml0b3IuZ2V0SW5zdGFuY2UoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW4gY29tcHJlaGVuc2l2ZSBwZXJmb3JtYW5jZSBiZW5jaG1hcmsgc3VpdGVcbiAgICovXG4gIGFzeW5jIHJ1bkZ1bGxCZW5jaG1hcmtTdWl0ZSgpOiBQcm9taXNlPEJlbmNobWFya1N1aXRlPiB7XG4gICAgbG9nZ2VyLmluZm8oJ1N0YXJ0aW5nIGNvbXByZWhlbnNpdmUgcGVyZm9ybWFuY2UgYmVuY2htYXJrIHN1aXRlJyk7XG4gICAgY29uc3Qgc3VpdGVTdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgLy8gQ2xlYXIgY2FjaGVzIGFuZCByZXNldCBzdGF0ZVxuICAgIGF3YWl0IHRoaXMucmVzZXRCZW5jaG1hcmtFbnZpcm9ubWVudCgpO1xuXG4gICAgY29uc3QgYmVuY2htYXJrcyA9IFtcbiAgICAgICgpID0+IHRoaXMuYmVuY2htYXJrU2VhcmNoUGVyZm9ybWFuY2UoKSxcbiAgICAgICgpID0+IHRoaXMuYmVuY2htYXJrTWVtb3J5VXNhZ2UoKSxcbiAgICAgICgpID0+IHRoaXMuYmVuY2htYXJrQ2FjaGVQZXJmb3JtYW5jZSgpLFxuICAgICAgKCkgPT4gdGhpcy5iZW5jaG1hcmtDb25jdXJyZW50T3BlcmF0aW9ucygpLFxuICAgICAgKCkgPT4gdGhpcy5iZW5jaG1hcmtMYXJnZURhdGFzZXRIYW5kbGluZygpLFxuICAgICAgKCkgPT4gdGhpcy5iZW5jaG1hcmtJbmRleEJ1aWxkaW5nKCksXG4gICAgICAoKSA9PiB0aGlzLmJlbmNobWFya1N0cmVhbWluZ1NlYXJjaCgpLFxuICAgICAgKCkgPT4gdGhpcy5iZW5jaG1hcmtMYXp5TG9hZGluZygpXG4gICAgXTtcblxuICAgIC8vIFJ1biBlYWNoIGJlbmNobWFya1xuICAgIGZvciAoY29uc3QgYmVuY2htYXJrIG9mIGJlbmNobWFya3MpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGJlbmNobWFyaygpO1xuICAgICAgICB0aGlzLmJlbmNobWFya1Jlc3VsdHMucHVzaChyZXN1bHQpO1xuICAgICAgICBcbiAgICAgICAgLy8gQWxsb3cgZ2FyYmFnZSBjb2xsZWN0aW9uIGJldHdlZW4gYmVuY2htYXJrc1xuICAgICAgICBhd2FpdCB0aGlzLndhaXRGb3JHQygpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgbG9nZ2VyLmVycm9yKCdCZW5jaG1hcmsgZmFpbGVkJywge1xuICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgc3VpdGU6IEJlbmNobWFya1N1aXRlID0ge1xuICAgICAgbmFtZTogJ0RvbGxob3VzZU1DUCBJbmRleCBQZXJmb3JtYW5jZSBTdWl0ZScsXG4gICAgICByZXN1bHRzOiB0aGlzLmJlbmNobWFya1Jlc3VsdHMsXG4gICAgICBzdW1tYXJ5OiB0aGlzLmdlbmVyYXRlU3VtbWFyeShEYXRlLm5vdygpIC0gc3VpdGVTdGFydFRpbWUpXG4gICAgfTtcblxuICAgIGxvZ2dlci5pbmZvKCdCZW5jaG1hcmsgc3VpdGUgY29tcGxldGVkJywge1xuICAgICAgdG90YWxCZW5jaG1hcmtzOiBzdWl0ZS5yZXN1bHRzLmxlbmd0aCxcbiAgICAgIHRvdGFsRHVyYXRpb246IHN1aXRlLnN1bW1hcnkudG90YWxEdXJhdGlvbixcbiAgICAgIHJlY29tbWVuZGF0aW9uczogc3VpdGUuc3VtbWFyeS5yZWNvbW1lbmRhdGlvbnMubGVuZ3RoXG4gICAgfSk7XG5cbiAgICByZXR1cm4gc3VpdGU7XG4gIH1cblxuICAvKipcbiAgICogQmVuY2htYXJrIHNlYXJjaCBwZXJmb3JtYW5jZSB3aXRoIHZhcmlvdXMgcXVlcnkgcGF0dGVybnNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYmVuY2htYXJrU2VhcmNoUGVyZm9ybWFuY2UoKTogUHJvbWlzZTxCZW5jaG1hcmtSZXN1bHQ+IHtcbiAgICBjb25zdCB0ZXN0UXVlcmllcyA9IFtcbiAgICAgICdjcmVhdGl2ZScsXG4gICAgICAncHJvZmVzc2lvbmFsIGFzc2lzdGFudCcsXG4gICAgICAnZGV2ZWxvcG1lbnQgdG9vbHMnLFxuICAgICAgJ2RhdGEgYW5hbHlzaXMnLFxuICAgICAgJ21hY2hpbmUgbGVhcm5pbmcgZXhwZXJ0JyxcbiAgICAgICdhIHZlcnkgbG9uZyBhbmQgY29tcGxleCBxdWVyeSB0aGF0IG1pZ2h0IHN0cmVzcyB0aGUgc2VhcmNoIHN5c3RlbSB3aXRoIG11bHRpcGxlIHRlcm1zIGFuZCBjb21wbGV4IHBhdHRlcm5zJyxcbiAgICAgICdzcGVjaWZpY19leGFjdF9tYXRjaCcsXG4gICAgICAnJyAgLy8gRW1wdHkgcXVlcnkgdGVzdFxuICAgIF07XG5cbiAgICBjb25zdCBtZW1vcnlCZWZvcmUgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG4gICAgbGV0IHBlYWtNZW1vcnkgPSBtZW1vcnlCZWZvcmU7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcblxuICAgIGxldCB0b3RhbE9wZXJhdGlvbnMgPSAwO1xuICAgIGxldCBjYWNoZUhpdHMgPSAwO1xuXG4gICAgZm9yIChjb25zdCBxdWVyeSBvZiB0ZXN0UXVlcmllcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAxMDsgaSsrKSB7IC8vIDEwIGl0ZXJhdGlvbnMgcGVyIHF1ZXJ5XG4gICAgICAgIGNvbnN0IG9wdGlvbnM6IFVuaWZpZWRTZWFyY2hPcHRpb25zID0ge1xuICAgICAgICAgIHF1ZXJ5LFxuICAgICAgICAgIGluY2x1ZGVMb2NhbDogdHJ1ZSxcbiAgICAgICAgICBpbmNsdWRlR2l0SHViOiB0cnVlLFxuICAgICAgICAgIGluY2x1ZGVDb2xsZWN0aW9uOiBmYWxzZSxcbiAgICAgICAgICBwYWdlU2l6ZTogMjBcbiAgICAgICAgfTtcblxuICAgICAgICBhd2FpdCB0aGlzLnVuaWZpZWRJbmRleE1hbmFnZXIuc2VhcmNoKG9wdGlvbnMpO1xuICAgICAgICB0b3RhbE9wZXJhdGlvbnMrKztcblxuICAgICAgICAvLyBUcmFjayBwZWFrIG1lbW9yeVxuICAgICAgICBjb25zdCBjdXJyZW50TWVtb3J5ID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgICAgICBpZiAoY3VycmVudE1lbW9yeSA+IHBlYWtNZW1vcnkpIHtcbiAgICAgICAgICBwZWFrTWVtb3J5ID0gY3VycmVudE1lbW9yeTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IG1lbW9yeUFmdGVyID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgIGNvbnN0IGR1cmF0aW9uID0gZW5kVGltZSAtIHN0YXJ0VGltZTtcblxuICAgIGNvbnN0IHBlcmZvcm1hbmNlU3RhdHMgPSB0aGlzLnVuaWZpZWRJbmRleE1hbmFnZXIuZ2V0UGVyZm9ybWFuY2VTdGF0cygpO1xuICAgIGNvbnN0IHNlYXJjaFN0YXRzID0gcGVyZm9ybWFuY2VTdGF0cy5zZWFyY2hTdGF0cztcblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnU2VhcmNoIFBlcmZvcm1hbmNlJyxcbiAgICAgIGR1cmF0aW9uLFxuICAgICAgbWVtb3J5VXNhZ2U6IHtcbiAgICAgICAgYmVmb3JlOiBtZW1vcnlCZWZvcmUgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICBhZnRlcjogbWVtb3J5QWZ0ZXIgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICBwZWFrOiBwZWFrTWVtb3J5IC8gKDEwMjQgKiAxMDI0KVxuICAgICAgfSxcbiAgICAgIHRocm91Z2hwdXQ6IHRvdGFsT3BlcmF0aW9ucyAvIChkdXJhdGlvbiAvIDEwMDApLFxuICAgICAgY2FjaGVTdGF0czoge1xuICAgICAgICBoaXRSYXRlOiBzZWFyY2hTdGF0cy5jYWNoZUhpdFJhdGUgfHwgMCxcbiAgICAgICAgdG90YWxPcGVyYXRpb25zXG4gICAgICB9LFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgYXZnU2VhcmNoVGltZTogc2VhcmNoU3RhdHMuYXZlcmFnZVRpbWUgfHwgMCxcbiAgICAgICAgcDk1U2VhcmNoVGltZTogc2VhcmNoU3RhdHMucDk1VGltZSB8fCAwLFxuICAgICAgICBzbG93UXVlcmllczogc2VhcmNoU3RhdHMuc2xvd1F1ZXJpZXMgfHwgMFxuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQmVuY2htYXJrIG1lbW9yeSB1c2FnZSB3aXRoIGxhcmdlIHJlc3VsdCBzZXRzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGJlbmNobWFya01lbW9yeVVzYWdlKCk6IFByb21pc2U8QmVuY2htYXJrUmVzdWx0PiB7XG4gICAgY29uc3QgbWVtb3J5QmVmb3JlID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgIGxldCBwZWFrTWVtb3J5ID0gbWVtb3J5QmVmb3JlO1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAvLyBDcmVhdGUgaW5jcmVhc2luZ2x5IGxhcmdlIHNlYXJjaCBvcGVyYXRpb25zXG4gICAgY29uc3QgbGFyZ2VCYXRjaGVzID0gWzEwMCwgNTAwLCAxMDAwLCAyMDAwXTtcbiAgICBcbiAgICBmb3IgKGNvbnN0IGJhdGNoU2l6ZSBvZiBsYXJnZUJhdGNoZXMpIHtcbiAgICAgIGNvbnN0IG9wdGlvbnM6IFVuaWZpZWRTZWFyY2hPcHRpb25zID0ge1xuICAgICAgICBxdWVyeTogJycsICAvLyBFbXB0eSBxdWVyeSB0byBnZXQgYWxsIHJlc3VsdHNcbiAgICAgICAgaW5jbHVkZUxvY2FsOiB0cnVlLFxuICAgICAgICBpbmNsdWRlR2l0SHViOiB0cnVlLFxuICAgICAgICBpbmNsdWRlQ29sbGVjdGlvbjogdHJ1ZSxcbiAgICAgICAgcGFnZVNpemU6IGJhdGNoU2l6ZSxcbiAgICAgICAgbWF4UmVzdWx0czogYmF0Y2hTaXplXG4gICAgICB9O1xuXG4gICAgICBhd2FpdCB0aGlzLnVuaWZpZWRJbmRleE1hbmFnZXIuc2VhcmNoKG9wdGlvbnMpO1xuXG4gICAgICBjb25zdCBjdXJyZW50TWVtb3J5ID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgICAgaWYgKGN1cnJlbnRNZW1vcnkgPiBwZWFrTWVtb3J5KSB7XG4gICAgICAgIHBlYWtNZW1vcnkgPSBjdXJyZW50TWVtb3J5O1xuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBmb3IgbWVtb3J5IGxlYWtzXG4gICAgICBpZiAoY3VycmVudE1lbW9yeSA+IG1lbW9yeUJlZm9yZSAqIDIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1BvdGVudGlhbCBtZW1vcnkgbGVhayBkZXRlY3RlZCcsIHtcbiAgICAgICAgICBiZWZvcmVNQjogbWVtb3J5QmVmb3JlIC8gKDEwMjQgKiAxMDI0KSxcbiAgICAgICAgICBjdXJyZW50TUI6IGN1cnJlbnRNZW1vcnkgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICAgIGJhdGNoU2l6ZVxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBlbmRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCBtZW1vcnlBZnRlciA9IHByb2Nlc3MubWVtb3J5VXNhZ2UoKS5oZWFwVXNlZDtcblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnTWVtb3J5IFVzYWdlJyxcbiAgICAgIGR1cmF0aW9uOiBlbmRUaW1lIC0gc3RhcnRUaW1lLFxuICAgICAgbWVtb3J5VXNhZ2U6IHtcbiAgICAgICAgYmVmb3JlOiBtZW1vcnlCZWZvcmUgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICBhZnRlcjogbWVtb3J5QWZ0ZXIgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICBwZWFrOiBwZWFrTWVtb3J5IC8gKDEwMjQgKiAxMDI0KVxuICAgICAgfSxcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIG1lbW9yeUdyb3d0aE1COiAobWVtb3J5QWZ0ZXIgLSBtZW1vcnlCZWZvcmUpIC8gKDEwMjQgKiAxMDI0KSxcbiAgICAgICAgcGVha0dyb3d0aE1COiAocGVha01lbW9yeSAtIG1lbW9yeUJlZm9yZSkgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICB0ZXN0ZWRCYXRjaFNpemVzOiBsYXJnZUJhdGNoZXNcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJlbmNobWFyayBjYWNoZSBwZXJmb3JtYW5jZSBhbmQgaGl0IHJhdGVzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGJlbmNobWFya0NhY2hlUGVyZm9ybWFuY2UoKTogUHJvbWlzZTxCZW5jaG1hcmtSZXN1bHQ+IHtcbiAgICBjb25zdCBtZW1vcnlCZWZvcmUgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcblxuICAgIC8vIFRlc3QgY2FjaGUgd2FybWluZyBhbmQgaGl0IHJhdGUgb3B0aW1pemF0aW9uXG4gICAgY29uc3QgcmF3UXVlcmllcyA9IFsndGVzdCcsICdwZXJmb3JtYW5jZScsICdiZW5jaG1hcmsnLCAnY2FjaGUnXTtcbiAgICAvLyBETUNQLVNFQy0wMDQgRklYOiBOb3JtYWxpemUgVW5pY29kZSBpbiBhbGwgdXNlciBpbnB1dFxuICAgIGNvbnN0IHRlc3RRdWVyaWVzID0gcmF3UXVlcmllcy5tYXAocSA9PiB7XG4gICAgICBjb25zdCBub3JtYWxpemVkID0gVW5pY29kZVZhbGlkYXRvci5ub3JtYWxpemUocSk7XG4gICAgICByZXR1cm4gbm9ybWFsaXplZC5pc1ZhbGlkID8gbm9ybWFsaXplZC5ub3JtYWxpemVkQ29udGVudCA6IHE7XG4gICAgfSk7XG4gICAgbGV0IHRvdGFsT3BlcmF0aW9ucyA9IDA7XG4gICAgbGV0IGNhY2hlSGl0c0JlZm9yZSA9IDA7XG5cbiAgICAvLyBGaXJzdCBwYXNzIC0gY2FjaGUgbWlzc2VzIGV4cGVjdGVkXG4gICAgZm9yIChjb25zdCBxdWVyeSBvZiB0ZXN0UXVlcmllcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA1OyBpKyspIHtcbiAgICAgICAgYXdhaXQgdGhpcy51bmlmaWVkSW5kZXhNYW5hZ2VyLnNlYXJjaCh7IHF1ZXJ5LCBwYWdlU2l6ZTogMTAgfSk7XG4gICAgICAgIHRvdGFsT3BlcmF0aW9ucysrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHN0YXRzQWZ0ZXJGaXJzdFBhc3MgPSB0aGlzLnVuaWZpZWRJbmRleE1hbmFnZXIuZ2V0UGVyZm9ybWFuY2VTdGF0cygpO1xuICAgIGNhY2hlSGl0c0JlZm9yZSA9IHN0YXRzQWZ0ZXJGaXJzdFBhc3MuY2FjaGVTdGF0cy5zZWFyY2hSZXN1bHRzLmhpdENvdW50O1xuXG4gICAgLy8gU2Vjb25kIHBhc3MgLSBjYWNoZSBoaXRzIGV4cGVjdGVkXG4gICAgZm9yIChjb25zdCBxdWVyeSBvZiB0ZXN0UXVlcmllcykge1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCA1OyBpKyspIHtcbiAgICAgICAgYXdhaXQgdGhpcy51bmlmaWVkSW5kZXhNYW5hZ2VyLnNlYXJjaCh7IHF1ZXJ5LCBwYWdlU2l6ZTogMTAgfSk7XG4gICAgICAgIHRvdGFsT3BlcmF0aW9ucysrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IG1lbW9yeUFmdGVyID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuXG4gICAgY29uc3QgZmluYWxTdGF0cyA9IHRoaXMudW5pZmllZEluZGV4TWFuYWdlci5nZXRQZXJmb3JtYW5jZVN0YXRzKCk7XG4gICAgY29uc3QgY2FjaGVTdGF0cyA9IGZpbmFsU3RhdHMuY2FjaGVTdGF0cy5zZWFyY2hSZXN1bHRzO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6ICdDYWNoZSBQZXJmb3JtYW5jZScsXG4gICAgICBkdXJhdGlvbjogZW5kVGltZSAtIHN0YXJ0VGltZSxcbiAgICAgIG1lbW9yeVVzYWdlOiB7XG4gICAgICAgIGJlZm9yZTogbWVtb3J5QmVmb3JlIC8gKDEwMjQgKiAxMDI0KSxcbiAgICAgICAgYWZ0ZXI6IG1lbW9yeUFmdGVyIC8gKDEwMjQgKiAxMDI0KSxcbiAgICAgICAgcGVhazogbWVtb3J5QWZ0ZXIgLyAoMTAyNCAqIDEwMjQpXG4gICAgICB9LFxuICAgICAgY2FjaGVTdGF0czoge1xuICAgICAgICBoaXRSYXRlOiBjYWNoZVN0YXRzLmhpdFJhdGUsXG4gICAgICAgIHRvdGFsT3BlcmF0aW9uc1xuICAgICAgfSxcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIGNhY2hlU2l6ZTogY2FjaGVTdGF0cy5zaXplLFxuICAgICAgICBldmljdGlvbnM6IGNhY2hlU3RhdHMuZXZpY3Rpb25Db3VudCxcbiAgICAgICAgaGl0UmF0ZUltcHJvdmVtZW50OiBjYWNoZVN0YXRzLmhpdFJhdGVcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJlbmNobWFyayBjb25jdXJyZW50IHNlYXJjaCBvcGVyYXRpb25zXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGJlbmNobWFya0NvbmN1cnJlbnRPcGVyYXRpb25zKCk6IFByb21pc2U8QmVuY2htYXJrUmVzdWx0PiB7XG4gICAgY29uc3QgbWVtb3J5QmVmb3JlID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgIGxldCBwZWFrTWVtb3J5ID0gbWVtb3J5QmVmb3JlO1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICBjb25zdCBjb25jdXJyZW5jeUxldmVscyA9IFs1LCAxMCwgMjAsIDUwXTtcbiAgICBsZXQgdG90YWxPcGVyYXRpb25zID0gMDtcblxuICAgIGZvciAoY29uc3QgY29uY3VycmVuY3kgb2YgY29uY3VycmVuY3lMZXZlbHMpIHtcbiAgICAgIGNvbnN0IHByb21pc2VzID0gW107XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY29uY3VycmVuY3k7IGkrKykge1xuICAgICAgICBjb25zdCBzZWFyY2hQcm9taXNlID0gdGhpcy51bmlmaWVkSW5kZXhNYW5hZ2VyLnNlYXJjaCh7XG4gICAgICAgICAgcXVlcnk6IGBjb25jdXJyZW50X3Rlc3RfJHtpfWAsXG4gICAgICAgICAgcGFnZVNpemU6IDIwXG4gICAgICAgIH0pO1xuICAgICAgICBwcm9taXNlcy5wdXNoKHNlYXJjaFByb21pc2UpO1xuICAgICAgICB0b3RhbE9wZXJhdGlvbnMrKztcbiAgICAgIH1cblxuICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpO1xuXG4gICAgICBjb25zdCBjdXJyZW50TWVtb3J5ID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgICAgaWYgKGN1cnJlbnRNZW1vcnkgPiBwZWFrTWVtb3J5KSB7XG4gICAgICAgIHBlYWtNZW1vcnkgPSBjdXJyZW50TWVtb3J5O1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IG1lbW9yeUFmdGVyID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgIGNvbnN0IGR1cmF0aW9uID0gZW5kVGltZSAtIHN0YXJ0VGltZTtcblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lOiAnQ29uY3VycmVudCBPcGVyYXRpb25zJyxcbiAgICAgIGR1cmF0aW9uLFxuICAgICAgbWVtb3J5VXNhZ2U6IHtcbiAgICAgICAgYmVmb3JlOiBtZW1vcnlCZWZvcmUgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICBhZnRlcjogbWVtb3J5QWZ0ZXIgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICBwZWFrOiBwZWFrTWVtb3J5IC8gKDEwMjQgKiAxMDI0KVxuICAgICAgfSxcbiAgICAgIHRocm91Z2hwdXQ6IHRvdGFsT3BlcmF0aW9ucyAvIChkdXJhdGlvbiAvIDEwMDApLFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgdGVzdGVkQ29uY3VycmVuY3lMZXZlbHM6IGNvbmN1cnJlbmN5TGV2ZWxzLFxuICAgICAgICB0b3RhbENvbmN1cnJlbnRPcHM6IHRvdGFsT3BlcmF0aW9uc1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQmVuY2htYXJrIGxhcmdlIGRhdGFzZXQgaGFuZGxpbmcgKHNpbXVsYXRlZClcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYmVuY2htYXJrTGFyZ2VEYXRhc2V0SGFuZGxpbmcoKTogUHJvbWlzZTxCZW5jaG1hcmtSZXN1bHQ+IHtcbiAgICBjb25zdCBtZW1vcnlCZWZvcmUgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG4gICAgbGV0IHBlYWtNZW1vcnkgPSBtZW1vcnlCZWZvcmU7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcblxuICAgIC8vIFNpbXVsYXRlIHNlYXJjaGVzIHRoYXQgd291bGQgc3RyZXNzIGEgbGFyZ2UgZGF0YXNldFxuICAgIGNvbnN0IHN0cmVzc1Rlc3RRdWVyaWVzID0gW1xuICAgICAgeyBxdWVyeTogJycsIHBhZ2VTaXplOiAxMDAwIH0sIC8vIEdldCBhbGwgcmVzdWx0c1xuICAgICAgeyBxdWVyeTogJ2NvbW1vbl90ZXJtJywgcGFnZVNpemU6IDUwMCB9LCAvLyBIaWdoIHJlc3VsdCBjb3VudFxuICAgICAgeyBxdWVyeTogJ3Zlcnlfc3BlY2lmaWNfdW5pcXVlX3Rlcm0nLCBwYWdlU2l6ZTogMTAwIH0sIC8vIExvdyByZXN1bHQgY291bnRcbiAgICAgIHsgcXVlcnk6ICdwYXJ0aWFsX21hdGNoX3Rlc3QnLCBwYWdlU2l6ZTogMjAwIH0gLy8gTWVkaXVtIHJlc3VsdCBjb3VudFxuICAgIF07XG5cbiAgICBsZXQgdG90YWxSZXN1bHRzID0gMDtcblxuICAgIGZvciAoY29uc3QgdGVzdENhc2Ugb2Ygc3RyZXNzVGVzdFF1ZXJpZXMpIHtcbiAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLnVuaWZpZWRJbmRleE1hbmFnZXIuc2VhcmNoKHtcbiAgICAgICAgcXVlcnk6IHRlc3RDYXNlLnF1ZXJ5LFxuICAgICAgICBwYWdlU2l6ZTogdGVzdENhc2UucGFnZVNpemUsXG4gICAgICAgIGluY2x1ZGVMb2NhbDogdHJ1ZSxcbiAgICAgICAgaW5jbHVkZUdpdEh1YjogdHJ1ZSxcbiAgICAgICAgaW5jbHVkZUNvbGxlY3Rpb246IHRydWVcbiAgICAgIH0pO1xuXG4gICAgICB0b3RhbFJlc3VsdHMgKz0gcmVzdWx0cy5sZW5ndGg7XG5cbiAgICAgIGNvbnN0IGN1cnJlbnRNZW1vcnkgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG4gICAgICBpZiAoY3VycmVudE1lbW9yeSA+IHBlYWtNZW1vcnkpIHtcbiAgICAgICAgcGVha01lbW9yeSA9IGN1cnJlbnRNZW1vcnk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZW5kVGltZSA9IERhdGUubm93KCk7XG4gICAgY29uc3QgbWVtb3J5QWZ0ZXIgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ0xhcmdlIERhdGFzZXQgSGFuZGxpbmcnLFxuICAgICAgZHVyYXRpb246IGVuZFRpbWUgLSBzdGFydFRpbWUsXG4gICAgICBtZW1vcnlVc2FnZToge1xuICAgICAgICBiZWZvcmU6IG1lbW9yeUJlZm9yZSAvICgxMDI0ICogMTAyNCksXG4gICAgICAgIGFmdGVyOiBtZW1vcnlBZnRlciAvICgxMDI0ICogMTAyNCksXG4gICAgICAgIHBlYWs6IHBlYWtNZW1vcnkgLyAoMTAyNCAqIDEwMjQpXG4gICAgICB9LFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgdG90YWxSZXN1bHRzUHJvY2Vzc2VkOiB0b3RhbFJlc3VsdHMsXG4gICAgICAgIGF2ZXJhZ2VSZXN1bHRzUGVyUXVlcnk6IHRvdGFsUmVzdWx0cyAvIHN0cmVzc1Rlc3RRdWVyaWVzLmxlbmd0aCxcbiAgICAgICAgbWVtb3J5UGVyUmVzdWx0OiAocGVha01lbW9yeSAtIG1lbW9yeUJlZm9yZSkgLyB0b3RhbFJlc3VsdHNcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJlbmNobWFyayBpbmRleCBidWlsZGluZyBwZXJmb3JtYW5jZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBiZW5jaG1hcmtJbmRleEJ1aWxkaW5nKCk6IFByb21pc2U8QmVuY2htYXJrUmVzdWx0PiB7XG4gICAgY29uc3QgbWVtb3J5QmVmb3JlID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAvLyBGb3JjZSByZWJ1aWxkIG9mIGFsbCBpbmRleGVzXG4gICAgYXdhaXQgdGhpcy51bmlmaWVkSW5kZXhNYW5hZ2VyLnJlYnVpbGRBbGwoKTtcblxuICAgIGNvbnN0IGVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IG1lbW9yeUFmdGVyID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuXG4gICAgY29uc3QgbG9jYWxTdGF0cyA9IGF3YWl0IFBvcnRmb2xpb0luZGV4TWFuYWdlci5nZXRJbnN0YW5jZSgpLmdldFN0YXRzKCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ0luZGV4IEJ1aWxkaW5nJyxcbiAgICAgIGR1cmF0aW9uOiBlbmRUaW1lIC0gc3RhcnRUaW1lLFxuICAgICAgbWVtb3J5VXNhZ2U6IHtcbiAgICAgICAgYmVmb3JlOiBtZW1vcnlCZWZvcmUgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICBhZnRlcjogbWVtb3J5QWZ0ZXIgLyAoMTAyNCAqIDEwMjQpLFxuICAgICAgICBwZWFrOiBtZW1vcnlBZnRlciAvICgxMDI0ICogMTAyNClcbiAgICAgIH0sXG4gICAgICBtZXRhZGF0YToge1xuICAgICAgICB0b3RhbEVsZW1lbnRzSW5kZXhlZDogbG9jYWxTdGF0cy50b3RhbEVsZW1lbnRzLFxuICAgICAgICBpbmRleGluZ1JhdGU6IGxvY2FsU3RhdHMudG90YWxFbGVtZW50cyAvICgoZW5kVGltZSAtIHN0YXJ0VGltZSkgLyAxMDAwKSxcbiAgICAgICAgaXNTdGFsZTogbG9jYWxTdGF0cy5pc1N0YWxlXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCZW5jaG1hcmsgc3RyZWFtaW5nIHNlYXJjaCBwZXJmb3JtYW5jZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBiZW5jaG1hcmtTdHJlYW1pbmdTZWFyY2goKTogUHJvbWlzZTxCZW5jaG1hcmtSZXN1bHQ+IHtcbiAgICBjb25zdCBtZW1vcnlCZWZvcmUgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG4gICAgbGV0IHBlYWtNZW1vcnkgPSBtZW1vcnlCZWZvcmU7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcblxuICAgIGNvbnN0IHN0cmVhbWluZ1F1ZXJpZXMgPSBbXG4gICAgICB7IHF1ZXJ5OiAndGVzdCcsIG1heFJlc3VsdHM6IDEwMCB9LFxuICAgICAgeyBxdWVyeTogJ2Fzc2lzdGFudCcsIG1heFJlc3VsdHM6IDIwMCB9LFxuICAgICAgeyBxdWVyeTogJ2NyZWF0aXZlJywgbWF4UmVzdWx0czogMTUwIH1cbiAgICBdO1xuXG4gICAgbGV0IHRvdGFsUmVzdWx0cyA9IDA7XG5cbiAgICBmb3IgKGNvbnN0IHRlc3RDYXNlIG9mIHN0cmVhbWluZ1F1ZXJpZXMpIHtcbiAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLnVuaWZpZWRJbmRleE1hbmFnZXIuc2VhcmNoKHtcbiAgICAgICAgcXVlcnk6IHRlc3RDYXNlLnF1ZXJ5LFxuICAgICAgICBzdHJlYW1SZXN1bHRzOiB0cnVlLFxuICAgICAgICBtYXhSZXN1bHRzOiB0ZXN0Q2FzZS5tYXhSZXN1bHRzLFxuICAgICAgICBpbmNsdWRlTG9jYWw6IHRydWUsXG4gICAgICAgIGluY2x1ZGVHaXRIdWI6IHRydWVcbiAgICAgIH0pO1xuXG4gICAgICB0b3RhbFJlc3VsdHMgKz0gcmVzdWx0cy5sZW5ndGg7XG5cbiAgICAgIGNvbnN0IGN1cnJlbnRNZW1vcnkgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG4gICAgICBpZiAoY3VycmVudE1lbW9yeSA+IHBlYWtNZW1vcnkpIHtcbiAgICAgICAgcGVha01lbW9yeSA9IGN1cnJlbnRNZW1vcnk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZW5kVGltZSA9IERhdGUubm93KCk7XG4gICAgY29uc3QgbWVtb3J5QWZ0ZXIgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ1N0cmVhbWluZyBTZWFyY2gnLFxuICAgICAgZHVyYXRpb246IGVuZFRpbWUgLSBzdGFydFRpbWUsXG4gICAgICBtZW1vcnlVc2FnZToge1xuICAgICAgICBiZWZvcmU6IG1lbW9yeUJlZm9yZSAvICgxMDI0ICogMTAyNCksXG4gICAgICAgIGFmdGVyOiBtZW1vcnlBZnRlciAvICgxMDI0ICogMTAyNCksXG4gICAgICAgIHBlYWs6IHBlYWtNZW1vcnkgLyAoMTAyNCAqIDEwMjQpXG4gICAgICB9LFxuICAgICAgdGhyb3VnaHB1dDogdG90YWxSZXN1bHRzIC8gKChlbmRUaW1lIC0gc3RhcnRUaW1lKSAvIDEwMDApLFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgdG90YWxTdHJlYW1lZFJlc3VsdHM6IHRvdGFsUmVzdWx0cyxcbiAgICAgICAgYXZlcmFnZU1lbW9yeVBlclJlc3VsdDogKHBlYWtNZW1vcnkgLSBtZW1vcnlCZWZvcmUpIC8gdG90YWxSZXN1bHRzXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCZW5jaG1hcmsgbGF6eSBsb2FkaW5nIHBlcmZvcm1hbmNlXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGJlbmNobWFya0xhenlMb2FkaW5nKCk6IFByb21pc2U8QmVuY2htYXJrUmVzdWx0PiB7XG4gICAgY29uc3QgbWVtb3J5QmVmb3JlID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgICAvLyBUZXN0IGxhenkgbG9hZGluZyB3aXRoIGRpZmZlcmVudCBjb25maWd1cmF0aW9uc1xuICAgIGNvbnN0IGxhenlMb2FkVGVzdHMgPSBbXG4gICAgICB7IHF1ZXJ5OiAnbGF6eV90ZXN0XzEnLCBsYXp5TG9hZDogdHJ1ZSwgaW5jbHVkZUxvY2FsOiB0cnVlLCBpbmNsdWRlR2l0SHViOiBmYWxzZSwgaW5jbHVkZUNvbGxlY3Rpb246IGZhbHNlIH0sXG4gICAgICB7IHF1ZXJ5OiAnbGF6eV90ZXN0XzInLCBsYXp5TG9hZDogdHJ1ZSwgaW5jbHVkZUxvY2FsOiBmYWxzZSwgaW5jbHVkZUdpdEh1YjogdHJ1ZSwgaW5jbHVkZUNvbGxlY3Rpb246IGZhbHNlIH0sXG4gICAgICB7IHF1ZXJ5OiAnbGF6eV90ZXN0XzMnLCBsYXp5TG9hZDogdHJ1ZSwgaW5jbHVkZUxvY2FsOiB0cnVlLCBpbmNsdWRlR2l0SHViOiB0cnVlLCBpbmNsdWRlQ29sbGVjdGlvbjogdHJ1ZSB9LFxuICAgICAgeyBxdWVyeTogJ2xhenlfdGVzdF80JywgbGF6eUxvYWQ6IGZhbHNlLCBpbmNsdWRlTG9jYWw6IHRydWUsIGluY2x1ZGVHaXRIdWI6IHRydWUsIGluY2x1ZGVDb2xsZWN0aW9uOiB0cnVlIH1cbiAgICBdO1xuXG4gICAgbGV0IHRvdGFsT3BlcmF0aW9ucyA9IDA7XG5cbiAgICBmb3IgKGNvbnN0IHRlc3RDYXNlIG9mIGxhenlMb2FkVGVzdHMpIHtcbiAgICAgIGF3YWl0IHRoaXMudW5pZmllZEluZGV4TWFuYWdlci5zZWFyY2godGVzdENhc2UpO1xuICAgICAgdG90YWxPcGVyYXRpb25zKys7XG4gICAgfVxuXG4gICAgY29uc3QgZW5kVGltZSA9IERhdGUubm93KCk7XG4gICAgY29uc3QgbWVtb3J5QWZ0ZXIgPSBwcm9jZXNzLm1lbW9yeVVzYWdlKCkuaGVhcFVzZWQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogJ0xhenkgTG9hZGluZycsXG4gICAgICBkdXJhdGlvbjogZW5kVGltZSAtIHN0YXJ0VGltZSxcbiAgICAgIG1lbW9yeVVzYWdlOiB7XG4gICAgICAgIGJlZm9yZTogbWVtb3J5QmVmb3JlIC8gKDEwMjQgKiAxMDI0KSxcbiAgICAgICAgYWZ0ZXI6IG1lbW9yeUFmdGVyIC8gKDEwMjQgKiAxMDI0KSxcbiAgICAgICAgcGVhazogbWVtb3J5QWZ0ZXIgLyAoMTAyNCAqIDEwMjQpXG4gICAgICB9LFxuICAgICAgdGhyb3VnaHB1dDogdG90YWxPcGVyYXRpb25zIC8gKChlbmRUaW1lIC0gc3RhcnRUaW1lKSAvIDEwMDApLFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgdG90YWxMYXp5T3BlcmF0aW9uczogdG90YWxPcGVyYXRpb25zLFxuICAgICAgICBhdmVyYWdlT3BlcmF0aW9uVGltZTogKGVuZFRpbWUgLSBzdGFydFRpbWUpIC8gdG90YWxPcGVyYXRpb25zXG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCBiZW5jaG1hcmsgZW52aXJvbm1lbnRcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcmVzZXRCZW5jaG1hcmtFbnZpcm9ubWVudCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnVuaWZpZWRJbmRleE1hbmFnZXIucmVidWlsZEFsbCgpO1xuICAgIHRoaXMucGVyZm9ybWFuY2VNb25pdG9yLnJlc2V0KCk7XG4gICAgdGhpcy5iZW5jaG1hcmtSZXN1bHRzID0gW107XG5cbiAgICAvLyBGb3JjZSBnYXJiYWdlIGNvbGxlY3Rpb24gaWYgYXZhaWxhYmxlXG4gICAgaWYgKGdsb2JhbC5nYykge1xuICAgICAgZ2xvYmFsLmdjKCk7XG4gICAgfVxuXG4gICAgYXdhaXQgdGhpcy53YWl0Rm9yR0MoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBXYWl0IGZvciBnYXJiYWdlIGNvbGxlY3Rpb24gdG8gY29tcGxldGVcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgd2FpdEZvckdDKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHNldEltbWVkaWF0ZSgoKSA9PiB7XG4gICAgICAgIGlmIChnbG9iYWwuZ2MpIHtcbiAgICAgICAgICBnbG9iYWwuZ2MoKTtcbiAgICAgICAgfVxuICAgICAgICBzZXRUaW1lb3V0KHJlc29sdmUsIDEwMCk7IC8vIFdhaXQgMTAwbXMgZm9yIEdDIHRvIGNvbXBsZXRlXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSBiZW5jaG1hcmsgc3VtbWFyeSBhbmQgcmVjb21tZW5kYXRpb25zXG4gICAqL1xuICBwcml2YXRlIGdlbmVyYXRlU3VtbWFyeSh0b3RhbER1cmF0aW9uOiBudW1iZXIpOiBCZW5jaG1hcmtTdWl0ZVsnc3VtbWFyeSddIHtcbiAgICBjb25zdCByZWNvbW1lbmRhdGlvbnM6IHN0cmluZ1tdID0gW107XG4gICAgbGV0IHRvdGFsTWVtb3J5VXNhZ2UgPSAwO1xuICAgIGxldCBwZWFrTWVtb3J5VXNhZ2UgPSAwO1xuXG4gICAgLy8gQW5hbHl6ZSByZXN1bHRzIGFuZCBnZW5lcmF0ZSByZWNvbW1lbmRhdGlvbnNcbiAgICBmb3IgKGNvbnN0IHJlc3VsdCBvZiB0aGlzLmJlbmNobWFya1Jlc3VsdHMpIHtcbiAgICAgIHRvdGFsTWVtb3J5VXNhZ2UgKz0gcmVzdWx0Lm1lbW9yeVVzYWdlLmFmdGVyIC0gcmVzdWx0Lm1lbW9yeVVzYWdlLmJlZm9yZTtcbiAgICAgIHBlYWtNZW1vcnlVc2FnZSA9IE1hdGgubWF4KHBlYWtNZW1vcnlVc2FnZSwgcmVzdWx0Lm1lbW9yeVVzYWdlLnBlYWspO1xuXG4gICAgICAvLyBDaGVjayBmb3IgcGVyZm9ybWFuY2UgaXNzdWVzXG4gICAgICBpZiAocmVzdWx0Lm5hbWUgPT09ICdTZWFyY2ggUGVyZm9ybWFuY2UnICYmIHJlc3VsdC5tZXRhZGF0YT8uYXZnU2VhcmNoVGltZSA+IDEwMCkge1xuICAgICAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnQXZlcmFnZSBzZWFyY2ggdGltZSBleGNlZWRzIDEwMG1zLiBDb25zaWRlciBxdWVyeSBvcHRpbWl6YXRpb24gb3IgaW5jcmVhc2VkIGNhY2hpbmcuJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXN1bHQubWVtb3J5VXNhZ2UucGVhayA+IDIwMCkge1xuICAgICAgICByZWNvbW1lbmRhdGlvbnMucHVzaChgSGlnaCBtZW1vcnkgdXNhZ2UgZGV0ZWN0ZWQgaW4gJHtyZXN1bHQubmFtZX0gKCR7cmVzdWx0Lm1lbW9yeVVzYWdlLnBlYWsudG9GaXhlZCgxKX1NQikuIENvbnNpZGVyIG1lbW9yeSBvcHRpbWl6YXRpb24uYCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXN1bHQuY2FjaGVTdGF0cz8uaGl0UmF0ZSAmJiByZXN1bHQuY2FjaGVTdGF0cy5oaXRSYXRlIDwgMC41KSB7XG4gICAgICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKGBMb3cgY2FjaGUgaGl0IHJhdGUgaW4gJHtyZXN1bHQubmFtZX0gKCR7cmVzdWx0LmNhY2hlU3RhdHMuaGl0UmF0ZS50b0ZpeGVkKDIpfSkuIENvbnNpZGVyIGNhY2hlIHNpemUgaW5jcmVhc2Ugb3IgVFRMIGFkanVzdG1lbnQuYCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXN1bHQudGhyb3VnaHB1dCAmJiByZXN1bHQudGhyb3VnaHB1dCA8IDEwKSB7XG4gICAgICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKGBMb3cgdGhyb3VnaHB1dCBpbiAke3Jlc3VsdC5uYW1lfSAoJHtyZXN1bHQudGhyb3VnaHB1dC50b0ZpeGVkKDEpfSBvcHMvc2VjKS4gQ29uc2lkZXIgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uLmApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEdlbmVyYWwgcmVjb21tZW5kYXRpb25zXG4gICAgaWYgKHBlYWtNZW1vcnlVc2FnZSA+IDUwKSB7XG4gICAgICByZWNvbW1lbmRhdGlvbnMucHVzaCgnUGVhayBtZW1vcnkgdXNhZ2UgZXhjZWVkcyA1ME1CLiBDb25zaWRlciBpbXBsZW1lbnRpbmcgbW9yZSBhZ2dyZXNzaXZlIG1lbW9yeSBjbGVhbnVwLicpO1xuICAgIH1cblxuICAgIGlmICh0b3RhbER1cmF0aW9uID4gMzAwMDApIHtcbiAgICAgIHJlY29tbWVuZGF0aW9ucy5wdXNoKCdUb3RhbCBiZW5jaG1hcmsgZHVyYXRpb24gZXhjZWVkcyAzMCBzZWNvbmRzLiBDb25zaWRlciBwZXJmb3JtYW5jZSBvcHRpbWl6YXRpb25zLicpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB0b3RhbER1cmF0aW9uLFxuICAgICAgYXZlcmFnZU1lbW9yeVVzYWdlOiB0b3RhbE1lbW9yeVVzYWdlIC8gdGhpcy5iZW5jaG1hcmtSZXN1bHRzLmxlbmd0aCxcbiAgICAgIHBlYWtNZW1vcnlVc2FnZSxcbiAgICAgIHJlY29tbWVuZGF0aW9uc1xuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogRXhwb3J0IGJlbmNobWFyayByZXN1bHRzIHRvIEpTT05cbiAgICovXG4gIGV4cG9ydFJlc3VsdHMoc3VpdGU6IEJlbmNobWFya1N1aXRlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoc3VpdGUsIG51bGwsIDIpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIGJlbmNobWFyayByZXBvcnRcbiAgICovXG4gIGdlbmVyYXRlUmVwb3J0KHN1aXRlOiBCZW5jaG1hcmtTdWl0ZSk6IHN0cmluZyB7XG4gICAgbGV0IHJlcG9ydCA9IGAjIERvbGxob3VzZU1DUCBJbmRleCBQZXJmb3JtYW5jZSBCZW5jaG1hcmsgUmVwb3J0XFxuXFxuYDtcbiAgICByZXBvcnQgKz0gYCoqR2VuZXJhdGVkOioqICR7bmV3IERhdGUoKS50b0lTT1N0cmluZygpfVxcbmA7XG4gICAgcmVwb3J0ICs9IGAqKlRvdGFsIER1cmF0aW9uOioqICR7c3VpdGUuc3VtbWFyeS50b3RhbER1cmF0aW9ufW1zXFxuYDtcbiAgICByZXBvcnQgKz0gYCoqUGVhayBNZW1vcnkgVXNhZ2U6KiogJHtzdWl0ZS5zdW1tYXJ5LnBlYWtNZW1vcnlVc2FnZS50b0ZpeGVkKDEpfU1CXFxuXFxuYDtcblxuICAgIHJlcG9ydCArPSBgIyMgQmVuY2htYXJrIFJlc3VsdHNcXG5cXG5gO1xuXG4gICAgZm9yIChjb25zdCByZXN1bHQgb2Ygc3VpdGUucmVzdWx0cykge1xuICAgICAgcmVwb3J0ICs9IGAjIyMgJHtyZXN1bHQubmFtZX1cXG5gO1xuICAgICAgcmVwb3J0ICs9IGAtICoqRHVyYXRpb246KiogJHtyZXN1bHQuZHVyYXRpb259bXNcXG5gO1xuICAgICAgcmVwb3J0ICs9IGAtICoqTWVtb3J5IFVzYWdlOioqICR7cmVzdWx0Lm1lbW9yeVVzYWdlLmJlZm9yZS50b0ZpeGVkKDEpfU1CIOKGkiAke3Jlc3VsdC5tZW1vcnlVc2FnZS5hZnRlci50b0ZpeGVkKDEpfU1CIChQZWFrOiAke3Jlc3VsdC5tZW1vcnlVc2FnZS5wZWFrLnRvRml4ZWQoMSl9TUIpXFxuYDtcbiAgICAgIFxuICAgICAgaWYgKHJlc3VsdC50aHJvdWdocHV0KSB7XG4gICAgICAgIHJlcG9ydCArPSBgLSAqKlRocm91Z2hwdXQ6KiogJHtyZXN1bHQudGhyb3VnaHB1dC50b0ZpeGVkKDEpfSBvcHMvc2VjXFxuYDtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKHJlc3VsdC5jYWNoZVN0YXRzKSB7XG4gICAgICAgIHJlcG9ydCArPSBgLSAqKkNhY2hlIEhpdCBSYXRlOioqICR7cmVzdWx0LmNhY2hlU3RhdHMuaGl0UmF0ZS50b0ZpeGVkKDIpfVxcbmA7XG4gICAgICB9XG4gICAgICBcbiAgICAgIHJlcG9ydCArPSBgXFxuYDtcbiAgICB9XG5cbiAgICByZXBvcnQgKz0gYCMjIFJlY29tbWVuZGF0aW9uc1xcblxcbmA7XG4gICAgXG4gICAgaWYgKHN1aXRlLnN1bW1hcnkucmVjb21tZW5kYXRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmVwb3J0ICs9IGBObyBwZXJmb3JtYW5jZSBpc3N1ZXMgZGV0ZWN0ZWQuIFN5c3RlbSBpcyBwZXJmb3JtaW5nIHdpdGhpbiBhY2NlcHRhYmxlIHBhcmFtZXRlcnMuXFxuYDtcbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChjb25zdCByZWNvbW1lbmRhdGlvbiBvZiBzdWl0ZS5zdW1tYXJ5LnJlY29tbWVuZGF0aW9ucykge1xuICAgICAgICByZXBvcnQgKz0gYC0gJHtyZWNvbW1lbmRhdGlvbn1cXG5gO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXBvcnQ7XG4gIH1cbn0iXX0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollectionCache.d.ts","sourceRoot":"","sources":["../../src/cache/CollectionCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuB;gBAExC,OAAO,
|
|
1
|
+
{"version":3,"file":"CollectionCache.d.ts","sourceRoot":"","sources":["../../src/cache/CollectionCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuB;gBAExC,OAAO,CAAC,EAAE,MAAM;IAc5B;;OAEG;YACW,cAAc;IAS5B;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAkCvD;;OAEG;IACG,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BtE;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAkB3D;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IASnE;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC;IAKtC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAWjC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAY1F"}
|