@dollhousemcp/mcp-server 1.5.2 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +494 -111
- package/data/agents/code-reviewer.md +8 -1
- package/data/agents/research-assistant.md +8 -1
- package/data/agents/task-manager.md +8 -1
- package/data/ensembles/business-advisor.md +8 -1
- package/data/ensembles/creative-studio.md +8 -1
- package/data/ensembles/development-team.md +8 -1
- package/data/ensembles/security-analysis-team.md +8 -1
- package/data/memories/conversation-history.md +8 -1
- package/data/memories/learning-progress.md +8 -1
- package/data/memories/project-context.md +8 -1
- package/data/personas/business-consultant.md +8 -1
- package/data/personas/creative-writer.md +8 -1
- package/data/personas/debug-detective.md +8 -1
- package/data/personas/eli5-explainer.md +8 -1
- package/data/personas/security-analyst.md +8 -1
- package/data/personas/technical-analyst.md +8 -1
- package/data/skills/code-review.md +8 -1
- package/data/skills/creative-writing.md +8 -1
- package/data/skills/data-analysis.md +8 -1
- package/data/skills/penetration-testing.md +8 -1
- package/data/skills/research.md +8 -1
- package/data/skills/threat-modeling.md +8 -1
- package/data/skills/translation.md +8 -1
- package/data/templates/code-documentation.md +8 -1
- package/data/templates/email-professional.md +8 -1
- package/data/templates/meeting-notes.md +8 -1
- package/data/templates/penetration-test-report.md +8 -1
- package/data/templates/project-brief.md +8 -1
- package/data/templates/report-executive.md +8 -1
- package/data/templates/security-vulnerability-report.md +8 -1
- package/data/templates/threat-assessment-report.md +8 -1
- package/dist/auth/GitHubAuthManager.d.ts +6 -1
- package/dist/auth/GitHubAuthManager.d.ts.map +1 -1
- package/dist/auth/GitHubAuthManager.js +45 -18
- package/dist/benchmarks/IndexPerformanceBenchmark.d.ts +98 -0
- package/dist/benchmarks/IndexPerformanceBenchmark.d.ts.map +1 -0
- package/dist/benchmarks/IndexPerformanceBenchmark.js +531 -0
- package/dist/cache/CollectionCache.d.ts.map +1 -1
- package/dist/cache/CollectionCache.js +13 -3
- package/dist/cache/CollectionIndexCache.d.ts +77 -0
- package/dist/cache/CollectionIndexCache.d.ts.map +1 -0
- package/dist/cache/CollectionIndexCache.js +349 -0
- package/dist/cache/LRUCache.d.ts +93 -0
- package/dist/cache/LRUCache.d.ts.map +1 -0
- package/dist/cache/LRUCache.js +299 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +2 -1
- package/dist/collection/CollectionBrowser.d.ts +21 -1
- package/dist/collection/CollectionBrowser.d.ts.map +1 -1
- package/dist/collection/CollectionBrowser.js +130 -10
- package/dist/collection/CollectionIndexManager.d.ts +151 -0
- package/dist/collection/CollectionIndexManager.d.ts.map +1 -0
- package/dist/collection/CollectionIndexManager.js +499 -0
- package/dist/collection/CollectionSearch.d.ts +55 -0
- package/dist/collection/CollectionSearch.d.ts.map +1 -1
- package/dist/collection/CollectionSearch.js +338 -13
- package/dist/collection/CollectionSeeder.d.ts.map +1 -1
- package/dist/collection/CollectionSeeder.js +38 -1
- package/dist/collection/ElementInstaller.d.ts +31 -0
- package/dist/collection/ElementInstaller.d.ts.map +1 -1
- package/dist/collection/ElementInstaller.js +77 -15
- package/dist/collection/PersonaSubmitter.d.ts +1 -1
- package/dist/collection/PersonaSubmitter.d.ts.map +1 -1
- package/dist/collection/PersonaSubmitter.js +2 -2
- package/dist/collection/index.d.ts +1 -0
- package/dist/collection/index.d.ts.map +1 -1
- package/dist/collection/index.js +2 -1
- package/dist/config/ConfigManager.d.ts +78 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +216 -0
- package/dist/config/element-types.d.ts +135 -0
- package/dist/config/element-types.d.ts.map +1 -0
- package/dist/config/element-types.js +108 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +3 -1
- package/dist/config/portfolio-constants.d.ts +83 -0
- package/dist/config/portfolio-constants.d.ts.map +1 -0
- package/dist/config/portfolio-constants.js +99 -0
- package/dist/elements/BaseElement.d.ts +14 -2
- package/dist/elements/BaseElement.d.ts.map +1 -1
- package/dist/elements/BaseElement.js +88 -6
- package/dist/elements/agents/Agent.d.ts +10 -1
- package/dist/elements/agents/Agent.d.ts.map +1 -1
- package/dist/elements/agents/Agent.js +66 -19
- package/dist/elements/agents/AgentManager.d.ts +2 -0
- package/dist/elements/agents/AgentManager.d.ts.map +1 -1
- package/dist/elements/agents/AgentManager.js +12 -10
- package/dist/elements/skills/Skill.d.ts +10 -1
- package/dist/elements/skills/Skill.d.ts.map +1 -1
- package/dist/elements/skills/Skill.js +40 -3
- package/dist/elements/skills/SkillManager.d.ts +1 -0
- package/dist/elements/skills/SkillManager.d.ts.map +1 -1
- package/dist/elements/skills/SkillManager.js +10 -4
- package/dist/elements/templates/Template.d.ts +10 -1
- package/dist/elements/templates/Template.d.ts.map +1 -1
- package/dist/elements/templates/Template.js +35 -18
- package/dist/elements/templates/TemplateManager.d.ts +1 -1
- package/dist/elements/templates/TemplateManager.d.ts.map +1 -1
- package/dist/elements/templates/TemplateManager.js +6 -5
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +3 -3
- package/dist/index.barrel.d.ts +1 -2
- package/dist/index.barrel.d.ts.map +1 -1
- package/dist/index.barrel.js +2 -4
- package/dist/index.d.ts +143 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1883 -310
- package/dist/persona/PersonaElement.d.ts +10 -0
- package/dist/persona/PersonaElement.d.ts.map +1 -1
- package/dist/persona/PersonaElement.js +55 -32
- package/dist/persona/PersonaElementManager.d.ts.map +1 -1
- package/dist/persona/PersonaElementManager.js +13 -11
- package/dist/persona/PersonaLoader.d.ts.map +1 -1
- package/dist/persona/PersonaLoader.js +8 -2
- package/dist/persona/export-import/PersonaImporter.d.ts.map +1 -1
- package/dist/persona/export-import/PersonaImporter.js +24 -5
- package/dist/persona/export-import/PersonaSharer.d.ts +21 -0
- package/dist/persona/export-import/PersonaSharer.d.ts.map +1 -1
- package/dist/persona/export-import/PersonaSharer.js +198 -22
- package/dist/portfolio/DefaultElementProvider.d.ts +90 -0
- package/dist/portfolio/DefaultElementProvider.d.ts.map +1 -1
- package/dist/portfolio/DefaultElementProvider.js +499 -7
- package/dist/portfolio/GitHubPortfolioIndexer.d.ts +129 -0
- package/dist/portfolio/GitHubPortfolioIndexer.d.ts.map +1 -0
- package/dist/portfolio/GitHubPortfolioIndexer.js +475 -0
- package/dist/portfolio/MigrationManager.d.ts.map +1 -1
- package/dist/portfolio/MigrationManager.js +136 -3
- package/dist/portfolio/PortfolioIndexManager.d.ts +130 -0
- package/dist/portfolio/PortfolioIndexManager.d.ts.map +1 -0
- package/dist/portfolio/PortfolioIndexManager.js +478 -0
- package/dist/portfolio/PortfolioManager.d.ts +5 -0
- package/dist/portfolio/PortfolioManager.d.ts.map +1 -1
- package/dist/portfolio/PortfolioManager.js +61 -20
- package/dist/portfolio/PortfolioRepoManager.d.ts +75 -0
- package/dist/portfolio/PortfolioRepoManager.d.ts.map +1 -0
- package/dist/portfolio/PortfolioRepoManager.js +337 -0
- package/dist/portfolio/UnifiedIndexManager.d.ts +388 -0
- package/dist/portfolio/UnifiedIndexManager.d.ts.map +1 -0
- package/dist/portfolio/UnifiedIndexManager.js +1434 -0
- package/dist/portfolio/index.d.ts +15 -0
- package/dist/portfolio/index.d.ts.map +1 -0
- package/dist/portfolio/index.js +15 -0
- package/dist/portfolio/types.d.ts +7 -0
- package/dist/portfolio/types.d.ts.map +1 -1
- package/dist/portfolio/types.js +6 -1
- package/dist/security/InputValidator.d.ts.map +1 -1
- package/dist/security/InputValidator.js +50 -48
- package/dist/security/audit/SecurityAuditor.d.ts.map +1 -1
- package/dist/security/audit/SecurityAuditor.js +17 -9
- package/dist/security/audit/config/suppressions.d.ts.map +1 -1
- package/dist/security/audit/config/suppressions.js +19 -3
- package/dist/security/contentValidator.d.ts +2 -0
- package/dist/security/contentValidator.d.ts.map +1 -1
- package/dist/security/contentValidator.js +115 -4
- package/dist/security/secureYamlParser.d.ts +1 -0
- package/dist/security/secureYamlParser.d.ts.map +1 -1
- package/dist/security/secureYamlParser.js +29 -7
- package/dist/security/securityMonitor.d.ts +1 -1
- package/dist/security/securityMonitor.d.ts.map +1 -1
- package/dist/security/securityMonitor.js +1 -1
- package/dist/security/tokenManager.d.ts +1 -1
- package/dist/security/tokenManager.d.ts.map +1 -1
- package/dist/security/tokenManager.js +30 -10
- package/dist/server/ServerSetup.d.ts +22 -2
- package/dist/server/ServerSetup.d.ts.map +1 -1
- package/dist/server/ServerSetup.js +77 -12
- package/dist/server/tools/AuthTools.d.ts.map +1 -1
- package/dist/server/tools/AuthTools.js +33 -1
- package/dist/server/tools/BuildInfoTools.d.ts +25 -0
- package/dist/server/tools/BuildInfoTools.d.ts.map +1 -0
- package/dist/server/tools/BuildInfoTools.js +36 -0
- package/dist/server/tools/CollectionTools.d.ts.map +1 -1
- package/dist/server/tools/CollectionTools.js +55 -46
- package/dist/server/tools/ConfigTools.d.ts.map +1 -1
- package/dist/server/tools/ConfigTools.js +29 -1
- package/dist/server/tools/PersonaTools.d.ts +4 -2
- package/dist/server/tools/PersonaTools.d.ts.map +1 -1
- package/dist/server/tools/PersonaTools.js +5 -152
- package/dist/server/tools/PortfolioTools.d.ts +12 -0
- package/dist/server/tools/PortfolioTools.d.ts.map +1 -0
- package/dist/server/tools/PortfolioTools.js +221 -0
- package/dist/server/tools/index.d.ts +3 -1
- package/dist/server/tools/index.d.ts.map +1 -1
- package/dist/server/tools/index.js +4 -2
- package/dist/server/types.d.ts +40 -5
- package/dist/server/types.d.ts.map +1 -1
- package/dist/server/types.js +1 -1
- package/dist/services/BuildInfoService.d.ts +84 -0
- package/dist/services/BuildInfoService.d.ts.map +1 -0
- package/dist/services/BuildInfoService.js +271 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.d.ts +54 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.d.ts.map +1 -0
- package/dist/tools/portfolio/PortfolioElementAdapter.js +229 -0
- package/dist/tools/portfolio/submitToPortfolioTool.d.ts +164 -0
- package/dist/tools/portfolio/submitToPortfolioTool.d.ts.map +1 -0
- package/dist/tools/portfolio/submitToPortfolioTool.js +1523 -0
- package/dist/tools/portfolio/types.d.ts +41 -0
- package/dist/tools/portfolio/types.d.ts.map +1 -0
- package/dist/tools/portfolio/types.js +15 -0
- package/dist/types/collection.d.ts +51 -0
- package/dist/types/collection.d.ts.map +1 -1
- package/dist/types/collection.js +1 -1
- package/dist/utils/EarlyTerminationSearch.d.ts +41 -0
- package/dist/utils/EarlyTerminationSearch.d.ts.map +1 -0
- package/dist/utils/EarlyTerminationSearch.js +164 -0
- package/dist/utils/ErrorHandler.d.ts +86 -0
- package/dist/utils/ErrorHandler.d.ts.map +1 -0
- package/dist/utils/ErrorHandler.js +201 -0
- package/dist/utils/FileDiscoveryUtil.d.ts +53 -0
- package/dist/utils/FileDiscoveryUtil.d.ts.map +1 -0
- package/dist/utils/FileDiscoveryUtil.js +169 -0
- package/dist/utils/GitHubRateLimiter.d.ts +88 -0
- package/dist/utils/GitHubRateLimiter.d.ts.map +1 -0
- package/dist/utils/GitHubRateLimiter.js +315 -0
- package/dist/utils/PerformanceMonitor.d.ts +134 -0
- package/dist/utils/PerformanceMonitor.d.ts.map +1 -0
- package/dist/utils/PerformanceMonitor.js +347 -0
- package/dist/utils/RateLimiter.d.ts.map +1 -0
- package/dist/utils/RateLimiter.js +172 -0
- package/dist/utils/SecureDownloader.d.ts +241 -0
- package/dist/utils/SecureDownloader.d.ts.map +1 -0
- package/dist/utils/SecureDownloader.js +759 -0
- package/dist/utils/ToolCache.d.ts +82 -0
- package/dist/utils/ToolCache.d.ts.map +1 -0
- package/dist/utils/ToolCache.js +196 -0
- package/dist/utils/errorCodes.d.ts +136 -0
- package/dist/utils/errorCodes.d.ts.map +1 -0
- package/dist/utils/errorCodes.js +87 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -1
- package/dist/utils/installation.d.ts +1 -1
- package/dist/utils/installation.d.ts.map +1 -1
- package/dist/utils/installation.js +9 -8
- package/dist/utils/searchUtils.d.ts +31 -0
- package/dist/utils/searchUtils.d.ts.map +1 -1
- package/dist/utils/searchUtils.js +62 -1
- package/package.json +17 -7
- package/dist/config/updateConfig.d.ts +0 -84
- package/dist/config/updateConfig.d.ts.map +0 -1
- package/dist/config/updateConfig.js +0 -148
- package/dist/server/tools/UpdateTools.d.ts +0 -10
- package/dist/server/tools/UpdateTools.d.ts.map +0 -1
- package/dist/server/tools/UpdateTools.js +0 -85
- package/dist/update/BackupManager.d.ts +0 -63
- package/dist/update/BackupManager.d.ts.map +0 -1
- package/dist/update/BackupManager.js +0 -370
- package/dist/update/DependencyChecker.d.ts +0 -41
- package/dist/update/DependencyChecker.d.ts.map +0 -1
- package/dist/update/DependencyChecker.js +0 -132
- package/dist/update/RateLimiter.d.ts.map +0 -1
- package/dist/update/RateLimiter.js +0 -172
- package/dist/update/SignatureVerifier.d.ts +0 -71
- package/dist/update/SignatureVerifier.d.ts.map +0 -1
- package/dist/update/SignatureVerifier.js +0 -214
- package/dist/update/UpdateChecker.d.ts +0 -132
- package/dist/update/UpdateChecker.d.ts.map +0 -1
- package/dist/update/UpdateChecker.js +0 -506
- package/dist/update/UpdateManager.d.ts +0 -60
- package/dist/update/UpdateManager.d.ts.map +0 -1
- package/dist/update/UpdateManager.js +0 -730
- package/dist/update/VersionManager.d.ts +0 -31
- package/dist/update/VersionManager.d.ts.map +0 -1
- package/dist/update/VersionManager.js +0 -181
- package/dist/update/index.d.ts +0 -9
- package/dist/update/index.d.ts.map +0 -1
- package/dist/update/index.js +0 -9
- /package/dist/{update → utils}/RateLimiter.d.ts +0 -0
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Portfolio Indexer - Fetches and indexes user's GitHub portfolio for fast searching
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Singleton pattern for efficient resource usage
|
|
6
|
+
* - Smart caching with TTL and invalidation after user actions
|
|
7
|
+
* - GraphQL/REST API integration for efficient fetching
|
|
8
|
+
* - Rate limiting and authentication handling
|
|
9
|
+
* - Fallback strategy for resilient operation
|
|
10
|
+
* - Performance optimized for 1000+ portfolio elements
|
|
11
|
+
*/
|
|
12
|
+
import { GitHubClient } from '../collection/GitHubClient.js';
|
|
13
|
+
import { PortfolioRepoManager } from './PortfolioRepoManager.js';
|
|
14
|
+
import { ElementType } from './types.js';
|
|
15
|
+
import { logger } from '../utils/logger.js';
|
|
16
|
+
import { SecurityMonitor } from '../security/securityMonitor.js';
|
|
17
|
+
import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
|
|
18
|
+
import { ErrorHandler, ErrorCategory } from '../utils/ErrorHandler.js';
|
|
19
|
+
import { APICache } from '../cache/APICache.js';
|
|
20
|
+
export class GitHubPortfolioIndexer {
|
|
21
|
+
static instance = null;
|
|
22
|
+
static instanceLock = false;
|
|
23
|
+
cache = null;
|
|
24
|
+
lastFetch = null;
|
|
25
|
+
ttl = 15 * 60 * 1000; // 15 minutes
|
|
26
|
+
recentUserAction = false;
|
|
27
|
+
actionTimestamp = null;
|
|
28
|
+
actionGracePeriod = 2 * 60 * 1000; // 2 minutes after action
|
|
29
|
+
githubClient;
|
|
30
|
+
portfolioRepoManager;
|
|
31
|
+
apiCache;
|
|
32
|
+
rateLimitTracker;
|
|
33
|
+
constructor() {
|
|
34
|
+
this.apiCache = new APICache(); // Uses default settings
|
|
35
|
+
this.rateLimitTracker = new Map();
|
|
36
|
+
this.githubClient = new GitHubClient(this.apiCache, this.rateLimitTracker);
|
|
37
|
+
this.portfolioRepoManager = new PortfolioRepoManager();
|
|
38
|
+
logger.debug('GitHubPortfolioIndexer created');
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Singleton pattern with thread safety
|
|
42
|
+
*/
|
|
43
|
+
static getInstance() {
|
|
44
|
+
if (!this.instance) {
|
|
45
|
+
if (this.instanceLock) {
|
|
46
|
+
throw new Error('GitHubPortfolioIndexer instance is being created by another thread');
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
this.instanceLock = true;
|
|
50
|
+
this.instance = new GitHubPortfolioIndexer();
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
this.instanceLock = false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return this.instance;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Main method to get GitHub portfolio index
|
|
60
|
+
*/
|
|
61
|
+
async getIndex(force = false) {
|
|
62
|
+
try {
|
|
63
|
+
// Check if we need fresh data
|
|
64
|
+
if (force || this.shouldFetchFresh()) {
|
|
65
|
+
return await this.fetchFresh();
|
|
66
|
+
}
|
|
67
|
+
// Return cached data if available and valid
|
|
68
|
+
if (this.cache && this.isCacheValid()) {
|
|
69
|
+
logger.debug('Returning cached GitHub portfolio index', {
|
|
70
|
+
username: this.cache.username,
|
|
71
|
+
totalElements: this.cache.totalElements,
|
|
72
|
+
age: this.lastFetch ? Date.now() - this.lastFetch.getTime() : 'unknown'
|
|
73
|
+
});
|
|
74
|
+
return this.cache;
|
|
75
|
+
}
|
|
76
|
+
// Try to fetch fresh, fall back to stale cache on failure
|
|
77
|
+
try {
|
|
78
|
+
return await this.fetchFresh();
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
logger.warn('Failed to fetch fresh GitHub portfolio index, checking for stale cache', {
|
|
82
|
+
error: error instanceof Error ? error.message : String(error)
|
|
83
|
+
});
|
|
84
|
+
// Return stale cache if available
|
|
85
|
+
if (this.cache) {
|
|
86
|
+
logger.info('Returning stale GitHub portfolio cache as fallback', {
|
|
87
|
+
username: this.cache.username,
|
|
88
|
+
age: this.lastFetch ? Date.now() - this.lastFetch.getTime() : 'unknown'
|
|
89
|
+
});
|
|
90
|
+
return this.cache;
|
|
91
|
+
}
|
|
92
|
+
// Return empty index as last resort
|
|
93
|
+
return this.createEmptyIndex();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
ErrorHandler.logError('GitHubPortfolioIndexer.getIndex', error);
|
|
98
|
+
// Return stale cache or empty index
|
|
99
|
+
if (this.cache) {
|
|
100
|
+
return this.cache;
|
|
101
|
+
}
|
|
102
|
+
return this.createEmptyIndex();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Invalidate cache after user actions
|
|
107
|
+
*/
|
|
108
|
+
invalidateAfterAction(action) {
|
|
109
|
+
logger.info('Invalidating GitHub portfolio cache after user action', { action });
|
|
110
|
+
this.recentUserAction = true;
|
|
111
|
+
this.actionTimestamp = new Date();
|
|
112
|
+
// Log security event for audit trail
|
|
113
|
+
SecurityMonitor.logSecurityEvent({
|
|
114
|
+
type: 'PORTFOLIO_CACHE_INVALIDATION',
|
|
115
|
+
severity: 'LOW',
|
|
116
|
+
source: 'GitHubPortfolioIndexer.invalidateAfterAction',
|
|
117
|
+
details: `Cache invalidated after user action: ${action}`,
|
|
118
|
+
metadata: { action }
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Clear all cached data
|
|
123
|
+
*/
|
|
124
|
+
clearCache() {
|
|
125
|
+
this.cache = null;
|
|
126
|
+
this.lastFetch = null;
|
|
127
|
+
this.recentUserAction = false;
|
|
128
|
+
this.actionTimestamp = null;
|
|
129
|
+
this.apiCache.clear();
|
|
130
|
+
logger.info('GitHub portfolio cache cleared');
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get cache statistics
|
|
134
|
+
*/
|
|
135
|
+
getCacheStats() {
|
|
136
|
+
return {
|
|
137
|
+
hasCachedData: this.cache !== null,
|
|
138
|
+
lastFetch: this.lastFetch,
|
|
139
|
+
isStale: !this.isCacheValid(),
|
|
140
|
+
recentUserAction: this.recentUserAction,
|
|
141
|
+
totalElements: this.cache?.totalElements || 0
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Fetch fresh data from GitHub
|
|
146
|
+
*/
|
|
147
|
+
async fetchFresh() {
|
|
148
|
+
const startTime = Date.now();
|
|
149
|
+
logger.info('Fetching fresh GitHub portfolio index...');
|
|
150
|
+
try {
|
|
151
|
+
// Get GitHub username from token
|
|
152
|
+
const username = await this.getGitHubUsername();
|
|
153
|
+
const repository = 'dollhouse-portfolio';
|
|
154
|
+
// Check if portfolio repository exists
|
|
155
|
+
const repoExists = await this.portfolioRepoManager.checkPortfolioExists(username);
|
|
156
|
+
if (!repoExists) {
|
|
157
|
+
logger.info('GitHub portfolio repository does not exist', { username });
|
|
158
|
+
return this.createEmptyIndex(username, repository);
|
|
159
|
+
}
|
|
160
|
+
// Fetch repository content using GitHub API
|
|
161
|
+
const index = await this.fetchRepositoryContent(username, repository);
|
|
162
|
+
// Update cache
|
|
163
|
+
this.cache = index;
|
|
164
|
+
this.lastFetch = new Date();
|
|
165
|
+
this.recentUserAction = false;
|
|
166
|
+
this.actionTimestamp = null;
|
|
167
|
+
const duration = Date.now() - startTime;
|
|
168
|
+
logger.info('GitHub portfolio index fetched successfully', {
|
|
169
|
+
username,
|
|
170
|
+
totalElements: index.totalElements,
|
|
171
|
+
duration: `${duration}ms`,
|
|
172
|
+
rateLimitRemaining: index.rateLimitInfo?.remaining
|
|
173
|
+
});
|
|
174
|
+
// Log security event
|
|
175
|
+
SecurityMonitor.logSecurityEvent({
|
|
176
|
+
type: 'PORTFOLIO_FETCH_SUCCESS',
|
|
177
|
+
severity: 'LOW',
|
|
178
|
+
source: 'GitHubPortfolioIndexer.fetchFresh',
|
|
179
|
+
details: `Fetched GitHub portfolio with ${index.totalElements} elements in ${duration}ms`,
|
|
180
|
+
metadata: { username, duration, totalElements: index.totalElements }
|
|
181
|
+
});
|
|
182
|
+
return index;
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
const duration = Date.now() - startTime;
|
|
186
|
+
ErrorHandler.logError('GitHubPortfolioIndexer.fetchFresh', error, { duration });
|
|
187
|
+
throw ErrorHandler.wrapError(error, 'Failed to fetch GitHub portfolio index', ErrorCategory.NETWORK_ERROR);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Fetch repository content from GitHub API
|
|
192
|
+
*/
|
|
193
|
+
async fetchRepositoryContent(username, repository) {
|
|
194
|
+
// Try GraphQL first for better performance, fallback to REST
|
|
195
|
+
try {
|
|
196
|
+
return await this.fetchWithGraphQL(username, repository);
|
|
197
|
+
}
|
|
198
|
+
catch (graphqlError) {
|
|
199
|
+
logger.debug('GraphQL fetch failed, falling back to REST API', {
|
|
200
|
+
error: graphqlError instanceof Error ? graphqlError.message : String(graphqlError)
|
|
201
|
+
});
|
|
202
|
+
return await this.fetchWithREST(username, repository);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Fetch using GraphQL for better performance
|
|
207
|
+
*/
|
|
208
|
+
async fetchWithGraphQL(username, repository) {
|
|
209
|
+
const query = `
|
|
210
|
+
query GetPortfolioContent($owner: String!, $name: String!) {
|
|
211
|
+
repository(owner: $owner, name: $name) {
|
|
212
|
+
defaultBranchRef {
|
|
213
|
+
target {
|
|
214
|
+
... on Commit {
|
|
215
|
+
oid
|
|
216
|
+
history(first: 1) {
|
|
217
|
+
nodes {
|
|
218
|
+
committedDate
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
object(expression: "HEAD:") {
|
|
225
|
+
... on Tree {
|
|
226
|
+
entries {
|
|
227
|
+
name
|
|
228
|
+
type
|
|
229
|
+
object {
|
|
230
|
+
... on Tree {
|
|
231
|
+
entries {
|
|
232
|
+
name
|
|
233
|
+
type
|
|
234
|
+
oid
|
|
235
|
+
object {
|
|
236
|
+
... on Blob {
|
|
237
|
+
byteSize
|
|
238
|
+
text
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
rateLimit {
|
|
249
|
+
remaining
|
|
250
|
+
resetAt
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
`;
|
|
254
|
+
const variables = { owner: username, name: repository };
|
|
255
|
+
const response = await this.githubClient.fetchFromGitHub('https://api.github.com/graphql', true);
|
|
256
|
+
// Note: This is a simplified GraphQL implementation
|
|
257
|
+
// In a real implementation, you would send POST request with query and variables
|
|
258
|
+
throw new Error('GraphQL implementation not yet complete');
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Fetch using REST API with pagination
|
|
262
|
+
*/
|
|
263
|
+
async fetchWithREST(username, repository) {
|
|
264
|
+
const normalizedUsername = UnicodeValidator.normalize(username).normalizedContent;
|
|
265
|
+
// Get repository info and latest commit
|
|
266
|
+
const repoInfo = await this.githubClient.fetchFromGitHub(`https://api.github.com/repos/${normalizedUsername}/${repository}`);
|
|
267
|
+
const latestCommit = await this.githubClient.fetchFromGitHub(`https://api.github.com/repos/${normalizedUsername}/${repository}/commits/HEAD`);
|
|
268
|
+
// Initialize index
|
|
269
|
+
const index = {
|
|
270
|
+
username: normalizedUsername,
|
|
271
|
+
repository,
|
|
272
|
+
lastUpdated: new Date(latestCommit.commit.committer.date),
|
|
273
|
+
elements: new Map(),
|
|
274
|
+
totalElements: 0,
|
|
275
|
+
sha: latestCommit.sha
|
|
276
|
+
};
|
|
277
|
+
// Initialize element type maps
|
|
278
|
+
for (const elementType of Object.values(ElementType)) {
|
|
279
|
+
index.elements.set(elementType, []);
|
|
280
|
+
}
|
|
281
|
+
// Fetch content for each element type
|
|
282
|
+
for (const elementType of Object.values(ElementType)) {
|
|
283
|
+
try {
|
|
284
|
+
const entries = await this.fetchElementTypeContent(normalizedUsername, repository, elementType);
|
|
285
|
+
index.elements.set(elementType, entries);
|
|
286
|
+
index.totalElements += entries.length;
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
logger.warn(`Failed to fetch ${elementType} from GitHub portfolio`, {
|
|
290
|
+
error: error instanceof Error ? error.message : String(error)
|
|
291
|
+
});
|
|
292
|
+
// Continue with other element types
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return index;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Fetch content for a specific element type
|
|
299
|
+
*/
|
|
300
|
+
async fetchElementTypeContent(username, repository, elementType) {
|
|
301
|
+
try {
|
|
302
|
+
// Get directory listing
|
|
303
|
+
const contents = await this.githubClient.fetchFromGitHub(`https://api.github.com/repos/${username}/${repository}/contents/${elementType}`);
|
|
304
|
+
if (!Array.isArray(contents)) {
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
307
|
+
const entries = [];
|
|
308
|
+
const maxConcurrent = 5; // Limit concurrent requests
|
|
309
|
+
// Process files in batches to avoid rate limiting
|
|
310
|
+
for (let i = 0; i < contents.length; i += maxConcurrent) {
|
|
311
|
+
const batch = contents.slice(i, i + maxConcurrent);
|
|
312
|
+
const batchPromises = batch
|
|
313
|
+
.filter(item => item.type === 'file' && item.name.endsWith('.md'))
|
|
314
|
+
.map(item => this.createGitHubIndexEntry(username, repository, elementType, item));
|
|
315
|
+
const batchResults = await Promise.allSettled(batchPromises);
|
|
316
|
+
for (const result of batchResults) {
|
|
317
|
+
if (result.status === 'fulfilled' && result.value) {
|
|
318
|
+
entries.push(result.value);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
// Add delay between batches to respect rate limits
|
|
322
|
+
if (i + maxConcurrent < contents.length) {
|
|
323
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return entries;
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
// Directory might not exist
|
|
330
|
+
if (error instanceof Error && error.message.includes('404')) {
|
|
331
|
+
return [];
|
|
332
|
+
}
|
|
333
|
+
throw error;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Create GitHub index entry from API response
|
|
338
|
+
*/
|
|
339
|
+
async createGitHubIndexEntry(username, repository, elementType, fileInfo) {
|
|
340
|
+
try {
|
|
341
|
+
// Parse metadata from filename or fetch content if needed
|
|
342
|
+
const name = fileInfo.name.replace('.md', '').replace(/-/g, ' ');
|
|
343
|
+
const entry = {
|
|
344
|
+
path: fileInfo.path,
|
|
345
|
+
name,
|
|
346
|
+
elementType,
|
|
347
|
+
sha: fileInfo.sha,
|
|
348
|
+
htmlUrl: fileInfo.html_url,
|
|
349
|
+
downloadUrl: fileInfo.download_url,
|
|
350
|
+
lastModified: new Date(), // GitHub API doesn't provide file modification time directly
|
|
351
|
+
size: fileInfo.size || 0
|
|
352
|
+
};
|
|
353
|
+
// Optionally fetch content to extract metadata
|
|
354
|
+
// This is expensive, so only do it for small files or when specifically needed
|
|
355
|
+
if (fileInfo.size && fileInfo.size < 10000) { // Only for files < 10KB
|
|
356
|
+
try {
|
|
357
|
+
const content = await this.githubClient.fetchFromGitHub(fileInfo.download_url);
|
|
358
|
+
const metadata = this.parseMetadataFromContent(content);
|
|
359
|
+
if (metadata.name)
|
|
360
|
+
entry.name = metadata.name;
|
|
361
|
+
if (metadata.description)
|
|
362
|
+
entry.description = metadata.description;
|
|
363
|
+
if (metadata.version)
|
|
364
|
+
entry.version = metadata.version;
|
|
365
|
+
if (metadata.author)
|
|
366
|
+
entry.author = metadata.author;
|
|
367
|
+
}
|
|
368
|
+
catch (metadataError) {
|
|
369
|
+
// Non-critical error, continue without metadata
|
|
370
|
+
logger.debug('Failed to fetch metadata for file', {
|
|
371
|
+
path: fileInfo.path,
|
|
372
|
+
error: metadataError instanceof Error ? metadataError.message : String(metadataError)
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return entry;
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
logger.debug('Failed to create GitHub index entry', {
|
|
380
|
+
path: fileInfo.path,
|
|
381
|
+
error: error instanceof Error ? error.message : String(error)
|
|
382
|
+
});
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Parse metadata from file content (frontmatter)
|
|
388
|
+
*/
|
|
389
|
+
parseMetadataFromContent(content) {
|
|
390
|
+
const metadata = {};
|
|
391
|
+
// Simple frontmatter parsing (could use a proper YAML parser)
|
|
392
|
+
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
393
|
+
if (frontmatterMatch) {
|
|
394
|
+
const frontmatter = frontmatterMatch[1];
|
|
395
|
+
const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
|
|
396
|
+
if (nameMatch)
|
|
397
|
+
metadata.name = nameMatch[1].trim();
|
|
398
|
+
const descMatch = frontmatter.match(/^description:\s*(.+)$/m);
|
|
399
|
+
if (descMatch)
|
|
400
|
+
metadata.description = descMatch[1].trim();
|
|
401
|
+
const versionMatch = frontmatter.match(/^version:\s*(.+)$/m);
|
|
402
|
+
if (versionMatch)
|
|
403
|
+
metadata.version = versionMatch[1].trim();
|
|
404
|
+
const authorMatch = frontmatter.match(/^author:\s*(.+)$/m);
|
|
405
|
+
if (authorMatch)
|
|
406
|
+
metadata.author = authorMatch[1].trim();
|
|
407
|
+
}
|
|
408
|
+
return metadata;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Get GitHub username from authenticated token
|
|
412
|
+
*/
|
|
413
|
+
async getGitHubUsername() {
|
|
414
|
+
try {
|
|
415
|
+
const userInfo = await this.githubClient.fetchFromGitHub('https://api.github.com/user', true);
|
|
416
|
+
return userInfo.login;
|
|
417
|
+
}
|
|
418
|
+
catch (error) {
|
|
419
|
+
throw new Error('Failed to get GitHub username. Please ensure you are authenticated with GitHub.');
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Check if cache is valid
|
|
424
|
+
*/
|
|
425
|
+
isCacheValid() {
|
|
426
|
+
if (!this.cache || !this.lastFetch) {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
const age = Date.now() - this.lastFetch.getTime();
|
|
430
|
+
return age < this.ttl;
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Determine if we should fetch fresh data
|
|
434
|
+
*/
|
|
435
|
+
shouldFetchFresh() {
|
|
436
|
+
// Always fetch if no cache
|
|
437
|
+
if (!this.cache || !this.lastFetch) {
|
|
438
|
+
return true;
|
|
439
|
+
}
|
|
440
|
+
// Check for recent user actions
|
|
441
|
+
if (this.recentUserAction && this.actionTimestamp) {
|
|
442
|
+
const actionAge = Date.now() - this.actionTimestamp.getTime();
|
|
443
|
+
if (actionAge < this.actionGracePeriod) {
|
|
444
|
+
logger.debug('Fetching fresh due to recent user action', { actionAge });
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
447
|
+
else {
|
|
448
|
+
// Grace period expired, clear action flag
|
|
449
|
+
this.recentUserAction = false;
|
|
450
|
+
this.actionTimestamp = null;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
// Check TTL
|
|
454
|
+
return !this.isCacheValid();
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Create empty index when no portfolio exists
|
|
458
|
+
*/
|
|
459
|
+
createEmptyIndex(username, repository) {
|
|
460
|
+
const index = {
|
|
461
|
+
username: username || 'unknown',
|
|
462
|
+
repository: repository || 'dollhouse-portfolio',
|
|
463
|
+
lastUpdated: new Date(),
|
|
464
|
+
elements: new Map(),
|
|
465
|
+
totalElements: 0,
|
|
466
|
+
sha: ''
|
|
467
|
+
};
|
|
468
|
+
// Initialize empty element type maps
|
|
469
|
+
for (const elementType of Object.values(ElementType)) {
|
|
470
|
+
index.elements.set(elementType, []);
|
|
471
|
+
}
|
|
472
|
+
return index;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiR2l0SHViUG9ydGZvbGlvSW5kZXhlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wb3J0Zm9saW8vR2l0SHViUG9ydGZvbGlvSW5kZXhlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7OztHQVVHO0FBRUgsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzdELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRWpFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDekMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNqRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQUM5RSxPQUFPLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQW9DaEQsTUFBTSxPQUFPLHNCQUFzQjtJQUN6QixNQUFNLENBQUMsUUFBUSxHQUFrQyxJQUFJLENBQUM7SUFDdEQsTUFBTSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7SUFFNUIsS0FBSyxHQUFnQyxJQUFJLENBQUM7SUFDMUMsU0FBUyxHQUFnQixJQUFJLENBQUM7SUFDckIsR0FBRyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsYUFBYTtJQUM1QyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7SUFDekIsZUFBZSxHQUFnQixJQUFJLENBQUM7SUFDM0IsaUJBQWlCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyx5QkFBeUI7SUFFckUsWUFBWSxDQUFlO0lBQzNCLG9CQUFvQixDQUF1QjtJQUMzQyxRQUFRLENBQVc7SUFDbkIs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QUU7WUFDbkIsYUFBYSxFQUFFLENBQUM7WUFDaEIsR0FBRyxFQUFFLEVBQUU7U0FDUixDQUFDO1FBRUYscUNBQXFDO1FBQ3JDLEtBQUssTUFBTSxXQUFXLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1lBQ3JELEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN0QyxDQUFDO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBHaXRIdWIgUG9ydGZvbGlvIEluZGV4ZXIgLSBGZXRjaGVzIGFuZCBpbmRleGVzIHVzZXIncyBHaXRIdWIgcG9ydGZvbGlvIGZvciBmYXN0IHNlYXJjaGluZ1xuICogXG4gKiBGZWF0dXJlczpcbiAqIC0gU2luZ2xldG9uIHBhdHRlcm4gZm9yIGVmZmljaWVudCByZXNvdXJjZSB1c2FnZVxuICogLSBTbWFydCBjYWNoaW5nIHdpdGggVFRMIGFuZCBpbnZhbGlkYXRpb24gYWZ0ZXIgdXNlciBhY3Rpb25zXG4gKiAtIEdyYXBoUUwvUkVTVCBBUEkgaW50ZWdyYXRpb24gZm9yIGVmZmljaWVudCBmZXRjaGluZ1xuICogLSBSYXRlIGxpbWl0aW5nIGFuZCBhdXRoZW50aWNhdGlvbiBoYW5kbGluZ1xuICogLSBGYWxsYmFjayBzdHJhdGVneSBmb3IgcmVzaWxpZW50IG9wZXJhdGlvblxuICogLSBQZXJmb3JtYW5jZSBvcHRpbWl6ZWQgZm9yIDEwMDArIHBvcnRmb2xpbyBlbGVtZW50c1xuICovXG5cbmltcG9ydCB7IEdpdEh1YkNsaWVudCB9IGZyb20gJy4uL2NvbGxlY3Rpb24vR2l0SHViQ2xpZW50LmpzJztcbmltcG9ydCB7IFBvcnRmb2xpb1JlcG9NYW5hZ2VyIH0gZnJvbSAnLi9Qb3J0Zm9saW9SZXBvTWFuYWdlci5qcyc7XG5pbXBvcnQgeyBUb2tlbk1hbmFnZXIgfSBmcm9tICcuLi9zZWN1cml0eS90b2tlbk1hbmFnZXIuanMnO1xuaW1wb3J0IHsgRWxlbWVudFR5cGUgfSBmcm9tICcuL3R5cGVzLmpzJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBTZWN1cml0eU1vbml0b3IgfSBmcm9tICcuLi9zZWN1cml0eS9zZWN1cml0eU1vbml0b3IuanMnO1xuaW1wb3J0IHsgVW5pY29kZVZhbGlkYXRvciB9IGZyb20gJy4uL3NlY3VyaXR5L3ZhbGlkYXRvcnMvdW5pY29kZVZhbGlkYXRvci5qcyc7XG5pbXBvcnQgeyBFcnJvckhhbmRsZXIsIEVycm9yQ2F0ZWdvcnkgfSBmcm9tICcuLi91dGlscy9FcnJvckhhbmRsZXIuanMnO1xuaW1wb3J0IHsgQVBJQ2FjaGUgfSBmcm9tICcuLi9jYWNoZS9BUElDYWNoZS5qcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2l0SHViSW5kZXhFbnRyeSB7XG4gIHBhdGg6IHN0cmluZztcbiAgbmFtZTogc3RyaW5nO1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgdmVyc2lvbj86IHN0cmluZztcbiAgYXV0aG9yPzogc3RyaW5nO1xuICBlbGVtZW50VHlwZTogRWxlbWVudFR5cGU7XG4gIHNoYTogc3RyaW5nOyAvLyBGaWxlIFNIQSBmb3IgY2hhbmdlIGRldGVjdGlvblxuICBodG1sVXJsOiBzdHJpbmc7IC8vIExpbmsgdG8gR2l0SHViXG4gIGRvd25sb2FkVXJsOiBzdHJpbmc7XG4gIGxhc3RNb2RpZmllZDogRGF0ZTtcbiAgc2l6ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdpdEh1YlBvcnRmb2xpb0luZGV4IHtcbiAgdXNlcm5hbWU6IHN0cmluZztcbiAgcmVwb3NpdG9yeTogc3RyaW5nO1xuICBsYXN0VXBkYXRlZDogRGF0ZTtcbiAgZWxlbWVudHM6IE1hcDxFbGVtZW50VHlwZSwgR2l0SHViSW5kZXhFbnRyeVtdPjtcbiAgdG90YWxFbGVtZW50czogbnVtYmVyO1xuICBzaGE6IHN0cmluZzsgLy8gTGF0ZXN0IGNvbW1pdCBTSEFcbiAgcmF0ZUxpbWl0SW5mbz86IHtcbiAgICByZW1haW5pbmc6IG51bWJlcjtcbiAgICByZXNldFRpbWU6IERhdGU7XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR2l0SHViRmV0Y2hPcHRpb25zIHtcbiAgZm9yY2U/OiBib29sZWFuO1xuICBtYXhFbGVtZW50cz86IG51bWJlcjtcbiAgZWxlbWVudFR5cGVzPzogRWxlbWVudFR5cGVbXTtcbiAgdXNlR3JhcGhRTD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBjbGFzcyBHaXRIdWJQb3J0Zm9saW9JbmRleGVyIHtcbiAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2U6IEdpdEh1YlBvcnRmb2xpb0luZGV4ZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2VMb2NrID0gZmFsc2U7XG4gIFxuICBwcml2YXRlIGNhY2hlOiBHaXRIdWJQb3J0Zm9saW9JbmRleCB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGxhc3RGZXRjaDogRGF0ZSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IHR0bCA9IDE1ICogNjAgKiAxMDAwOyAvLyAxNSBtaW51dGVzXG4gIHByaXZhdGUgcmVjZW50VXNlckFjdGlvbiA9IGZhbHNlO1xuICBwcml2YXRlIGFjdGlvblRpbWVzdGFtcDogRGF0ZSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IGFjdGlvbkdyYWNlUGVyaW9kID0gMiAqIDYwICogMTAwMDsgLy8gMiBtaW51dGVzIGFmdGVyIGFjdGlvblxuICBcbiAgcHJpdmF0ZSBnaXRodWJDbGllbnQ6IEdpdEh1YkNsaWVudDtcbiAgcHJpdmF0ZSBwb3J0Zm9saW9SZXBvTWFuYWdlcjogUG9ydGZvbGlvUmVwb01hbmFnZXI7XG4gIHByaXZhdGUgYXBpQ2FjaGU6IEFQSUNhY2hlO1xuICBwcml2YXRlIHJhdGVMaW1pdFRyYWNrZXI6IE1hcDxzdHJpbmcsIG51bWJlcltdPjtcbiAgXG4gIHByaXZhdGUgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5hcGlDYWNoZSA9IG5ldyBBUElDYWNoZSgpOyAvLyBVc2VzIGRlZmF1bHQgc2V0dGluZ3NcbiAgICB0aGlzLnJhdGVMaW1pdFRyYWNrZXIgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5naXRodWJDbGllbnQgPSBuZXcgR2l0SHViQ2xpZW50KHRoaXMuYXBpQ2FjaGUsIHRoaXMucmF0ZUxpbWl0VHJhY2tlcik7XG4gICAgdGhpcy5wb3J0Zm9saW9SZXBvTWFuYWdlciA9IG5ldyBQb3J0Zm9saW9SZXBvTWFuYWdlcigpO1xuICAgIFxuICAgIGxvZ2dlci5kZWJ1ZygnR2l0SHViUG9ydGZvbGlvSW5kZXhlciBjcmVhdGVkJyk7XG4gIH1cblxuICAvKipcbiAgICogU2luZ2xldG9uIHBhdHRlcm4gd2l0aCB0aHJlYWQgc2FmZXR5XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGdldEluc3RhbmNlKCk6IEdpdEh1YlBvcnRmb2xpb0luZGV4ZXIge1xuICAgIGlmICghdGhpcy5pbnN0YW5jZSkge1xuICAgICAgaWYgKHRoaXMuaW5zdGFuY2VMb2NrKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignR2l0SHViUG9ydGZvbGlvSW5kZXhlciBpbnN0YW5jZSBpcyBiZWluZyBjcmVhdGVkIGJ5IGFub3RoZXIgdGhyZWFkJyk7XG4gICAgICB9XG4gICAgICBcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuaW5zdGFuY2VMb2NrID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5pbnN0YW5jZSA9IG5ldyBHaXRIdWJQb3J0Zm9saW9JbmRleGVyKCk7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB0aGlzLmluc3RhbmNlTG9jayA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5pbnN0YW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYWluIG1ldGhvZCB0byBnZXQgR2l0SHViIHBvcnRmb2xpbyBpbmRleFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGdldEluZGV4KGZvcmNlID0gZmFsc2UpOiBQcm9taXNlPEdpdEh1YlBvcnRmb2xpb0luZGV4PiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIENoZWNrIGlmIHdlIG5lZWQgZnJlc2ggZGF0YVxuICAgICAgaWYgKGZvcmNlIHx8IHRoaXMuc2hvdWxkRmV0Y2hGcmVzaCgpKSB7XG4gICAgICAgIHJldHVybiBhd2FpdCB0aGlzLmZldGNoRnJlc2goKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gUmV0dXJuIGNhY2hlZCBkYXRhIGlmIGF2YWlsYWJsZSBhbmQgdmFsaWRcbiAgICAgIGlmICh0aGlzLmNhY2hlICYmIHRoaXMuaXNDYWNoZVZhbGlkKCkpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdSZXR1cm5pbmcgY2FjaGVkIEdpdEh1YiBwb3J0Zm9saW8gaW5kZXgnLCB7XG4gICAgICAgICAgdXNlcm5hbWU6IHRoaXMuY2FjaGUudXNlcm5hbWUsXG4gICAgICAgICAgdG90YWxFbGVtZW50czogdGhpcy5jYWNoZS50b3RhbEVsZW1lbnRzLFxuICAgICAgICAgIGFnZTogdGhpcy5sYXN0RmV0Y2ggPyBEYXRlLm5vdygpIC0gdGhpcy5sYXN0RmV0Y2guZ2V0VGltZSgpIDogJ3Vua25vd24nXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdGhpcy5jYWNoZTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gVHJ5IHRvIGZldGNoIGZyZXNoLCBmYWxsIGJhY2sgdG8gc3RhbGUgY2FjaGUgb24gZmFpbHVyZVxuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZmV0Y2hGcmVzaCgpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ0ZhaWxlZCB0byBmZXRjaCBmcmVzaCBHaXRIdWIgcG9ydGZvbGlvIGluZGV4LCBjaGVja2luZyBmb3Igc3RhbGUgY2FjaGUnLCB7XG4gICAgICAgICAgZXJyb3I6IGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKVxuICAgICAgICB9KTtcbiAgICAgICAgXG4gICAgICAgIC8vIFJldHVybiBzdGFsZSBjYWNoZSBpZiBhdmFpbGFibGVcbiAgICAgICAgaWYgKHRoaXMuY2FjaGUpIHtcbiAgICAgICAgICBsb2dnZXIuaW5mbygnUmV0dXJuaW5nIHN0YWxlIEdpdEh1YiBwb3J0Zm9saW8gY2FjaGUgYXMgZmFsbGJhY2snLCB7XG4gICAgICAgICAgICB1c2VybmFtZTogdGhpcy5jYWNoZS51c2VybmFtZSxcbiAgICAgICAgICAgIGFnZTogdGhpcy5sYXN0RmV0Y2ggPyBEYXRlLm5vdygpIC0gdGhpcy5sYXN0RmV0Y2guZ2V0VGltZSgpIDogJ3Vua25vd24nXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuY2FjaGU7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIC8vIFJldHVybiBlbXB0eSBpbmRleCBhcyBsYXN0IHJlc29ydFxuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVFbXB0eUluZGV4KCk7XG4gICAgICB9XG4gICAgICBcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgRXJyb3JIYW5kbGVyLmxvZ0Vycm9yKCdHaXRIdWJQb3J0Zm9saW9JbmRleGVyLmdldEluZGV4JywgZXJyb3IpO1xuICAgICAgXG4gICAgICAvLyBSZXR1cm4gc3RhbGUgY2FjaGUgb3IgZW1wdHkgaW5kZXhcbiAgICAgIGlmICh0aGlzLmNhY2hlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhY2hlO1xuICAgICAgfVxuICAgICAgXG4gICAgICByZXR1cm4gdGhpcy5jcmVhdGVFbXB0eUluZGV4KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEludmFsaWRhdGUgY2FjaGUgYWZ0ZXIgdXNlciBhY3Rpb25zXG4gICAqL1xuICBwdWJsaWMgaW52YWxpZGF0ZUFmdGVyQWN0aW9uKGFjdGlvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgbG9nZ2VyLmluZm8oJ0ludmFsaWRhdGluZyBHaXRIdWIgcG9ydGZvbGlvIGNhY2hlIGFmdGVyIHVzZXIgYWN0aW9uJywgeyBhY3Rpb24gfSk7XG4gICAgXG4gICAgdGhpcy5yZWNlbnRVc2VyQWN0aW9uID0gdHJ1ZTtcbiAgICB0aGlzLmFjdGlvblRpbWVzdGFtcCA9IG5ldyBEYXRlKCk7XG4gICAgXG4gICAgLy8gTG9nIHNlY3VyaXR5IGV2ZW50IGZvciBhdWRpdCB0cmFpbFxuICAgIFNlY3VyaXR5TW9uaXRvci5sb2dTZWN1cml0eUV2ZW50KHtcbiAgICAgIHR5cGU6ICdQT1JURk9MSU9fQ0FDSEVfSU5WQUxJREFUSU9OJyxcbiAgICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICAgIHNvdXJjZTogJ0dpdEh1YlBvcnRmb2xpb0luZGV4ZXIuaW52YWxpZGF0ZUFmdGVyQWN0aW9uJyxcbiAgICAgIGRldGFpbHM6IGBDYWNoZSBpbnZhbGlkYXRlZCBhZnRlciB1c2VyIGFjdGlvbjogJHthY3Rpb259YCxcbiAgICAgIG1ldGFkYXRhOiB7IGFjdGlvbiB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgYWxsIGNhY2hlZCBkYXRhXG4gICAqL1xuICBwdWJsaWMgY2xlYXJDYWNoZSgpOiB2b2lkIHtcbiAgICB0aGlzLmNhY2hlID0gbnVsbDtcbiAgICB0aGlzLmxhc3RGZXRjaCA9IG51bGw7XG4gICAgdGhpcy5yZWNlbnRVc2VyQWN0aW9uID0gZmFsc2U7XG4gICAgdGhpcy5hY3Rpb25UaW1lc3RhbXAgPSBudWxsO1xuICAgIHRoaXMuYXBpQ2FjaGUuY2xlYXIoKTtcbiAgICBcbiAgICBsb2dnZXIuaW5mbygnR2l0SHViIHBvcnRmb2xpbyBjYWNoZSBjbGVhcmVkJyk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNhY2hlIHN0YXRpc3RpY3NcbiAgICovXG4gIHB1YmxpYyBnZXRDYWNoZVN0YXRzKCk6IHtcbiAgICBoYXNDYWNoZWREYXRhOiBib29sZWFuO1xuICAgIGxhc3RGZXRjaDogRGF0ZSB8IG51bGw7XG4gICAgaXNTdGFsZTogYm9vbGVhbjtcbiAgICByZWNlbnRVc2VyQWN0aW9uOiBib29sZWFuO1xuICAgIHRvdGFsRWxlbWVudHM6IG51bWJlcjtcbiAgfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGhhc0NhY2hlZERhdGE6IHRoaXMuY2FjaGUgIT09IG51bGwsXG4gICAgICBsYXN0RmV0Y2g6IHRoaXMubGFzdEZldGNoLFxuICAgICAgaXNTdGFsZTogIXRoaXMuaXNDYWNoZVZhbGlkKCksXG4gICAgICByZWNlbnRVc2VyQWN0aW9uOiB0aGlzLnJlY2VudFVzZXJBY3Rpb24sXG4gICAgICB0b3RhbEVsZW1lbnRzOiB0aGlzLmNhY2hlPy50b3RhbEVsZW1lbnRzIHx8IDBcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEZldGNoIGZyZXNoIGRhdGEgZnJvbSBHaXRIdWJcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hGcmVzaCgpOiBQcm9taXNlPEdpdEh1YlBvcnRmb2xpb0luZGV4PiB7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBsb2dnZXIuaW5mbygnRmV0Y2hpbmcgZnJlc2ggR2l0SHViIHBvcnRmb2xpbyBpbmRleC4uLicpO1xuICAgIFxuICAgIHRyeSB7XG4gICAgICAvLyBHZXQgR2l0SHViIHVzZXJuYW1lIGZyb20gdG9rZW5cbiAgICAgIGNvbnN0IHVzZXJuYW1lID0gYXdhaXQgdGhpcy5nZXRHaXRIdWJVc2VybmFtZSgpO1xuICAgICAgY29uc3QgcmVwb3NpdG9yeSA9ICdkb2xsaG91c2UtcG9ydGZvbGlvJztcbiAgICAgIFxuICAgICAgLy8gQ2hlY2sgaWYgcG9ydGZvbGlvIHJlcG9zaXRvcnkgZXhpc3RzXG4gICAgICBjb25zdCByZXBvRXhpc3RzID0gYXdhaXQgdGhpcy5wb3J0Zm9saW9SZXBvTWFuYWdlci5jaGVja1BvcnRmb2xpb0V4aXN0cyh1c2VybmFtZSk7XG4gICAgICBpZiAoIXJlcG9FeGlzdHMpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oJ0dpdEh1YiBwb3J0Zm9saW8gcmVwb3NpdG9yeSBkb2VzIG5vdCBleGlzdCcsIHsgdXNlcm5hbWUgfSk7XG4gICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUVtcHR5SW5kZXgodXNlcm5hbWUsIHJlcG9zaXRvcnkpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBGZXRjaCByZXBvc2l0b3J5IGNvbnRlbnQgdXNpbmcgR2l0SHViIEFQSVxuICAgICAgY29uc3QgaW5kZXggPSBhd2FpdCB0aGlzLmZldGNoUmVwb3NpdG9yeUNvbnRlbnQodXNlcm5hbWUsIHJlcG9zaXRvcnkpO1xuICAgICAgXG4gICAgICAvLyBVcGRhdGUgY2FjaGVcbiAgICAgIHRoaXMuY2FjaGUgPSBpbmRleDtcbiAgICAgIHRoaXMubGFzdEZldGNoID0gbmV3IERhdGUoKTtcbiAgICAgIHRoaXMucmVjZW50VXNlckFjdGlvbiA9IGZhbHNlO1xuICAgICAgdGhpcy5hY3Rpb25UaW1lc3RhbXAgPSBudWxsO1xuICAgICAgXG4gICAgICBjb25zdCBkdXJhdGlvbiA9IERhdGUubm93KCkgLSBzdGFydFRpbWU7XG4gICAgICBsb2dnZXIuaW5mbygnR2l0SHViIHBvcnRmb2xpbyBpbmRleCBmZXRjaGVkIHN1Y2Nlc3NmdWxseScsIHtcbiAgICAgICAgdXNlcm5hbWUsXG4gICAgICAgIHRvdGFsRWxlbWVudHM6IGluZGV4LnRvdGFsRWxlbWVudHMsXG4gICAgICAgIGR1cmF0aW9uOiBgJHtkdXJhdGlvbn1tc2AsXG4gICAgICAgIHJhdGVMaW1pdFJlbWFpbmluZzogaW5kZXgucmF0ZUxpbWl0SW5mbz8ucmVtYWluaW5nXG4gICAgICB9KTtcbiAgICAgIFxuICAgICAgLy8gTG9nIHNlY3VyaXR5IGV2ZW50XG4gICAgICBTZWN1cml0eU1vbml0b3IubG9nU2VjdXJpdHlFdmVudCh7XG4gICAgICAgIHR5cGU6ICdQT1JURk9MSU9fRkVUQ0hfU1VDQ0VTUycsXG4gICAgICAgIHNldmVyaXR5OiAnTE9XJyxcbiAgICAgICAgc291cmNlOiAnR2l0SHViUG9ydGZvbGlvSW5kZXhlci5mZXRjaEZyZXNoJyxcbiAgICAgICAgZGV0YWlsczogYEZldGNoZWQgR2l0SHViIHBvcnRmb2xpbyB3aXRoICR7aW5kZXgudG90YWxFbGVtZW50c30gZWxlbWVudHMgaW4gJHtkdXJhdGlvbn1tc2AsXG4gICAgICAgIG1ldGFkYXRhOiB7IHVzZXJuYW1lLCBkdXJhdGlvbiwgdG90YWxFbGVtZW50czogaW5kZXgudG90YWxFbGVtZW50cyB9XG4gICAgICB9KTtcbiAgICAgIFxuICAgICAgcmV0dXJuIGluZGV4O1xuICAgICAgXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IGR1cmF0aW9uID0gRGF0ZS5ub3coKSAtIHN0YXJ0VGltZTtcbiAgICAgIEVycm9ySGFuZGxlci5sb2dFcnJvcignR2l0SHViUG9ydGZvbGlvSW5kZXhlci5mZXRjaEZyZXNoJywgZXJyb3IsIHsgZHVyYXRpb24gfSk7XG4gICAgICB0aHJvdyBFcnJvckhhbmRsZXIud3JhcEVycm9yKGVycm9yLCAnRmFpbGVkIHRvIGZldGNoIEdpdEh1YiBwb3J0Zm9saW8gaW5kZXgnLCBFcnJvckNhdGVnb3J5Lk5FVFdPUktfRVJST1IpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaCByZXBvc2l0b3J5IGNvbnRlbnQgZnJvbSBHaXRIdWIgQVBJXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGZldGNoUmVwb3NpdG9yeUNvbnRlbnQodXNlcm5hbWU6IHN0cmluZywgcmVwb3NpdG9yeTogc3RyaW5nKTogUHJvbWlzZTxHaXRIdWJQb3J0Zm9saW9JbmRleD4ge1xuICAgIC8vIFRyeSBHcmFwaFFMIGZpcnN0IGZvciBiZXR0ZXIgcGVyZm9ybWFuY2UsIGZhbGxiYWNrIHRvIFJFU1RcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuZmV0Y2hXaXRoR3JhcGhRTCh1c2VybmFtZSwgcmVwb3NpdG9yeSk7XG4gICAgfSBjYXRjaCAoZ3JhcGhxbEVycm9yKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0dyYXBoUUwgZmV0Y2ggZmFpbGVkLCBmYWxsaW5nIGJhY2sgdG8gUkVTVCBBUEknLCB7XG4gICAgICAgIGVycm9yOiBncmFwaHFsRXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGdyYXBocWxFcnJvci5tZXNzYWdlIDogU3RyaW5nKGdyYXBocWxFcnJvcilcbiAgICAgIH0pO1xuICAgICAgXG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5mZXRjaFdpdGhSRVNUKHVzZXJuYW1lLCByZXBvc2l0b3J5KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2ggdXNpbmcgR3JhcGhRTCBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGZldGNoV2l0aEdyYXBoUUwodXNlcm5hbWU6IHN0cmluZywgcmVwb3NpdG9yeTogc3RyaW5nKTogUHJvbWlzZTxHaXRIdWJQb3J0Zm9saW9JbmRleD4ge1xuICAgIGNvbnN0IHF1ZXJ5ID0gYFxuICAgICAgcXVlcnkgR2V0UG9ydGZvbGlvQ29udGVudCgkb3duZXI6IFN0cmluZyEsICRuYW1lOiBTdHJpbmchKSB7XG4gICAgICAgIHJlcG9zaXRvcnkob3duZXI6ICRvd25lciwgbmFtZTogJG5hbWUpIHtcbiAgICAgICAgICBkZWZhdWx0QnJhbmNoUmVmIHtcbiAgICAgICAgICAgIHRhcmdldCB7XG4gICAgICAgICAgICAgIC4uLiBvbiBDb21taXQge1xuICAgICAgICAgICAgICAgIG9pZFxuICAgICAgICAgICAgICAgIGhpc3RvcnkoZmlyc3Q6IDEpIHtcbiAgICAgICAgICAgICAgICAgIG5vZGVzIHtcbiAgICAgICAgICAgICAgICAgICAgY29tbWl0dGVkRGF0ZVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBvYmplY3QoZXhwcmVzc2lvbjogXCJIRUFEOlwiKSB7XG4gICAgICAgICAgICAuLi4gb24gVHJlZSB7XG4gICAgICAgICAgICAgIGVudHJpZXMge1xuICAgICAgICAgICAgICAgIG5hbWVcbiAgICAgICAgICAgICAgICB0eXBlXG4gICAgICAgICAgICAgICAgb2JqZWN0IHtcbiAgICAgICAgICAgICAgICAgIC4uLiBvbiBUcmVlIHtcbiAgICAgICAgICAgICAgICAgICAgZW50cmllcyB7XG4gICAgICAgICAgICAgICAgICAgICAgbmFtZVxuICAgICAgICAgICAgICAgICAgICAgIHR5cGVcbiAgICAgICAgICAgICAgICAgICAgICBvaWRcbiAgICAgICAgICAgICAgICAgICAgICBvYmplY3Qge1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4uIG9uIEJsb2Ige1xuICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlU2l6ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICB0ZXh0XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJhdGVMaW1pdCB7XG4gICAgICAgICAgcmVtYWluaW5nXG4gICAgICAgICAgcmVzZXRBdFxuICAgICAgICB9XG4gICAgICB9XG4gICAgYDtcbiAgICBcbiAgICBjb25zdCB2YXJpYWJsZXMgPSB7IG93bmVyOiB1c2VybmFtZSwgbmFtZTogcmVwb3NpdG9yeSB9O1xuICAgIFxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5naXRodWJDbGllbnQuZmV0Y2hGcm9tR2l0SHViKCdodHRwczovL2FwaS5naXRodWIuY29tL2dyYXBocWwnLCB0cnVlKTtcbiAgICBcbiAgICAvLyBOb3RlOiBUaGlzIGlzIGEgc2ltcGxpZmllZCBHcmFwaFFMIGltcGxlbWVudGF0aW9uXG4gICAgLy8gSW4gYSByZWFsIGltcGxlbWVudGF0aW9uLCB5b3Ugd291bGQgc2VuZCBQT1NUIHJlcXVlc3Qgd2l0aCBxdWVyeSBhbmQgdmFyaWFibGVzXG4gICAgdGhyb3cgbmV3IEVycm9yKCdHcmFwaFFMIGltcGxlbWVudGF0aW9uIG5vdCB5ZXQgY29tcGxldGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGZXRjaCB1c2luZyBSRVNUIEFQSSB3aXRoIHBhZ2luYXRpb25cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hXaXRoUkVTVCh1c2VybmFtZTogc3RyaW5nLCByZXBvc2l0b3J5OiBzdHJpbmcpOiBQcm9taXNlPEdpdEh1YlBvcnRmb2xpb0luZGV4PiB7XG4gICAgY29uc3Qgbm9ybWFsaXplZFVzZXJuYW1lID0gVW5pY29kZVZhbGlkYXRvci5ub3JtYWxpemUodXNlcm5hbWUpLm5vcm1hbGl6ZWRDb250ZW50O1xuICAgIFxuICAgIC8vIEdldCByZXBvc2l0b3J5IGluZm8gYW5kIGxhdGVzdCBjb21taXRcbiAgICBjb25zdCByZXBvSW5mbyA9IGF3YWl0IHRoaXMuZ2l0aHViQ2xpZW50LmZldGNoRnJvbUdpdEh1YihcbiAgICAgIGBodHRwczovL2FwaS5naXRodWIuY29tL3JlcG9zLyR7bm9ybWFsaXplZFVzZXJuYW1lfS8ke3JlcG9zaXRvcnl9YFxuICAgICk7XG4gICAgXG4gICAgY29uc3QgbGF0ZXN0Q29tbWl0ID0gYXdhaXQgdGhpcy5naXRodWJDbGllbnQuZmV0Y2hGcm9tR2l0SHViKFxuICAgICAgYGh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vcmVwb3MvJHtub3JtYWxpemVkVXNlcm5hbWV9LyR7cmVwb3NpdG9yeX0vY29tbWl0cy9IRUFEYFxuICAgICk7XG4gICAgXG4gICAgLy8gSW5pdGlhbGl6ZSBpbmRleFxuICAgIGNvbnN0IGluZGV4OiBHaXRIdWJQb3J0Zm9saW9JbmRleCA9IHtcbiAgICAgIHVzZXJuYW1lOiBub3JtYWxpemVkVXNlcm5hbWUsXG4gICAgICByZXBvc2l0b3J5LFxuICAgICAgbGFzdFVwZGF0ZWQ6IG5ldyBEYXRlKGxhdGVzdENvbW1pdC5jb21taXQuY29tbWl0dGVyLmRhdGUpLFxuICAgICAgZWxlbWVudHM6IG5ldyBNYXAoKSxcbiAgICAgIHRvdGFsRWxlbWVudHM6IDAsXG4gICAgICBzaGE6IGxhdGVzdENvbW1pdC5zaGFcbiAgICB9O1xuICAgIFxuICAgIC8vIEluaXRpYWxpemUgZWxlbWVudCB0eXBlIG1hcHNcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnRUeXBlIG9mIE9iamVjdC52YWx1ZXMoRWxlbWVudFR5cGUpKSB7XG4gICAgICBpbmRleC5lbGVtZW50cy5zZXQoZWxlbWVudFR5cGUsIFtdKTtcbiAgICB9XG4gICAgXG4gICAgLy8gRmV0Y2ggY29udGVudCBmb3IgZWFjaCBlbGVtZW50IHR5cGVcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnRUeXBlIG9mIE9iamVjdC52YWx1ZXMoRWxlbWVudFR5cGUpKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBlbnRyaWVzID0gYXdhaXQgdGhpcy5mZXRjaEVsZW1lbnRUeXBlQ29udGVudChub3JtYWxpemVkVXNlcm5hbWUsIHJlcG9zaXRvcnksIGVsZW1lbnRUeXBlKTtcbiAgICAgICAgaW5kZXguZWxlbWVudHMuc2V0KGVsZW1lbnRUeXBlLCBlbnRyaWVzKTtcbiAgICAgICAgaW5kZXgudG90YWxFbGVtZW50cyArPSBlbnRyaWVzLmxlbmd0aDtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKGBGYWlsZWQgdG8gZmV0Y2ggJHtlbGVtZW50VHlwZX0gZnJvbSBHaXRIdWIgcG9ydGZvbGlvYCwge1xuICAgICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIENvbnRpbnVlIHdpdGggb3RoZXIgZWxlbWVudCB0eXBlc1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICByZXR1cm4gaW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogRmV0Y2ggY29udGVudCBmb3IgYSBzcGVjaWZpYyBlbGVtZW50IHR5cGVcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hFbGVtZW50VHlwZUNvbnRlbnQoXG4gICAgdXNlcm5hbWU6IHN0cmluZyxcbiAgICByZXBvc2l0b3J5OiBzdHJpbmcsXG4gICAgZWxlbWVudFR5cGU6IEVsZW1lbnRUeXBlXG4gICk6IFByb21pc2U8R2l0SHViSW5kZXhFbnRyeVtdPiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vIEdldCBkaXJlY3RvcnkgbGlzdGluZ1xuICAgICAgY29uc3QgY29udGVudHMgPSBhd2FpdCB0aGlzLmdpdGh1YkNsaWVudC5mZXRjaEZyb21HaXRIdWIoXG4gICAgICAgIGBodHRwczovL2FwaS5naXRodWIuY29tL3JlcG9zLyR7dXNlcm5hbWV9LyR7cmVwb3NpdG9yeX0vY29udGVudHMvJHtlbGVtZW50VHlwZX1gXG4gICAgICApO1xuICAgICAgXG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkoY29udGVudHMpKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgY29uc3QgZW50cmllczogR2l0SHViSW5kZXhFbnRyeVtdID0gW107XG4gICAgICBjb25zdCBtYXhDb25jdXJyZW50ID0gNTsgLy8gTGltaXQgY29uY3VycmVudCByZXF1ZXN0c1xuICAgICAgXG4gICAgICAvLyBQcm9jZXNzIGZpbGVzIGluIGJhdGNoZXMgdG8gYXZvaWQgcmF0ZSBsaW1pdGluZ1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb250ZW50cy5sZW5ndGg7IGkgKz0gbWF4Q29uY3VycmVudCkge1xuICAgICAgICBjb25zdCBiYXRjaCA9IGNvbnRlbnRzLnNsaWNlKGksIGkgKyBtYXhDb25jdXJyZW50KTtcbiAgICAgICAgY29uc3QgYmF0Y2hQcm9taXNlcyA9IGJhdGNoXG4gICAgICAgICAgLmZpbHRlcihpdGVtID0+IGl0ZW0udHlwZSA9PT0gJ2ZpbGUnICYmIGl0ZW0ubmFtZS5lbmRzV2l0aCgnLm1kJykpXG4gICAgICAgICAgLm1hcChpdGVtID0+IHRoaXMuY3JlYXRlR2l0SHViSW5kZXhFbnRyeSh1c2VybmFtZSwgcmVwb3NpdG9yeSwgZWxlbWVudFR5cGUsIGl0ZW0pKTtcbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGJhdGNoUmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsU2V0dGxlZChiYXRjaFByb21pc2VzKTtcbiAgICAgICAgXG4gICAgICAgIGZvciAoY29uc3QgcmVzdWx0IG9mIGJhdGNoUmVzdWx0cykge1xuICAgICAgICAgIGlmIChyZXN1bHQuc3RhdHVzID09PSAnZnVsZmlsbGVkJyAmJiByZXN1bHQudmFsdWUpIHtcbiAgICAgICAgICAgIGVudHJpZXMucHVzaChyZXN1bHQudmFsdWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gQWRkIGRlbGF5IGJldHdlZW4gYmF0Y2hlcyB0byByZXNwZWN0IHJhdGUgbGltaXRzXG4gICAgICAgIGlmIChpICsgbWF4Q29uY3VycmVudCA8IGNvbnRlbnRzLmxlbmd0aCkge1xuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCAxMDApKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgXG4gICAgICByZXR1cm4gZW50cmllcztcbiAgICAgIFxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBEaXJlY3RvcnkgbWlnaHQgbm90IGV4aXN0XG4gICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvciAmJiBlcnJvci5tZXNzYWdlLmluY2x1ZGVzKCc0MDQnKSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIEdpdEh1YiBpbmRleCBlbnRyeSBmcm9tIEFQSSByZXNwb25zZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjcmVhdGVHaXRIdWJJbmRleEVudHJ5KFxuICAgIHVzZXJuYW1lOiBzdHJpbmcsXG4gICAgcmVwb3NpdG9yeTogc3RyaW5nLFxuICAgIGVsZW1lbnRUeXBlOiBFbGVtZW50VHlwZSxcbiAgICBmaWxlSW5mbzogYW55XG4gICk6IFByb21pc2U8R2l0SHViSW5kZXhFbnRyeSB8IG51bGw+IHtcbiAgICB0cnkge1xuICAgICAgLy8gUGFyc2UgbWV0YWRhdGEgZnJvbSBmaWxlbmFtZSBvciBmZXRjaCBjb250ZW50IGlmIG5lZWRlZFxuICAgICAgY29uc3QgbmFtZSA9IGZpbGVJbmZvLm5hbWUucmVwbGFjZSgnLm1kJywgJycpLnJlcGxhY2UoLy0vZywgJyAnKTtcbiAgICAgIFxuICAgICAgY29uc3QgZW50cnk6IEdpdEh1YkluZGV4RW50cnkgPSB7XG4gICAgICAgIHBhdGg6IGZpbGVJbmZvLnBhdGgsXG4gICAgICAgIG5hbWUsXG4gICAgICAgIGVsZW1lbnRUeXBlLFxuICAgICAgICBzaGE6IGZpbGVJbmZvLnNoYSxcbiAgICAgICAgaHRtbFVybDogZmlsZUluZm8uaHRtbF91cmwsXG4gICAgICAgIGRvd25sb2FkVXJsOiBmaWxlSW5mby5kb3dubG9hZF91cmwsXG4gICAgICAgIGxhc3RNb2RpZmllZDogbmV3IERhdGUoKSwgLy8gR2l0SHViIEFQSSBkb2Vzbid0IHByb3ZpZGUgZmlsZSBtb2RpZmljYXRpb24gdGltZSBkaXJlY3RseVxuICAgICAgICBzaXplOiBmaWxlSW5mby5zaXplIHx8IDBcbiAgICAgIH07XG4gICAgICBcbiAgICAgIC8vIE9wdGlvbmFsbHkgZmV0Y2ggY29udGVudCB0byBleHRyYWN0IG1ldGFkYXRhXG4gICAgICAvLyBUaGlzIGlzIGV4cGVuc2l2ZSwgc28gb25seSBkbyBpdCBmb3Igc21hbGwgZmlsZXMgb3Igd2hlbiBzcGVjaWZpY2FsbHkgbmVlZGVkXG4gICAgICBpZiAoZmlsZUluZm8uc2l6ZSAmJiBmaWxlSW5mby5zaXplIDwgMTAwMDApIHsgLy8gT25seSBmb3IgZmlsZXMgPCAxMEtCXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgY29udGVudCA9IGF3YWl0IHRoaXMuZ2l0aHViQ2xpZW50LmZldGNoRnJvbUdpdEh1YihmaWxlSW5mby5kb3dubG9hZF91cmwpO1xuICAgICAgICAgIGNvbnN0IG1ldGFkYXRhID0gdGhpcy5wYXJzZU1ldGFkYXRhRnJvbUNvbnRlbnQoY29udGVudCk7XG4gICAgICAgICAgXG4gICAgICAgICAgaWYgKG1ldGFkYXRhLm5hbWUpIGVudHJ5Lm5hbWUgPSBtZXRhZGF0YS5uYW1lO1xuICAgICAgICAgIGlmIChtZXRhZGF0YS5kZXNjcmlwdGlvbikgZW50cnkuZGVzY3JpcHRpb24gPSBtZXRhZGF0YS5kZXNjcmlwdGlvbjtcbiAgICAgICAgICBpZiAobWV0YWRhdGEudmVyc2lvbikgZW50cnkudmVyc2lvbiA9IG1ldGFkYXRhLnZlcnNpb247XG4gICAgICAgICAgaWYgKG1ldGFkYXRhLmF1dGhvcikgZW50cnkuYXV0aG9yID0gbWV0YWRhdGEuYXV0aG9yO1xuICAgICAgICB9IGNhdGNoIChtZXRhZGF0YUVycm9yKSB7XG4gICAgICAgICAgLy8gTm9uLWNyaXRpY2FsIGVycm9yLCBjb250aW51ZSB3aXRob3V0IG1ldGFkYXRhXG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKCdGYWlsZWQgdG8gZmV0Y2ggbWV0YWRhdGEgZm9yIGZpbGUnLCB7XG4gICAgICAgICAgICBwYXRoOiBmaWxlSW5mby5wYXRoLFxuICAgICAgICAgICAgZXJyb3I6IG1ldGFkYXRhRXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IG1ldGFkYXRhRXJyb3IubWVzc2FnZSA6IFN0cmluZyhtZXRhZGF0YUVycm9yKVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBcbiAgICAgIHJldHVybiBlbnRyeTtcbiAgICAgIFxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBsb2dnZXIuZGVidWcoJ0ZhaWxlZCB0byBjcmVhdGUgR2l0SHViIGluZGV4IGVudHJ5Jywge1xuICAgICAgICBwYXRoOiBmaWxlSW5mby5wYXRoLFxuICAgICAgICBlcnJvcjogZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQYXJzZSBtZXRhZGF0YSBmcm9tIGZpbGUgY29udGVudCAoZnJvbnRtYXR0ZXIpXG4gICAqL1xuICBwcml2YXRlIHBhcnNlTWV0YWRhdGFGcm9tQ29udGVudChjb250ZW50OiBzdHJpbmcpOiB7XG4gICAgbmFtZT86IHN0cmluZztcbiAgICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgICB2ZXJzaW9uPzogc3RyaW5nO1xuICAgIGF1dGhvcj86IHN0cmluZztcbiAgfSB7XG4gICAgY29uc3QgbWV0YWRhdGE6IGFueSA9IHt9O1xuICAgIFxuICAgIC8vIFNpbXBsZSBmcm9udG1hdHRlciBwYXJzaW5nIChjb3VsZCB1c2UgYSBwcm9wZXIgWUFNTCBwYXJzZXIpXG4gICAgY29uc3QgZnJvbnRtYXR0ZXJNYXRjaCA9IGNvbnRlbnQubWF0Y2goL14tLS1cXG4oW1xcc1xcU10qPylcXG4tLS0vKTtcbiAgICBpZiAoZnJvbnRtYXR0ZXJNYXRjaCkge1xuICAgICAgY29uc3QgZnJvbnRtYXR0ZXIgPSBmcm9udG1hdHRlck1hdGNoWzFdO1xuICAgICAgXG4gICAgICBjb25zdCBuYW1lTWF0Y2ggPSBmcm9udG1hdHRlci5tYXRjaCgvXm5hbWU6XFxzKiguKykkL20pO1xuICAgICAgaWYgKG5hbWVNYXRjaCkgbWV0YWRhdGEubmFtZSA9IG5hbWVNYXRjaFsxXS50cmltKCk7XG4gICAgICBcbiAgICAgIGNvbnN0IGRlc2NNYXRjaCA9IGZyb250bWF0dGVyLm1hdGNoKC9eZGVzY3JpcHRpb246XFxzKiguKykkL20pO1xuICAgICAgaWYgKGRlc2NNYXRjaCkgbWV0YWRhdGEuZGVzY3JpcHRpb24gPSBkZXNjTWF0Y2hbMV0udHJpbSgpO1xuICAgICAgXG4gICAgICBjb25zdCB2ZXJzaW9uTWF0Y2ggPSBmcm9udG1hdHRlci5tYXRjaCgvXnZlcnNpb246XFxzKiguKykkL20pO1xuICAgICAgaWYgKHZlcnNpb25NYXRjaCkgbWV0YWRhdGEudmVyc2lvbiA9IHZlcnNpb25NYXRjaFsxXS50cmltKCk7XG4gICAgICBcbiAgICAgIGNvbnN0IGF1dGhvck1hdGNoID0gZnJvbnRtYXR0ZXIubWF0Y2goL15hdXRob3I6XFxzKiguKykkL20pO1xuICAgICAgaWYgKGF1dGhvck1hdGNoKSBtZXRhZGF0YS5hdXRob3IgPSBhdXRob3JNYXRjaFsxXS50cmltKCk7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBtZXRhZGF0YTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgR2l0SHViIHVzZXJuYW1lIGZyb20gYXV0aGVudGljYXRlZCB0b2tlblxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBnZXRHaXRIdWJVc2VybmFtZSgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB1c2VySW5mbyA9IGF3YWl0IHRoaXMuZ2l0aHViQ2xpZW50LmZldGNoRnJvbUdpdEh1YignaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2VyJywgdHJ1ZSk7XG4gICAgICByZXR1cm4gdXNlckluZm8ubG9naW47XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRmFpbGVkIHRvIGdldCBHaXRIdWIgdXNlcm5hbWUuIFBsZWFzZSBlbnN1cmUgeW91IGFyZSBhdXRoZW50aWNhdGVkIHdpdGggR2l0SHViLicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBjYWNoZSBpcyB2YWxpZFxuICAgKi9cbiAgcHJpdmF0ZSBpc0NhY2hlVmFsaWQoKTogYm9vbGVhbiB7XG4gICAgaWYgKCF0aGlzLmNhY2hlIHx8ICF0aGlzLmxhc3RGZXRjaCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBcbiAgICBjb25zdCBhZ2UgPSBEYXRlLm5vdygpIC0gdGhpcy5sYXN0RmV0Y2guZ2V0VGltZSgpO1xuICAgIHJldHVybiBhZ2UgPCB0aGlzLnR0bDtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmUgaWYgd2Ugc2hvdWxkIGZldGNoIGZyZXNoIGRhdGFcbiAgICovXG4gIHByaXZhdGUgc2hvdWxkRmV0Y2hGcmVzaCgpOiBib29sZWFuIHtcbiAgICAvLyBBbHdheXMgZmV0Y2ggaWYgbm8gY2FjaGVcbiAgICBpZiAoIXRoaXMuY2FjaGUgfHwgIXRoaXMubGFzdEZldGNoKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgXG4gICAgLy8gQ2hlY2sgZm9yIHJlY2VudCB1c2VyIGFjdGlvbnNcbiAgICBpZiAodGhpcy5yZWNlbnRVc2VyQWN0aW9uICYmIHRoaXMuYWN0aW9uVGltZXN0YW1wKSB7XG4gICAgICBjb25zdCBhY3Rpb25BZ2UgPSBEYXRlLm5vdygpIC0gdGhpcy5hY3Rpb25UaW1lc3RhbXAuZ2V0VGltZSgpO1xuICAgICAgaWYgKGFjdGlvbkFnZSA8IHRoaXMuYWN0aW9uR3JhY2VQZXJpb2QpIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdGZXRjaGluZyBmcmVzaCBkdWUgdG8gcmVjZW50IHVzZXIgYWN0aW9uJywgeyBhY3Rpb25BZ2UgfSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gR3JhY2UgcGVyaW9kIGV4cGlyZWQsIGNsZWFyIGFjdGlvbiBmbGFnXG4gICAgICAgIHRoaXMucmVjZW50VXNlckFjdGlvbiA9IGZhbHNlO1xuICAgICAgICB0aGlzLmFjdGlvblRpbWVzdGFtcCA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIC8vIENoZWNrIFRUTFxuICAgIHJldHVybiAhdGhpcy5pc0NhY2hlVmFsaWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgZW1wdHkgaW5kZXggd2hlbiBubyBwb3J0Zm9saW8gZXhpc3RzXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZUVtcHR5SW5kZXgodXNlcm5hbWU/OiBzdHJpbmcsIHJlcG9zaXRvcnk/OiBzdHJpbmcpOiBHaXRIdWJQb3J0Zm9saW9JbmRleCB7XG4gICAgY29uc3QgaW5kZXg6IEdpdEh1YlBvcnRmb2xpb0luZGV4ID0ge1xuICAgICAgdXNlcm5hbWU6IHVzZXJuYW1lIHx8ICd1bmtub3duJyxcbiAgICAgIHJlcG9zaXRvcnk6IHJlcG9zaXRvcnkgfHwgJ2RvbGxob3VzZS1wb3J0Zm9saW8nLFxuICAgICAgbGFzdFVwZGF0ZWQ6IG5ldyBEYXRlKCksXG4gICAgICBlbGVtZW50czogbmV3IE1hcCgpLFxuICAgICAgdG90YWxFbGVtZW50czogMCxcbiAgICAgIHNoYTogJydcbiAgICB9O1xuICAgIFxuICAgIC8vIEluaXRpYWxpemUgZW1wdHkgZWxlbWVudCB0eXBlIG1hcHNcbiAgICBmb3IgKGNvbnN0IGVsZW1lbnRUeXBlIG9mIE9iamVjdC52YWx1ZXMoRWxlbWVudFR5cGUpKSB7XG4gICAgICBpbmRleC5lbGVtZW50cy5zZXQoZWxlbWVudFR5cGUsIFtdKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG59Il19
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MigrationManager.d.ts","sourceRoot":"","sources":["../../src/portfolio/MigrationManager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"MigrationManager.d.ts","sourceRoot":"","sources":["../../src/portfolio/MigrationManager.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAOzC,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,gBAAgB,CAAmB;gBAE/B,gBAAgB,EAAE,gBAAgB;IAI9C;;OAEG;IACU,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAQ/C;;OAEG;IACU,OAAO,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,eAAe,CAAC;IA8I9E;;OAEG;YACW,cAAc;IA6F5B;;OAEG;YACW,YAAY;IAwC1B;;OAEG;IACU,kBAAkB,IAAI,OAAO,CAAC;QACzC,iBAAiB,EAAE,OAAO,CAAC;QAC3B,kBAAkB,EAAE,MAAM,CAAC;QAC3B,eAAe,EAAE,OAAO,CAAC;QACzB,cAAc,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;KAC7C,CAAC;CAsBH"}
|