@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
@@ -12,8 +12,18 @@ export class CollectionCache {
12
12
  cacheDir;
13
13
  cacheFile;
14
14
  CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours for collection cache
15
- constructor(baseDir = process.cwd()) {
16
- this.cacheDir = path.join(baseDir, '.dollhousemcp', 'cache');
15
+ constructor(baseDir) {
16
+ // Use environment variable if set, otherwise fall back to parameter or default
17
+ const envCacheDir = process.env.DOLLHOUSE_CACHE_DIR;
18
+ if (envCacheDir) {
19
+ this.cacheDir = envCacheDir;
20
+ logger.debug(`CollectionCache: Using environment cache directory: ${this.cacheDir}`);
21
+ }
22
+ else {
23
+ const defaultBaseDir = baseDir || process.cwd();
24
+ this.cacheDir = path.join(defaultBaseDir, '.dollhousemcp', 'cache');
25
+ logger.debug(`CollectionCache: Using default cache directory: ${this.cacheDir}`);
26
+ }
17
27
  this.cacheFile = path.join(this.cacheDir, 'collection-cache.json');
18
28
  }
19
29
  /**
@@ -159,4 +169,4 @@ export class CollectionCache {
159
169
  };
160
170
  }
161
171
  }
162
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29sbGVjdGlvbkNhY2hlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NhY2hlL0NvbGxlY3Rpb25DYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU1QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFnQmpFOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFDbEIsUUFBUSxDQUFTO0lBQ2pCLFNBQVMsQ0FBUztJQUNULFlBQVksR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxnQ0FBZ0M7SUFFckYsWUFBWSxVQUFrQixPQUFPLENBQUMsR0FBRyxFQUFFO1FBQ3pDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLHVCQUF1QixDQUFDLENBQUM7SUFDckUsQ0FBQztJQUVEOztPQUVHO0lBQ0ssS0FBSyxDQUFDLGNBQWM7UUFDMUIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sQ0FBQyxLQUFLLENBQUMscUNBQXFDLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDM0QsTUFBTSxLQUFLLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FB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SSxJQUFJLENBQUMsWUFBWTtTQUMzRCxDQUFDO0lBQ0osQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQZXJzaXN0ZW50IGNhY2hlIGZvciBjb2xsZWN0aW9uIGRhdGEgdG8gc3VwcG9ydCBvZmZsaW5lL2Fub255bW91cyBicm93c2luZ1xuICovXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzL3Byb21pc2VzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgUGF0aFZhbGlkYXRvciB9IGZyb20gJy4uL3NlY3VyaXR5L3BhdGhWYWxpZGF0b3IuanMnO1xuaW1wb3J0IHsgU2VjdXJpdHlNb25pdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvc2VjdXJpdHlNb25pdG9yLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBDb2xsZWN0aW9uSXRlbSB7XG4gIG5hbWU6IHN0cmluZztcbiAgcGF0aDogc3RyaW5nO1xuICBzaGE6IHN0cmluZztcbiAgY29udGVudD86IHN0cmluZztcbiAgbGFzdF9tb2RpZmllZD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb2xsZWN0aW9uQ2FjaGVFbnRyeSB7XG4gIGl0ZW1zOiBDb2xsZWN0aW9uSXRlbVtdO1xuICB0aW1lc3RhbXA6IG51bWJlcjtcbiAgZXRhZz86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQZXJzaXN0ZW50IGNhY2hlIGZvciBjb2xsZWN0aW9uIGRhdGEgdGhhdCBzdXBwb3J0cyBvZmZsaW5lIGJyb3dzaW5nXG4gKi9cbmV4cG9ydCBjbGFzcyBDb2xsZWN0aW9uQ2FjaGUge1xuICBwcml2YXRlIGNhY2hlRGlyOiBzdHJpbmc7XG4gIHByaXZhdGUgY2FjaGVGaWxlOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgQ0FDSEVfVFRMX01TID0gMjQgKiA2MCAqIDYwICogMTAwMDsgLy8gMjQgaG91cnMgZm9yIGNvbGxlY3Rpb24gY2FjaGVcbiAgXG4gIGNvbnN0cnVjdG9yKGJhc2VEaXI6IHN0cmluZyA9IHByb2Nlc3MuY3dkKCkpIHtcbiAgICB0aGlzLmNhY2hlRGlyID0gcGF0aC5qb2luKGJhc2VEaXIsICcuZG9sbGhvdXNlbWNwJywgJ2NhY2hlJyk7XG4gICAgdGhpcy5jYWNoZUZpbGUgPSBwYXRoLmpvaW4odGhpcy5jYWNoZURpciwgJ2NvbGxlY3Rpb24tY2FjaGUuanNvbicpO1xuICB9XG4gIFxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBjYWNoZSBkaXJlY3RvcnlcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlQ2FjaGVEaXIoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGZzLm1rZGlyKHRoaXMuY2FjaGVEaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBjcmVhdGUgY2FjaGUgZGlyZWN0b3J5OiAke2Vycm9yfWApO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogTG9hZCBjb2xsZWN0aW9uIGRhdGEgZnJvbSBwZXJzaXN0ZW50IGNhY2hlXG4gICAqL1xuICBhc3luYyBsb2FkQ2FjaGUoKTogUHJvbWlzZTxDb2xsZWN0aW9uQ2FjaGVFbnRyeSB8IG51bGw+IHtcbiAgICB0cnkge1xuICAgICAgLy8gVmFsaWRhdGUgY2FjaGUgZmlsZSBwYXRoIChiYXNpYyBzZWN1cml0eSBjaGVjaylcbiAgICAgIGlmICh0aGlzLmNhY2hlRmlsZS5pbmNsdWRlcygnLi4nKSB8fCB0aGlzLmNhY2hlRmlsZS5pbmNsdWRlcygnXFwwJykpIHtcbiAgICAgICAgLy8gU0VDVVJJVFkgRklYOiBBZGQgYXVkaXQgbG9nZ2luZyBmb3IgcGF0aCB0cmF2ZXJzYWwgYXR0ZW1wdCBkZXRlY3Rpb25cbiAgICAgICAgU2VjdXJpdHlNb25pdG9yLmxvZ1NlY3VyaXR5RXZlbnQoe1xuICAgICAgICAgIHR5cGU6ICdQQVRIX1RSQVZFUlNBTF9BVFRFTVBUJyxcbiAgICAgICAgICBzZXZlcml0eTogJ0hJR0gnLFxuICAgICAgICAgIHNvdXJjZTogJ0NvbGxlY3Rpb25DYWNoZS5sb2FkQ2FjaGUnLFxuICAgICAgICAgIGRldGFpbHM6IGBQb3RlbnRpYWwgcGF0aCB0cmF2ZXJzYWwgYXR0ZW1wdCBkZXRlY3RlZCBpbiBjYWNoZSBmaWxlIHBhdGg6ICR7dGhpcy5jYWNoZUZpbGUuc3Vic3RyaW5nKDAsIDEwMCl9YFxuICAgICAgICB9KTtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ0ludmFsaWQgY2FjaGUgZmlsZSBwYXRoLCBza2lwcGluZyBjYWNoZSBsb2FkJyk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgXG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgZnMucmVhZEZpbGUodGhpcy5jYWNoZUZpbGUsICd1dGY4Jyk7XG4gICAgICBjb25zdCBjYWNoZTogQ29sbGVjdGlvbkNhY2hlRW50cnkgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgXG4gICAgICAvLyBDaGVjayBpZiBjYWNoZSBpcyBleHBpcmVkXG4gICAgICBpZiAoRGF0ZS5ub3coKSAtIGNhY2hlLnRpbWVzdGFtcCA+IHRoaXMuQ0FDSEVfVFRMX01TKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnQ29sbGVjdGlvbiBjYWNoZSBleHBpcmVkLCB3aWxsIHJlZnJlc2ggZnJvbSBHaXRIdWInKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgTG9hZGVkICR7Y2FjaGUuaXRlbXMubGVuZ3RofSBpdGVtcyBmcm9tIGNvbGxlY3Rpb24gY2FjaGVgKTtcbiAgICAgIHJldHVybiBjYWNoZTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKChlcnJvciBhcyBhbnkpLmNvZGUgIT09ICdFTk9FTlQnKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgRmFpbGVkIHRvIGxvYWQgY29sbGVjdGlvbiBjYWNoZTogJHtlcnJvcn1gKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIFNhdmUgY29sbGVjdGlvbiBkYXRhIHRvIHBlcnNpc3RlbnQgY2FjaGVcbiAgICovXG4gIGFzeW5jIHNhdmVDYWNoZShpdGVtczogQ29sbGVjdGlvbkl0ZW1bXSwgZXRhZz86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVuc3VyZUNhY2hlRGlyKCk7XG4gICAgICBcbiAgICAgIGNvbnN0IGNhY2hlRW50cnk6IENvbGxlY3Rpb25DYWNoZUVudHJ5ID0ge1xuICAgICAgICBpdGVtcyxcbiAgICAgICAgdGltZXN0YW1wOiBEYXRlLm5vdygpLFxuICAgICAgICBldGFnXG4gICAgICB9O1xuICAgICAgXG4gICAgICBjb25zdCBkYXRhID0gSlNPTi5zdHJpbmdpZnkoY2FjaGVFbnRyeSwgbnVsbCwgMik7XG4gICAgICBhd2FpdCBmcy53cml0ZUZpbGUodGhpcy5jYWNoZUZpbGUsIGRhdGEsICd1dGY4Jyk7XG4gICAgICBcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgU2F2ZWQgJHtpdGVtcy5sZW5ndGh9IGl0ZW1zIHRvIGNvbGxlY3Rpb24gY2FjaGVgKTtcbiAgICAgIFxuICAgICAgLy8gU0VDVVJJVFkgRklYOiBBZGQgYXVkaXQgbG9nZ2luZyBmb3IgY2FjaGUgd3JpdGUgb3BlcmF0aW9uc1xuICAgICAgbG9nZ2VyLmRlYnVnKCdTZWN1cml0eSBhdWRpdDogQ2FjaGUgd3JpdGUgb3BlcmF0aW9uIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHknKTtcbiAgICAgIFxuICAgICAgLy8gTG9nIG9wZXJhdGlvbiBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5XG4gICAgICBsb2dnZXIuZGVidWcoYENhY2hlIGZpbGUgb3BlcmF0aW9uIGNvbXBsZXRlZCB3aXRoICR7aXRlbXMubGVuZ3RofSBpdGVtc2ApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZXJyb3IoYEZhaWxlZCB0byBzYXZlIGNvbGxlY3Rpb24gY2FjaGU6ICR7ZXJyb3J9YCk7XG4gICAgICAvLyBEb24ndCB0aHJvdyAtIGNhY2hpbmcgZmFpbHVyZXMgc2hvdWxkbid0IGJyZWFrIGZ1bmN0aW9uYWxpdHlcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBTZWFyY2ggY2FjaGVkIGNvbGxlY3Rpb24gaXRlbXMgd2l0aCBmdXp6eSBtYXRjaGluZ1xuICAgKi9cbiAgYXN5bmMgc2VhcmNoQ2FjaGUocXVlcnk6IHN0cmluZyk6IFByb21pc2U8Q29sbGVjdGlvbkl0ZW1bXT4ge1xuICAgIGNvbnN0IGNhY2hlID0gYXdhaXQgdGhpcy5sb2FkQ2FjaGUoKTtcbiAgICBpZiAoIWNhY2hlKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIFxuICAgIGNvbnN0IG5vcm1hbGl6ZWRRdWVyeSA9IHRoaXMubm9ybWFsaXplU2VhcmNoVGVybShxdWVyeSk7XG4gICAgcmV0dXJuIGNhY2hlLml0ZW1zLmZpbHRlcihpdGVtID0+IHtcbiAgICAgIC8vIFNlYXJjaCBpbiBmaWxlbmFtZSBhbmQgcGF0aCB3aXRoIG5vcm1hbGl6YXRpb25cbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWROYW1lID0gdGhpcy5ub3JtYWxpemVTZWFyY2hUZXJtKGl0ZW0ubmFtZSk7XG4gICAgICBjb25zdCBub3JtYWxpemVkUGF0aCA9IHRoaXMubm9ybWFsaXplU2VhcmNoVGVybShpdGVtLnBhdGgpO1xuICAgICAgXG4gICAgICByZXR1cm4gbm9ybWFsaXplZE5hbWUuaW5jbHVkZXMobm9ybWFsaXplZFF1ZXJ5KSB8fCBcbiAgICAgICAgICAgICBub3JtYWxpemVkUGF0aC5pbmNsdWRlcyhub3JtYWxpemVkUXVlcnkpIHx8XG4gICAgICAgICAgICAgKGl0ZW0uY29udGVudCAmJiB0aGlzLm5vcm1hbGl6ZVNlYXJjaFRlcm0oaXRlbS5jb250ZW50KS5pbmNsdWRlcyhub3JtYWxpemVkUXVlcnkpKTtcbiAgICB9KTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIE5vcm1hbGl6ZSBzZWFyY2ggdGVybXMgZm9yIGJldHRlciBtYXRjaGluZyAoaGFuZGxlcyBzcGFjZXMsIGRhc2hlcywgZXRjLilcbiAgICovXG4gIHByaXZhdGUgbm9ybWFsaXplU2VhcmNoVGVybSh0ZXJtOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0ZXJtLnRvTG93ZXJDYXNlKClcbiAgICAgIC5yZXBsYWNlKC9bLV9cXHNdKy9nLCAnICcpICAvLyBDb252ZXJ0IGRhc2hlcywgdW5kZXJzY29yZXMgdG8gc3BhY2VzXG4gICAgICAucmVwbGFjZSgvXFwubWQkLywgJycpICAgICAgIC8vIFJlbW92ZSAubWQgZXh0ZW5zaW9uXG4gICAgICAudHJpbSgpO1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IGNhY2hlZCBjb2xsZWN0aW9uIGl0ZW1zIGJ5IHR5cGUvcGF0aFxuICAgKi9cbiAgYXN5bmMgZ2V0SXRlbXNCeVBhdGgocGF0aFByZWZpeDogc3RyaW5nKTogUHJvbWlzZTxDb2xsZWN0aW9uSXRlbVtdPiB7XG4gICAgY29uc3QgY2FjaGUgPSBhd2FpdCB0aGlzLmxvYWRDYWNoZSgpO1xuICAgIGlmICghY2FjaGUpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGNhY2hlLml0ZW1zLmZpbHRlcihpdGVtID0+IGl0ZW0ucGF0aC5zdGFydHNXaXRoKHBhdGhQcmVmaXgpKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIENoZWNrIGlmIGNhY2hlIGV4aXN0cyBhbmQgaXMgdmFsaWRcbiAgICovXG4gIGFzeW5jIGlzQ2FjaGVWYWxpZCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBjYWNoZSA9IGF3YWl0IHRoaXMubG9hZENhY2hlKCk7XG4gICAgcmV0dXJuIGNhY2hlICE9PSBudWxsO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2xlYXIgdGhlIGNhY2hlXG4gICAqL1xuICBhc3luYyBjbGVhckNhY2hlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmcy51bmxpbmsodGhpcy5jYWNoZUZpbGUpO1xuICAgICAgbG9nZ2VyLmRlYnVnKCdDb2xsZWN0aW9uIGNhY2hlIGNsZWFyZWQnKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKChlcnJvciBhcyBhbnkpLmNvZGUgIT09ICdFTk9FTlQnKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhgRmFpbGVkIHRvIGNsZWFyIGNvbGxlY3Rpb24gY2FjaGU6ICR7ZXJyb3J9YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogR2V0IGNhY2hlIHN0YXRzIGZvciBkZWJ1Z2dpbmdcbiAgICovXG4gIGFzeW5jIGdldENhY2hlU3RhdHMoKTogUHJvbWlzZTx7IGl0ZW1Db3VudDogbnVtYmVyOyBjYWNoZUFnZTogbnVtYmVyOyBpc1ZhbGlkOiBib29sZWFuIH0+IHtcbiAgICBjb25zdCBjYWNoZSA9IGF3YWl0IHRoaXMubG9hZENhY2hlKCk7XG4gICAgaWYgKCFjYWNoZSkge1xuICAgICAgcmV0dXJuIHsgaXRlbUNvdW50OiAwLCBjYWNoZUFnZTogMCwgaXNWYWxpZDogZmFsc2UgfTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHtcbiAgICAgIGl0ZW1Db3VudDogY2FjaGUuaXRlbXMubGVuZ3RoLFxuICAgICAgY2FjaGVBZ2U6IERhdGUubm93KCkgLSBjYWNoZS50aW1lc3RhbXAsXG4gICAgICBpc1ZhbGlkOiBEYXRlLm5vdygpIC0gY2FjaGUudGltZXN0YW1wIDw9IHRoaXMuQ0FDSEVfVFRMX01TXG4gICAgfTtcbiAgfVxufSJdfQ==
172
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29sbGVjdGlvbkNhY2hlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NhY2hlL0NvbGxlY3Rpb25DYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILE9BQU8sS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDO0FBQzdCLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU1QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFnQmpFOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFDbEIsUUFBUSxDQUFTO0lBQ2pCLFNBQVMsQ0FBUztJQUNULFlBQVksR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxnQ0FBZ0M7SUFFckYsWUFBWSxPQUFnQjtRQUMxQiwrRUFBK0U7UUFDL0UsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQztRQUNwRCxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLElBQUksQ0FBQyxRQUFRLEdBQUcsV0FBVyxDQUFDO1lBQzVCLE1BQU0sQ0FBQyxLQUFLLENBQUMsdURBQXVELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZGLENBQUM7YUFBTSxDQUFDO1lBQ04sTUFBTSxjQUFjLEdBQUcsT0FBTyxJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLGVBQWUsRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNwRSxNQUFNLENBQUMsS0FBSyxDQUFDLG1EQUFtRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUNuRixDQUFDO1FBQ0QsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENB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QUcsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ1gsT0FBTyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDdkQsQ0FBQztRQUVELE9BQU87WUFDTCxTQUFTLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNO1lBQzdCLFFBQVEsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsS0FBSyxDQUFDLFNBQVM7WUFDdEMsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLENBQUMsU0FBUyxJQUFJLElBQUksQ0FBQyxZQUFZO1NBQzNELENBQUM7SUFDSixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBlcnNpc3RlbnQgY2FjaGUgZm9yIGNvbGxlY3Rpb24gZGF0YSB0byBzdXBwb3J0IG9mZmxpbmUvYW5vbnltb3VzIGJyb3dzaW5nXG4gKi9cblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMvcHJvbWlzZXMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBQYXRoVmFsaWRhdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvcGF0aFZhbGlkYXRvci5qcyc7XG5pbXBvcnQgeyBTZWN1cml0eU1vbml0b3IgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cml0eU1vbml0b3IuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbGxlY3Rpb25JdGVtIHtcbiAgbmFtZTogc3RyaW5nO1xuICBwYXRoOiBzdHJpbmc7XG4gIHNoYTogc3RyaW5nO1xuICBjb250ZW50Pzogc3RyaW5nO1xuICBsYXN0X21vZGlmaWVkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbGxlY3Rpb25DYWNoZUVudHJ5IHtcbiAgaXRlbXM6IENvbGxlY3Rpb25JdGVtW107XG4gIHRpbWVzdGFtcDogbnVtYmVyO1xuICBldGFnPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFBlcnNpc3RlbnQgY2FjaGUgZm9yIGNvbGxlY3Rpb24gZGF0YSB0aGF0IHN1cHBvcnRzIG9mZmxpbmUgYnJvd3NpbmdcbiAqL1xuZXhwb3J0IGNsYXNzIENvbGxlY3Rpb25DYWNoZSB7XG4gIHByaXZhdGUgY2FjaGVEaXI6IHN0cmluZztcbiAgcHJpdmF0ZSBjYWNoZUZpbGU6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBDQUNIRV9UVExfTVMgPSAyNCAqIDYwICogNjAgKiAxMDAwOyAvLyAyNCBob3VycyBmb3IgY29sbGVjdGlvbiBjYWNoZVxuICBcbiAgY29uc3RydWN0b3IoYmFzZURpcj86IHN0cmluZykge1xuICAgIC8vIFVzZSBlbnZpcm9ubWVudCB2YXJpYWJsZSBpZiBzZXQsIG90aGVyd2lzZSBmYWxsIGJhY2sgdG8gcGFyYW1ldGVyIG9yIGRlZmF1bHRcbiAgICBjb25zdCBlbnZDYWNoZURpciA9IHByb2Nlc3MuZW52LkRPTExIT1VTRV9DQUNIRV9ESVI7XG4gICAgaWYgKGVudkNhY2hlRGlyKSB7XG4gICAgICB0aGlzLmNhY2hlRGlyID0gZW52Q2FjaGVEaXI7XG4gICAgICBsb2dnZXIuZGVidWcoYENvbGxlY3Rpb25DYWNoZTogVXNpbmcgZW52aXJvbm1lbnQgY2FjaGUgZGlyZWN0b3J5OiAke3RoaXMuY2FjaGVEaXJ9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IGRlZmF1bHRCYXNlRGlyID0gYmFzZURpciB8fCBwcm9jZXNzLmN3ZCgpO1xuICAgICAgdGhpcy5jYWNoZURpciA9IHBhdGguam9pbihkZWZhdWx0QmFzZURpciwgJy5kb2xsaG91c2VtY3AnLCAnY2FjaGUnKTtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgQ29sbGVjdGlvbkNhY2hlOiBVc2luZyBkZWZhdWx0IGNhY2hlIGRpcmVjdG9yeTogJHt0aGlzLmNhY2hlRGlyfWApO1xuICAgIH1cbiAgICB0aGlzLmNhY2hlRmlsZSA9IHBhdGguam9pbih0aGlzLmNhY2hlRGlyLCAnY29sbGVjdGlvbi1jYWNoZS5qc29uJyk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBJbml0aWFsaXplIGNhY2hlIGRpcmVjdG9yeVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBlbnN1cmVDYWNoZURpcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZnMubWtkaXIodGhpcy5jYWNoZURpciwgeyByZWN1cnNpdmU6IHRydWUgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIGNyZWF0ZSBjYWNoZSBkaXJlY3Rvcnk6ICR7ZXJyb3J9YCk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBMb2FkIGNvbGxlY3Rpb24gZGF0YSBmcm9tIHBlcnNpc3RlbnQgY2FjaGVcbiAgICovXG4gIGFzeW5jIGxvYWRDYWNoZSgpOiBQcm9taXNlPENvbGxlY3Rpb25DYWNoZUVudHJ5IHwgbnVsbD4ge1xuICAgIHRyeSB7XG4gICAgICAvLyBWYWxpZGF0ZSBjYWNoZSBmaWxlIHBhdGggKGJhc2ljIHNlY3VyaXR5IGNoZWNrKVxuICAgICAgaWYgKHRoaXMuY2FjaGVGaWxlLmluY2x1ZGVzKCcuLicpIHx8IHRoaXMuY2FjaGVGaWxlLmluY2x1ZGVzKCdcXDAnKSkge1xuICAgICAgICAvLyBTRUNVUklUWSBGSVg6IEFkZCBhdWRpdCBsb2dnaW5nIGZvciBwYXRoIHRyYXZlcnNhbCBhdHRlbXB0IGRldGVjdGlvblxuICAgICAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICAgICAgdHlwZTogJ1BBVEhfVFJBVkVSU0FMX0FUVEVNUFQnLFxuICAgICAgICAgIHNldmVyaXR5OiAnSElHSCcsXG4gICAgICAgICAgc291cmNlOiAnQ29sbGVjdGlvbkNhY2hlLmxvYWRDYWNoZScsXG4gICAgICAgICAgZGV0YWlsczogYFBvdGVudGlhbCBwYXRoIHRyYXZlcnNhbCBhdHRlbXB0IGRldGVjdGVkIGluIGNhY2hlIGZpbGUgcGF0aDogJHt0aGlzLmNhY2hlRmlsZS5zdWJzdHJpbmcoMCwgMTAwKX1gXG4gICAgICAgIH0pO1xuICAgICAgICBsb2dnZXIud2FybignSW52YWxpZCBjYWNoZSBmaWxlIHBhdGgsIHNraXBwaW5nIGNhY2hlIGxvYWQnKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICBcbiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBmcy5yZWFkRmlsZSh0aGlzLmNhY2hlRmlsZSwgJ3V0ZjgnKTtcbiAgICAgIGNvbnN0IGNhY2hlOiBDb2xsZWN0aW9uQ2FjaGVFbnRyeSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICBcbiAgICAgIC8vIENoZWNrIGlmIGNhY2hlIGlzIGV4cGlyZWRcbiAgICAgIGlmIChEYXRlLm5vdygpIC0gY2FjaGUudGltZXN0YW1wID4gdGhpcy5DQUNIRV9UVExfTVMpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdDb2xsZWN0aW9uIGNhY2hlIGV4cGlyZWQsIHdpbGwgcmVmcmVzaCBmcm9tIEdpdEh1YicpO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgbG9nZ2VyLmRlYnVnKGBMb2FkZWQgJHtjYWNoZS5pdGVtcy5sZW5ndGh9IGl0ZW1zIGZyb20gY29sbGVjdGlvbiBjYWNoZWApO1xuICAgICAgcmV0dXJuIGNhY2hlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoKGVycm9yIGFzIGFueSkuY29kZSAhPT0gJ0VOT0VOVCcpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBGYWlsZWQgdG8gbG9hZCBjb2xsZWN0aW9uIGNhY2hlOiAke2Vycm9yfWApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogU2F2ZSBjb2xsZWN0aW9uIGRhdGEgdG8gcGVyc2lzdGVudCBjYWNoZVxuICAgKi9cbiAgYXN5bmMgc2F2ZUNhY2hlKGl0ZW1zOiBDb2xsZWN0aW9uSXRlbVtdLCBldGFnPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlQ2FjaGVEaXIoKTtcbiAgICAgIFxuICAgICAgY29uc3QgY2FjaGVFbnRyeTogQ29sbGVjdGlvbkNhY2hlRW50cnkgPSB7XG4gICAgICAgIGl0ZW1zLFxuICAgICAgICB0aW1lc3RhbXA6IERhdGUubm93KCksXG4gICAgICAgIGV0YWdcbiAgICAgIH07XG4gICAgICBcbiAgICAgIGNvbnN0IGRhdGEgPSBKU09OLnN0cmluZ2lmeShjYWNoZUVudHJ5LCBudWxsLCAyKTtcbiAgICAgIGF3YWl0IGZzLndyaXRlRmlsZSh0aGlzLmNhY2hlRmlsZSwgZGF0YSwgJ3V0ZjgnKTtcbiAgICAgIFxuICAgICAgbG9nZ2VyLmRlYnVnKGBTYXZlZCAke2l0ZW1zLmxlbmd0aH0gaXRlbXMgdG8gY29sbGVjdGlvbiBjYWNoZWApO1xuICAgICAgXG4gICAgICAvLyBTRUNVUklUWSBGSVg6IEFkZCBhdWRpdCBsb2dnaW5nIGZvciBjYWNoZSB3cml0ZSBvcGVyYXRpb25zXG4gICAgICBsb2dnZXIuZGVidWcoJ1NlY3VyaXR5IGF1ZGl0OiBDYWNoZSB3cml0ZSBvcGVyYXRpb24gY29tcGxldGVkIHN1Y2Nlc3NmdWxseScpO1xuICAgICAgXG4gICAgICAvLyBMb2cgb3BlcmF0aW9uIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHlcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgQ2FjaGUgZmlsZSBvcGVyYXRpb24gY29tcGxldGVkIHdpdGggJHtpdGVtcy5sZW5ndGh9IGl0ZW1zYCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcihgRmFpbGVkIHRvIHNhdmUgY29sbGVjdGlvbiBjYWNoZTogJHtlcnJvcn1gKTtcbiAgICAgIC8vIERvbid0IHRocm93IC0gY2FjaGluZyBmYWlsdXJlcyBzaG91bGRuJ3QgYnJlYWsgZnVuY3Rpb25hbGl0eVxuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIFNlYXJjaCBjYWNoZWQgY29sbGVjdGlvbiBpdGVtcyB3aXRoIGZ1enp5IG1hdGNoaW5nXG4gICAqL1xuICBhc3luYyBzZWFyY2hDYWNoZShxdWVyeTogc3RyaW5nKTogUHJvbWlzZTxDb2xsZWN0aW9uSXRlbVtdPiB7XG4gICAgY29uc3QgY2FjaGUgPSBhd2FpdCB0aGlzLmxvYWRDYWNoZSgpO1xuICAgIGlmICghY2FjaGUpIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgXG4gICAgY29uc3Qgbm9ybWFsaXplZFF1ZXJ5ID0gdGhpcy5ub3JtYWxpemVTZWFyY2hUZXJtKHF1ZXJ5KTtcbiAgICByZXR1cm4gY2FjaGUuaXRlbXMuZmlsdGVyKGl0ZW0gPT4ge1xuICAgICAgLy8gU2VhcmNoIGluIGZpbGVuYW1lIGFuZCBwYXRoIHdpdGggbm9ybWFsaXphdGlvblxuICAgICAgY29uc3Qgbm9ybWFsaXplZE5hbWUgPSB0aGlzLm5vcm1hbGl6ZVNlYXJjaFRlcm0oaXRlbS5uYW1lKTtcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWRQYXRoID0gdGhpcy5ub3JtYWxpemVTZWFyY2hUZXJtKGl0ZW0ucGF0aCk7XG4gICAgICBcbiAgICAgIHJldHVybiBub3JtYWxpemVkTmFtZS5pbmNsdWRlcyhub3JtYWxpemVkUXVlcnkpIHx8IFxuICAgICAgICAgICAgIG5vcm1hbGl6ZWRQYXRoLmluY2x1ZGVzKG5vcm1hbGl6ZWRRdWVyeSkgfHxcbiAgICAgICAgICAgICAoaXRlbS5jb250ZW50ICYmIHRoaXMubm9ybWFsaXplU2VhcmNoVGVybShpdGVtLmNvbnRlbnQpLmluY2x1ZGVzKG5vcm1hbGl6ZWRRdWVyeSkpO1xuICAgIH0pO1xuICB9XG4gIFxuICAvKipcbiAgICogTm9ybWFsaXplIHNlYXJjaCB0ZXJtcyBmb3IgYmV0dGVyIG1hdGNoaW5nIChoYW5kbGVzIHNwYWNlcywgZGFzaGVzLCBldGMuKVxuICAgKi9cbiAgcHJpdmF0ZSBub3JtYWxpemVTZWFyY2hUZXJtKHRlcm06IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRlcm0udG9Mb3dlckNhc2UoKVxuICAgICAgLnJlcGxhY2UoL1stX1xcc10rL2csICcgJykgIC8vIENvbnZlcnQgZGFzaGVzLCB1bmRlcnNjb3JlcyB0byBzcGFjZXNcbiAgICAgIC5yZXBsYWNlKC9cXC5tZCQvLCAnJykgICAgICAgLy8gUmVtb3ZlIC5tZCBleHRlbnNpb25cbiAgICAgIC50cmltKCk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgY2FjaGVkIGNvbGxlY3Rpb24gaXRlbXMgYnkgdHlwZS9wYXRoXG4gICAqL1xuICBhc3luYyBnZXRJdGVtc0J5UGF0aChwYXRoUHJlZml4OiBzdHJpbmcpOiBQcm9taXNlPENvbGxlY3Rpb25JdGVtW10+IHtcbiAgICBjb25zdCBjYWNoZSA9IGF3YWl0IHRoaXMubG9hZENhY2hlKCk7XG4gICAgaWYgKCFjYWNoZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gY2FjaGUuaXRlbXMuZmlsdGVyKGl0ZW0gPT4gaXRlbS5wYXRoLnN0YXJ0c1dpdGgocGF0aFByZWZpeCkpO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2hlY2sgaWYgY2FjaGUgZXhpc3RzIGFuZCBpcyB2YWxpZFxuICAgKi9cbiAgYXN5bmMgaXNDYWNoZVZhbGlkKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGNhY2hlID0gYXdhaXQgdGhpcy5sb2FkQ2FjaGUoKTtcbiAgICByZXR1cm4gY2FjaGUgIT09IG51bGw7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDbGVhciB0aGUgY2FjaGVcbiAgICovXG4gIGFzeW5jIGNsZWFyQ2FjaGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGZzLnVubGluayh0aGlzLmNhY2hlRmlsZSk7XG4gICAgICBsb2dnZXIuZGVidWcoJ0NvbGxlY3Rpb24gY2FjaGUgY2xlYXJlZCcpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoKGVycm9yIGFzIGFueSkuY29kZSAhPT0gJ0VOT0VOVCcpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGBGYWlsZWQgdG8gY2xlYXIgY29sbGVjdGlvbiBjYWNoZTogJHtlcnJvcn1gKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgY2FjaGUgc3RhdHMgZm9yIGRlYnVnZ2luZ1xuICAgKi9cbiAgYXN5bmMgZ2V0Q2FjaGVTdGF0cygpOiBQcm9taXNlPHsgaXRlbUNvdW50OiBudW1iZXI7IGNhY2hlQWdlOiBudW1iZXI7IGlzVmFsaWQ6IGJvb2xlYW4gfT4ge1xuICAgIGNvbnN0IGNhY2hlID0gYXdhaXQgdGhpcy5sb2FkQ2FjaGUoKTtcbiAgICBpZiAoIWNhY2hlKSB7XG4gICAgICByZXR1cm4geyBpdGVtQ291bnQ6IDAsIGNhY2hlQWdlOiAwLCBpc1ZhbGlkOiBmYWxzZSB9O1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4ge1xuICAgICAgaXRlbUNvdW50OiBjYWNoZS5pdGVtcy5sZW5ndGgsXG4gICAgICBjYWNoZUFnZTogRGF0ZS5ub3coKSAtIGNhY2hlLnRpbWVzdGFtcCxcbiAgICAgIGlzVmFsaWQ6IERhdGUubm93KCkgLSBjYWNoZS50aW1lc3RhbXAgPD0gdGhpcy5DQUNIRV9UVExfTVNcbiAgICB9O1xuICB9XG59Il19
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Smart cache for collection index with conditional fetching and performance optimization
3
+ */
4
+ import { CollectionIndex } from '../types/collection.js';
5
+ import { GitHubClient } from '../collection/GitHubClient.js';
6
+ export declare class CollectionIndexCache {
7
+ private cache;
8
+ private readonly TTL;
9
+ private readonly INDEX_URL;
10
+ private cacheDir;
11
+ private cacheFile;
12
+ private githubClient;
13
+ private performanceMonitor;
14
+ private memoryCache;
15
+ private fetchPromise;
16
+ constructor(githubClient: GitHubClient, baseDir?: string);
17
+ /**
18
+ * Get the collection index with performance optimization and lazy loading
19
+ */
20
+ getIndex(lazyLoad?: boolean): Promise<CollectionIndex>;
21
+ /**
22
+ * Check if current cache is valid (within TTL)
23
+ */
24
+ private isValid;
25
+ /**
26
+ * Fetch fresh index from GitHub with conditional requests
27
+ */
28
+ private fetchFresh;
29
+ /**
30
+ * Validate the structure of a collection index
31
+ */
32
+ private validateIndexStructure;
33
+ /**
34
+ * Save cache to persistent storage
35
+ */
36
+ private saveToDisk;
37
+ /**
38
+ * Load cache from persistent storage
39
+ */
40
+ private loadFromDisk;
41
+ /**
42
+ * Ensure cache directory exists
43
+ */
44
+ private ensureCacheDir;
45
+ /**
46
+ * Clear all cache data with performance monitoring
47
+ */
48
+ clearCache(): Promise<void>;
49
+ /**
50
+ * Get comprehensive cache statistics for debugging and monitoring
51
+ */
52
+ getCacheStats(): {
53
+ isValid: boolean;
54
+ age: number;
55
+ hasCache: boolean;
56
+ elements: number;
57
+ memoryCache: any;
58
+ performanceMetrics: any;
59
+ };
60
+ /**
61
+ * Fetch fresh index with comprehensive fallback strategy
62
+ */
63
+ private fetchFreshWithFallback;
64
+ /**
65
+ * Record performance metrics for cache operations
66
+ */
67
+ private recordPerformanceMetrics;
68
+ /**
69
+ * Calculate cache hit rate (placeholder for future implementation)
70
+ */
71
+ private calculateCacheHitRate;
72
+ /**
73
+ * Calculate average access time (placeholder for future implementation)
74
+ */
75
+ private calculateAverageAccessTime;
76
+ }
77
+ //# sourceMappingURL=CollectionIndexCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectionIndexCache.d.ts","sourceRoot":"","sources":["../../src/cache/CollectionIndexCache.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,eAAe,EAAe,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAK7D,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAkB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiG;IAC3H,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,WAAW,CAAgB;IACnC,OAAO,CAAC,YAAY,CAAyC;gBAEjD,YAAY,EAAE,YAAY,EAAE,OAAO,GAAE,MAAsB;IAiBvE;;OAEG;IACG,QAAQ,CAAC,QAAQ,GAAE,OAAe,GAAG,OAAO,CAAC,eAAe,CAAC;IAiEnE;;OAEG;IACH,OAAO,CAAC,OAAO;IASf;;OAEG;YACW,UAAU;IAiExB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAc9B;;OAEG;YACW,UAAU;IAmBxB;;OAEG;YACW,YAAY;IA4B1B;;OAEG;YACW,cAAc;IAS5B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBjC;;OAEG;IACH,aAAa,IAAI;QACf,OAAO,EAAE,OAAO,CAAC;QACjB,GAAG,EAAE,MAAM,CAAC;QACZ,QAAQ,EAAE,OAAO,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,GAAG,CAAC;QACjB,kBAAkB,EAAE,GAAG,CAAC;KACzB;IA8BD;;OAEG;YACW,sBAAsB;IAuBpC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAqBhC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAK7B;;OAEG;IACH,OAAO,CAAC,0BAA0B;CAInC"}
@@ -0,0 +1,349 @@
1
+ /**
2
+ * Smart cache for collection index with conditional fetching and performance optimization
3
+ */
4
+ import * as fs from 'fs/promises';
5
+ import * as path from 'path';
6
+ import { logger } from '../utils/logger.js';
7
+ import { SecurityMonitor } from '../security/securityMonitor.js';
8
+ import { CacheFactory } from './LRUCache.js';
9
+ import { PerformanceMonitor } from '../utils/PerformanceMonitor.js';
10
+ export class CollectionIndexCache {
11
+ cache = null;
12
+ TTL = 15 * 60 * 1000; // 15 minutes in milliseconds
13
+ INDEX_URL = 'https://raw.githubusercontent.com/DollhouseMCP/collection/main/public/collection-index.json';
14
+ cacheDir;
15
+ cacheFile;
16
+ githubClient;
17
+ performanceMonitor;
18
+ memoryCache;
19
+ fetchPromise = null; // Prevent concurrent fetches
20
+ constructor(githubClient, baseDir = process.cwd()) {
21
+ this.githubClient = githubClient;
22
+ this.cacheDir = path.join(baseDir, '.dollhousemcp', 'cache');
23
+ this.cacheFile = path.join(this.cacheDir, 'collection-index-cache.json');
24
+ this.performanceMonitor = PerformanceMonitor.getInstance();
25
+ // Initialize memory cache for frequently accessed data
26
+ this.memoryCache = CacheFactory.createAPICache({
27
+ maxSize: 50,
28
+ maxMemoryMB: 10,
29
+ ttlMs: 5 * 60 * 1000, // 5 minutes
30
+ onEviction: (key, value) => {
31
+ logger.debug('Collection memory cache eviction', { key });
32
+ }
33
+ });
34
+ }
35
+ /**
36
+ * Get the collection index with performance optimization and lazy loading
37
+ */
38
+ async getIndex(lazyLoad = false) {
39
+ const startTime = Date.now();
40
+ const memoryBefore = process.memoryUsage().heapUsed;
41
+ try {
42
+ // Check memory cache first for fastest access
43
+ const memoryCached = this.memoryCache.get('collection-index');
44
+ if (memoryCached && this.isValid()) {
45
+ logger.debug('Using memory cached collection index');
46
+ this.recordPerformanceMetrics(startTime, memoryBefore, 'memory-hit');
47
+ return memoryCached;
48
+ }
49
+ // Check if we have valid disk cached data
50
+ if (this.isValid()) {
51
+ logger.debug('Using valid disk cached collection index');
52
+ const result = this.cache.data;
53
+ this.memoryCache.set('collection-index', result);
54
+ this.recordPerformanceMetrics(startTime, memoryBefore, 'disk-hit');
55
+ return result;
56
+ }
57
+ // Prevent concurrent fetches
58
+ if (this.fetchPromise) {
59
+ logger.debug('Waiting for ongoing collection index fetch');
60
+ return await this.fetchPromise;
61
+ }
62
+ // Lazy loading: Only fetch if not in lazy mode or absolutely necessary
63
+ if (lazyLoad && this.cache?.data) {
64
+ logger.debug('Using stale cache in lazy load mode');
65
+ this.recordPerformanceMetrics(startTime, memoryBefore, 'lazy-stale');
66
+ return this.cache.data;
67
+ }
68
+ // Create fetch promise to prevent concurrent requests
69
+ this.fetchPromise = this.fetchFreshWithFallback();
70
+ try {
71
+ const result = await this.fetchPromise;
72
+ this.memoryCache.set('collection-index', result);
73
+ this.recordPerformanceMetrics(startTime, memoryBefore, 'fresh-fetch');
74
+ return result;
75
+ }
76
+ finally {
77
+ this.fetchPromise = null;
78
+ }
79
+ }
80
+ catch (error) {
81
+ logger.error('Failed to get collection index:', error);
82
+ // Try loading from persistent cache as last resort
83
+ const persistentCache = await this.loadFromDisk();
84
+ if (persistentCache) {
85
+ logger.debug('Using persistent cache as last resort');
86
+ this.cache = persistentCache;
87
+ const result = persistentCache.data;
88
+ this.memoryCache.set('collection-index', result);
89
+ this.recordPerformanceMetrics(startTime, memoryBefore, 'disk-fallback');
90
+ return result;
91
+ }
92
+ throw error;
93
+ }
94
+ }
95
+ /**
96
+ * Check if current cache is valid (within TTL)
97
+ */
98
+ isValid() {
99
+ if (!this.cache) {
100
+ return false;
101
+ }
102
+ const age = Date.now() - this.cache.fetchedAt.getTime();
103
+ return age < this.TTL;
104
+ }
105
+ /**
106
+ * Fetch fresh index from GitHub with conditional requests
107
+ */
108
+ async fetchFresh() {
109
+ try {
110
+ // Build headers for conditional request
111
+ const headers = {
112
+ 'Accept': 'application/json',
113
+ 'User-Agent': 'DollhouseMCP/1.0'
114
+ };
115
+ // Add conditional headers if we have cache
116
+ if (this.cache?.etag) {
117
+ headers['If-None-Match'] = this.cache.etag;
118
+ }
119
+ if (this.cache?.lastModified) {
120
+ headers['If-Modified-Since'] = this.cache.lastModified;
121
+ }
122
+ // Use fetch directly for better control over conditional requests
123
+ const response = await fetch(this.INDEX_URL, { headers });
124
+ // 304 Not Modified - use cached data
125
+ if (response.status === 304) {
126
+ if (this.cache) {
127
+ // Update timestamp to extend cache validity
128
+ this.cache.fetchedAt = new Date();
129
+ await this.saveToDisk(this.cache);
130
+ logger.debug('Collection index not modified - refreshed cache timestamp');
131
+ return this.cache.data;
132
+ }
133
+ }
134
+ if (!response.ok) {
135
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
136
+ }
137
+ const indexData = await response.json();
138
+ // Validate the index structure
139
+ if (!this.validateIndexStructure(indexData)) {
140
+ throw new Error('Invalid collection index structure received');
141
+ }
142
+ // Create new cache entry
143
+ const newCache = {
144
+ data: indexData,
145
+ fetchedAt: new Date(),
146
+ etag: response.headers.get('etag') || undefined,
147
+ lastModified: response.headers.get('last-modified') || undefined
148
+ };
149
+ this.cache = newCache;
150
+ // Save to persistent cache in background
151
+ this.saveToDisk(newCache).catch(error => {
152
+ logger.debug('Failed to save index cache to disk:', error);
153
+ });
154
+ logger.debug(`Fresh collection index fetched with ${indexData.total_elements} elements`);
155
+ return indexData;
156
+ }
157
+ catch (error) {
158
+ logger.debug('Failed to fetch fresh collection index:', error);
159
+ return null;
160
+ }
161
+ }
162
+ /**
163
+ * Validate the structure of a collection index
164
+ */
165
+ validateIndexStructure(index) {
166
+ return (index &&
167
+ typeof index === 'object' &&
168
+ typeof index.version === 'string' &&
169
+ typeof index.generated === 'string' &&
170
+ typeof index.total_elements === 'number' &&
171
+ index.index &&
172
+ typeof index.index === 'object' &&
173
+ index.metadata &&
174
+ typeof index.metadata === 'object');
175
+ }
176
+ /**
177
+ * Save cache to persistent storage
178
+ */
179
+ async saveToDisk(cache) {
180
+ try {
181
+ await this.ensureCacheDir();
182
+ const cacheData = {
183
+ ...cache,
184
+ fetchedAt: cache.fetchedAt.toISOString() // Serialize date
185
+ };
186
+ const data = JSON.stringify(cacheData, null, 2);
187
+ await fs.writeFile(this.cacheFile, data, 'utf8');
188
+ logger.debug('Collection index cache saved to disk');
189
+ }
190
+ catch (error) {
191
+ logger.debug('Failed to save collection index cache:', error);
192
+ // Don't throw - cache persistence failures shouldn't break functionality
193
+ }
194
+ }
195
+ /**
196
+ * Load cache from persistent storage
197
+ */
198
+ async loadFromDisk() {
199
+ try {
200
+ // Basic security check for path traversal
201
+ if (this.cacheFile.includes('..') || this.cacheFile.includes('\0')) {
202
+ SecurityMonitor.logSecurityEvent({
203
+ type: 'PATH_TRAVERSAL_ATTEMPT',
204
+ severity: 'HIGH',
205
+ source: 'CollectionIndexCache.loadFromDisk',
206
+ details: `Potential path traversal attempt detected: ${this.cacheFile.substring(0, 100)}`
207
+ });
208
+ return null;
209
+ }
210
+ const data = await fs.readFile(this.cacheFile, 'utf8');
211
+ const cacheData = JSON.parse(data);
212
+ return {
213
+ ...cacheData,
214
+ fetchedAt: new Date(cacheData.fetchedAt) // Deserialize date
215
+ };
216
+ }
217
+ catch (error) {
218
+ if (error.code !== 'ENOENT') {
219
+ logger.debug('Failed to load collection index cache from disk:', error);
220
+ }
221
+ return null;
222
+ }
223
+ }
224
+ /**
225
+ * Ensure cache directory exists
226
+ */
227
+ async ensureCacheDir() {
228
+ try {
229
+ await fs.mkdir(this.cacheDir, { recursive: true });
230
+ }
231
+ catch (error) {
232
+ logger.error('Failed to create cache directory:', error);
233
+ throw error;
234
+ }
235
+ }
236
+ /**
237
+ * Clear all cache data with performance monitoring
238
+ */
239
+ async clearCache() {
240
+ const startTime = Date.now();
241
+ this.cache = null;
242
+ this.memoryCache.clear();
243
+ // Cancel any ongoing fetch
244
+ this.fetchPromise = null;
245
+ try {
246
+ await fs.unlink(this.cacheFile);
247
+ logger.debug('Collection index cache cleared from disk');
248
+ }
249
+ catch (error) {
250
+ if (error.code !== 'ENOENT') {
251
+ logger.debug('Failed to clear collection index cache:', error);
252
+ }
253
+ }
254
+ logger.debug('Collection cache cleared', {
255
+ duration: Date.now() - startTime,
256
+ memoryFreed: this.memoryCache.getMemoryUsageMB()
257
+ });
258
+ }
259
+ /**
260
+ * Get comprehensive cache statistics for debugging and monitoring
261
+ */
262
+ getCacheStats() {
263
+ if (!this.cache) {
264
+ return {
265
+ isValid: false,
266
+ age: 0,
267
+ hasCache: false,
268
+ elements: 0,
269
+ memoryCache: this.memoryCache.getStats(),
270
+ performanceMetrics: null
271
+ };
272
+ }
273
+ const age = Date.now() - this.cache.fetchedAt.getTime();
274
+ return {
275
+ isValid: this.isValid(),
276
+ age,
277
+ hasCache: true,
278
+ elements: this.cache.data.total_elements,
279
+ memoryCache: this.memoryCache.getStats(),
280
+ performanceMetrics: {
281
+ cacheHitRate: this.calculateCacheHitRate(),
282
+ averageAccessTime: this.calculateAverageAccessTime()
283
+ }
284
+ };
285
+ }
286
+ // =====================================================
287
+ // PRIVATE HELPER METHODS FOR PERFORMANCE
288
+ // =====================================================
289
+ /**
290
+ * Fetch fresh index with comprehensive fallback strategy
291
+ */
292
+ async fetchFreshWithFallback() {
293
+ try {
294
+ // Try to fetch fresh index
295
+ const freshIndex = await this.fetchFresh();
296
+ if (freshIndex) {
297
+ logger.debug('Collection index fetched successfully');
298
+ return freshIndex;
299
+ }
300
+ }
301
+ catch (error) {
302
+ logger.warn('Fresh fetch failed, trying fallback', {
303
+ error: error instanceof Error ? error.message : String(error)
304
+ });
305
+ }
306
+ // Fall back to stale cache if available
307
+ if (this.cache?.data) {
308
+ logger.debug('Using stale cached collection index as fallback');
309
+ return this.cache.data;
310
+ }
311
+ throw new Error('No collection index available - fresh fetch failed and no cache exists');
312
+ }
313
+ /**
314
+ * Record performance metrics for cache operations
315
+ */
316
+ recordPerformanceMetrics(startTime, memoryBefore, operation) {
317
+ const duration = Date.now() - startTime;
318
+ const memoryAfter = process.memoryUsage().heapUsed;
319
+ logger.debug('Collection cache operation completed', {
320
+ operation,
321
+ duration,
322
+ memoryUsageMB: (memoryAfter - memoryBefore) / (1024 * 1024)
323
+ });
324
+ // Record cache performance metrics
325
+ this.performanceMonitor.recordCachePerformance('collectionIndex', {
326
+ hitRate: operation.includes('hit') ? 1 : 0,
327
+ avgHitTime: operation.includes('hit') ? duration : 0,
328
+ avgMissTime: operation.includes('hit') ? 0 : duration,
329
+ totalHits: operation.includes('hit') ? 1 : 0,
330
+ totalMisses: operation.includes('hit') ? 0 : 1,
331
+ evictions: 0
332
+ });
333
+ }
334
+ /**
335
+ * Calculate cache hit rate (placeholder for future implementation)
336
+ */
337
+ calculateCacheHitRate() {
338
+ // This would be implemented with actual metrics tracking
339
+ return this.memoryCache.getStats().hitRate;
340
+ }
341
+ /**
342
+ * Calculate average access time (placeholder for future implementation)
343
+ */
344
+ calculateAverageAccessTime() {
345
+ // This would be implemented with actual timing metrics
346
+ return 5; // Placeholder value
347
+ }
348
+ }
349
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29sbGVjdGlvbkluZGV4Q2FjaGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY2FjaGUvQ29sbGVjdGlvbkluZGV4Q2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUU3QixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFNUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2pFLE9BQU8sRUFBWSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFcEUsTUFBTSxPQUFPLG9CQUFvQjtJQUN2QixLQUFLLEdBQXVCLElBQUksQ0FBQztJQUN4QixHQUFHLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyw2QkFBNkI7SUFDbkQsU0FBUyxHQUFHLDZGQUE2RixDQUFDO0lBQ25ILFFBQVEsQ0FBUztJQUNqQixTQUFTLENBQVM7SUFDbEIsWUFBWSxDQUFlO0lBQzNCLGtCQUFrQixDQUFxQjtJQUN2QyxXQUFXLENBQWdCO0lBQzNCLFlBQVksR0FBb0MsSUFBSSxDQUFDLENBQUMsNkJBQTZCO0lBRTNGLFlBQVksWUFBMEIsRUFBRSxVQUFrQixPQUFPLENBQUMsR0FBRyxFQUFFO1FBQ3JFLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO1FBQ2pDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLDZCQUE2QixDQUFDLENBQUM7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SyxxQkFBcUI7UUFDM0IseURBQXlEO1FBQ3pELE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxPQUFPLENBQUM7SUFDN0MsQ0FBQztJQUVEOztPQUVHO0lBQ0ssMEJBQTBCO1FBQ2hDLHVEQUF1RDtRQUN2RCxPQUFPLENBQUMsQ0FBQyxDQUFDLG9CQUFvQjtJQUNoQyxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNtYXJ0IGNhY2hlIGZvciBjb2xsZWN0aW9uIGluZGV4IHdpdGggY29uZGl0aW9uYWwgZmV0Y2hpbmcgYW5kIHBlcmZvcm1hbmNlIG9wdGltaXphdGlvblxuICovXG5cbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzL3Byb21pc2VzJztcbmltcG9ydCAqIGFzIHBhdGggZnJvbSAncGF0aCc7XG5pbXBvcnQgeyBDb2xsZWN0aW9uSW5kZXgsIENhY2hlZEluZGV4IH0gZnJvbSAnLi4vdHlwZXMvY29sbGVjdGlvbi5qcyc7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgR2l0SHViQ2xpZW50IH0gZnJvbSAnLi4vY29sbGVjdGlvbi9HaXRIdWJDbGllbnQuanMnO1xuaW1wb3J0IHsgU2VjdXJpdHlNb25pdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvc2VjdXJpdHlNb25pdG9yLmpzJztcbmltcG9ydCB7IExSVUNhY2hlLCBDYWNoZUZhY3RvcnkgfSBmcm9tICcuL0xSVUNhY2hlLmpzJztcbmltcG9ydCB7IFBlcmZvcm1hbmNlTW9uaXRvciB9IGZyb20gJy4uL3V0aWxzL1BlcmZvcm1hbmNlTW9uaXRvci5qcyc7XG5cbmV4cG9ydCBjbGFzcyBDb2xsZWN0aW9uSW5kZXhDYWNoZSB7XG4gIHByaXZhdGUgY2FjaGU6IENhY2hlZEluZGV4IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgVFRMID0gMTUgKiA2MCAqIDEwMDA7IC8vIDE1IG1pbnV0ZXMgaW4gbWlsbGlzZWNvbmRzXG4gIHByaXZhdGUgcmVhZG9ubHkgSU5ERVhfVVJMID0gJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9tYWluL3B1YmxpYy9jb2xsZWN0aW9uLWluZGV4Lmpzb24nO1xuICBwcml2YXRlIGNhY2hlRGlyOiBzdHJpbmc7XG4gIHByaXZhdGUgY2FjaGVGaWxlOiBzdHJpbmc7XG4gIHByaXZhdGUgZ2l0aHViQ2xpZW50OiBHaXRIdWJDbGllbnQ7XG4gIHByaXZhdGUgcGVyZm9ybWFuY2VNb25pdG9yOiBQZXJmb3JtYW5jZU1vbml0b3I7XG4gIHByaXZhdGUgbWVtb3J5Q2FjaGU6IExSVUNhY2hlPGFueT47XG4gIHByaXZhdGUgZmV0Y2hQcm9taXNlOiBQcm9taXNlPENvbGxlY3Rpb25JbmRleD4gfCBudWxsID0gbnVsbDsgLy8gUHJldmVudCBjb25jdXJyZW50IGZldGNoZXNcbiAgXG4gIGNvbnN0cnVjdG9yKGdpdGh1YkNsaWVudDogR2l0SHViQ2xpZW50LCBiYXNlRGlyOiBzdHJpbmcgPSBwcm9jZXNzLmN3ZCgpKSB7XG4gICAgdGhpcy5naXRodWJDbGllbnQgPSBnaXRodWJDbGllbnQ7XG4gICAgdGhpcy5jYWNoZURpciA9IHBhdGguam9pbihiYXNlRGlyLCAnLmRvbGxob3VzZW1jcCcsICdjYWNoZScpO1xuICAgIHRoaXMuY2FjaGVGaWxlID0gcGF0aC5qb2luKHRoaXMuY2FjaGVEaXIsICdjb2xsZWN0aW9uLWluZGV4LWNhY2hlLmpzb24nKTtcbiAgICB0aGlzLnBlcmZvcm1hbmNlTW9uaXRvciA9IFBlcmZvcm1hbmNlTW9uaXRvci5nZXRJbnN0YW5jZSgpO1xuICAgIFxuICAgIC8vIEluaXRpYWxpemUgbWVtb3J5IGNhY2hlIGZvciBmcmVxdWVudGx5IGFjY2Vzc2VkIGRhdGFcbiAgICB0aGlzLm1lbW9yeUNhY2hlID0gQ2FjaGVGYWN0b3J5LmNyZWF0ZUFQSUNhY2hlKHtcbiAgICAgIG1heFNpemU6IDUwLFxuICAgICAgbWF4TWVtb3J5TUI6IDEwLFxuICAgICAgdHRsTXM6IDUgKiA2MCAqIDEwMDAsIC8vIDUgbWludXRlc1xuICAgICAgb25FdmljdGlvbjogKGtleSwgdmFsdWUpID0+IHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdDb2xsZWN0aW9uIG1lbW9yeSBjYWNoZSBldmljdGlvbicsIHsga2V5IH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IHRoZSBjb2xsZWN0aW9uIGluZGV4IHdpdGggcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uIGFuZCBsYXp5IGxvYWRpbmdcbiAgICovXG4gIGFzeW5jIGdldEluZGV4KGxhenlMb2FkOiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPENvbGxlY3Rpb25JbmRleD4ge1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgY29uc3QgbWVtb3J5QmVmb3JlID0gcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLmhlYXBVc2VkO1xuICAgIFxuICAgIHRyeSB7XG4gICAgICAvLyBDaGVjayBtZW1vcnkgY2FjaGUgZmlyc3QgZm9yIGZhc3Rlc3QgYWNjZXNzXG4gICAgICBjb25zdCBtZW1vcnlDYWNoZWQgPSB0aGlzLm1lbW9yeUNhY2hlLmdldCgnY29sbGVjdGlvbi1pbmRleCcpO1xuICAgICAgaWYgKG1lbW9yeUNhY2hlZCAmJiB0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1VzaW5nIG1lbW9yeSBjYWNoZWQgY29sbGVjdGlvbiBpbmRleCcpO1xuICAgICAgICB0aGlzLnJlY29yZFBlcmZvcm1hbmNlTWV0cmljcyhzdGFydFRpbWUsIG1lbW9yeUJlZm9yZSwgJ21lbW9yeS1oaXQnKTtcbiAgICAgICAgcmV0dXJuIG1lbW9yeUNhY2hlZDtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSB2YWxpZCBkaXNrIGNhY2hlZCBkYXRhXG4gICAgICBpZiAodGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdVc2luZyB2YWxpZCBkaXNrIGNhY2hlZCBjb2xsZWN0aW9uIGluZGV4Jyk7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuY2FjaGUhLmRhdGE7XG4gICAgICAgIHRoaXMubWVtb3J5Q2FjaGUuc2V0KCdjb2xsZWN0aW9uLWluZGV4JywgcmVzdWx0KTtcbiAgICAgICAgdGhpcy5yZWNvcmRQZXJmb3JtYW5jZU1ldHJpY3Moc3RhcnRUaW1lLCBtZW1vcnlCZWZvcmUsICdkaXNrLWhpdCcpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBQcmV2ZW50IGNvbmN1cnJlbnQgZmV0Y2hlc1xuICAgICAgaWYgKHRoaXMuZmV0Y2hQcm9taXNlKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnV2FpdGluZyBmb3Igb25nb2luZyBjb2xsZWN0aW9uIGluZGV4IGZldGNoJyk7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmZldGNoUHJvbWlzZTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gTGF6eSBsb2FkaW5nOiBPbmx5IGZldGNoIGlmIG5vdCBpbiBsYXp5IG1vZGUgb3IgYWJzb2x1dGVseSBuZWNlc3NhcnlcbiAgICAgIGlmIChsYXp5TG9hZCAmJiB0aGlzLmNhY2hlPy5kYXRhKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnVXNpbmcgc3RhbGUgY2FjaGUgaW4gbGF6eSBsb2FkIG1vZGUnKTtcbiAgICAgICAgdGhpcy5yZWNvcmRQZXJmb3JtYW5jZU1ldHJpY3Moc3RhcnRUaW1lLCBtZW1vcnlCZWZvcmUsICdsYXp5LXN0YWxlJyk7XG4gICAgICAgIHJldHVybiB0aGlzLmNhY2hlLmRhdGE7XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIENyZWF0ZSBmZXRjaCBwcm9taXNlIHRvIHByZXZlbnQgY29uY3VycmVudCByZXF1ZXN0c1xuICAgICAgdGhpcy5mZXRjaFByb21pc2UgPSB0aGlzLmZldGNoRnJlc2hXaXRoRmFsbGJhY2soKTtcbiAgICAgIFxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5mZXRjaFByb21pc2U7XG4gICAgICAgIHRoaXMubWVtb3J5Q2FjaGUuc2V0KCdjb2xsZWN0aW9uLWluZGV4JywgcmVzdWx0KTtcbiAgICAgICAgdGhpcy5yZWNvcmRQZXJmb3JtYW5jZU1ldHJpY3Moc3RhcnRUaW1lLCBtZW1vcnlCZWZvcmUsICdmcmVzaC1mZXRjaCcpO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgdGhpcy5mZXRjaFByb21pc2UgPSBudWxsO1xuICAgICAgfVxuICAgICAgXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignRmFpbGVkIHRvIGdldCBjb2xsZWN0aW9uIGluZGV4OicsIGVycm9yKTtcbiAgICAgIFxuICAgICAgLy8gVHJ5IGxvYWRpbmcgZnJvbSBwZXJzaXN0ZW50IGNhY2hlIGFzIGxhc3QgcmVzb3J0XG4gICAgICBjb25zdCBwZXJzaXN0ZW50Q2FjaGUgPSBhd2FpdCB0aGlzLmxvYWRGcm9tRGlzaygpO1xuICAgICAgaWYgKHBlcnNpc3RlbnRDYWNoZSkge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1VzaW5nIHBlcnNpc3RlbnQgY2FjaGUgYXMgbGFzdCByZXNvcnQnKTtcbiAgICAgICAgdGhpcy5jYWNoZSA9IHBlcnNpc3RlbnRDYWNoZTtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gcGVyc2lzdGVudENhY2hlLmRhdGE7XG4gICAgICAgIHRoaXMubWVtb3J5Q2FjaGUuc2V0KCdjb2xsZWN0aW9uLWluZGV4JywgcmVzdWx0KTtcbiAgICAgICAgdGhpcy5yZWNvcmRQZXJmb3JtYW5jZU1ldHJpY3Moc3RhcnRUaW1lLCBtZW1vcnlCZWZvcmUsICdkaXNrLWZhbGxiYWNrJyk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgICBcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIENoZWNrIGlmIGN1cnJlbnQgY2FjaGUgaXMgdmFsaWQgKHdpdGhpbiBUVEwpXG4gICAqL1xuICBwcml2YXRlIGlzVmFsaWQoKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLmNhY2hlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIFxuICAgIGNvbnN0IGFnZSA9IERhdGUubm93KCkgLSB0aGlzLmNhY2hlLmZldGNoZWRBdC5nZXRUaW1lKCk7XG4gICAgcmV0dXJuIGFnZSA8IHRoaXMuVFRMO1xuICB9XG4gIFxuICAvKipcbiAgICogRmV0Y2ggZnJlc2ggaW5kZXggZnJvbSBHaXRIdWIgd2l0aCBjb25kaXRpb25hbCByZXF1ZXN0c1xuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaEZyZXNoKCk6IFByb21pc2U8Q29sbGVjdGlvbkluZGV4IHwgbnVsbD4ge1xuICAgIHRyeSB7XG4gICAgICAvLyBCdWlsZCBoZWFkZXJzIGZvciBjb25kaXRpb25hbCByZXF1ZXN0XG4gICAgICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgICAnQWNjZXB0JzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAnVXNlci1BZ2VudCc6ICdEb2xsaG91c2VNQ1AvMS4wJ1xuICAgICAgfTtcbiAgICAgIFxuICAgICAgLy8gQWRkIGNvbmRpdGlvbmFsIGhlYWRlcnMgaWYgd2UgaGF2ZSBjYWNoZVxuICAgICAgaWYgKHRoaXMuY2FjaGU/LmV0YWcpIHtcbiAgICAgICAgaGVhZGVyc1snSWYtTm9uZS1NYXRjaCddID0gdGhpcy5jYWNoZS5ldGFnO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuY2FjaGU/Lmxhc3RNb2RpZmllZCkge1xuICAgICAgICBoZWFkZXJzWydJZi1Nb2RpZmllZC1TaW5jZSddID0gdGhpcy5jYWNoZS5sYXN0TW9kaWZpZWQ7XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIFVzZSBmZXRjaCBkaXJlY3RseSBmb3IgYmV0dGVyIGNvbnRyb2wgb3ZlciBjb25kaXRpb25hbCByZXF1ZXN0c1xuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh0aGlzLklOREVYX1VSTCwgeyBoZWFkZXJzIH0pO1xuICAgICAgXG4gICAgICAvLyAzMDQgTm90IE1vZGlmaWVkIC0gdXNlIGNhY2hlZCBkYXRhXG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09PSAzMDQpIHtcbiAgICAgICAgaWYgKHRoaXMuY2FjaGUpIHtcbiAgICAgICAgICAvLyBVcGRhdGUgdGltZXN0YW1wIHRvIGV4dGVuZCBjYWNoZSB2YWxpZGl0eVxuICAgICAgICAgIHRoaXMuY2FjaGUuZmV0Y2hlZEF0ID0gbmV3IERhdGUoKTtcbiAgICAgICAgICBhd2FpdCB0aGlzLnNhdmVUb0Rpc2sodGhpcy5jYWNoZSk7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKCdDb2xsZWN0aW9uIGluZGV4IG5vdCBtb2RpZmllZCAtIHJlZnJlc2hlZCBjYWNoZSB0aW1lc3RhbXAnKTtcbiAgICAgICAgICByZXR1cm4gdGhpcy5jYWNoZS5kYXRhO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBcbiAgICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBIVFRQICR7cmVzcG9uc2Uuc3RhdHVzfTogJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgICAgfVxuICAgICAgXG4gICAgICBjb25zdCBpbmRleERhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCkgYXMgQ29sbGVjdGlvbkluZGV4O1xuICAgICAgXG4gICAgICAvLyBWYWxpZGF0ZSB0aGUgaW5kZXggc3RydWN0dXJlXG4gICAgICBpZiAoIXRoaXMudmFsaWRhdGVJbmRleFN0cnVjdHVyZShpbmRleERhdGEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb2xsZWN0aW9uIGluZGV4IHN0cnVjdHVyZSByZWNlaXZlZCcpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBDcmVhdGUgbmV3IGNhY2hlIGVudHJ5XG4gICAgICBjb25zdCBuZXdDYWNoZTogQ2FjaGVkSW5kZXggPSB7XG4gICAgICAgIGRhdGE6IGluZGV4RGF0YSxcbiAgICAgICAgZmV0Y2hlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICBldGFnOiByZXNwb25zZS5oZWFkZXJzLmdldCgnZXRhZycpIHx8IHVuZGVmaW5lZCxcbiAgICAgICAgbGFzdE1vZGlmaWVkOiByZXNwb25zZS5oZWFkZXJzLmdldCgnbGFzdC1tb2RpZmllZCcpIHx8IHVuZGVmaW5lZFxuICAgICAgfTtcbiAgICAgIFxuICAgICAgdGhpcy5jYWNoZSA9IG5ld0NhY2hlO1xuICAgICAgXG4gICAgICAvLyBTYXZlIHRvIHBlcnNpc3RlbnQgY2FjaGUgaW4gYmFja2dyb3VuZFxuICAgICAgdGhpcy5zYXZlVG9EaXNrKG5ld0NhY2hlKS5jYXRjaChlcnJvciA9PiB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnRmFpbGVkIHRvIHNhdmUgaW5kZXggY2FjaGUgdG8gZGlzazonLCBlcnJvcik7XG4gICAgICB9KTtcbiAgICAgIFxuICAgICAgbG9nZ2VyLmRlYnVnKGBGcmVzaCBjb2xsZWN0aW9uIGluZGV4IGZldGNoZWQgd2l0aCAke2luZGV4RGF0YS50b3RhbF9lbGVtZW50c30gZWxlbWVudHNgKTtcbiAgICAgIHJldHVybiBpbmRleERhdGE7XG4gICAgICBcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdGYWlsZWQgdG8gZmV0Y2ggZnJlc2ggY29sbGVjdGlvbiBpbmRleDonLCBlcnJvcik7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGUgc3RydWN0dXJlIG9mIGEgY29sbGVjdGlvbiBpbmRleFxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUluZGV4U3RydWN0dXJlKGluZGV4OiBhbnkpOiBpbmRleCBpcyBDb2xsZWN0aW9uSW5kZXgge1xuICAgIHJldHVybiAoXG4gICAgICBpbmRleCAmJlxuICAgICAgdHlwZW9mIGluZGV4ID09PSAnb2JqZWN0JyAmJlxuICAgICAgdHlwZW9mIGluZGV4LnZlcnNpb24gPT09ICdzdHJpbmcnICYmXG4gICAgICB0eXBlb2YgaW5kZXguZ2VuZXJhdGVkID09PSAnc3RyaW5nJyAmJlxuICAgICAgdHlwZW9mIGluZGV4LnRvdGFsX2VsZW1lbnRzID09PSAnbnVtYmVyJyAmJlxuICAgICAgaW5kZXguaW5kZXggJiZcbiAgICAgIHR5cGVvZiBpbmRleC5pbmRleCA9PT0gJ29iamVjdCcgJiZcbiAgICAgIGluZGV4Lm1ldGFkYXRhICYmXG4gICAgICB0eXBlb2YgaW5kZXgubWV0YWRhdGEgPT09ICdvYmplY3QnXG4gICAgKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIFNhdmUgY2FjaGUgdG8gcGVyc2lzdGVudCBzdG9yYWdlXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNhdmVUb0Rpc2soY2FjaGU6IENhY2hlZEluZGV4KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZW5zdXJlQ2FjaGVEaXIoKTtcbiAgICAgIFxuICAgICAgY29uc3QgY2FjaGVEYXRhID0ge1xuICAgICAgICAuLi5jYWNoZSxcbiAgICAgICAgZmV0Y2hlZEF0OiBjYWNoZS5mZXRjaGVkQXQudG9JU09TdHJpbmcoKSAvLyBTZXJpYWxpemUgZGF0ZVxuICAgICAgfTtcbiAgICAgIFxuICAgICAgY29uc3QgZGF0YSA9IEpTT04uc3RyaW5naWZ5KGNhY2hlRGF0YSwgbnVsbCwgMik7XG4gICAgICBhd2FpdCBmcy53cml0ZUZpbGUodGhpcy5jYWNoZUZpbGUsIGRhdGEsICd1dGY4Jyk7XG4gICAgICBcbiAgICAgIGxvZ2dlci5kZWJ1ZygnQ29sbGVjdGlvbiBpbmRleCBjYWNoZSBzYXZlZCB0byBkaXNrJyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZygnRmFpbGVkIHRvIHNhdmUgY29sbGVjdGlvbiBpbmRleCBjYWNoZTonLCBlcnJvcik7XG4gICAgICAvLyBEb24ndCB0aHJvdyAtIGNhY2hlIHBlcnNpc3RlbmNlIGZhaWx1cmVzIHNob3VsZG4ndCBicmVhayBmdW5jdGlvbmFsaXR5XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogTG9hZCBjYWNoZSBmcm9tIHBlcnNpc3RlbnQgc3RvcmFnZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBsb2FkRnJvbURpc2soKTogUHJvbWlzZTxDYWNoZWRJbmRleCB8IG51bGw+IHtcbiAgICB0cnkge1xuICAgICAgLy8gQmFzaWMgc2VjdXJpdHkgY2hlY2sgZm9yIHBhdGggdHJhdmVyc2FsXG4gICAgICBpZiAodGhpcy5jYWNoZUZpbGUuaW5jbHVkZXMoJy4uJykgfHwgdGhpcy5jYWNoZUZpbGUuaW5jbHVkZXMoJ1xcMCcpKSB7XG4gICAgICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgICAgICB0eXBlOiAnUEFUSF9UUkFWRVJTQUxfQVRURU1QVCcsXG4gICAgICAgICAgc2V2ZXJpdHk6ICdISUdIJyxcbiAgICAgICAgICBzb3VyY2U6ICdDb2xsZWN0aW9uSW5kZXhDYWNoZS5sb2FkRnJvbURpc2snLFxuICAgICAgICAgIGRldGFpbHM6IGBQb3RlbnRpYWwgcGF0aCB0cmF2ZXJzYWwgYXR0ZW1wdCBkZXRlY3RlZDogJHt0aGlzLmNhY2hlRmlsZS5zdWJzdHJpbmcoMCwgMTAwKX1gXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IGZzLnJlYWRGaWxlKHRoaXMuY2FjaGVGaWxlLCAndXRmOCcpO1xuICAgICAgY29uc3QgY2FjaGVEYXRhID0gSlNPTi5wYXJzZShkYXRhKTtcbiAgICAgIFxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4uY2FjaGVEYXRhLFxuICAgICAgICBmZXRjaGVkQXQ6IG5ldyBEYXRlKGNhY2hlRGF0YS5mZXRjaGVkQXQpIC8vIERlc2VyaWFsaXplIGRhdGVcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICgoZXJyb3IgYXMgYW55KS5jb2RlICE9PSAnRU5PRU5UJykge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ0ZhaWxlZCB0byBsb2FkIGNvbGxlY3Rpb24gaW5kZXggY2FjaGUgZnJvbSBkaXNrOicsIGVycm9yKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEVuc3VyZSBjYWNoZSBkaXJlY3RvcnkgZXhpc3RzXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGVuc3VyZUNhY2hlRGlyKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmcy5ta2Rpcih0aGlzLmNhY2hlRGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKCdGYWlsZWQgdG8gY3JlYXRlIGNhY2hlIGRpcmVjdG9yeTonLCBlcnJvcik7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDbGVhciBhbGwgY2FjaGUgZGF0YSB3aXRoIHBlcmZvcm1hbmNlIG1vbml0b3JpbmdcbiAgICovXG4gIGFzeW5jIGNsZWFyQ2FjaGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBcbiAgICB0aGlzLmNhY2hlID0gbnVsbDtcbiAgICB0aGlzLm1lbW9yeUNhY2hlLmNsZWFyKCk7XG4gICAgXG4gICAgLy8gQ2FuY2VsIGFueSBvbmdvaW5nIGZldGNoXG4gICAgdGhpcy5mZXRjaFByb21pc2UgPSBudWxsO1xuICAgIFxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBmcy51bmxpbmsodGhpcy5jYWNoZUZpbGUpO1xuICAgICAgbG9nZ2VyLmRlYnVnKCdDb2xsZWN0aW9uIGluZGV4IGNhY2hlIGNsZWFyZWQgZnJvbSBkaXNrJyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICgoZXJyb3IgYXMgYW55KS5jb2RlICE9PSAnRU5PRU5UJykge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ0ZhaWxlZCB0byBjbGVhciBjb2xsZWN0aW9uIGluZGV4IGNhY2hlOicsIGVycm9yKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgbG9nZ2VyLmRlYnVnKCdDb2xsZWN0aW9uIGNhY2hlIGNsZWFyZWQnLCB7XG4gICAgICBkdXJhdGlvbjogRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSxcbiAgICAgIG1lbW9yeUZyZWVkOiB0aGlzLm1lbW9yeUNhY2hlLmdldE1lbW9yeVVzYWdlTUIoKVxuICAgIH0pO1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IGNvbXByZWhlbnNpdmUgY2FjaGUgc3RhdGlzdGljcyBmb3IgZGVidWdnaW5nIGFuZCBtb25pdG9yaW5nXG4gICAqL1xuICBnZXRDYWNoZVN0YXRzKCk6IHsgXG4gICAgaXNWYWxpZDogYm9vbGVhbjsgXG4gICAgYWdlOiBudW1iZXI7IFxuICAgIGhhc0NhY2hlOiBib29sZWFuOyBcbiAgICBlbGVtZW50czogbnVtYmVyO1xuICAgIG1lbW9yeUNhY2hlOiBhbnk7XG4gICAgcGVyZm9ybWFuY2VNZXRyaWNzOiBhbnk7XG4gIH0ge1xuICAgIGlmICghdGhpcy5jYWNoZSkge1xuICAgICAgcmV0dXJuIHsgXG4gICAgICAgIGlzVmFsaWQ6IGZhbHNlLCBcbiAgICAgICAgYWdlOiAwLCBcbiAgICAgICAgaGFzQ2FjaGU6IGZhbHNlLCBcbiAgICAgICAgZWxlbWVudHM6IDAsXG4gICAgICAgIG1lbW9yeUNhY2hlOiB0aGlzLm1lbW9yeUNhY2hlLmdldFN0YXRzKCksXG4gICAgICAgIHBlcmZvcm1hbmNlTWV0cmljczogbnVsbFxuICAgICAgfTtcbiAgICB9XG4gICAgXG4gICAgY29uc3QgYWdlID0gRGF0ZS5ub3coKSAtIHRoaXMuY2FjaGUuZmV0Y2hlZEF0LmdldFRpbWUoKTtcbiAgICByZXR1cm4ge1xuICAgICAgaXNWYWxpZDogdGhpcy5pc1ZhbGlkKCksXG4gICAgICBhZ2UsXG4gICAgICBoYXNDYWNoZTogdHJ1ZSxcbiAgICAgIGVsZW1lbnRzOiB0aGlzLmNhY2hlLmRhdGEudG90YWxfZWxlbWVudHMsXG4gICAgICBtZW1vcnlDYWNoZTogdGhpcy5tZW1vcnlDYWNoZS5nZXRTdGF0cygpLFxuICAgICAgcGVyZm9ybWFuY2VNZXRyaWNzOiB7XG4gICAgICAgIGNhY2hlSGl0UmF0ZTogdGhpcy5jYWxjdWxhdGVDYWNoZUhpdFJhdGUoKSxcbiAgICAgICAgYXZlcmFnZUFjY2Vzc1RpbWU6IHRoaXMuY2FsY3VsYXRlQXZlcmFnZUFjY2Vzc1RpbWUoKVxuICAgICAgfVxuICAgIH07XG4gIH1cbiAgXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFBSSVZBVEUgSEVMUEVSIE1FVEhPRFMgRk9SIFBFUkZPUk1BTkNFXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIFxuICAvKipcbiAgICogRmV0Y2ggZnJlc2ggaW5kZXggd2l0aCBjb21wcmVoZW5zaXZlIGZhbGxiYWNrIHN0cmF0ZWd5XG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGZldGNoRnJlc2hXaXRoRmFsbGJhY2soKTogUHJvbWlzZTxDb2xsZWN0aW9uSW5kZXg+IHtcbiAgICB0cnkge1xuICAgICAgLy8gVHJ5IHRvIGZldGNoIGZyZXNoIGluZGV4XG4gICAgICBjb25zdCBmcmVzaEluZGV4ID0gYXdhaXQgdGhpcy5mZXRjaEZyZXNoKCk7XG4gICAgICBpZiAoZnJlc2hJbmRleCkge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ0NvbGxlY3Rpb24gaW5kZXggZmV0Y2hlZCBzdWNjZXNzZnVsbHknKTtcbiAgICAgICAgcmV0dXJuIGZyZXNoSW5kZXg7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci53YXJuKCdGcmVzaCBmZXRjaCBmYWlsZWQsIHRyeWluZyBmYWxsYmFjaycsIHtcbiAgICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKVxuICAgICAgfSk7XG4gICAgfVxuICAgIFxuICAgIC8vIEZhbGwgYmFjayB0byBzdGFsZSBjYWNoZSBpZiBhdmFpbGFibGVcbiAgICBpZiAodGhpcy5jYWNoZT8uZGF0YSkge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdVc2luZyBzdGFsZSBjYWNoZWQgY29sbGVjdGlvbiBpbmRleCBhcyBmYWxsYmFjaycpO1xuICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZGF0YTtcbiAgICB9XG4gICAgXG4gICAgdGhyb3cgbmV3IEVycm9yKCdObyBjb2xsZWN0aW9uIGluZGV4IGF2YWlsYWJsZSAtIGZyZXNoIGZldGNoIGZhaWxlZCBhbmQgbm8gY2FjaGUgZXhpc3RzJyk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBSZWNvcmQgcGVyZm9ybWFuY2UgbWV0cmljcyBmb3IgY2FjaGUgb3BlcmF0aW9uc1xuICAgKi9cbiAgcHJpdmF0ZSByZWNvcmRQZXJmb3JtYW5jZU1ldHJpY3Moc3RhcnRUaW1lOiBudW1iZXIsIG1lbW9yeUJlZm9yZTogbnVtYmVyLCBvcGVyYXRpb246IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IGR1cmF0aW9uID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcbiAgICBjb25zdCBtZW1vcnlBZnRlciA9IHByb2Nlc3MubWVtb3J5VXNhZ2UoKS5oZWFwVXNlZDtcbiAgICBcbiAgICBsb2dnZXIuZGVidWcoJ0NvbGxlY3Rpb24gY2FjaGUgb3BlcmF0aW9uIGNvbXBsZXRlZCcsIHtcbiAgICAgIG9wZXJhdGlvbixcbiAgICAgIGR1cmF0aW9uLFxuICAgICAgbWVtb3J5VXNhZ2VNQjogKG1lbW9yeUFmdGVyIC0gbWVtb3J5QmVmb3JlKSAvICgxMDI0ICogMTAyNClcbiAgICB9KTtcbiAgICBcbiAgICAvLyBSZWNvcmQgY2FjaGUgcGVyZm9ybWFuY2UgbWV0cmljc1xuICAgIHRoaXMucGVyZm9ybWFuY2VNb25pdG9yLnJlY29yZENhY2hlUGVyZm9ybWFuY2UoJ2NvbGxlY3Rpb25JbmRleCcsIHtcbiAgICAgIGhpdFJhdGU6IG9wZXJhdGlvbi5pbmNsdWRlcygnaGl0JykgPyAxIDogMCxcbiAgICAgIGF2Z0hpdFRpbWU6IG9wZXJhdGlvbi5pbmNsdWRlcygnaGl0JykgPyBkdXJhdGlvbiA6IDAsXG4gICAgICBhdmdNaXNzVGltZTogb3BlcmF0aW9uLmluY2x1ZGVzKCdoaXQnKSA/IDAgOiBkdXJhdGlvbixcbiAgICAgIHRvdGFsSGl0czogb3BlcmF0aW9uLmluY2x1ZGVzKCdoaXQnKSA/IDEgOiAwLFxuICAgICAgdG90YWxNaXNzZXM6IG9wZXJhdGlvbi5pbmNsdWRlcygnaGl0JykgPyAwIDogMSxcbiAgICAgIGV2aWN0aW9uczogMFxuICAgIH0pO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2FsY3VsYXRlIGNhY2hlIGhpdCByYXRlIChwbGFjZWhvbGRlciBmb3IgZnV0dXJlIGltcGxlbWVudGF0aW9uKVxuICAgKi9cbiAgcHJpdmF0ZSBjYWxjdWxhdGVDYWNoZUhpdFJhdGUoKTogbnVtYmVyIHtcbiAgICAvLyBUaGlzIHdvdWxkIGJlIGltcGxlbWVudGVkIHdpdGggYWN0dWFsIG1ldHJpY3MgdHJhY2tpbmdcbiAgICByZXR1cm4gdGhpcy5tZW1vcnlDYWNoZS5nZXRTdGF0cygpLmhpdFJhdGU7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgYXZlcmFnZSBhY2Nlc3MgdGltZSAocGxhY2Vob2xkZXIgZm9yIGZ1dHVyZSBpbXBsZW1lbnRhdGlvbilcbiAgICovXG4gIHByaXZhdGUgY2FsY3VsYXRlQXZlcmFnZUFjY2Vzc1RpbWUoKTogbnVtYmVyIHtcbiAgICAvLyBUaGlzIHdvdWxkIGJlIGltcGxlbWVudGVkIHdpdGggYWN0dWFsIHRpbWluZyBtZXRyaWNzXG4gICAgcmV0dXJuIDU7IC8vIFBsYWNlaG9sZGVyIHZhbHVlXG4gIH1cbn0iXX0=