@dollhousemcp/mcp-server 1.5.1 → 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 (274) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +497 -110
  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 +65 -0
  41. package/dist/cache/CollectionCache.d.ts.map +1 -0
  42. package/dist/cache/CollectionCache.js +172 -0
  43. package/dist/cache/CollectionIndexCache.d.ts +77 -0
  44. package/dist/cache/CollectionIndexCache.d.ts.map +1 -0
  45. package/dist/cache/CollectionIndexCache.js +349 -0
  46. package/dist/cache/LRUCache.d.ts +93 -0
  47. package/dist/cache/LRUCache.d.ts.map +1 -0
  48. package/dist/cache/LRUCache.js +299 -0
  49. package/dist/cache/index.d.ts +2 -0
  50. package/dist/cache/index.d.ts.map +1 -1
  51. package/dist/cache/index.js +3 -1
  52. package/dist/collection/CollectionBrowser.d.ts +44 -1
  53. package/dist/collection/CollectionBrowser.d.ts.map +1 -1
  54. package/dist/collection/CollectionBrowser.js +260 -28
  55. package/dist/collection/CollectionIndexManager.d.ts +151 -0
  56. package/dist/collection/CollectionIndexManager.d.ts.map +1 -0
  57. package/dist/collection/CollectionIndexManager.js +499 -0
  58. package/dist/collection/CollectionSearch.d.ts +75 -1
  59. package/dist/collection/CollectionSearch.d.ts.map +1 -1
  60. package/dist/collection/CollectionSearch.js +435 -6
  61. package/dist/collection/CollectionSeeder.d.ts +36 -0
  62. package/dist/collection/CollectionSeeder.d.ts.map +1 -0
  63. package/dist/collection/CollectionSeeder.js +267 -0
  64. package/dist/collection/ElementInstaller.d.ts +31 -0
  65. package/dist/collection/ElementInstaller.d.ts.map +1 -1
  66. package/dist/collection/ElementInstaller.js +77 -15
  67. package/dist/collection/PersonaSubmitter.d.ts +48 -1
  68. package/dist/collection/PersonaSubmitter.d.ts.map +1 -1
  69. package/dist/collection/PersonaSubmitter.js +170 -34
  70. package/dist/collection/index.d.ts +2 -0
  71. package/dist/collection/index.d.ts.map +1 -1
  72. package/dist/collection/index.js +3 -1
  73. package/dist/config/ConfigManager.d.ts +78 -0
  74. package/dist/config/ConfigManager.d.ts.map +1 -0
  75. package/dist/config/ConfigManager.js +216 -0
  76. package/dist/config/element-types.d.ts +135 -0
  77. package/dist/config/element-types.d.ts.map +1 -0
  78. package/dist/config/element-types.js +108 -0
  79. package/dist/config/index.d.ts +2 -0
  80. package/dist/config/index.d.ts.map +1 -1
  81. package/dist/config/index.js +3 -1
  82. package/dist/config/portfolio-constants.d.ts +83 -0
  83. package/dist/config/portfolio-constants.d.ts.map +1 -0
  84. package/dist/config/portfolio-constants.js +99 -0
  85. package/dist/elements/BaseElement.d.ts +14 -2
  86. package/dist/elements/BaseElement.d.ts.map +1 -1
  87. package/dist/elements/BaseElement.js +88 -6
  88. package/dist/elements/agents/Agent.d.ts +10 -1
  89. package/dist/elements/agents/Agent.d.ts.map +1 -1
  90. package/dist/elements/agents/Agent.js +66 -19
  91. package/dist/elements/agents/AgentManager.d.ts +2 -0
  92. package/dist/elements/agents/AgentManager.d.ts.map +1 -1
  93. package/dist/elements/agents/AgentManager.js +12 -10
  94. package/dist/elements/skills/Skill.d.ts +10 -1
  95. package/dist/elements/skills/Skill.d.ts.map +1 -1
  96. package/dist/elements/skills/Skill.js +40 -3
  97. package/dist/elements/skills/SkillManager.d.ts +1 -0
  98. package/dist/elements/skills/SkillManager.d.ts.map +1 -1
  99. package/dist/elements/skills/SkillManager.js +10 -4
  100. package/dist/elements/templates/Template.d.ts +10 -1
  101. package/dist/elements/templates/Template.d.ts.map +1 -1
  102. package/dist/elements/templates/Template.js +35 -18
  103. package/dist/elements/templates/TemplateManager.d.ts +1 -1
  104. package/dist/elements/templates/TemplateManager.d.ts.map +1 -1
  105. package/dist/elements/templates/TemplateManager.js +6 -5
  106. package/dist/generated/version.d.ts +2 -2
  107. package/dist/generated/version.js +3 -3
  108. package/dist/index.barrel.d.ts +1 -2
  109. package/dist/index.barrel.d.ts.map +1 -1
  110. package/dist/index.barrel.js +2 -4
  111. package/dist/index.d.ts +154 -25
  112. package/dist/index.d.ts.map +1 -1
  113. package/dist/index.js +1951 -264
  114. package/dist/persona/PersonaElement.d.ts +10 -0
  115. package/dist/persona/PersonaElement.d.ts.map +1 -1
  116. package/dist/persona/PersonaElement.js +55 -32
  117. package/dist/persona/PersonaElementManager.d.ts.map +1 -1
  118. package/dist/persona/PersonaElementManager.js +13 -11
  119. package/dist/persona/PersonaLoader.d.ts.map +1 -1
  120. package/dist/persona/PersonaLoader.js +8 -2
  121. package/dist/persona/export-import/PersonaImporter.d.ts.map +1 -1
  122. package/dist/persona/export-import/PersonaImporter.js +24 -5
  123. package/dist/persona/export-import/PersonaSharer.d.ts +21 -0
  124. package/dist/persona/export-import/PersonaSharer.d.ts.map +1 -1
  125. package/dist/persona/export-import/PersonaSharer.js +198 -22
  126. package/dist/portfolio/DefaultElementProvider.d.ts +90 -0
  127. package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
  128. package/dist/portfolio/DefaultElementProvider.js +499 -7
  129. package/dist/portfolio/GitHubPortfolioIndexer.d.ts +129 -0
  130. package/dist/portfolio/GitHubPortfolioIndexer.d.ts.map +1 -0
  131. package/dist/portfolio/GitHubPortfolioIndexer.js +475 -0
  132. package/dist/portfolio/MigrationManager.d.ts.map +1 -1
  133. package/dist/portfolio/MigrationManager.js +136 -3
  134. package/dist/portfolio/PortfolioIndexManager.d.ts +130 -0
  135. package/dist/portfolio/PortfolioIndexManager.d.ts.map +1 -0
  136. package/dist/portfolio/PortfolioIndexManager.js +478 -0
  137. package/dist/portfolio/PortfolioManager.d.ts +5 -0
  138. package/dist/portfolio/PortfolioManager.d.ts.map +1 -1
  139. package/dist/portfolio/PortfolioManager.js +61 -20
  140. package/dist/portfolio/PortfolioRepoManager.d.ts +75 -0
  141. package/dist/portfolio/PortfolioRepoManager.d.ts.map +1 -0
  142. package/dist/portfolio/PortfolioRepoManager.js +337 -0
  143. package/dist/portfolio/UnifiedIndexManager.d.ts +388 -0
  144. package/dist/portfolio/UnifiedIndexManager.d.ts.map +1 -0
  145. package/dist/portfolio/UnifiedIndexManager.js +1434 -0
  146. package/dist/portfolio/index.d.ts +15 -0
  147. package/dist/portfolio/index.d.ts.map +1 -0
  148. package/dist/portfolio/index.js +15 -0
  149. package/dist/portfolio/types.d.ts +7 -0
  150. package/dist/portfolio/types.d.ts.map +1 -1
  151. package/dist/portfolio/types.js +6 -1
  152. package/dist/security/InputValidator.d.ts.map +1 -1
  153. package/dist/security/InputValidator.js +50 -48
  154. package/dist/security/audit/SecurityAuditor.d.ts.map +1 -1
  155. package/dist/security/audit/SecurityAuditor.js +17 -9
  156. package/dist/security/audit/config/suppressions.d.ts.map +1 -1
  157. package/dist/security/audit/config/suppressions.js +19 -3
  158. package/dist/security/contentValidator.d.ts +2 -0
  159. package/dist/security/contentValidator.d.ts.map +1 -1
  160. package/dist/security/contentValidator.js +115 -4
  161. package/dist/security/secureYamlParser.d.ts +1 -0
  162. package/dist/security/secureYamlParser.d.ts.map +1 -1
  163. package/dist/security/secureYamlParser.js +29 -7
  164. package/dist/security/securityMonitor.d.ts +1 -1
  165. package/dist/security/securityMonitor.d.ts.map +1 -1
  166. package/dist/security/securityMonitor.js +1 -1
  167. package/dist/security/tokenManager.d.ts +1 -1
  168. package/dist/security/tokenManager.d.ts.map +1 -1
  169. package/dist/security/tokenManager.js +30 -10
  170. package/dist/server/ServerSetup.d.ts +22 -2
  171. package/dist/server/ServerSetup.d.ts.map +1 -1
  172. package/dist/server/ServerSetup.js +77 -12
  173. package/dist/server/tools/AuthTools.d.ts.map +1 -1
  174. package/dist/server/tools/AuthTools.js +33 -1
  175. package/dist/server/tools/BuildInfoTools.d.ts +25 -0
  176. package/dist/server/tools/BuildInfoTools.d.ts.map +1 -0
  177. package/dist/server/tools/BuildInfoTools.js +36 -0
  178. package/dist/server/tools/CollectionTools.d.ts.map +1 -1
  179. package/dist/server/tools/CollectionTools.js +62 -42
  180. package/dist/server/tools/ConfigTools.d.ts.map +1 -1
  181. package/dist/server/tools/ConfigTools.js +29 -1
  182. package/dist/server/tools/PersonaTools.d.ts +4 -2
  183. package/dist/server/tools/PersonaTools.d.ts.map +1 -1
  184. package/dist/server/tools/PersonaTools.js +5 -152
  185. package/dist/server/tools/PortfolioTools.d.ts +12 -0
  186. package/dist/server/tools/PortfolioTools.d.ts.map +1 -0
  187. package/dist/server/tools/PortfolioTools.js +221 -0
  188. package/dist/server/tools/index.d.ts +3 -1
  189. package/dist/server/tools/index.d.ts.map +1 -1
  190. package/dist/server/tools/index.js +4 -2
  191. package/dist/server/types.d.ts +41 -5
  192. package/dist/server/types.d.ts.map +1 -1
  193. package/dist/server/types.js +1 -1
  194. package/dist/services/BuildInfoService.d.ts +84 -0
  195. package/dist/services/BuildInfoService.d.ts.map +1 -0
  196. package/dist/services/BuildInfoService.js +271 -0
  197. package/dist/tools/portfolio/PortfolioElementAdapter.d.ts +54 -0
  198. package/dist/tools/portfolio/PortfolioElementAdapter.d.ts.map +1 -0
  199. package/dist/tools/portfolio/PortfolioElementAdapter.js +229 -0
  200. package/dist/tools/portfolio/submitToPortfolioTool.d.ts +164 -0
  201. package/dist/tools/portfolio/submitToPortfolioTool.d.ts.map +1 -0
  202. package/dist/tools/portfolio/submitToPortfolioTool.js +1523 -0
  203. package/dist/tools/portfolio/types.d.ts +41 -0
  204. package/dist/tools/portfolio/types.d.ts.map +1 -0
  205. package/dist/tools/portfolio/types.js +15 -0
  206. package/dist/types/collection.d.ts +51 -0
  207. package/dist/types/collection.d.ts.map +1 -1
  208. package/dist/types/collection.js +1 -1
  209. package/dist/utils/EarlyTerminationSearch.d.ts +41 -0
  210. package/dist/utils/EarlyTerminationSearch.d.ts.map +1 -0
  211. package/dist/utils/EarlyTerminationSearch.js +164 -0
  212. package/dist/utils/ErrorHandler.d.ts +86 -0
  213. package/dist/utils/ErrorHandler.d.ts.map +1 -0
  214. package/dist/utils/ErrorHandler.js +201 -0
  215. package/dist/utils/FileDiscoveryUtil.d.ts +53 -0
  216. package/dist/utils/FileDiscoveryUtil.d.ts.map +1 -0
  217. package/dist/utils/FileDiscoveryUtil.js +169 -0
  218. package/dist/utils/GitHubRateLimiter.d.ts +88 -0
  219. package/dist/utils/GitHubRateLimiter.d.ts.map +1 -0
  220. package/dist/utils/GitHubRateLimiter.js +315 -0
  221. package/dist/utils/PerformanceMonitor.d.ts +134 -0
  222. package/dist/utils/PerformanceMonitor.d.ts.map +1 -0
  223. package/dist/utils/PerformanceMonitor.js +347 -0
  224. package/dist/utils/RateLimiter.d.ts.map +1 -0
  225. package/dist/utils/RateLimiter.js +172 -0
  226. package/dist/utils/SecureDownloader.d.ts +241 -0
  227. package/dist/utils/SecureDownloader.d.ts.map +1 -0
  228. package/dist/utils/SecureDownloader.js +759 -0
  229. package/dist/utils/ToolCache.d.ts +82 -0
  230. package/dist/utils/ToolCache.d.ts.map +1 -0
  231. package/dist/utils/ToolCache.js +196 -0
  232. package/dist/utils/errorCodes.d.ts +136 -0
  233. package/dist/utils/errorCodes.d.ts.map +1 -0
  234. package/dist/utils/errorCodes.js +87 -0
  235. package/dist/utils/index.d.ts +3 -0
  236. package/dist/utils/index.d.ts.map +1 -1
  237. package/dist/utils/index.js +4 -1
  238. package/dist/utils/installation.d.ts +1 -1
  239. package/dist/utils/installation.d.ts.map +1 -1
  240. package/dist/utils/installation.js +9 -8
  241. package/dist/utils/searchUtils.d.ts +54 -0
  242. package/dist/utils/searchUtils.d.ts.map +1 -0
  243. package/dist/utils/searchUtils.js +118 -0
  244. package/package.json +17 -7
  245. package/dist/config/updateConfig.d.ts +0 -84
  246. package/dist/config/updateConfig.d.ts.map +0 -1
  247. package/dist/config/updateConfig.js +0 -148
  248. package/dist/server/tools/UpdateTools.d.ts +0 -10
  249. package/dist/server/tools/UpdateTools.d.ts.map +0 -1
  250. package/dist/server/tools/UpdateTools.js +0 -85
  251. package/dist/update/BackupManager.d.ts +0 -63
  252. package/dist/update/BackupManager.d.ts.map +0 -1
  253. package/dist/update/BackupManager.js +0 -370
  254. package/dist/update/DependencyChecker.d.ts +0 -41
  255. package/dist/update/DependencyChecker.d.ts.map +0 -1
  256. package/dist/update/DependencyChecker.js +0 -132
  257. package/dist/update/RateLimiter.d.ts.map +0 -1
  258. package/dist/update/RateLimiter.js +0 -172
  259. package/dist/update/SignatureVerifier.d.ts +0 -71
  260. package/dist/update/SignatureVerifier.d.ts.map +0 -1
  261. package/dist/update/SignatureVerifier.js +0 -214
  262. package/dist/update/UpdateChecker.d.ts +0 -132
  263. package/dist/update/UpdateChecker.d.ts.map +0 -1
  264. package/dist/update/UpdateChecker.js +0 -506
  265. package/dist/update/UpdateManager.d.ts +0 -60
  266. package/dist/update/UpdateManager.d.ts.map +0 -1
  267. package/dist/update/UpdateManager.js +0 -730
  268. package/dist/update/VersionManager.d.ts +0 -31
  269. package/dist/update/VersionManager.d.ts.map +0 -1
  270. package/dist/update/VersionManager.js +0 -181
  271. package/dist/update/index.d.ts +0 -9
  272. package/dist/update/index.d.ts.map +0 -1
  273. package/dist/update/index.js +0 -9
  274. /package/dist/{update → utils}/RateLimiter.d.ts +0 -0
