@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.
Files changed (272) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +494 -111
  3. package/data/agents/code-reviewer.md +8 -1
  4. package/data/agents/research-assistant.md +8 -1
  5. package/data/agents/task-manager.md +8 -1
  6. package/data/ensembles/business-advisor.md +8 -1
  7. package/data/ensembles/creative-studio.md +8 -1
  8. package/data/ensembles/development-team.md +8 -1
  9. package/data/ensembles/security-analysis-team.md +8 -1
  10. package/data/memories/conversation-history.md +8 -1
  11. package/data/memories/learning-progress.md +8 -1
  12. package/data/memories/project-context.md +8 -1
  13. package/data/personas/business-consultant.md +8 -1
  14. package/data/personas/creative-writer.md +8 -1
  15. package/data/personas/debug-detective.md +8 -1
  16. package/data/personas/eli5-explainer.md +8 -1
  17. package/data/personas/security-analyst.md +8 -1
  18. package/data/personas/technical-analyst.md +8 -1
  19. package/data/skills/code-review.md +8 -1
  20. package/data/skills/creative-writing.md +8 -1
  21. package/data/skills/data-analysis.md +8 -1
  22. package/data/skills/penetration-testing.md +8 -1
  23. package/data/skills/research.md +8 -1
  24. package/data/skills/threat-modeling.md +8 -1
  25. package/data/skills/translation.md +8 -1
  26. package/data/templates/code-documentation.md +8 -1
  27. package/data/templates/email-professional.md +8 -1
  28. package/data/templates/meeting-notes.md +8 -1
  29. package/data/templates/penetration-test-report.md +8 -1
  30. package/data/templates/project-brief.md +8 -1
  31. package/data/templates/report-executive.md +8 -1
  32. package/data/templates/security-vulnerability-report.md +8 -1
  33. package/data/templates/threat-assessment-report.md +8 -1
  34. package/dist/auth/GitHubAuthManager.d.ts +6 -1
  35. package/dist/auth/GitHubAuthManager.d.ts.map +1 -1
  36. package/dist/auth/GitHubAuthManager.js +45 -18
  37. package/dist/benchmarks/IndexPerformanceBenchmark.d.ts +98 -0
  38. package/dist/benchmarks/IndexPerformanceBenchmark.d.ts.map +1 -0
  39. package/dist/benchmarks/IndexPerformanceBenchmark.js +531 -0
  40. package/dist/cache/CollectionCache.d.ts.map +1 -1
  41. package/dist/cache/CollectionCache.js +13 -3
  42. package/dist/cache/CollectionIndexCache.d.ts +77 -0
  43. package/dist/cache/CollectionIndexCache.d.ts.map +1 -0
  44. package/dist/cache/CollectionIndexCache.js +349 -0
  45. package/dist/cache/LRUCache.d.ts +93 -0
  46. package/dist/cache/LRUCache.d.ts.map +1 -0
  47. package/dist/cache/LRUCache.js +299 -0
  48. package/dist/cache/index.d.ts +1 -0
  49. package/dist/cache/index.d.ts.map +1 -1
  50. package/dist/cache/index.js +2 -1
  51. package/dist/collection/CollectionBrowser.d.ts +21 -1
  52. package/dist/collection/CollectionBrowser.d.ts.map +1 -1
  53. package/dist/collection/CollectionBrowser.js +130 -10
  54. package/dist/collection/CollectionIndexManager.d.ts +151 -0
  55. package/dist/collection/CollectionIndexManager.d.ts.map +1 -0
  56. package/dist/collection/CollectionIndexManager.js +499 -0
  57. package/dist/collection/CollectionSearch.d.ts +55 -0
  58. package/dist/collection/CollectionSearch.d.ts.map +1 -1
  59. package/dist/collection/CollectionSearch.js +338 -13
  60. package/dist/collection/CollectionSeeder.d.ts.map +1 -1
  61. package/dist/collection/CollectionSeeder.js +38 -1
  62. package/dist/collection/ElementInstaller.d.ts +31 -0
  63. package/dist/collection/ElementInstaller.d.ts.map +1 -1
  64. package/dist/collection/ElementInstaller.js +77 -15
  65. package/dist/collection/PersonaSubmitter.d.ts +1 -1
  66. package/dist/collection/PersonaSubmitter.d.ts.map +1 -1
  67. package/dist/collection/PersonaSubmitter.js +2 -2
  68. package/dist/collection/index.d.ts +1 -0
  69. package/dist/collection/index.d.ts.map +1 -1
  70. package/dist/collection/index.js +2 -1
  71. package/dist/config/ConfigManager.d.ts +78 -0
  72. package/dist/config/ConfigManager.d.ts.map +1 -0
  73. package/dist/config/ConfigManager.js +216 -0
  74. package/dist/config/element-types.d.ts +135 -0
  75. package/dist/config/element-types.d.ts.map +1 -0
  76. package/dist/config/element-types.js +108 -0
  77. package/dist/config/index.d.ts +2 -0
  78. package/dist/config/index.d.ts.map +1 -1
  79. package/dist/config/index.js +3 -1
  80. package/dist/config/portfolio-constants.d.ts +83 -0
  81. package/dist/config/portfolio-constants.d.ts.map +1 -0
  82. package/dist/config/portfolio-constants.js +99 -0
  83. package/dist/elements/BaseElement.d.ts +14 -2
  84. package/dist/elements/BaseElement.d.ts.map +1 -1
  85. package/dist/elements/BaseElement.js +88 -6
  86. package/dist/elements/agents/Agent.d.ts +10 -1
  87. package/dist/elements/agents/Agent.d.ts.map +1 -1
  88. package/dist/elements/agents/Agent.js +66 -19
  89. package/dist/elements/agents/AgentManager.d.ts +2 -0
  90. package/dist/elements/agents/AgentManager.d.ts.map +1 -1
  91. package/dist/elements/agents/AgentManager.js +12 -10
  92. package/dist/elements/skills/Skill.d.ts +10 -1
  93. package/dist/elements/skills/Skill.d.ts.map +1 -1
  94. package/dist/elements/skills/Skill.js +40 -3
  95. package/dist/elements/skills/SkillManager.d.ts +1 -0
  96. package/dist/elements/skills/SkillManager.d.ts.map +1 -1
  97. package/dist/elements/skills/SkillManager.js +10 -4
  98. package/dist/elements/templates/Template.d.ts +10 -1
  99. package/dist/elements/templates/Template.d.ts.map +1 -1
  100. package/dist/elements/templates/Template.js +35 -18
  101. package/dist/elements/templates/TemplateManager.d.ts +1 -1
  102. package/dist/elements/templates/TemplateManager.d.ts.map +1 -1
  103. package/dist/elements/templates/TemplateManager.js +6 -5
  104. package/dist/generated/version.d.ts +2 -2
  105. package/dist/generated/version.js +3 -3
  106. package/dist/index.barrel.d.ts +1 -2
  107. package/dist/index.barrel.d.ts.map +1 -1
  108. package/dist/index.barrel.js +2 -4
  109. package/dist/index.d.ts +143 -25
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +1883 -310
  112. package/dist/persona/PersonaElement.d.ts +10 -0
  113. package/dist/persona/PersonaElement.d.ts.map +1 -1
  114. package/dist/persona/PersonaElement.js +55 -32
  115. package/dist/persona/PersonaElementManager.d.ts.map +1 -1
  116. package/dist/persona/PersonaElementManager.js +13 -11
  117. package/dist/persona/PersonaLoader.d.ts.map +1 -1
  118. package/dist/persona/PersonaLoader.js +8 -2
  119. package/dist/persona/export-import/PersonaImporter.d.ts.map +1 -1
  120. package/dist/persona/export-import/PersonaImporter.js +24 -5
  121. package/dist/persona/export-import/PersonaSharer.d.ts +21 -0
  122. package/dist/persona/export-import/PersonaSharer.d.ts.map +1 -1
  123. package/dist/persona/export-import/PersonaSharer.js +198 -22
  124. package/dist/portfolio/DefaultElementProvider.d.ts +90 -0
  125. package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
  126. package/dist/portfolio/DefaultElementProvider.js +499 -7
  127. package/dist/portfolio/GitHubPortfolioIndexer.d.ts +129 -0
  128. package/dist/portfolio/GitHubPortfolioIndexer.d.ts.map +1 -0
  129. package/dist/portfolio/GitHubPortfolioIndexer.js +475 -0
  130. package/dist/portfolio/MigrationManager.d.ts.map +1 -1
  131. package/dist/portfolio/MigrationManager.js +136 -3
  132. package/dist/portfolio/PortfolioIndexManager.d.ts +130 -0
  133. package/dist/portfolio/PortfolioIndexManager.d.ts.map +1 -0
  134. package/dist/portfolio/PortfolioIndexManager.js +478 -0
  135. package/dist/portfolio/PortfolioManager.d.ts +5 -0
  136. package/dist/portfolio/PortfolioManager.d.ts.map +1 -1
  137. package/dist/portfolio/PortfolioManager.js +61 -20
  138. package/dist/portfolio/PortfolioRepoManager.d.ts +75 -0
  139. package/dist/portfolio/PortfolioRepoManager.d.ts.map +1 -0
  140. package/dist/portfolio/PortfolioRepoManager.js +337 -0
  141. package/dist/portfolio/UnifiedIndexManager.d.ts +388 -0
  142. package/dist/portfolio/UnifiedIndexManager.d.ts.map +1 -0
  143. package/dist/portfolio/UnifiedIndexManager.js +1434 -0
  144. package/dist/portfolio/index.d.ts +15 -0
  145. package/dist/portfolio/index.d.ts.map +1 -0
  146. package/dist/portfolio/index.js +15 -0
  147. package/dist/portfolio/types.d.ts +7 -0
  148. package/dist/portfolio/types.d.ts.map +1 -1
  149. package/dist/portfolio/types.js +6 -1
  150. package/dist/security/InputValidator.d.ts.map +1 -1
  151. package/dist/security/InputValidator.js +50 -48
  152. package/dist/security/audit/SecurityAuditor.d.ts.map +1 -1
  153. package/dist/security/audit/SecurityAuditor.js +17 -9
  154. package/dist/security/audit/config/suppressions.d.ts.map +1 -1
  155. package/dist/security/audit/config/suppressions.js +19 -3
  156. package/dist/security/contentValidator.d.ts +2 -0
  157. package/dist/security/contentValidator.d.ts.map +1 -1
  158. package/dist/security/contentValidator.js +115 -4
  159. package/dist/security/secureYamlParser.d.ts +1 -0
  160. package/dist/security/secureYamlParser.d.ts.map +1 -1
  161. package/dist/security/secureYamlParser.js +29 -7
  162. package/dist/security/securityMonitor.d.ts +1 -1
  163. package/dist/security/securityMonitor.d.ts.map +1 -1
  164. package/dist/security/securityMonitor.js +1 -1
  165. package/dist/security/tokenManager.d.ts +1 -1
  166. package/dist/security/tokenManager.d.ts.map +1 -1
  167. package/dist/security/tokenManager.js +30 -10
  168. package/dist/server/ServerSetup.d.ts +22 -2
  169. package/dist/server/ServerSetup.d.ts.map +1 -1
  170. package/dist/server/ServerSetup.js +77 -12
  171. package/dist/server/tools/AuthTools.d.ts.map +1 -1
  172. package/dist/server/tools/AuthTools.js +33 -1
  173. package/dist/server/tools/BuildInfoTools.d.ts +25 -0
  174. package/dist/server/tools/BuildInfoTools.d.ts.map +1 -0
  175. package/dist/server/tools/BuildInfoTools.js +36 -0
  176. package/dist/server/tools/CollectionTools.d.ts.map +1 -1
  177. package/dist/server/tools/CollectionTools.js +55 -46
  178. package/dist/server/tools/ConfigTools.d.ts.map +1 -1
  179. package/dist/server/tools/ConfigTools.js +29 -1
  180. package/dist/server/tools/PersonaTools.d.ts +4 -2
  181. package/dist/server/tools/PersonaTools.d.ts.map +1 -1
  182. package/dist/server/tools/PersonaTools.js +5 -152
  183. package/dist/server/tools/PortfolioTools.d.ts +12 -0
  184. package/dist/server/tools/PortfolioTools.d.ts.map +1 -0
  185. package/dist/server/tools/PortfolioTools.js +221 -0
  186. package/dist/server/tools/index.d.ts +3 -1
  187. package/dist/server/tools/index.d.ts.map +1 -1
  188. package/dist/server/tools/index.js +4 -2
  189. package/dist/server/types.d.ts +40 -5
  190. package/dist/server/types.d.ts.map +1 -1
  191. package/dist/server/types.js +1 -1
  192. package/dist/services/BuildInfoService.d.ts +84 -0
  193. package/dist/services/BuildInfoService.d.ts.map +1 -0
  194. package/dist/services/BuildInfoService.js +271 -0
  195. package/dist/tools/portfolio/PortfolioElementAdapter.d.ts +54 -0
  196. package/dist/tools/portfolio/PortfolioElementAdapter.d.ts.map +1 -0
  197. package/dist/tools/portfolio/PortfolioElementAdapter.js +229 -0
  198. package/dist/tools/portfolio/submitToPortfolioTool.d.ts +164 -0
  199. package/dist/tools/portfolio/submitToPortfolioTool.d.ts.map +1 -0
  200. package/dist/tools/portfolio/submitToPortfolioTool.js +1523 -0
  201. package/dist/tools/portfolio/types.d.ts +41 -0
  202. package/dist/tools/portfolio/types.d.ts.map +1 -0
  203. package/dist/tools/portfolio/types.js +15 -0
  204. package/dist/types/collection.d.ts +51 -0
  205. package/dist/types/collection.d.ts.map +1 -1
  206. package/dist/types/collection.js +1 -1
  207. package/dist/utils/EarlyTerminationSearch.d.ts +41 -0
  208. package/dist/utils/EarlyTerminationSearch.d.ts.map +1 -0
  209. package/dist/utils/EarlyTerminationSearch.js +164 -0
  210. package/dist/utils/ErrorHandler.d.ts +86 -0
  211. package/dist/utils/ErrorHandler.d.ts.map +1 -0
  212. package/dist/utils/ErrorHandler.js +201 -0
  213. package/dist/utils/FileDiscoveryUtil.d.ts +53 -0
  214. package/dist/utils/FileDiscoveryUtil.d.ts.map +1 -0
  215. package/dist/utils/FileDiscoveryUtil.js +169 -0
  216. package/dist/utils/GitHubRateLimiter.d.ts +88 -0
  217. package/dist/utils/GitHubRateLimiter.d.ts.map +1 -0
  218. package/dist/utils/GitHubRateLimiter.js +315 -0
  219. package/dist/utils/PerformanceMonitor.d.ts +134 -0
  220. package/dist/utils/PerformanceMonitor.d.ts.map +1 -0
  221. package/dist/utils/PerformanceMonitor.js +347 -0
  222. package/dist/utils/RateLimiter.d.ts.map +1 -0
  223. package/dist/utils/RateLimiter.js +172 -0
  224. package/dist/utils/SecureDownloader.d.ts +241 -0
  225. package/dist/utils/SecureDownloader.d.ts.map +1 -0
  226. package/dist/utils/SecureDownloader.js +759 -0
  227. package/dist/utils/ToolCache.d.ts +82 -0
  228. package/dist/utils/ToolCache.d.ts.map +1 -0
  229. package/dist/utils/ToolCache.js +196 -0
  230. package/dist/utils/errorCodes.d.ts +136 -0
  231. package/dist/utils/errorCodes.d.ts.map +1 -0
  232. package/dist/utils/errorCodes.js +87 -0
  233. package/dist/utils/index.d.ts +3 -0
  234. package/dist/utils/index.d.ts.map +1 -1
  235. package/dist/utils/index.js +4 -1
  236. package/dist/utils/installation.d.ts +1 -1
  237. package/dist/utils/installation.d.ts.map +1 -1
  238. package/dist/utils/installation.js +9 -8
  239. package/dist/utils/searchUtils.d.ts +31 -0
  240. package/dist/utils/searchUtils.d.ts.map +1 -1
  241. package/dist/utils/searchUtils.js +62 -1
  242. package/package.json +17 -7
  243. package/dist/config/updateConfig.d.ts +0 -84
  244. package/dist/config/updateConfig.d.ts.map +0 -1
  245. package/dist/config/updateConfig.js +0 -148
  246. package/dist/server/tools/UpdateTools.d.ts +0 -10
  247. package/dist/server/tools/UpdateTools.d.ts.map +0 -1
  248. package/dist/server/tools/UpdateTools.js +0 -85
  249. package/dist/update/BackupManager.d.ts +0 -63
  250. package/dist/update/BackupManager.d.ts.map +0 -1
  251. package/dist/update/BackupManager.js +0 -370
  252. package/dist/update/DependencyChecker.d.ts +0 -41
  253. package/dist/update/DependencyChecker.d.ts.map +0 -1
  254. package/dist/update/DependencyChecker.js +0 -132
  255. package/dist/update/RateLimiter.d.ts.map +0 -1
  256. package/dist/update/RateLimiter.js +0 -172
  257. package/dist/update/SignatureVerifier.d.ts +0 -71
  258. package/dist/update/SignatureVerifier.d.ts.map +0 -1
  259. package/dist/update/SignatureVerifier.js +0 -214
  260. package/dist/update/UpdateChecker.d.ts +0 -132
  261. package/dist/update/UpdateChecker.d.ts.map +0 -1
  262. package/dist/update/UpdateChecker.js +0 -506
  263. package/dist/update/UpdateManager.d.ts +0 -60
  264. package/dist/update/UpdateManager.d.ts.map +0 -1
  265. package/dist/update/UpdateManager.js +0 -730
  266. package/dist/update/VersionManager.d.ts +0 -31
  267. package/dist/update/VersionManager.d.ts.map +0 -1
  268. package/dist/update/VersionManager.js +0 -181
  269. package/dist/update/index.d.ts +0 -9
  270. package/dist/update/index.d.ts.map +0 -1
  271. package/dist/update/index.js +0 -9
  272. /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,GAAE,MAAsB;IAK3C;;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"}
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"}