@@ -1,47 +1,283 @@
1
1
  /**
2
2
  * Browse collection content from GitHub
3
3
  */
4
+ import { CollectionCache } from '../cache/CollectionCache.js';
5
+ import { CollectionSeeder } from './CollectionSeeder.js';
6
+ import { CollectionIndexManager } from './CollectionIndexManager.js';
7
+ import { logger } from '../utils/logger.js';
8
+ import { ElementType } from '../portfolio/types.js';
9
+ // Content types supported by MCP server (Issue #144)
10
+ // Hide: memories, ensembles from MCP queries
11
+ // ⚠️ CRITICAL: When adding new element types, you MUST update this array!
12
+ // Also update validTypes array in src/index.ts
13
+ // See docs/development/ADDING_NEW_ELEMENT_TYPES_CHECKLIST.md for complete guide
14
+ const MCP_SUPPORTED_TYPES = [
15
+ ElementType.PERSONA, // personas - supported by PersonaTools and ElementTools
16
+ ElementType.SKILL, // skills - supported by ElementTools
17
+ ElementType.AGENT, // agents - supported by ElementTools
18
+ ElementType.TEMPLATE // templates - supported by ElementTools
19
+ ];
20
+ /**
21
+ * Type guard to safely check if a string is a valid ElementType
22
+ */
23
+ function isElementType(value) {
24
+ return Object.values(ElementType).includes(value);
25
+ }
26
+ /**
27
+ * Type guard to safely check if an ElementType is supported by MCP
28
+ */
29
+ function isMCPSupportedType(elementType) {
30
+ return MCP_SUPPORTED_TYPES.includes(elementType);
31
+ }
4
32
  export class CollectionBrowser {
5
33
  githubClient;
34
+ collectionCache;
35
+ indexManager;
6
36
  baseUrl = 'https://api.github.com/repos/DollhouseMCP/collection/contents';
7
- constructor(githubClient) {
37
+ constructor(githubClient, collectionCache, indexManager) {
8
38
  this.githubClient = githubClient;
39
+ this.collectionCache = collectionCache || new CollectionCache();
40
+ this.indexManager = indexManager || new CollectionIndexManager();
9
41
  }
10
42
  /**
11
43
  * Browse collection content by section and type
44
+ * Uses CollectionIndexManager for fast browsing with background refresh
45
+ * Falls back to cached data when GitHub API is not available or not authenticated
12
46
  * @param section - Top level section: library, showcase, or catalog
13
47
  * @param type - Optional content type within the library section (personas, skills, etc.)
14
48
  */
15
49
  async browseCollection(section, type) {
16
- let url = this.baseUrl;
17
- // If no section provided, show top-level sections
18
- if (!section) {
19
- const data = await this.githubClient.fetchFromGitHub(url);
50
+ try {
51
+ // Try using collection index first for faster browsing
52
+ const indexResult = await this.browseFromIndex(section, type);
53
+ if (indexResult) {
54
+ logger.debug('Used collection index for browsing');
55
+ return indexResult;
56
+ }
57
+ // Fallback to GitHub API
58
+ let url = this.baseUrl;
59
+ // If no section provided, show top-level sections
60
+ if (!section) {
61
+ const data = await this.githubClient.fetchFromGitHub(url, false);
62
+ if (!Array.isArray(data)) {
63
+ throw new Error('Invalid collection response. Expected directory listing.');
64
+ }
65
+ // Filter to only show content directories
66
+ const sections = data.filter((item) => item.type === 'dir' && ['library', 'showcase', 'catalog'].includes(item.name));
67
+ return { items: [], categories: [], sections };
68
+ }
69
+ // Browse within a section
70
+ url = type
71
+ ? `${this.baseUrl}/${section}/${type}`
72
+ : `${this.baseUrl}/${section}`;
73
+ const data = await this.githubClient.fetchFromGitHub(url, false);
20
74
  if (!Array.isArray(data)) {
21
75
  throw new Error('Invalid collection response. Expected directory listing.');
22
76
  }
23
- // Filter to only show content directories
24
- const sections = data.filter((item) => item.type === 'dir' && ['library', 'showcase', 'catalog'].includes(item.name));
25
- return { items: [], categories: [], sections };
77
+ // In the library section, we have content type directories
78
+ if (section === 'library' && !type) {
79
+ // Filter to only show MCP-supported content types
80
+ const contentTypes = data.filter((item) => {
81
+ if (item.type !== 'dir')
82
+ return false;
83
+ const elementType = isElementType(item.name) ? item.name : null;
84
+ return elementType && isMCPSupportedType(elementType);
85
+ });
86
+ return { items: [], categories: contentTypes };
87
+ }
88
+ // For library content types, show files directly (flat structure)
89
+ const items = data.filter((item) => item.type === 'file' && item.name.endsWith('.md'));
90
+ // For non-library sections, they might still have subdirectories
91
+ const categories = section === 'library' ? [] : data.filter((item) => item.type === 'dir');
92
+ return { items, categories };
26
93
  }
27
- // Browse within a section
28
- url = type
29
- ? `${this.baseUrl}/${section}/${type}`
30
- : `${this.baseUrl}/${section}`;
31
- const data = await this.githubClient.fetchFromGitHub(url);
32
- if (!Array.isArray(data)) {
33
- throw new Error('Invalid collection response. Expected directory listing.');
94
+ catch (error) {
95
+ logger.debug(`GitHub API browse failed, falling back to cache: ${error}`);
96
+ // Fallback to cached data
97
+ return this.browseFromCache(section, type);
34
98
  }
35
- // In the library section, we have content type directories
99
+ }
100
+ /**
101
+ * Browse collection using the fast collection index
102
+ * Returns null if index is not available or browsing fails
103
+ */
104
+ async browseFromIndex(section, type) {
105
+ try {
106
+ const index = await this.indexManager.getIndex();
107
+ // If no section provided, show top-level sections
108
+ if (!section) {
109
+ const sections = [
110
+ { name: 'library', type: 'dir' },
111
+ { name: 'showcase', type: 'dir' },
112
+ { name: 'catalog', type: 'dir' }
113
+ ];
114
+ return { items: [], categories: [], sections };
115
+ }
116
+ // In the library section, we have content type directories
117
+ if (section === 'library' && !type) {
118
+ // Get unique content types from index
119
+ const contentTypes = this.getContentTypesFromIndex(index);
120
+ return { items: [], categories: contentTypes };
121
+ }
122
+ // Get items for specific type or all items in section
123
+ const items = this.getItemsFromIndex(index, section, type);
124
+ const formattedItems = this.convertIndexItemsToGitHubFormat(items);
125
+ return { items: formattedItems, categories: [] };
126
+ }
127
+ catch (error) {
128
+ logger.debug('Failed to browse from collection index', { error: error instanceof Error ? error.message : String(error) });
129
+ return null;
130
+ }
131
+ }
132
+ /**
133
+ * Get unique content types from collection index
134
+ */
135
+ getContentTypesFromIndex(index) {
136
+ const types = new Set();
137
+ // Extract types from index keys and filter for MCP-supported types
138
+ Object.keys(index.index).forEach(typeName => {
139
+ const elementType = isElementType(typeName) ? typeName : null;
140
+ if (elementType && isMCPSupportedType(elementType)) {
141
+ types.add(typeName);
142
+ }
143
+ });
144
+ return Array.from(types).map(type => ({
145
+ name: type,
146
+ type: 'dir'
147
+ }));
148
+ }
149
+ /**
150
+ * Get items from collection index by section and type
151
+ */
152
+ getItemsFromIndex(index, section, type) {
153
+ // For library section with type, get items from that type
154
+ if (section === 'library' && type) {
155
+ return index.index[type] || [];
156
+ }
157
+ // For library section without type, return empty (should show categories)
36
158
  if (section === 'library' && !type) {
37
- const contentTypes = data.filter((item) => item.type === 'dir' && ['personas', 'skills', 'agents', 'prompts', 'templates', 'tools', 'ensembles', 'memories'].includes(item.name));
159
+ return [];
160
+ }
161
+ // For other sections (showcase, catalog), return all items that match
162
+ // Note: The current index structure is primarily for library content
163
+ // Future enhancement: extend index to include showcase/catalog sections
164
+ return [];
165
+ }
166
+ /**
167
+ * Convert index entries to GitHub API format for compatibility
168
+ */
169
+ convertIndexItemsToGitHubFormat(items) {
170
+ return items.map(item => ({
171
+ name: item.name.endsWith('.md') ? item.name : `${item.name}.md`,
172
+ path: item.path,
173
+ sha: item.sha,
174
+ type: 'file',
175
+ url: `https://api.github.com/repos/DollhouseMCP/collection/contents/${item.path}`,
176
+ html_url: `https://github.com/DollhouseMCP/collection/blob/main/${item.path}`
177
+ }));
178
+ }
179
+ /**
180
+ * Browse collection from cached data
181
+ */
182
+ async browseFromCache(section, type) {
183
+ try {
184
+ // If no section provided, show available sections from seed data
185
+ if (!section) {
186
+ const sections = [
187
+ { name: 'library', type: 'dir' }
188
+ ];
189
+ return { items: [], categories: [], sections };
190
+ }
191
+ // Get cached or seed data
192
+ let cachedItems = await this.collectionCache.loadCache();
193
+ if (!cachedItems || cachedItems.items.length === 0) {
194
+ // Use seed data if cache is empty
195
+ const seedData = CollectionSeeder.getSeedData();
196
+ await this.collectionCache.saveCache(seedData);
197
+ cachedItems = { items: seedData, timestamp: Date.now() };
198
+ logger.debug('Using seed data for collection browsing');
199
+ }
200
+ // In the library section, we have content type directories
201
+ if (section === 'library' && !type) {
202
+ const contentTypes = this.getContentTypesFromItems(cachedItems.items);
203
+ return { items: [], categories: contentTypes };
204
+ }
205
+ // Get items for specific type or all items in section
206
+ const items = this.filterItemsBySection(cachedItems.items, section, type);
207
+ const formattedItems = this.convertCacheItemsToGitHubFormat(items);
208
+ return { items: formattedItems, categories: [] };
209
+ }
210
+ catch (error) {
211
+ logger.error(`Cache browse failed: ${error}`);
212
+ // Last resort: use seed data directly
213
+ return this.browseFromSeedData(section, type);
214
+ }
215
+ }
216
+ /**
217
+ * Browse collection from seed data as last resort
218
+ */
219
+ browseFromSeedData(section, type) {
220
+ if (!section) {
221
+ const sections = [{ name: 'library', type: 'dir' }];
222
+ return { items: [], categories: [], sections };
223
+ }
224
+ const seedData = CollectionSeeder.getSeedData();
225
+ if (section === 'library' && !type) {
226
+ const contentTypes = this.getContentTypesFromItems(seedData);
38
227
  return { items: [], categories: contentTypes };
39
228
  }
40
- // For library content types, show files directly (flat structure)
41
- const items = data.filter((item) => item.type === 'file' && item.name.endsWith('.md'));
42
- // For non-library sections, they might still have subdirectories
43
- const categories = section === 'library' ? [] : data.filter((item) => item.type === 'dir');
44
- return { items, categories };
229
+ const items = this.filterItemsBySection(seedData, section, type);
230
+ const formattedItems = this.convertCacheItemsToGitHubFormat(items);
231
+ return { items: formattedItems, categories: [] };
232
+ }
233
+ /**
234
+ * Get unique content types from items
235
+ */
236
+ getContentTypesFromItems(items) {
237
+ const types = new Set();
238
+ items.forEach(item => {
239
+ const pathParts = item.path.split('/');
240
+ if (pathParts.length >= 2 && pathParts[0] === 'library') {
241
+ // Only include MCP-supported types in cache browsing
242
+ const typeName = pathParts[1];
243
+ const elementType = isElementType(typeName) ? typeName : null;
244
+ if (elementType && isMCPSupportedType(elementType)) {
245
+ types.add(typeName);
246
+ }
247
+ }
248
+ });
249
+ return Array.from(types).map(type => ({
250
+ name: type,
251
+ type: 'dir'
252
+ }));
253
+ }
254
+ /**
255
+ * Filter items by section and type
256
+ */
257
+ filterItemsBySection(items, section, type) {
258
+ return items.filter(item => {
259
+ const pathParts = item.path.split('/');
260
+ if (pathParts[0] !== section) {
261
+ return false;
262
+ }
263
+ if (type && pathParts[1] !== type) {
264
+ return false;
265
+ }
266
+ return true;
267
+ });
268
+ }
269
+ /**
270
+ * Convert cache items to GitHub API format
271
+ */
272
+ convertCacheItemsToGitHubFormat(items) {
273
+ return items.map(item => ({
274
+ name: item.name,
275
+ path: item.path,
276
+ sha: item.sha,
277
+ type: 'file',
278
+ url: `https://api.github.com/repos/DollhouseMCP/collection/contents/${item.path}`,
279
+ html_url: `https://github.com/DollhouseMCP/collection/blob/main/${item.path}`
280
+ }));
45
281
  }
46
282
  /**
47
283
  * Format collection browse results
@@ -60,7 +296,7 @@ export class CollectionBrowser {
60
296
  const icon = sectionIcons[sec.name] || '📁';
61
297
  const descriptions = {
62
298
  'library': 'Free community content',
63
- 'showcase': 'Featured high-quality content',
299
+ 'showcase': 'Featured high-quality content (coming soon)',
64
300
  'catalog': 'Premium content (coming soon)'
65
301
  };
66
302
  textParts.push(` ${icon} **${sec.name}** - ${descriptions[sec.name] || 'Content collection'}\n`, ` Browse: \`browse_collection "${sec.name}"\`\n\n`);
@@ -75,9 +311,7 @@ export class CollectionBrowser {
75
311
  'personas': '🎭',
76
312
  'skills': '🛠️',
77
313
  'agents': '🤖',
78
- 'prompts': '💬',
79
314
  'templates': '📄',
80
- 'tools': '🔧',
81
315
  'ensembles': '🎼',
82
316
  'memories': '🧠'
83
317
  };
@@ -101,9 +335,7 @@ export class CollectionBrowser {
101
335
  'personas': '🎭',
102
336
  'skills': '🛠️',
103
337
  'agents': '🤖',
104
- 'prompts': '💬',
105
338
  'templates': '📄',
106
- 'tools': '🔧',
107
339
  'ensembles': '🎼',
108
340
  'memories': '🧠'
109
341
  };
@@ -117,4 +349,4 @@ export class CollectionBrowser {
117
349
  return textParts.join('');
118
350
  }
119
351
  }
120
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29sbGVjdGlvbkJyb3dzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29sbGVjdGlvbi9Db2xsZWN0aW9uQnJvd3Nlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUtILE1BQU0sT0FBTyxpQkFBaUI7SUFDcEIsWUFBWSxDQUFlO0lBQzNCLE9BQU8sR0FBRywrREFBK0QsQ0FBQztJQUVsRixZQUFZLFlBQTBCO1FBQ3BDLElBQUksQ0FBQyxZQUFZLEdBQUcsWUFBWSxDQUFDO0lBQ25DLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUFDLE9BQWdCLEVBQUUsSUFBYTtRQUNwRCxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBRXZCLGtEQUFrRDtRQUNsRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQzFELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ3pCLE1BQU0sSUFBSSxLQUFLLENBQUMsMERBQTBELENBQUMsQ0FBQztZQUM5RSxDQUFDO1lBRUQsMENBQTBDO1lBQzFDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFTLEVBQUUsRUFBRSxDQUN6QyxJQUFJLENBQUMsSUFBSSxLQUFLLEtBQUssSUFBSSxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsU0FBUyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FDOUUsQ0FBQztZQUVGLE9BQU8sRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLFVBQVUsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUM7UUFDakQsQ0FBQztRQUVELDBCQUEwQjtRQUMxQixHQUFHLEdBQUcs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SixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBUyxFQUFFLEVBQUU7Z0JBQzFCLE1BQU0sUUFBUSxHQUFHLE9BQU8sR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ3RFLFNBQVMsQ0FBQyxJQUFJLENBQ1osV0FBVyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLE1BQU0sRUFDN0Msd0NBQXdDLFFBQVEsT0FBTyxFQUN2RCxnREFBZ0QsUUFBUSxTQUFTLENBQ2xFLENBQUM7WUFDSixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDNUIsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCcm93c2UgY29sbGVjdGlvbiBjb250ZW50IGZyb20gR2l0SHViXG4gKi9cblxuaW1wb3J0IHsgR2l0SHViQ2xpZW50IH0gZnJvbSAnLi9HaXRIdWJDbGllbnQuanMnO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcblxuZXhwb3J0IGNsYXNzIENvbGxlY3Rpb25Ccm93c2VyIHtcbiAgcHJpdmF0ZSBnaXRodWJDbGllbnQ6IEdpdEh1YkNsaWVudDtcbiAgcHJpdmF0ZSBiYXNlVXJsID0gJ2h0dHBzOi8vYXBpLmdpdGh1Yi5jb20vcmVwb3MvRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vY29udGVudHMnO1xuICBcbiAgY29uc3RydWN0b3IoZ2l0aHViQ2xpZW50OiBHaXRIdWJDbGllbnQpIHtcbiAgICB0aGlzLmdpdGh1YkNsaWVudCA9IGdpdGh1YkNsaWVudDtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEJyb3dzZSBjb2xsZWN0aW9uIGNvbnRlbnQgYnkgc2VjdGlvbiBhbmQgdHlwZVxuICAgKiBAcGFyYW0gc2VjdGlvbiAtIFRvcCBsZXZlbCBzZWN0aW9uOiBsaWJyYXJ5LCBzaG93Y2FzZSwgb3IgY2F0YWxvZ1xuICAgKiBAcGFyYW0gdHlwZSAtIE9wdGlvbmFsIGNvbnRlbnQgdHlwZSB3aXRoaW4gdGhlIGxpYnJhcnkgc2VjdGlvbiAocGVyc29uYXMsIHNraWxscywgZXRjLilcbiAgICovXG4gIGFzeW5jIGJyb3dzZUNvbGxlY3Rpb24oc2VjdGlvbj86IHN0cmluZywgdHlwZT86IHN0cmluZyk6IFByb21pc2U8eyBpdGVtczogYW55W10sIGNhdGVnb3JpZXM6IGFueVtdLCBzZWN0aW9ucz86IGFueVtdIH0+IHtcbiAgICBsZXQgdXJsID0gdGhpcy5iYXNlVXJsO1xuICAgIFxuICAgIC8vIElmIG5vIHNlY3Rpb24gcHJvdmlkZWQsIHNob3cgdG9wLWxldmVsIHNlY3Rpb25zXG4gICAgaWYgKCFzZWN0aW9uKSB7XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5naXRodWJDbGllbnQuZmV0Y2hGcm9tR2l0SHViKHVybCk7XG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbGxlY3Rpb24gcmVzcG9uc2UuIEV4cGVjdGVkIGRpcmVjdG9yeSBsaXN0aW5nLicpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBGaWx0ZXIgdG8gb25seSBzaG93IGNvbnRlbnQgZGlyZWN0b3JpZXNcbiAgICAgIGNvbnN0IHNlY3Rpb25zID0gZGF0YS5maWx0ZXIoKGl0ZW06IGFueSkgPT4gXG4gICAgICAgIGl0ZW0udHlwZSA9PT0gJ2RpcicgJiYgWydsaWJyYXJ5JywgJ3Nob3djYXNlJywgJ2NhdGFsb2cnXS5pbmNsdWRlcyhpdGVtLm5hbWUpXG4gICAgICApO1xuICAgICAgXG4gICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IFtdLCBzZWN0aW9ucyB9O1xuICAgIH1cbiAgICBcbiAgICAvLyBCcm93c2Ugd2l0aGluIGEgc2VjdGlvblxuICAgIHVybCA9IHR5cGUgXG4gICAgICA/IGAke3RoaXMuYmFzZVVybH0vJHtzZWN0aW9ufS8ke3R5cGV9YCBcbiAgICAgIDogYCR7dGhpcy5iYXNlVXJsfS8ke3NlY3Rpb259YDtcbiAgICBcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5naXRodWJDbGllbnQuZmV0Y2hGcm9tR2l0SHViKHVybCk7XG4gICAgXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29sbGVjdGlvbiByZXNwb25zZS4gRXhwZWN0ZWQgZGlyZWN0b3J5IGxpc3RpbmcuJyk7XG4gICAgfVxuICAgIFxuICAgIC8vIEluIHRoZSBsaWJyYXJ5IHNlY3Rpb24sIHdlIGhhdmUgY29udGVudCB0eXBlIGRpcmVjdG9yaWVzXG4gICAgaWYgKHNlY3Rpb24gPT09ICdsaWJyYXJ5JyAmJiAhdHlwZSkge1xuICAgICAgY29uc3QgY29udGVudFR5cGVzID0gZGF0YS5maWx0ZXIoKGl0ZW06IGFueSkgPT4gXG4gICAgICAgIGl0ZW0udHlwZSA9PT0gJ2RpcicgJiYgWydwZXJzb25hcycsICdza2lsbHMnLCAnYWdlbnRzJywgJ3Byb21wdHMnLCAndGVtcGxhdGVzJywgJ3Rvb2xzJywgJ2Vuc2VtYmxlcycsICdtZW1vcmllcyddLmluY2x1ZGVzKGl0ZW0ubmFtZSlcbiAgICAgICk7XG4gICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IGNvbnRlbnRUeXBlcyB9O1xuICAgIH1cbiAgICBcbiAgICAvLyBGb3IgbGlicmFyeSBjb250ZW50IHR5cGVzLCBzaG93IGZpbGVzIGRpcmVjdGx5IChmbGF0IHN0cnVjdHVyZSlcbiAgICBjb25zdCBpdGVtcyA9IGRhdGEuZmlsdGVyKChpdGVtOiBhbnkpID0+IGl0ZW0udHlwZSA9PT0gJ2ZpbGUnICYmIGl0ZW0ubmFtZS5lbmRzV2l0aCgnLm1kJykpO1xuICAgIC8vIEZvciBub24tbGlicmFyeSBzZWN0aW9ucywgdGhleSBtaWdodCBzdGlsbCBoYXZlIHN1YmRpcmVjdG9yaWVzXG4gICAgY29uc3QgY2F0ZWdvcmllcyA9IHNlY3Rpb24gPT09ICdsaWJyYXJ5JyA/IFtdIDogZGF0YS5maWx0ZXIoKGl0ZW06IGFueSkgPT4gaXRlbS50eXBlID09PSAnZGlyJyk7XG4gICAgXG4gICAgcmV0dXJuIHsgaXRlbXMsIGNhdGVnb3JpZXMgfTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEZvcm1hdCBjb2xsZWN0aW9uIGJyb3dzZSByZXN1bHRzXG4gICAqL1xuICBmb3JtYXRCcm93c2VSZXN1bHRzKGl0ZW1zOiBhbnlbXSwgY2F0ZWdvcmllczogYW55W10sIHNlY3Rpb24/OiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcsIHBlcnNvbmFJbmRpY2F0b3I6IHN0cmluZyA9ICcnKTogc3RyaW5nIHtcbiAgICBjb25zdCB0ZXh0UGFydHMgPSBbYCR7cGVyc29uYUluZGljYXRvcn3wn4+qICoqRG9sbGhvdXNlTUNQIENvbGxlY3Rpb24qKlxcblxcbmBdO1xuICAgIFxuICAgIC8vIFNob3cgdG9wLWxldmVsIHNlY3Rpb25zIGlmIG5vIHNlY3Rpb24gc3BlY2lmaWVkXG4gICAgaWYgKCFzZWN0aW9uICYmIGNhdGVnb3JpZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGV4dFBhcnRzLnB1c2goYCoq8J+TmiBDb2xsZWN0aW9uIFNlY3Rpb25zICgke2NhdGVnb3JpZXMubGVuZ3RofSk6KipcXG5gKTtcbiAgICAgIGNhdGVnb3JpZXMuZm9yRWFjaCgoc2VjOiBhbnkpID0+IHtcbiAgICAgICAgY29uc3Qgc2VjdGlvbkljb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgICAgICdsaWJyYXJ5JzogJ/Cfk5YnLFxuICAgICAgICAgICdzaG93Y2FzZSc6ICfirZAnLFxuICAgICAgICAgICdjYXRhbG9nJzogJ/Cfko4nXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGljb24gPSBzZWN0aW9uSWNvbnNbc2VjLm5hbWVdIHx8ICfwn5OBJztcbiAgICAgICAgY29uc3QgZGVzY3JpcHRpb25zOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgICAgICdsaWJyYXJ5JzogJ0ZyZWUgY29tbXVuaXR5IGNvbnRlbnQnLFxuICAgICAgICAgICdzaG93Y2FzZSc6ICdGZWF0dXJlZCBoaWdoLXF1YWxpdHkgY29udGVudCcsXG4gICAgICAgICAgJ2NhdGFsb2cnOiAnUHJlbWl1bSBjb250ZW50IChjb21pbmcgc29vbiknXG4gICAgICAgIH07XG4gICAgICAgIHRleHRQYXJ0cy5wdXNoKFxuICAgICAgICAgIGAgICAke2ljb259ICoqJHtzZWMubmFtZX0qKiAtICR7ZGVzY3JpcHRpb25zW3NlYy5uYW1lXSB8fCAnQ29udGVudCBjb2xsZWN0aW9uJ31cXG5gLFxuICAgICAgICAgIGAgICAgICBCcm93c2U6IFxcYGJyb3dzZV9jb2xsZWN0aW9uIFwiJHtzZWMubmFtZX1cIlxcYFxcblxcbmBcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHRleHRQYXJ0cy5qb2luKCcnKTtcbiAgICB9XG4gICAgXG4gICAgLy8gU2hvdyBjb250ZW50IHR5cGVzIHdpdGhpbiBsaWJyYXJ5IHNlY3Rpb25cbiAgICBpZiAoc2VjdGlvbiA9PT0gJ2xpYnJhcnknICYmICF0eXBlICYmIGNhdGVnb3JpZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGV4dFBhcnRzLnB1c2goYCoq8J+TliBMaWJyYXJ5IENvbnRlbnQgVHlwZXMgKCR7Y2F0ZWdvcmllcy5sZW5ndGh9KToqKlxcbmApO1xuICAgICAgY2F0ZWdvcmllcy5mb3JFYWNoKChjYXQ6IGFueSkgPT4ge1xuICAgICAgICBjb25zdCB0eXBlSWNvbnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAgICAgJ3BlcnNvbmFzJzogJ/Cfjq0nLFxuICAgICAgICAgICdza2lsbHMnOiAn8J+boO+4jycsXG4gICAgICAgICAgJ2FnZW50cyc6ICfwn6SWJyxcbiAgICAgICAgICAncHJvbXB0cyc6ICfwn5KsJyxcbiAgICAgICAgICAndGVtcGxhdGVzJzogJ/Cfk4QnLFxuICAgICAgICAgICd0b29scyc6ICfwn5SnJyxcbiAgICAgICAgICAnZW5zZW1ibGVzJzogJ/CfjrwnLFxuICAgICAgICAgICdtZW1vcmllcyc6ICfwn6egJ1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBpY29uID0gdHlwZUljb25zW2NhdC5uYW1lXSB8fCAn8J+TgSc7XG4gICAgICAgIHRleHRQYXJ0cy5wdXNoKGAgICAke2ljb259ICoqJHtjYXQubmFtZX0qKiAtIEJyb3dzZTogXFxgYnJvd3NlX2NvbGxlY3Rpb24gXCJsaWJyYXJ5XCIgXCIke2NhdC5uYW1lfVwiXFxgXFxuYCk7XG4gICAgICB9KTtcbiAgICAgIHRleHRQYXJ0cy5wdXNoKCdcXG4nKTtcbiAgICB9IGVsc2UgaWYgKGNhdGVnb3JpZXMubGVuZ3RoID4gMCkge1xuICAgICAgLy8gT25seSBzaG93IGNhdGVnb3J5IG5hdmlnYXRpb24gZm9yIG5vbi1saWJyYXJ5IHNlY3Rpb25zIChzaG93Y2FzZSwgY2F0YWxvZylcbiAgICAgIHRleHRQYXJ0cy5wdXNoKGAqKvCfk4EgU3ViZGlyZWN0b3JpZXMgaW4gJHtzZWN0aW9ufSR7dHlwZSA/IGAvJHt0eXBlfWAgOiAnJ30gKCR7Y2F0ZWdvcmllcy5sZW5ndGh9KToqKlxcbmApO1xuICAgICAgY2F0ZWdvcmllcy5mb3JFYWNoKChjYXQ6IGFueSkgPT4ge1xuICAgICAgICBjb25zdCBicm93c2VQYXRoID0gdHlwZSA/IGBcIiR7c2VjdGlvbn1cIiBcIiR7dHlwZX0vJHtjYXQubmFtZX1cImAgOiBgXCIke3NlY3Rpb259XCIgXCIke2NhdC5uYW1lfVwiYDtcbiAgICAgICAgdGV4dFBhcnRzLnB1c2goYCAgIPCfk4IgKioke2NhdC5uYW1lfSoqIC0gQnJvd3NlOiBcXGBicm93c2VfY29sbGVjdGlvbiAke2Jyb3dzZVBhdGh9XFxgXFxuYCk7XG4gICAgICB9KTtcbiAgICAgIHRleHRQYXJ0cy5wdXNoKCdcXG4nKTtcbiAgICB9XG4gICAgXG4gICAgaWYgKGl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGNvbnRlbnRUeXBlID0gdHlwZSB8fCAnY29udGVudCc7XG4gICAgICBjb25zdCBjb250ZW50SWNvbnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAgICdwZXJzb25hcyc6ICfwn46tJyxcbiAgICAgICAgJ3NraWxscyc6ICfwn5ug77iPJyxcbiAgICAgICAgJ2FnZW50cyc6ICfwn6SWJyxcbiAgICAgICAgJ3Byb21wdHMnOiAn8J+SrCcsXG4gICAgICAgICd0ZW1wbGF0ZXMnOiAn8J+ThCcsXG4gICAgICAgICd0b29scyc6ICfwn5SnJyxcbiAgICAgICAgJ2Vuc2VtYmxlcyc6ICfwn468JyxcbiAgICAgICAgJ21lbW9yaWVzJzogJ/Cfp6AnXG4gICAgICB9O1xuICAgICAgY29uc3QgaWNvbiA9IGNvbnRlbnRJY29uc1tjb250ZW50VHlwZV0gfHwgJ/Cfk4QnO1xuICAgICAgXG4gICAgICB0ZXh0UGFydHMucHVzaChgKioke2ljb259ICR7Y29udGVudFR5cGUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBjb250ZW50VHlwZS5zbGljZSgxKX0gaW4gJHtzZWN0aW9ufSR7dHlwZSA/IGAvJHt0eXBlfWAgOiAnJ30gKCR7aXRlbXMubGVuZ3RofSk6KipcXG5gKTtcbiAgICAgIGl0ZW1zLmZvckVhY2goKGl0ZW06IGFueSkgPT4ge1xuICAgICAgICBjb25zdCBmdWxsUGF0aCA9IHNlY3Rpb24gKyAodHlwZSA/IGAvJHt0eXBlfWAgOiAnJykgKyBgLyR7aXRlbS5uYW1lfWA7XG4gICAgICAgIHRleHRQYXJ0cy5wdXNoKFxuICAgICAgICAgIGAgICDilqvvuI8gKioke2l0ZW0ubmFtZS5yZXBsYWNlKCcubWQnLCAnJyl9KipcXG5gLFxuICAgICAgICAgIGAgICAgICDwn5OlIEluc3RhbGw6IFxcYGluc3RhbGxfY29udGVudCBcIiR7ZnVsbFBhdGh9XCJcXGBcXG5gLFxuICAgICAgICAgIGAgICAgICDwn5GB77iPIERldGFpbHM6IFxcYGdldF9jb2xsZWN0aW9uX2NvbnRlbnQgXCIke2Z1bGxQYXRofVwiXFxgXFxuXFxuYFxuICAgICAgICApO1xuICAgICAgfSk7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiB0ZXh0UGFydHMuam9pbignJyk7XG4gIH1cbn0iXX0=
352
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29sbGVjdGlvbkJyb3dzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29sbGVjdGlvbi9Db2xsZWN0aW9uQnJvd3Nlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUdILE9BQU8sRUFBRSxlQUFlLEVBQWtCLE1BQU0sNkJBQTZCLENBQUM7QUFDOUUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDekQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFckUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUVwRCxxREFBcUQ7QUFDckQsNkNBQTZDO0FBQzdDLDBFQUEwRTtBQUMxRSwrQ0FBK0M7QUFDL0MsZ0ZBQWdGO0FBQ2hGLE1BQU0sbUJBQW1CLEdBQUc7SUFDMUIsV0FBVyxDQUFDLE9BQU8sRUFBSyx3REFBd0Q7SUFDaEYsV0FBVyxDQUFDLEtBQUssRUFBTyxxQ0FBcUM7SUFDN0QsV0FBVyxDQUFDLEtBQUssRUFBTyx1Q0FBdUM7SUFDL0QsV0FBVyxDQUFDLFFBQVEsQ0FBSSx3Q0FBd0M7Q0FDakUsQ0FBQztBQUVGOztHQUVHO0FBQ0gsU0FBUyxhQUFhLENBQUMsS0FBYTtJQUNsQyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQW9CLENBQUMsQ0FBQztBQUNuRSxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLGtCQUFrQixDQUFDLFdBQXdCO0lBQ2xELE9BQU8sbUJBQW1CLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ25ELENBQUM7QUFFRCxNQUFNLE9BQU8saUJBQWlCO0lBQ3BCLFlBQVksQ0FBZTtJQUMzQixlQUFlLENBQWtCO0lBQ2pDLFlBQVksQ0FBeUI7SUFDckMsT0FBTyxH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QUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsTUFBTSxFQUM3Qyx3Q0FBd0MsUUFBUSxPQUFPLEVBQ3ZELGdEQUFnRCxRQUFRLFNBQVMsQ0FDbEUsQ0FBQztZQUNKLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUM1QixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEJyb3dzZSBjb2xsZWN0aW9uIGNvbnRlbnQgZnJvbSBHaXRIdWJcbiAqL1xuXG5pbXBvcnQgeyBHaXRIdWJDbGllbnQgfSBmcm9tICcuL0dpdEh1YkNsaWVudC5qcyc7XG5pbXBvcnQgeyBDb2xsZWN0aW9uQ2FjaGUsIENvbGxlY3Rpb25JdGVtIH0gZnJvbSAnLi4vY2FjaGUvQ29sbGVjdGlvbkNhY2hlLmpzJztcbmltcG9ydCB7IENvbGxlY3Rpb25TZWVkZXIgfSBmcm9tICcuL0NvbGxlY3Rpb25TZWVkZXIuanMnO1xuaW1wb3J0IHsgQ29sbGVjdGlvbkluZGV4TWFuYWdlciB9IGZyb20gJy4vQ29sbGVjdGlvbkluZGV4TWFuYWdlci5qcyc7XG5pbXBvcnQgeyBDb2xsZWN0aW9uSW5kZXgsIEluZGV4RW50cnkgfSBmcm9tICcuLi90eXBlcy9jb2xsZWN0aW9uLmpzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBFbGVtZW50VHlwZSB9IGZyb20gJy4uL3BvcnRmb2xpby90eXBlcy5qcyc7XG5cbi8vIENvbnRlbnQgdHlwZXMgc3VwcG9ydGVkIGJ5IE1DUCBzZXJ2ZXIgKElzc3VlICMxNDQpXG4vLyBIaWRlOiBtZW1vcmllcywgZW5zZW1ibGVzIGZyb20gTUNQIHF1ZXJpZXNcbi8vIOKaoO+4jyBDUklUSUNBTDogV2hlbiBhZGRpbmcgbmV3IGVsZW1lbnQgdHlwZXMsIHlvdSBNVVNUIHVwZGF0ZSB0aGlzIGFycmF5IVxuLy8gQWxzbyB1cGRhdGUgdmFsaWRUeXBlcyBhcnJheSBpbiBzcmMvaW5kZXgudHNcbi8vIFNlZSBkb2NzL2RldmVsb3BtZW50L0FERElOR19ORVdfRUxFTUVOVF9UWVBFU19DSEVDS0xJU1QubWQgZm9yIGNvbXBsZXRlIGd1aWRlXG5jb25zdCBNQ1BfU1VQUE9SVEVEX1RZUEVTID0gW1xuICBFbGVtZW50VHlwZS5QRVJTT05BLCAgICAvLyBwZXJzb25hcyAtIHN1cHBvcnRlZCBieSBQZXJzb25hVG9vbHMgYW5kIEVsZW1lbnRUb29sc1xuICBFbGVtZW50VHlwZS5TS0lMTCwgICAgICAvLyBza2lsbHMgLSBzdXBwb3J0ZWQgYnkgRWxlbWVudFRvb2xzXG4gIEVsZW1lbnRUeXBlLkFHRU5ULCAgICAgIC8vIGFnZW50cyAtIHN1cHBvcnRlZCBieSBFbGVtZW50VG9vbHMgIFxuICBFbGVtZW50VHlwZS5URU1QTEFURSAgICAvLyB0ZW1wbGF0ZXMgLSBzdXBwb3J0ZWQgYnkgRWxlbWVudFRvb2xzXG5dO1xuXG4vKipcbiAqIFR5cGUgZ3VhcmQgdG8gc2FmZWx5IGNoZWNrIGlmIGEgc3RyaW5nIGlzIGEgdmFsaWQgRWxlbWVudFR5cGVcbiAqL1xuZnVuY3Rpb24gaXNFbGVtZW50VHlwZSh2YWx1ZTogc3RyaW5nKTogdmFsdWUgaXMgRWxlbWVudFR5cGUge1xuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhFbGVtZW50VHlwZSkuaW5jbHVkZXModmFsdWUgYXMgRWxlbWVudFR5cGUpO1xufVxuXG4vKipcbiAqIFR5cGUgZ3VhcmQgdG8gc2FmZWx5IGNoZWNrIGlmIGFuIEVsZW1lbnRUeXBlIGlzIHN1cHBvcnRlZCBieSBNQ1BcbiAqL1xuZnVuY3Rpb24gaXNNQ1BTdXBwb3J0ZWRUeXBlKGVsZW1lbnRUeXBlOiBFbGVtZW50VHlwZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gTUNQX1NVUFBPUlRFRF9UWVBFUy5pbmNsdWRlcyhlbGVtZW50VHlwZSk7XG59XG5cbmV4cG9ydCBjbGFzcyBDb2xsZWN0aW9uQnJvd3NlciB7XG4gIHByaXZhdGUgZ2l0aHViQ2xpZW50OiBHaXRIdWJDbGllbnQ7XG4gIHByaXZhdGUgY29sbGVjdGlvbkNhY2hlOiBDb2xsZWN0aW9uQ2FjaGU7XG4gIHByaXZhdGUgaW5kZXhNYW5hZ2VyOiBDb2xsZWN0aW9uSW5kZXhNYW5hZ2VyO1xuICBwcml2YXRlIGJhc2VVcmwgPSAnaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9jb250ZW50cyc7XG4gIFxuICBjb25zdHJ1Y3RvcihnaXRodWJDbGllbnQ6IEdpdEh1YkNsaWVudCwgY29sbGVjdGlvbkNhY2hlPzogQ29sbGVjdGlvbkNhY2hlLCBpbmRleE1hbmFnZXI/OiBDb2xsZWN0aW9uSW5kZXhNYW5hZ2VyKSB7XG4gICAgdGhpcy5naXRodWJDbGllbnQgPSBnaXRodWJDbGllbnQ7XG4gICAgdGhpcy5jb2xsZWN0aW9uQ2FjaGUgPSBjb2xsZWN0aW9uQ2FjaGUgfHwgbmV3IENvbGxlY3Rpb25DYWNoZSgpO1xuICAgIHRoaXMuaW5kZXhNYW5hZ2VyID0gaW5kZXhNYW5hZ2VyIHx8IG5ldyBDb2xsZWN0aW9uSW5kZXhNYW5hZ2VyKCk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBCcm93c2UgY29sbGVjdGlvbiBjb250ZW50IGJ5IHNlY3Rpb24gYW5kIHR5cGVcbiAgICogVXNlcyBDb2xsZWN0aW9uSW5kZXhNYW5hZ2VyIGZvciBmYXN0IGJyb3dzaW5nIHdpdGggYmFja2dyb3VuZCByZWZyZXNoXG4gICAqIEZhbGxzIGJhY2sgdG8gY2FjaGVkIGRhdGEgd2hlbiBHaXRIdWIgQVBJIGlzIG5vdCBhdmFpbGFibGUgb3Igbm90IGF1dGhlbnRpY2F0ZWRcbiAgICogQHBhcmFtIHNlY3Rpb24gLSBUb3AgbGV2ZWwgc2VjdGlvbjogbGlicmFyeSwgc2hvd2Nhc2UsIG9yIGNhdGFsb2dcbiAgICogQHBhcmFtIHR5cGUgLSBPcHRpb25hbCBjb250ZW50IHR5cGUgd2l0aGluIHRoZSBsaWJyYXJ5IHNlY3Rpb24gKHBlcnNvbmFzLCBza2lsbHMsIGV0Yy4pXG4gICAqL1xuICBhc3luYyBicm93c2VDb2xsZWN0aW9uKHNlY3Rpb24/OiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcpOiBQcm9taXNlPHsgaXRlbXM6IGFueVtdLCBjYXRlZ29yaWVzOiBhbnlbXSwgc2VjdGlvbnM/OiBhbnlbXSB9PiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIFRyeSB1c2luZyBjb2xsZWN0aW9uIGluZGV4IGZpcnN0IGZvciBmYXN0ZXIgYnJvd3NpbmdcbiAgICAgIGNvbnN0IGluZGV4UmVzdWx0ID0gYXdhaXQgdGhpcy5icm93c2VGcm9tSW5kZXgoc2VjdGlvbiwgdHlwZSk7XG4gICAgICBpZiAoaW5kZXhSZXN1bHQpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdVc2VkIGNvbGxlY3Rpb24gaW5kZXggZm9yIGJyb3dzaW5nJyk7XG4gICAgICAgIHJldHVybiBpbmRleFJlc3VsdDtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gRmFsbGJhY2sgdG8gR2l0SHViIEFQSVxuICAgICAgbGV0IHVybCA9IHRoaXMuYmFzZVVybDtcbiAgICAgIFxuICAgICAgLy8gSWYgbm8gc2VjdGlvbiBwcm92aWRlZCwgc2hvdyB0b3AtbGV2ZWwgc2VjdGlvbnNcbiAgICAgIGlmICghc2VjdGlvbikge1xuICAgICAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5naXRodWJDbGllbnQuZmV0Y2hGcm9tR2l0SHViKHVybCwgZmFsc2UpO1xuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29sbGVjdGlvbiByZXNwb25zZS4gRXhwZWN0ZWQgZGlyZWN0b3J5IGxpc3RpbmcuJyk7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIEZpbHRlciB0byBvbmx5IHNob3cgY29udGVudCBkaXJlY3Rvcmllc1xuICAgICAgICBjb25zdCBzZWN0aW9ucyA9IGRhdGEuZmlsdGVyKChpdGVtOiBhbnkpID0+IFxuICAgICAgICAgIGl0ZW0udHlwZSA9PT0gJ2RpcicgJiYgWydsaWJyYXJ5JywgJ3Nob3djYXNlJywgJ2NhdGFsb2cnXS5pbmNsdWRlcyhpdGVtLm5hbWUpXG4gICAgICAgICk7XG4gICAgICAgIFxuICAgICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IFtdLCBzZWN0aW9ucyB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBCcm93c2Ugd2l0aGluIGEgc2VjdGlvblxuICAgICAgdXJsID0gdHlwZSBcbiAgICAgICAgPyBgJHt0aGlzLmJhc2VVcmx9LyR7c2VjdGlvbn0vJHt0eXBlfWAgXG4gICAgICAgIDogYCR7dGhpcy5iYXNlVXJsfS8ke3NlY3Rpb259YDtcbiAgICAgIFxuICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuZ2l0aHViQ2xpZW50LmZldGNoRnJvbUdpdEh1Yih1cmwsIGZhbHNlKTtcbiAgICAgIFxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGRhdGEpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb2xsZWN0aW9uIHJlc3BvbnNlLiBFeHBlY3RlZCBkaXJlY3RvcnkgbGlzdGluZy4nKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gSW4gdGhlIGxpYnJhcnkgc2VjdGlvbiwgd2UgaGF2ZSBjb250ZW50IHR5cGUgZGlyZWN0b3JpZXNcbiAgICAgIGlmIChzZWN0aW9uID09PSAnbGlicmFyeScgJiYgIXR5cGUpIHtcbiAgICAgICAgLy8gRmlsdGVyIHRvIG9ubHkgc2hvdyBNQ1Atc3VwcG9ydGVkIGNvbnRlbnQgdHlwZXNcbiAgICAgICAgY29uc3QgY29udGVudFR5cGVzID0gZGF0YS5maWx0ZXIoKGl0ZW06IGFueSkgPT4ge1xuICAgICAgICAgIGlmIChpdGVtLnR5cGUgIT09ICdkaXInKSByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgY29uc3QgZWxlbWVudFR5cGUgPSBpc0VsZW1lbnRUeXBlKGl0ZW0ubmFtZSkgPyBpdGVtLm5hbWUgYXMgRWxlbWVudFR5cGUgOiBudWxsO1xuICAgICAgICAgIHJldHVybiBlbGVtZW50VHlwZSAmJiBpc01DUFN1cHBvcnRlZFR5cGUoZWxlbWVudFR5cGUpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHsgaXRlbXM6IFtdLCBjYXRlZ29yaWVzOiBjb250ZW50VHlwZXMgfTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gRm9yIGxpYnJhcnkgY29udGVudCB0eXBlcywgc2hvdyBmaWxlcyBkaXJlY3RseSAoZmxhdCBzdHJ1Y3R1cmUpXG4gICAgICBjb25zdCBpdGVtcyA9IGRhdGEuZmlsdGVyKChpdGVtOiBhbnkpID0+IGl0ZW0udHlwZSA9PT0gJ2ZpbGUnICYmIGl0ZW0ubmFtZS5lbmRzV2l0aCgnLm1kJykpO1xuICAgICAgLy8gRm9yIG5vbi1saWJyYXJ5IHNlY3Rpb25zLCB0aGV5IG1pZ2h0IHN0aWxsIGhhdmUgc3ViZGlyZWN0b3JpZXNcbiAgICAgIGNvbnN0IGNhdGVnb3JpZXMgPSBzZWN0aW9uID09PSAnbGlicmFyeScgPyBbXSA6IGRhdGEuZmlsdGVyKChpdGVtOiBhbnkpID0+IGl0ZW0udHlwZSA9PT0gJ2RpcicpO1xuICAgICAgXG4gICAgICByZXR1cm4geyBpdGVtcywgY2F0ZWdvcmllcyB9O1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZGVidWcoYEdpdEh1YiBBUEkgYnJvd3NlIGZhaWxlZCwgZmFsbGluZyBiYWNrIHRvIGNhY2hlOiAke2Vycm9yfWApO1xuICAgICAgXG4gICAgICAvLyBGYWxsYmFjayB0byBjYWNoZWQgZGF0YVxuICAgICAgcmV0dXJuIHRoaXMuYnJvd3NlRnJvbUNhY2hlKHNlY3Rpb24sIHR5cGUpO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEJyb3dzZSBjb2xsZWN0aW9uIHVzaW5nIHRoZSBmYXN0IGNvbGxlY3Rpb24gaW5kZXhcbiAgICogUmV0dXJucyBudWxsIGlmIGluZGV4IGlzIG5vdCBhdmFpbGFibGUgb3IgYnJvd3NpbmcgZmFpbHNcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYnJvd3NlRnJvbUluZGV4KHNlY3Rpb24/OiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcpOiBQcm9taXNlPHsgaXRlbXM6IGFueVtdLCBjYXRlZ29yaWVzOiBhbnlbXSwgc2VjdGlvbnM/OiBhbnlbXSB9IHwgbnVsbD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpbmRleCA9IGF3YWl0IHRoaXMuaW5kZXhNYW5hZ2VyLmdldEluZGV4KCk7XG4gICAgICBcbiAgICAgIC8vIElmIG5vIHNlY3Rpb24gcHJvdmlkZWQsIHNob3cgdG9wLWxldmVsIHNlY3Rpb25zXG4gICAgICBpZiAoIXNlY3Rpb24pIHtcbiAgICAgICAgY29uc3Qgc2VjdGlvbnMgPSBbXG4gICAgICAgICAgeyBuYW1lOiAnbGlicmFyeScsIHR5cGU6ICdkaXInIH0sXG4gICAgICAgICAgeyBuYW1lOiAnc2hvd2Nhc2UnLCB0eXBlOiAnZGlyJyB9LFxuICAgICAgICAgIHsgbmFtZTogJ2NhdGFsb2cnLCB0eXBlOiAnZGlyJyB9XG4gICAgICAgIF07XG4gICAgICAgIHJldHVybiB7IGl0ZW1zOiBbXSwgY2F0ZWdvcmllczogW10sIHNlY3Rpb25zIH07XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIEluIHRoZSBsaWJyYXJ5IHNlY3Rpb24sIHdlIGhhdmUgY29udGVudCB0eXBlIGRpcmVjdG9yaWVzXG4gICAgICBpZiAoc2VjdGlvbiA9PT0gJ2xpYnJhcnknICYmICF0eXBlKSB7XG4gICAgICAgIC8vIEdldCB1bmlxdWUgY29udGVudCB0eXBlcyBmcm9tIGluZGV4XG4gICAgICAgIGNvbnN0IGNvbnRlbnRUeXBlcyA9IHRoaXMuZ2V0Q29udGVudFR5cGVzRnJvbUluZGV4KGluZGV4KTtcbiAgICAgICAgcmV0dXJuIHsgaXRlbXM6IFtdLCBjYXRlZ29yaWVzOiBjb250ZW50VHlwZXMgfTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gR2V0IGl0ZW1zIGZvciBzcGVjaWZpYyB0eXBlIG9yIGFsbCBpdGVtcyBpbiBzZWN0aW9uXG4gICAgICBjb25zdCBpdGVtcyA9IHRoaXMuZ2V0SXRlbXNGcm9tSW5kZXgoaW5kZXgsIHNlY3Rpb24sIHR5cGUpO1xuICAgICAgY29uc3QgZm9ybWF0dGVkSXRlbXMgPSB0aGlzLmNvbnZlcnRJbmRleEl0ZW1zVG9HaXRIdWJGb3JtYXQoaXRlbXMpO1xuICAgICAgXG4gICAgICByZXR1cm4geyBpdGVtczogZm9ybWF0dGVkSXRlbXMsIGNhdGVnb3JpZXM6IFtdIH07XG4gICAgICBcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmRlYnVnKCdGYWlsZWQgdG8gYnJvd3NlIGZyb20gY29sbGVjdGlvbiBpbmRleCcsIHsgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKSB9KTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCB1bmlxdWUgY29udGVudCB0eXBlcyBmcm9tIGNvbGxlY3Rpb24gaW5kZXhcbiAgICovXG4gIHByaXZhdGUgZ2V0Q29udGVudFR5cGVzRnJvbUluZGV4KGluZGV4OiBDb2xsZWN0aW9uSW5kZXgpOiBhbnlbXSB7XG4gICAgY29uc3QgdHlwZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBcbiAgICAvLyBFeHRyYWN0IHR5cGVzIGZyb20gaW5kZXgga2V5cyBhbmQgZmlsdGVyIGZvciBNQ1Atc3VwcG9ydGVkIHR5cGVzXG4gICAgT2JqZWN0LmtleXMoaW5kZXguaW5kZXgpLmZvckVhY2godHlwZU5hbWUgPT4ge1xuICAgICAgY29uc3QgZWxlbWVudFR5cGUgPSBpc0VsZW1lbnRUeXBlKHR5cGVOYW1lKSA/IHR5cGVOYW1lIGFzIEVsZW1lbnRUeXBlIDogbnVsbDtcbiAgICAgIGlmIChlbGVtZW50VHlwZSAmJiBpc01DUFN1cHBvcnRlZFR5cGUoZWxlbWVudFR5cGUpKSB7XG4gICAgICAgIHR5cGVzLmFkZCh0eXBlTmFtZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgXG4gICAgcmV0dXJuIEFycmF5LmZyb20odHlwZXMpLm1hcCh0eXBlID0+ICh7XG4gICAgICBuYW1lOiB0eXBlLFxuICAgICAgdHlwZTogJ2RpcidcbiAgICB9KSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgaXRlbXMgZnJvbSBjb2xsZWN0aW9uIGluZGV4IGJ5IHNlY3Rpb24gYW5kIHR5cGVcbiAgICovXG4gIHByaXZhdGUgZ2V0SXRlbXNGcm9tSW5kZXgoaW5kZXg6IENvbGxlY3Rpb25JbmRleCwgc2VjdGlvbjogc3RyaW5nLCB0eXBlPzogc3RyaW5nKTogSW5kZXhFbnRyeVtdIHtcbiAgICAvLyBGb3IgbGlicmFyeSBzZWN0aW9uIHdpdGggdHlwZSwgZ2V0IGl0ZW1zIGZyb20gdGhhdCB0eXBlXG4gICAgaWYgKHNlY3Rpb24gPT09ICdsaWJyYXJ5JyAmJiB0eXBlKSB7XG4gICAgICByZXR1cm4gaW5kZXguaW5kZXhbdHlwZV0gfHwgW107XG4gICAgfVxuICAgIFxuICAgIC8vIEZvciBsaWJyYXJ5IHNlY3Rpb24gd2l0aG91dCB0eXBlLCByZXR1cm4gZW1wdHkgKHNob3VsZCBzaG93IGNhdGVnb3JpZXMpXG4gICAgaWYgKHNlY3Rpb24gPT09ICdsaWJyYXJ5JyAmJiAhdHlwZSkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBcbiAgICAvLyBGb3Igb3RoZXIgc2VjdGlvbnMgKHNob3djYXNlLCBjYXRhbG9nKSwgcmV0dXJuIGFsbCBpdGVtcyB0aGF0IG1hdGNoXG4gICAgLy8gTm90ZTogVGhlIGN1cnJlbnQgaW5kZXggc3RydWN0dXJlIGlzIHByaW1hcmlseSBmb3IgbGlicmFyeSBjb250ZW50XG4gICAgLy8gRnV0dXJlIGVuaGFuY2VtZW50OiBleHRlbmQgaW5kZXggdG8gaW5jbHVkZSBzaG93Y2FzZS9jYXRhbG9nIHNlY3Rpb25zXG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIFxuICAvKipcbiAgICogQ29udmVydCBpbmRleCBlbnRyaWVzIHRvIEdpdEh1YiBBUEkgZm9ybWF0IGZvciBjb21wYXRpYmlsaXR5XG4gICAqL1xuICBwcml2YXRlIGNvbnZlcnRJbmRleEl0ZW1zVG9HaXRIdWJGb3JtYXQoaXRlbXM6IEluZGV4RW50cnlbXSk6IGFueVtdIHtcbiAgICByZXR1cm4gaXRlbXMubWFwKGl0ZW0gPT4gKHtcbiAgICAgIG5hbWU6IGl0ZW0ubmFtZS5lbmRzV2l0aCgnLm1kJykgPyBpdGVtLm5hbWUgOiBgJHtpdGVtLm5hbWV9Lm1kYCxcbiAgICAgIHBhdGg6IGl0ZW0ucGF0aCxcbiAgICAgIHNoYTogaXRlbS5zaGEsXG4gICAgICB0eXBlOiAnZmlsZScsXG4gICAgICB1cmw6IGBodHRwczovL2FwaS5naXRodWIuY29tL3JlcG9zL0RvbGxob3VzZU1DUC9jb2xsZWN0aW9uL2NvbnRlbnRzLyR7aXRlbS5wYXRofWAsXG4gICAgICBodG1sX3VybDogYGh0dHBzOi8vZ2l0aHViLmNvbS9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9ibG9iL21haW4vJHtpdGVtLnBhdGh9YFxuICAgIH0pKTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEJyb3dzZSBjb2xsZWN0aW9uIGZyb20gY2FjaGVkIGRhdGFcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgYnJvd3NlRnJvbUNhY2hlKHNlY3Rpb24/OiBzdHJpbmcsIHR5cGU/OiBzdHJpbmcpOiBQcm9taXNlPHsgaXRlbXM6IGFueVtdLCBjYXRlZ29yaWVzOiBhbnlbXSwgc2VjdGlvbnM/OiBhbnlbXSB9PiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIElmIG5vIHNlY3Rpb24gcHJvdmlkZWQsIHNob3cgYXZhaWxhYmxlIHNlY3Rpb25zIGZyb20gc2VlZCBkYXRhXG4gICAgICBpZiAoIXNlY3Rpb24pIHtcbiAgICAgICAgY29uc3Qgc2VjdGlvbnMgPSBbXG4gICAgICAgICAgeyBuYW1lOiAnbGlicmFyeScsIHR5cGU6ICdkaXInIH1cbiAgICAgICAgXTtcbiAgICAgICAgcmV0dXJuIHsgaXRlbXM6IFtdLCBjYXRlZ29yaWVzOiBbXSwgc2VjdGlvbnMgfTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gR2V0IGNhY2hlZCBvciBzZWVkIGRhdGFcbiAgICAgIGxldCBjYWNoZWRJdGVtcyA9IGF3YWl0IHRoaXMuY29sbGVjdGlvbkNhY2hlLmxvYWRDYWNoZSgpO1xuICAgICAgXG4gICAgICBpZiAoIWNhY2hlZEl0ZW1zIHx8IGNhY2hlZEl0ZW1zLml0ZW1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAvLyBVc2Ugc2VlZCBkYXRhIGlmIGNhY2hlIGlzIGVtcHR5XG4gICAgICAgIGNvbnN0IHNlZWREYXRhID0gQ29sbGVjdGlvblNlZWRlci5nZXRTZWVkRGF0YSgpO1xuICAgICAgICBhd2FpdCB0aGlzLmNvbGxlY3Rpb25DYWNoZS5zYXZlQ2FjaGUoc2VlZERhdGEpO1xuICAgICAgICBjYWNoZWRJdGVtcyA9IHsgaXRlbXM6IHNlZWREYXRhLCB0aW1lc3RhbXA6IERhdGUubm93KCkgfTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdVc2luZyBzZWVkIGRhdGEgZm9yIGNvbGxlY3Rpb24gYnJvd3NpbmcnKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gSW4gdGhlIGxpYnJhcnkgc2VjdGlvbiwgd2UgaGF2ZSBjb250ZW50IHR5cGUgZGlyZWN0b3JpZXNcbiAgICAgIGlmIChzZWN0aW9uID09PSAnbGlicmFyeScgJiYgIXR5cGUpIHtcbiAgICAgICAgY29uc3QgY29udGVudFR5cGVzID0gdGhpcy5nZXRDb250ZW50VHlwZXNGcm9tSXRlbXMoY2FjaGVkSXRlbXMuaXRlbXMpO1xuICAgICAgICByZXR1cm4geyBpdGVtczogW10sIGNhdGVnb3JpZXM6IGNvbnRlbnRUeXBlcyB9O1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBHZXQgaXRlbXMgZm9yIHNwZWNpZmljIHR5cGUgb3IgYWxsIGl0ZW1zIGluIHNlY3Rpb25cbiAgICAgIGNvbnN0IGl0ZW1zID0gdGhpcy5maWx0ZXJJdGVtc0J5U2VjdGlvbihjYWNoZWRJdGVtcy5pdGVtcywgc2VjdGlvbiwgdHlwZSk7XG4gICAgICBjb25zdCBmb3JtYXR0ZWRJdGVtcyA9IHRoaXMuY29udmVydENhY2hlSXRlbXNUb0dpdEh1YkZvcm1hdChpdGVtcyk7XG4gICAgICBcbiAgICAgIHJldHVybiB7IGl0ZW1zOiBmb3JtYXR0ZWRJdGVtcywgY2F0ZWdvcmllczogW10gfTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgbG9nZ2VyLmVycm9yKGBDYWNoZSBicm93c2UgZmFpbGVkOiAke2Vycm9yfWApO1xuICAgICAgXG4gICAgICAvLyBMYXN0IHJlc29ydDogdXNlIHNlZWQgZGF0YSBkaXJlY3RseVxuICAgICAgcmV0dXJuIHRoaXMuYnJvd3NlRnJvbVNlZWREYXRhKHNlY3Rpb24sIHR5cGUpO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEJyb3dzZSBjb2xsZWN0aW9uIGZyb20gc2VlZCBkYXRhIGFzIGxhc3QgcmVzb3J0XG4gICAqL1xuICBwcml2YXRlIGJyb3dzZUZyb21TZWVkRGF0YShzZWN0aW9uPzogc3RyaW5nLCB0eXBlPzogc3RyaW5nKTogeyBpdGVtczogYW55W10sIGNhdGVnb3JpZXM6IGFueVtdLCBzZWN0aW9ucz86IGFueVtdIH0ge1xuICAgIGlmICghc2VjdGlvbikge1xuICAgICAgY29uc3Qgc2VjdGlvbnMgPSBbeyBuYW1lOiAnbGlicmFyeScsIHR5cGU6ICdkaXInIH1dO1xuICAgICAgcmV0dXJuIHsgaXRlbXM6IFtdLCBjYXRlZ29yaWVzOiBbXSwgc2VjdGlvbnMgfTtcbiAgICB9XG4gICAgXG4gICAgY29uc3Qgc2VlZERhdGEgPSBDb2xsZWN0aW9uU2VlZGVyLmdldFNlZWREYXRhKCk7XG4gICAgXG4gICAgaWYgKHNlY3Rpb24gPT09ICdsaWJyYXJ5JyAmJiAhdHlwZSkge1xuICAgICAgY29uc3QgY29udGVudFR5cGVzID0gdGhpcy5nZXRDb250ZW50VHlwZXNGcm9tSXRlbXMoc2VlZERhdGEpO1xuICAgICAgcmV0dXJuIHsgaXRlbXM6IFtdLCBjYXRlZ29yaWVzOiBjb250ZW50VHlwZXMgfTtcbiAgICB9XG4gICAgXG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLmZpbHRlckl0ZW1zQnlTZWN0aW9uKHNlZWREYXRhLCBzZWN0aW9uLCB0eXBlKTtcbiAgICBjb25zdCBmb3JtYXR0ZWRJdGVtcyA9IHRoaXMuY29udmVydENhY2hlSXRlbXNUb0dpdEh1YkZvcm1hdChpdGVtcyk7XG4gICAgXG4gICAgcmV0dXJuIHsgaXRlbXM6IGZvcm1hdHRlZEl0ZW1zLCBjYXRlZ29yaWVzOiBbXSB9O1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IHVuaXF1ZSBjb250ZW50IHR5cGVzIGZyb20gaXRlbXNcbiAgICovXG4gIHByaXZhdGUgZ2V0Q29udGVudFR5cGVzRnJvbUl0ZW1zKGl0ZW1zOiBDb2xsZWN0aW9uSXRlbVtdKTogYW55W10ge1xuICAgIGNvbnN0IHR5cGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgXG4gICAgaXRlbXMuZm9yRWFjaChpdGVtID0+IHtcbiAgICAgIGNvbnN0IHBhdGhQYXJ0cyA9IGl0ZW0ucGF0aC5zcGxpdCgnLycpO1xuICAgICAgaWYgKHBhdGhQYXJ0cy5sZW5ndGggPj0gMiAmJiBwYXRoUGFydHNbMF0gPT09ICdsaWJyYXJ5Jykge1xuICAgICAgICAvLyBPbmx5IGluY2x1ZGUgTUNQLXN1cHBvcnRlZCB0eXBlcyBpbiBjYWNoZSBicm93c2luZ1xuICAgICAgICBjb25zdCB0eXBlTmFtZSA9IHBhdGhQYXJ0c1sxXTtcbiAgICAgICAgY29uc3QgZWxlbWVudFR5cGUgPSBpc0VsZW1lbnRUeXBlKHR5cGVOYW1lKSA/IHR5cGVOYW1lIGFzIEVsZW1lbnRUeXBlIDogbnVsbDtcbiAgICAgICAgaWYgKGVsZW1lbnRUeXBlICYmIGlzTUNQU3VwcG9ydGVkVHlwZShlbGVtZW50VHlwZSkpIHtcbiAgICAgICAgICB0eXBlcy5hZGQodHlwZU5hbWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgXG4gICAgcmV0dXJuIEFycmF5LmZyb20odHlwZXMpLm1hcCh0eXBlID0+ICh7XG4gICAgICBuYW1lOiB0eXBlLFxuICAgICAgdHlwZTogJ2RpcidcbiAgICB9KSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBGaWx0ZXIgaXRlbXMgYnkgc2VjdGlvbiBhbmQgdHlwZVxuICAgKi9cbiAgcHJpdmF0ZSBmaWx0ZXJJdGVtc0J5U2VjdGlvbihpdGVtczogQ29sbGVjdGlvbkl0ZW1bXSwgc2VjdGlvbjogc3RyaW5nLCB0eXBlPzogc3RyaW5nKTogQ29sbGVjdGlvbkl0ZW1bXSB7XG4gICAgcmV0dXJuIGl0ZW1zLmZpbHRlcihpdGVtID0+IHtcbiAgICAgIGNvbnN0IHBhdGhQYXJ0cyA9IGl0ZW0ucGF0aC5zcGxpdCgnLycpO1xuICAgICAgXG4gICAgICBpZiAocGF0aFBhcnRzWzBdICE9PSBzZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYgKHR5cGUgJiYgcGF0aFBhcnRzWzFdICE9PSB0eXBlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDb252ZXJ0IGNhY2hlIGl0ZW1zIHRvIEdpdEh1YiBBUEkgZm9ybWF0XG4gICAqL1xuICBwcml2YXRlIGNvbnZlcnRDYWNoZUl0ZW1zVG9HaXRIdWJGb3JtYXQoaXRlbXM6IENvbGxlY3Rpb25JdGVtW10pOiBhbnlbXSB7XG4gICAgcmV0dXJuIGl0ZW1zLm1hcChpdGVtID0+ICh7XG4gICAgICBuYW1lOiBpdGVtLm5hbWUsXG4gICAgICBwYXRoOiBpdGVtLnBhdGgsXG4gICAgICBzaGE6IGl0ZW0uc2hhLFxuICAgICAgdHlwZTogJ2ZpbGUnLFxuICAgICAgdXJsOiBgaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy9Eb2xsaG91c2VNQ1AvY29sbGVjdGlvbi9jb250ZW50cy8ke2l0ZW0ucGF0aH1gLFxuICAgICAgaHRtbF91cmw6IGBodHRwczovL2dpdGh1Yi5jb20vRG9sbGhvdXNlTUNQL2NvbGxlY3Rpb24vYmxvYi9tYWluLyR7aXRlbS5wYXRofWBcbiAgICB9KSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBGb3JtYXQgY29sbGVjdGlvbiBicm93c2UgcmVzdWx0c1xuICAgKi9cbiAgZm9ybWF0QnJvd3NlUmVzdWx0cyhpdGVtczogYW55W10sIGNhdGVnb3JpZXM6IGFueVtdLCBzZWN0aW9uPzogc3RyaW5nLCB0eXBlPzogc3RyaW5nLCBwZXJzb25hSW5kaWNhdG9yOiBzdHJpbmcgPSAnJyk6IHN0cmluZyB7XG4gICAgY29uc3QgdGV4dFBhcnRzID0gW2Ake3BlcnNvbmFJbmRpY2F0b3J98J+PqiAqKkRvbGxob3VzZU1DUCBDb2xsZWN0aW9uKipcXG5cXG5gXTtcbiAgICBcbiAgICAvLyBTaG93IHRvcC1sZXZlbCBzZWN0aW9ucyBpZiBubyBzZWN0aW9uIHNwZWNpZmllZFxuICAgIGlmICghc2VjdGlvbiAmJiBjYXRlZ29yaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRleHRQYXJ0cy5wdXNoKGAqKvCfk5ogQ29sbGVjdGlvbiBTZWN0aW9ucyAoJHtjYXRlZ29yaWVzLmxlbmd0aH0pOioqXFxuYCk7XG4gICAgICBjYXRlZ29yaWVzLmZvckVhY2goKHNlYzogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IHNlY3Rpb25JY29uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgICAgICAgICAnbGlicmFyeSc6ICfwn5OWJyxcbiAgICAgICAgICAnc2hvd2Nhc2UnOiAn4q2QJyxcbiAgICAgICAgICAnY2F0YWxvZyc6ICfwn5KOJ1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBpY29uID0gc2VjdGlvbkljb25zW3NlYy5uYW1lXSB8fCAn8J+TgSc7XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgICAgICAgICAnbGlicmFyeSc6ICdGcmVlIGNvbW11bml0eSBjb250ZW50JyxcbiAgICAgICAgICAnc2hvd2Nhc2UnOiAnRmVhdHVyZWQgaGlnaC1xdWFsaXR5IGNvbnRlbnQgKGNvbWluZyBzb29uKScsXG4gICAgICAgICAgJ2NhdGFsb2cnOiAnUHJlbWl1bSBjb250ZW50IChjb21pbmcgc29vbiknXG4gICAgICAgIH07XG4gICAgICAgIHRleHRQYXJ0cy5wdXNoKFxuICAgICAgICAgIGAgICAke2ljb259ICoqJHtzZWMubmFtZX0qKiAtICR7ZGVzY3JpcHRpb25zW3NlYy5uYW1lXSB8fCAnQ29udGVudCBjb2xsZWN0aW9uJ31cXG5gLFxuICAgICAgICAgIGAgICAgICBCcm93c2U6IFxcYGJyb3dzZV9jb2xsZWN0aW9uIFwiJHtzZWMubmFtZX1cIlxcYFxcblxcbmBcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHRleHRQYXJ0cy5qb2luKCcnKTtcbiAgICB9XG4gICAgXG4gICAgLy8gU2hvdyBjb250ZW50IHR5cGVzIHdpdGhpbiBsaWJyYXJ5IHNlY3Rpb25cbiAgICBpZiAoc2VjdGlvbiA9PT0gJ2xpYnJhcnknICYmICF0eXBlICYmIGNhdGVnb3JpZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGV4dFBhcnRzLnB1c2goYCoq8J+TliBMaWJyYXJ5IENvbnRlbnQgVHlwZXMgKCR7Y2F0ZWdvcmllcy5sZW5ndGh9KToqKlxcbmApO1xuICAgICAgY2F0ZWdvcmllcy5mb3JFYWNoKChjYXQ6IGFueSkgPT4ge1xuICAgICAgICBjb25zdCB0eXBlSWNvbnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAgICAgJ3BlcnNvbmFzJzogJ/Cfjq0nLFxuICAgICAgICAgICdza2lsbHMnOiAn8J+boO+4jycsXG4gICAgICAgICAgJ2FnZW50cyc6ICfwn6SWJyxcbiAgICAgICAgICAndGVtcGxhdGVzJzogJ/Cfk4QnLFxuICAgICAgICAgICdlbnNlbWJsZXMnOiAn8J+OvCcsXG4gICAgICAgICAgJ21lbW9yaWVzJzogJ/Cfp6AnXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IGljb24gPSB0eXBlSWNvbnNbY2F0Lm5hbWVdIHx8ICfwn5OBJztcbiAgICAgICAgdGV4dFBhcnRzLnB1c2goYCAgICR7aWNvbn0gKioke2NhdC5uYW1lfSoqIC0gQnJvd3NlOiBcXGBicm93c2VfY29sbGVjdGlvbiBcImxpYnJhcnlcIiBcIiR7Y2F0Lm5hbWV9XCJcXGBcXG5gKTtcbiAgICAgIH0pO1xuICAgICAgdGV4dFBhcnRzLnB1c2goJ1xcbicpO1xuICAgIH0gZWxzZSBpZiAoY2F0ZWdvcmllcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBPbmx5IHNob3cgY2F0ZWdvcnkgbmF2aWdhdGlvbiBmb3Igbm9uLWxpYnJhcnkgc2VjdGlvbnMgKHNob3djYXNlLCBjYXRhbG9nKVxuICAgICAgdGV4dFBhcnRzLnB1c2goYCoq8J+TgSBTdWJkaXJlY3RvcmllcyBpbiAke3NlY3Rpb259JHt0eXBlID8gYC8ke3R5cGV9YCA6ICcnfSAoJHtjYXRlZ29yaWVzLmxlbmd0aH0pOioqXFxuYCk7XG4gICAgICBjYXRlZ29yaWVzLmZvckVhY2goKGNhdDogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IGJyb3dzZVBhdGggPSB0eXBlID8gYFwiJHtzZWN0aW9ufVwiIFwiJHt0eXBlfS8ke2NhdC5uYW1lfVwiYCA6IGBcIiR7c2VjdGlvbn1cIiBcIiR7Y2F0Lm5hbWV9XCJgO1xuICAgICAgICB0ZXh0UGFydHMucHVzaChgICAg8J+TgiAqKiR7Y2F0Lm5hbWV9KiogLSBCcm93c2U6IFxcYGJyb3dzZV9jb2xsZWN0aW9uICR7YnJvd3NlUGF0aH1cXGBcXG5gKTtcbiAgICAgIH0pO1xuICAgICAgdGV4dFBhcnRzLnB1c2goJ1xcbicpO1xuICAgIH1cbiAgICBcbiAgICBpZiAoaXRlbXMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgY29udGVudFR5cGUgPSB0eXBlIHx8ICdjb250ZW50JztcbiAgICAgIGNvbnN0IGNvbnRlbnRJY29uczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHtcbiAgICAgICAgJ3BlcnNvbmFzJzogJ/Cfjq0nLFxuICAgICAgICAnc2tpbGxzJzogJ/Cfm6DvuI8nLFxuICAgICAgICAnYWdlbnRzJzogJ/CfpJYnLFxuICAgICAgICAndGVtcGxhdGVzJzogJ/Cfk4QnLFxuICAgICAgICAnZW5zZW1ibGVzJzogJ/CfjrwnLFxuICAgICAgICAnbWVtb3JpZXMnOiAn8J+noCdcbiAgICAgIH07XG4gICAgICBjb25zdCBpY29uID0gY29udGVudEljb25zW2NvbnRlbnRUeXBlXSB8fCAn8J+ThCc7XG4gICAgICBcbiAgICAgIHRleHRQYXJ0cy5wdXNoKGAqKiR7aWNvbn0gJHtjb250ZW50VHlwZS5jaGFyQXQoMCkudG9VcHBlckNhc2UoKSArIGNvbnRlbnRUeXBlLnNsaWNlKDEpfSBpbiAke3NlY3Rpb259JHt0eXBlID8gYC8ke3R5cGV9YCA6ICcnfSAoJHtpdGVtcy5sZW5ndGh9KToqKlxcbmApO1xuICAgICAgaXRlbXMuZm9yRWFjaCgoaXRlbTogYW55KSA9PiB7XG4gICAgICAgIGNvbnN0IGZ1bGxQYXRoID0gc2VjdGlvbiArICh0eXBlID8gYC8ke3R5cGV9YCA6ICcnKSArIGAvJHtpdGVtLm5hbWV9YDtcbiAgICAgICAgdGV4dFBhcnRzLnB1c2goXG4gICAgICAgICAgYCAgIOKWq++4jyAqKiR7aXRlbS5uYW1lLnJlcGxhY2UoJy5tZCcsICcnKX0qKlxcbmAsXG4gICAgICAgICAgYCAgICAgIPCfk6UgSW5zdGFsbDogXFxgaW5zdGFsbF9jb250ZW50IFwiJHtmdWxsUGF0aH1cIlxcYFxcbmAsXG4gICAgICAgICAgYCAgICAgIPCfkYHvuI8gRGV0YWlsczogXFxgZ2V0X2NvbGxlY3Rpb25fY29udGVudCBcIiR7ZnVsbFBhdGh9XCJcXGBcXG5cXG5gXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHRleHRQYXJ0cy5qb2luKCcnKTtcbiAgfVxufSJdfQ==
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Collection Index Manager with Background Refresh and Robust Caching
3
+ *
4
+ * This manager implements:
5
+ * - 1-hour TTL with local file caching
6
+ * - Background refresh without blocking operations
7
+ * - Exponential backoff retry logic
8
+ * - Configurable timeouts via environment variables
9
+ * - Return stale cache while refreshing in background
10
+ * - Comprehensive error handling for production use
11
+ */
12
+ import { CollectionIndex } from '../types/collection';
13
+ export interface CollectionIndexCacheEntry {
14
+ data: CollectionIndex;
15
+ timestamp: number;
16
+ etag?: string;
17
+ lastModified?: string;
18
+ version: string;
19
+ checksum: string;
20
+ }
21
+ export interface CollectionIndexManagerConfig {
22
+ ttlMs?: number;
23
+ fetchTimeoutMs?: number;
24
+ maxRetries?: number;
25
+ baseRetryDelayMs?: number;
26
+ maxRetryDelayMs?: number;
27
+ cacheDir?: string;
28
+ }
29
+ export declare class CollectionIndexManager {
30
+ private readonly INDEX_URL;
31
+ private readonly TTL_MS;
32
+ private readonly FETCH_TIMEOUT_MS;
33
+ private readonly MAX_RETRIES;
34
+ private readonly BASE_RETRY_DELAY_MS;
35
+ private readonly MAX_RETRY_DELAY_MS;
36
+ private readonly CACHE_FILE;
37
+ private cachedIndex;
38
+ private backgroundRefreshPromise;
39
+ private isRefreshing;
40
+ private circuitBreakerFailures;
41
+ private circuitBreakerLastFailure;
42
+ private readonly CIRCUIT_BREAKER_THRESHOLD;
43
+ private readonly CIRCUIT_BREAKER_TIMEOUT_MS;
44
+ private readonly REFRESH_THRESHOLD;
45
+ private readonly JITTER_FACTOR;
46
+ private readonly DEFAULT_TTL_MS;
47
+ private readonly DEFAULT_MAX_RETRIES;
48
+ private readonly DEFAULT_BASE_RETRY_DELAY_MS;
49
+ private readonly DEFAULT_MAX_RETRY_DELAY_MS;
50
+ private readonly DEFAULT_FETCH_TIMEOUT_MS;
51
+ private readonly CHECKSUM_LENGTH;
52
+ private readonly JSON_INDENT;
53
+ constructor(config?: CollectionIndexManagerConfig);
54
+ /**
55
+ * Parse fetch timeout from config or environment variable
56
+ */
57
+ private parseFetchTimeout;
58
+ /**
59
+ * Get collection index with stale-while-revalidate pattern
60
+ * Returns cached data immediately if available, refreshes in background
61
+ */
62
+ getIndex(): Promise<CollectionIndex>;
63
+ /**
64
+ * Force refresh the collection index
65
+ */
66
+ forceRefresh(): Promise<CollectionIndex>;
67
+ /**
68
+ * Check if cache should be refreshed (within TTL but getting close to expiry)
69
+ */
70
+ private shouldRefreshCache;
71
+ /**
72
+ * Check if cache is expired
73
+ */
74
+ private isCacheExpired;
75
+ /**
76
+ * Start background refresh without blocking
77
+ */
78
+ private startBackgroundRefresh;
79
+ /**
80
+ * Perform background refresh
81
+ */
82
+ private performBackgroundRefresh;
83
+ /**
84
+ * Fetch collection index with retry logic and exponential backoff
85
+ */
86
+ private fetchWithRetry;
87
+ /**
88
+ * Calculate retry delay with exponential backoff and jitter
89
+ */
90
+ private calculateRetryDelay;
91
+ /**
92
+ * Add jitter (±25% randomness) to a delay to prevent thundering herd problems
93
+ */
94
+ private addJitter;
95
+ /**
96
+ * Fetch collection index from GitHub
97
+ */
98
+ private fetchCollectionIndex;
99
+ /**
100
+ * Validate collection index structure
101
+ */
102
+ private validateIndexStructure;
103
+ /**
104
+ * Update cache with new data
105
+ */
106
+ private updateCache;
107
+ /**
108
+ * Calculate checksum for data integrity verification
109
+ */
110
+ private calculateChecksum;
111
+ /**
112
+ * Load cache from disk
113
+ */
114
+ private loadFromDisk;
115
+ /**
116
+ * Save cache to disk
117
+ */
118
+ private saveToDisk;
119
+ /**
120
+ * Circuit breaker logic
121
+ */
122
+ private isCircuitBreakerOpen;
123
+ private recordCircuitBreakerFailure;
124
+ /**
125
+ * Utility methods
126
+ */
127
+ private sleep;
128
+ private getErrorMessage;
129
+ /**
130
+ * Get cache statistics for monitoring
131
+ */
132
+ getCacheStats(): {
133
+ isValid: boolean;
134
+ age: number;
135
+ hasCache: boolean;
136
+ version?: string;
137
+ totalElements?: number;
138
+ isRefreshing: boolean;
139
+ circuitBreakerFailures: number;
140
+ circuitBreakerOpen: boolean;
141
+ };
142
+ /**
143
+ * Clear all cache data
144
+ */
145
+ clearCache(): Promise<void>;
146
+ /**
147
+ * Wait for any ongoing background refresh to complete
148
+ */
149
+ waitForBackgroundRefresh(): Promise<void>;
150
+ }
151
+ //# sourceMappingURL=CollectionIndexManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CollectionIndexManager.d.ts","sourceRoot":"","sources":["../../src/collection/CollectionIndexManager.ts"],"names":[],"mappings":"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"}