@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,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized error handling utilities for consistent error processing
|
|
3
|
+
* Preserves stack traces and provides user-friendly messages
|
|
4
|
+
*/
|
|
5
|
+
import { logger } from './logger.js';
|
|
6
|
+
/**
|
|
7
|
+
* Error categories for better error handling
|
|
8
|
+
*/
|
|
9
|
+
export var ErrorCategory;
|
|
10
|
+
(function (ErrorCategory) {
|
|
11
|
+
ErrorCategory["USER_ERROR"] = "USER_ERROR";
|
|
12
|
+
ErrorCategory["SYSTEM_ERROR"] = "SYSTEM_ERROR";
|
|
13
|
+
ErrorCategory["NETWORK_ERROR"] = "NETWORK_ERROR";
|
|
14
|
+
ErrorCategory["AUTH_ERROR"] = "AUTH_ERROR";
|
|
15
|
+
ErrorCategory["VALIDATION_ERROR"] = "VALIDATION_ERROR"; // Validation failures
|
|
16
|
+
})(ErrorCategory || (ErrorCategory = {}));
|
|
17
|
+
/**
|
|
18
|
+
* Custom error class with additional context
|
|
19
|
+
*/
|
|
20
|
+
export class ApplicationError extends Error {
|
|
21
|
+
category;
|
|
22
|
+
code;
|
|
23
|
+
details;
|
|
24
|
+
originalError;
|
|
25
|
+
constructor(message, category = ErrorCategory.SYSTEM_ERROR, code, details, originalError) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'ApplicationError';
|
|
28
|
+
this.category = category;
|
|
29
|
+
this.code = code;
|
|
30
|
+
this.details = details;
|
|
31
|
+
this.originalError = originalError;
|
|
32
|
+
// Maintain proper stack trace with truncation to prevent memory issues
|
|
33
|
+
if (originalError?.stack) {
|
|
34
|
+
const truncatedOriginalStack = ErrorHandler.truncateStack(originalError.stack);
|
|
35
|
+
this.stack = `${this.stack}\nCaused by: ${truncatedOriginalStack}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Utility class for consistent error handling
|
|
41
|
+
*/
|
|
42
|
+
export class ErrorHandler {
|
|
43
|
+
/**
|
|
44
|
+
* Maximum stack trace depth to prevent memory issues
|
|
45
|
+
*/
|
|
46
|
+
static MAX_STACK_DEPTH = 10;
|
|
47
|
+
/**
|
|
48
|
+
* Maximum length for stack trace strings
|
|
49
|
+
*/
|
|
50
|
+
static MAX_STACK_LENGTH = 5000;
|
|
51
|
+
/**
|
|
52
|
+
* Truncate stack trace to prevent memory issues
|
|
53
|
+
*/
|
|
54
|
+
static truncateStack(stack) {
|
|
55
|
+
if (!stack)
|
|
56
|
+
return undefined;
|
|
57
|
+
// Limit total length
|
|
58
|
+
if (stack.length > this.MAX_STACK_LENGTH) {
|
|
59
|
+
stack = stack.substring(0, this.MAX_STACK_LENGTH) + '\n... (truncated)';
|
|
60
|
+
}
|
|
61
|
+
// Limit number of stack frames
|
|
62
|
+
const lines = stack.split('\n');
|
|
63
|
+
if (lines.length > this.MAX_STACK_DEPTH) {
|
|
64
|
+
return lines.slice(0, this.MAX_STACK_DEPTH).join('\n') + '\n... (truncated)';
|
|
65
|
+
}
|
|
66
|
+
return stack;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Extract error information while preserving context
|
|
70
|
+
*/
|
|
71
|
+
static extractErrorInfo(error) {
|
|
72
|
+
// Handle ApplicationError
|
|
73
|
+
if (error instanceof ApplicationError) {
|
|
74
|
+
return {
|
|
75
|
+
message: error.message,
|
|
76
|
+
category: error.category,
|
|
77
|
+
code: error.code,
|
|
78
|
+
details: error.details,
|
|
79
|
+
stack: this.truncateStack(error.stack),
|
|
80
|
+
originalError: error.originalError
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// Handle standard Error
|
|
84
|
+
if (error instanceof Error) {
|
|
85
|
+
return {
|
|
86
|
+
message: error.message,
|
|
87
|
+
category: ErrorCategory.SYSTEM_ERROR,
|
|
88
|
+
stack: this.truncateStack(error.stack),
|
|
89
|
+
originalError: error
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Handle string errors
|
|
93
|
+
if (typeof error === 'string') {
|
|
94
|
+
return {
|
|
95
|
+
message: error,
|
|
96
|
+
category: ErrorCategory.SYSTEM_ERROR
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// Handle unknown errors
|
|
100
|
+
return {
|
|
101
|
+
message: 'An unknown error occurred',
|
|
102
|
+
category: ErrorCategory.SYSTEM_ERROR,
|
|
103
|
+
details: error
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get user-friendly error message
|
|
108
|
+
*/
|
|
109
|
+
static getUserMessage(error) {
|
|
110
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
111
|
+
// Provide user-friendly messages based on category
|
|
112
|
+
switch (errorInfo.category) {
|
|
113
|
+
case ErrorCategory.AUTH_ERROR:
|
|
114
|
+
return `Authentication error: ${errorInfo.message}`;
|
|
115
|
+
case ErrorCategory.VALIDATION_ERROR:
|
|
116
|
+
return `Validation error: ${errorInfo.message}`;
|
|
117
|
+
case ErrorCategory.NETWORK_ERROR:
|
|
118
|
+
return `Network error: ${errorInfo.message}. Please check your connection and try again.`;
|
|
119
|
+
case ErrorCategory.USER_ERROR:
|
|
120
|
+
return errorInfo.message; // User errors should already be user-friendly
|
|
121
|
+
default:
|
|
122
|
+
// For system errors, provide a generic message
|
|
123
|
+
return 'An unexpected error occurred. Please try again later.';
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Log error with appropriate level and context
|
|
128
|
+
*/
|
|
129
|
+
static logError(context, error, additionalInfo) {
|
|
130
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
131
|
+
const logData = {
|
|
132
|
+
context,
|
|
133
|
+
category: errorInfo.category,
|
|
134
|
+
code: errorInfo.code,
|
|
135
|
+
message: errorInfo.message,
|
|
136
|
+
...additionalInfo
|
|
137
|
+
};
|
|
138
|
+
// Log based on category
|
|
139
|
+
switch (errorInfo.category) {
|
|
140
|
+
case ErrorCategory.USER_ERROR:
|
|
141
|
+
case ErrorCategory.VALIDATION_ERROR:
|
|
142
|
+
logger.warn(`${context}: ${errorInfo.message}`, logData);
|
|
143
|
+
break;
|
|
144
|
+
case ErrorCategory.AUTH_ERROR:
|
|
145
|
+
logger.warn(`${context}: Authentication error`, logData);
|
|
146
|
+
break;
|
|
147
|
+
case ErrorCategory.NETWORK_ERROR:
|
|
148
|
+
logger.error(`${context}: Network error`, {
|
|
149
|
+
...logData,
|
|
150
|
+
stack: errorInfo.stack
|
|
151
|
+
});
|
|
152
|
+
break;
|
|
153
|
+
default:
|
|
154
|
+
logger.error(`${context}: System error`, {
|
|
155
|
+
...logData,
|
|
156
|
+
stack: errorInfo.stack,
|
|
157
|
+
details: errorInfo.details
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
// Log stack trace in debug mode for all errors (already truncated)
|
|
161
|
+
if (errorInfo.stack) {
|
|
162
|
+
logger.debug(`${context} - Stack trace:`, { stack: errorInfo.stack });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Create an error with context preservation
|
|
167
|
+
*/
|
|
168
|
+
static createError(message, category = ErrorCategory.SYSTEM_ERROR, code, originalError) {
|
|
169
|
+
const original = originalError instanceof Error ? originalError : undefined;
|
|
170
|
+
return new ApplicationError(message, category, code, undefined, original);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Wrap an error with additional context
|
|
174
|
+
*/
|
|
175
|
+
static wrapError(error, context, category) {
|
|
176
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
177
|
+
return new ApplicationError(`${context}: ${errorInfo.message}`, category || errorInfo.category, errorInfo.code, errorInfo.details, errorInfo.originalError);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Check if error is of a specific category
|
|
181
|
+
*/
|
|
182
|
+
static isErrorCategory(error, category) {
|
|
183
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
184
|
+
return errorInfo.category === category;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Format error for API response
|
|
188
|
+
*/
|
|
189
|
+
static formatForResponse(error) {
|
|
190
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
191
|
+
const userMessage = this.getUserMessage(error);
|
|
192
|
+
return {
|
|
193
|
+
success: false,
|
|
194
|
+
message: userMessage,
|
|
195
|
+
error: errorInfo.code || errorInfo.category,
|
|
196
|
+
// Only include details in development
|
|
197
|
+
details: process.env.NODE_ENV === 'development' ? errorInfo.details : undefined
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRXJyb3JIYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3V0aWxzL0Vycm9ySGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXJDOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksYUFNWDtBQU5ELFdBQVksYUFBYTtJQUN2QiwwQ0FBeUIsQ0FBQTtJQUN6Qiw4Q0FBNkIsQ0FBQTtJQUM3QixnREFBK0IsQ0FBQTtJQUMvQiwwQ0FBeUIsQ0FBQTtJQUN6QixzREFBcUMsQ0FBQSxDQUFDLHNCQUFzQjtBQUM5RCxDQUFDLEVBTlcsYUFBYSxLQUFiLGFBQWEsUUFNeEI7QUFjRDs7R0FFRztBQUNILE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxLQUFLO0lBQ3pCLFFBQVEsQ0FBZ0I7SUFDeEIsSUFBSSxDQUFVO0lBQ2QsT0FBTyxDQUEyQjtJQUNsQyxhQUFhLENBQVM7SUFFdEMsWUFDRSxPQUFlLEVBQ2YsV0FBMEIsYUFBYSxDQUFDLFlBQVksRUFDcEQsSUFBYSxFQUNiLE9BQWlDLEVBQ2pDLGFBQXFCO1FBRXJCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsa0JBQWtCLENBQUM7UUFDL0IsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7UUFDekIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLENBQUM7UUFFbkMsdUVBQXVFO1FBQ3ZFLElBQUksYUFBYSxFQUFFLEtBQUssRUFBRSxDQUFDO1lBQ3pCLE1BQU0sc0JBQXNCLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0UsSUFBSSxDQUFDLEtBQUss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LEVBQ2pCLFNBQVMsQ0FBQyxhQUFhLENBQ3hCLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsZUFBZSxDQUFDLEtBQWMsRUFBRSxRQUF1QjtRQUM1RCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDL0MsT0FBTyxTQUFTLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQztJQUN6QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsaUJBQWlCLENBQUMsS0FBYztRQU1yQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDL0MsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUvQyxPQUFPO1lBQ0wsT0FBTyxFQUFFLEtBQUs7WUFDZCxPQUFPLEVBQUUsV0FBVztZQUNwQixLQUFLLEVBQUUsU0FBUyxDQUFDLElBQUksSUFBSSxTQUFTLENBQUMsUUFBUTtZQUMzQyxzQ0FBc0M7WUFDdEMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxLQUFLLGFBQWEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUztTQUNoRixDQUFDO0lBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ2VudHJhbGl6ZWQgZXJyb3IgaGFuZGxpbmcgdXRpbGl0aWVzIGZvciBjb25zaXN0ZW50IGVycm9yIHByb2Nlc3NpbmdcbiAqIFByZXNlcnZlcyBzdGFjayB0cmFjZXMgYW5kIHByb3ZpZGVzIHVzZXItZnJpZW5kbHkgbWVzc2FnZXNcbiAqL1xuXG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuL2xvZ2dlci5qcyc7XG5cbi8qKlxuICogRXJyb3IgY2F0ZWdvcmllcyBmb3IgYmV0dGVyIGVycm9yIGhhbmRsaW5nXG4gKi9cbmV4cG9ydCBlbnVtIEVycm9yQ2F0ZWdvcnkge1xuICBVU0VSX0VSUk9SID0gJ1VTRVJfRVJST1InLCAgICAgICAgLy8gVXNlciBpbnB1dCBpc3N1ZXNcbiAgU1lTVEVNX0VSUk9SID0gJ1NZU1RFTV9FUlJPUicsICAgIC8vIEludGVybmFsIHN5c3RlbSBmYWlsdXJlc1xuICBORVRXT1JLX0VSUk9SID0gJ05FVFdPUktfRVJST1InLCAgLy8gQVBJL25ldHdvcmsgaXNzdWVzXG4gIEFVVEhfRVJST1IgPSAnQVVUSF9FUlJPUicsICAgICAgICAvLyBBdXRoZW50aWNhdGlvbi9hdXRob3JpemF0aW9uXG4gIFZBTElEQVRJT05fRVJST1IgPSAnVkFMSURBVElPTl9FUlJPUicgLy8gVmFsaWRhdGlvbiBmYWlsdXJlc1xufVxuXG4vKipcbiAqIFN0cnVjdHVyZWQgZXJyb3IgaW5mb3JtYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFcnJvckluZm8ge1xuICBtZXNzYWdlOiBzdHJpbmc7XG4gIGNhdGVnb3J5OiBFcnJvckNhdGVnb3J5O1xuICBjb2RlPzogc3RyaW5nO1xuICBkZXRhaWxzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIHN0YWNrPzogc3RyaW5nO1xuICBvcmlnaW5hbEVycm9yPzogRXJyb3I7XG59XG5cbi8qKlxuICogQ3VzdG9tIGVycm9yIGNsYXNzIHdpdGggYWRkaXRpb25hbCBjb250ZXh0XG4gKi9cbmV4cG9ydCBjbGFzcyBBcHBsaWNhdGlvbkVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBwdWJsaWMgcmVhZG9ubHkgY2F0ZWdvcnk6IEVycm9yQ2F0ZWdvcnk7XG4gIHB1YmxpYyByZWFkb25seSBjb2RlPzogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgZGV0YWlscz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICBwdWJsaWMgcmVhZG9ubHkgb3JpZ2luYWxFcnJvcj86IEVycm9yO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIG1lc3NhZ2U6IHN0cmluZyxcbiAgICBjYXRlZ29yeTogRXJyb3JDYXRlZ29yeSA9IEVycm9yQ2F0ZWdvcnkuU1lTVEVNX0VSUk9SLFxuICAgIGNvZGU/OiBzdHJpbmcsXG4gICAgZGV0YWlscz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+LFxuICAgIG9yaWdpbmFsRXJyb3I/OiBFcnJvclxuICApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSAnQXBwbGljYXRpb25FcnJvcic7XG4gICAgdGhpcy5jYXRlZ29yeSA9IGNhdGVnb3J5O1xuICAgIHRoaXMuY29kZSA9IGNvZGU7XG4gICAgdGhpcy5kZXRhaWxzID0gZGV0YWlscztcbiAgICB0aGlzLm9yaWdpbmFsRXJyb3IgPSBvcmlnaW5hbEVycm9yO1xuXG4gICAgLy8gTWFpbnRhaW4gcHJvcGVyIHN0YWNrIHRyYWNlIHdpdGggdHJ1bmNhdGlvbiB0byBwcmV2ZW50IG1lbW9yeSBpc3N1ZXNcbiAgICBpZiAob3JpZ2luYWxFcnJvcj8uc3RhY2spIHtcbiAgICAgIGNvbnN0IHRydW5jYXRlZE9yaWdpbmFsU3RhY2sgPSBFcnJvckhhbmRsZXIudHJ1bmNhdGVTdGFjayhvcmlnaW5hbEVycm9yLnN0YWNrKTtcbiAgICAgIHRoaXMuc3RhY2sgPSBgJHt0aGlzLnN0YWNrfVxcbkNhdXNlZCBieTogJHt0cnVuY2F0ZWRPcmlnaW5hbFN0YWNrfWA7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVXRpbGl0eSBjbGFzcyBmb3IgY29uc2lzdGVudCBlcnJvciBoYW5kbGluZ1xuICovXG5leHBvcnQgY2xhc3MgRXJyb3JIYW5kbGVyIHtcbiAgLyoqXG4gICAqIE1heGltdW0gc3RhY2sgdHJhY2UgZGVwdGggdG8gcHJldmVudCBtZW1vcnkgaXNzdWVzXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBNQVhfU1RBQ0tfREVQVEggPSAxMDtcbiAgXG4gIC8qKlxuICAgKiBNYXhpbXVtIGxlbmd0aCBmb3Igc3RhY2sgdHJhY2Ugc3RyaW5nc1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgTUFYX1NUQUNLX0xFTkdUSCA9IDUwMDA7XG4gIFxuICAvKipcbiAgICogVHJ1bmNhdGUgc3RhY2sgdHJhY2UgdG8gcHJldmVudCBtZW1vcnkgaXNzdWVzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHRydW5jYXRlU3RhY2soc3RhY2s/OiBzdHJpbmcpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGlmICghc3RhY2spIHJldHVybiB1bmRlZmluZWQ7XG4gICAgXG4gICAgLy8gTGltaXQgdG90YWwgbGVuZ3RoXG4gICAgaWYgKHN0YWNrLmxlbmd0aCA+IHRoaXMuTUFYX1NUQUNLX0xFTkdUSCkge1xuICAgICAgc3RhY2sgPSBzdGFjay5zdWJzdHJpbmcoMCwgdGhpcy5NQVhfU1RBQ0tfTEVOR1RIKSArICdcXG4uLi4gKHRydW5jYXRlZCknO1xuICAgIH1cbiAgICBcbiAgICAvLyBMaW1pdCBudW1iZXIgb2Ygc3RhY2sgZnJhbWVzXG4gICAgY29uc3QgbGluZXMgPSBzdGFjay5zcGxpdCgnXFxuJyk7XG4gICAgaWYgKGxpbmVzLmxlbmd0aCA+IHRoaXMuTUFYX1NUQUNLX0RFUFRIKSB7XG4gICAgICByZXR1cm4gbGluZXMuc2xpY2UoMCwgdGhpcy5NQVhfU1RBQ0tfREVQVEgpLmpvaW4oJ1xcbicpICsgJ1xcbi4uLiAodHJ1bmNhdGVkKSc7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBzdGFjaztcbiAgfVxuICBcbiAgLyoqXG4gICAqIEV4dHJhY3QgZXJyb3IgaW5mb3JtYXRpb24gd2hpbGUgcHJlc2VydmluZyBjb250ZXh0XG4gICAqL1xuICBzdGF0aWMgZXh0cmFjdEVycm9ySW5mbyhlcnJvcjogdW5rbm93bik6IEVycm9ySW5mbyB7XG4gICAgLy8gSGFuZGxlIEFwcGxpY2F0aW9uRXJyb3JcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBBcHBsaWNhdGlvbkVycm9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLFxuICAgICAgICBjYXRlZ29yeTogZXJyb3IuY2F0ZWdvcnksXG4gICAgICAgIGNvZGU6IGVycm9yLmNvZGUsXG4gICAgICAgIGRldGFpbHM6IGVycm9yLmRldGFpbHMsXG4gICAgICAgIHN0YWNrOiB0aGlzLnRydW5jYXRlU3RhY2soZXJyb3Iuc3RhY2spLFxuICAgICAgICBvcmlnaW5hbEVycm9yOiBlcnJvci5vcmlnaW5hbEVycm9yXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSBzdGFuZGFyZCBFcnJvclxuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBtZXNzYWdlOiBlcnJvci5tZXNzYWdlLFxuICAgICAgICBjYXRlZ29yeTogRXJyb3JDYXRlZ29yeS5TWVNURU1fRVJST1IsXG4gICAgICAgIHN0YWNrOiB0aGlzLnRydW5jYXRlU3RhY2soZXJyb3Iuc3RhY2spLFxuICAgICAgICBvcmlnaW5hbEVycm9yOiBlcnJvclxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgc3RyaW5nIGVycm9yc1xuICAgIGlmICh0eXBlb2YgZXJyb3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBtZXNzYWdlOiBlcnJvcixcbiAgICAgICAgY2F0ZWdvcnk6IEVycm9yQ2F0ZWdvcnkuU1lTVEVNX0VSUk9SXG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSB1bmtub3duIGVycm9yc1xuICAgIHJldHVybiB7XG4gICAgICBtZXNzYWdlOiAnQW4gdW5rbm93biBlcnJvciBvY2N1cnJlZCcsXG4gICAgICBjYXRlZ29yeTogRXJyb3JDYXRlZ29yeS5TWVNURU1fRVJST1IsXG4gICAgICBkZXRhaWxzOiBlcnJvciBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHVzZXItZnJpZW5kbHkgZXJyb3IgbWVzc2FnZVxuICAgKi9cbiAgc3RhdGljIGdldFVzZXJNZXNzYWdlKGVycm9yOiB1bmtub3duKTogc3RyaW5nIHtcbiAgICBjb25zdCBlcnJvckluZm8gPSB0aGlzLmV4dHJhY3RFcnJvckluZm8oZXJyb3IpO1xuICAgIFxuICAgIC8vIFByb3ZpZGUgdXNlci1mcmllbmRseSBtZXNzYWdlcyBiYXNlZCBvbiBjYXRlZ29yeVxuICAgIHN3aXRjaCAoZXJyb3JJbmZvLmNhdGVnb3J5KSB7XG4gICAgICBjYXNlIEVycm9yQ2F0ZWdvcnkuQVVUSF9FUlJPUjpcbiAgICAgICAgcmV0dXJuIGBBdXRoZW50aWNhdGlvbiBlcnJvcjogJHtlcnJvckluZm8ubWVzc2FnZX1gO1xuICAgICAgY2FzZSBFcnJvckNhdGVnb3J5LlZBTElEQVRJT05fRVJST1I6XG4gICAgICAgIHJldHVybiBgVmFsaWRhdGlvbiBlcnJvcjogJHtlcnJvckluZm8ubWVzc2FnZX1gO1xuICAgICAgY2FzZSBFcnJvckNhdGVnb3J5Lk5FVFdPUktfRVJST1I6XG4gICAgICAgIHJldHVybiBgTmV0d29yayBlcnJvcjogJHtlcnJvckluZm8ubWVzc2FnZX0uIFBsZWFzZSBjaGVjayB5b3VyIGNvbm5lY3Rpb24gYW5kIHRyeSBhZ2Fpbi5gO1xuICAgICAgY2FzZSBFcnJvckNhdGVnb3J5LlVTRVJfRVJST1I6XG4gICAgICAgIHJldHVybiBlcnJvckluZm8ubWVzc2FnZTsgLy8gVXNlciBlcnJvcnMgc2hvdWxkIGFscmVhZHkgYmUgdXNlci1mcmllbmRseVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gRm9yIHN5c3RlbSBlcnJvcnMsIHByb3ZpZGUgYSBnZW5lcmljIG1lc3NhZ2VcbiAgICAgICAgcmV0dXJuICdBbiB1bmV4cGVjdGVkIGVycm9yIG9jY3VycmVkLiBQbGVhc2UgdHJ5IGFnYWluIGxhdGVyLic7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExvZyBlcnJvciB3aXRoIGFwcHJvcHJpYXRlIGxldmVsIGFuZCBjb250ZXh0XG4gICAqL1xuICBzdGF0aWMgbG9nRXJyb3IoXG4gICAgY29udGV4dDogc3RyaW5nLFxuICAgIGVycm9yOiB1bmtub3duLFxuICAgIGFkZGl0aW9uYWxJbmZvPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj5cbiAgKTogdm9pZCB7XG4gICAgY29uc3QgZXJyb3JJbmZvID0gdGhpcy5leHRyYWN0RXJyb3JJbmZvKGVycm9yKTtcbiAgICBcbiAgICBjb25zdCBsb2dEYXRhID0ge1xuICAgICAgY29udGV4dCxcbiAgICAgIGNhdGVnb3J5OiBlcnJvckluZm8uY2F0ZWdvcnksXG4gICAgICBjb2RlOiBlcnJvckluZm8uY29kZSxcbiAgICAgIG1lc3NhZ2U6IGVycm9ySW5mby5tZXNzYWdlLFxuICAgICAgLi4uYWRkaXRpb25hbEluZm9cbiAgICB9O1xuXG4gICAgLy8gTG9nIGJhc2VkIG9uIGNhdGVnb3J5XG4gICAgc3dpdGNoIChlcnJvckluZm8uY2F0ZWdvcnkpIHtcbiAgICAgIGNhc2UgRXJyb3JDYXRlZ29yeS5VU0VSX0VSUk9SOlxuICAgICAgY2FzZSBFcnJvckNhdGVnb3J5LlZBTElEQVRJT05fRVJST1I6XG4gICAgICAgIGxvZ2dlci53YXJuKGAke2NvbnRleHR9OiAke2Vycm9ySW5mby5tZXNzYWdlfWAsIGxvZ0RhdGEpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgRXJyb3JDYXRlZ29yeS5BVVRIX0VSUk9SOlxuICAgICAgICBsb2dnZXIud2FybihgJHtjb250ZXh0fTogQXV0aGVudGljYXRpb24gZXJyb3JgLCBsb2dEYXRhKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEVycm9yQ2F0ZWdvcnkuTkVUV09SS19FUlJPUjpcbiAgICAgICAgbG9nZ2VyLmVycm9yKGAke2NvbnRleHR9OiBOZXR3b3JrIGVycm9yYCwge1xuICAgICAgICAgIC4uLmxvZ0RhdGEsXG4gICAgICAgICAgc3RhY2s6IGVycm9ySW5mby5zdGFja1xuICAgICAgICB9KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBsb2dnZXIuZXJyb3IoYCR7Y29udGV4dH06IFN5c3RlbSBlcnJvcmAsIHtcbiAgICAgICAgICAuLi5sb2dEYXRhLFxuICAgICAgICAgIHN0YWNrOiBlcnJvckluZm8uc3RhY2ssXG4gICAgICAgICAgZGV0YWlsczogZXJyb3JJbmZvLmRldGFpbHNcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gTG9nIHN0YWNrIHRyYWNlIGluIGRlYnVnIG1vZGUgZm9yIGFsbCBlcnJvcnMgKGFscmVhZHkgdHJ1bmNhdGVkKVxuICAgIGlmIChlcnJvckluZm8uc3RhY2spIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhgJHtjb250ZXh0fSAtIFN0YWNrIHRyYWNlOmAsIHsgc3RhY2s6IGVycm9ySW5mby5zdGFjayB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGFuIGVycm9yIHdpdGggY29udGV4dCBwcmVzZXJ2YXRpb25cbiAgICovXG4gIHN0YXRpYyBjcmVhdGVFcnJvcihcbiAgICBtZXNzYWdlOiBzdHJpbmcsXG4gICAgY2F0ZWdvcnk6IEVycm9yQ2F0ZWdvcnkgPSBFcnJvckNhdGVnb3J5LlNZU1RFTV9FUlJPUixcbiAgICBjb2RlPzogc3RyaW5nLFxuICAgIG9yaWdpbmFsRXJyb3I/OiB1bmtub3duXG4gICk6IEFwcGxpY2F0aW9uRXJyb3Ige1xuICAgIGNvbnN0IG9yaWdpbmFsID0gb3JpZ2luYWxFcnJvciBpbnN0YW5jZW9mIEVycm9yID8gb3JpZ2luYWxFcnJvciA6IHVuZGVmaW5lZDtcbiAgICByZXR1cm4gbmV3IEFwcGxpY2F0aW9uRXJyb3IobWVzc2FnZSwgY2F0ZWdvcnksIGNvZGUsIHVuZGVmaW5lZCwgb3JpZ2luYWwpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdyYXAgYW4gZXJyb3Igd2l0aCBhZGRpdGlvbmFsIGNvbnRleHRcbiAgICovXG4gIHN0YXRpYyB3cmFwRXJyb3IoXG4gICAgZXJyb3I6IHVua25vd24sXG4gICAgY29udGV4dDogc3RyaW5nLFxuICAgIGNhdGVnb3J5PzogRXJyb3JDYXRlZ29yeVxuICApOiBBcHBsaWNhdGlvbkVycm9yIHtcbiAgICBjb25zdCBlcnJvckluZm8gPSB0aGlzLmV4dHJhY3RFcnJvckluZm8oZXJyb3IpO1xuICAgIHJldHVybiBuZXcgQXBwbGljYXRpb25FcnJvcihcbiAgICAgIGAke2NvbnRleHR9OiAke2Vycm9ySW5mby5tZXNzYWdlfWAsXG4gICAgICBjYXRlZ29yeSB8fCBlcnJvckluZm8uY2F0ZWdvcnksXG4gICAgICBlcnJvckluZm8uY29kZSxcbiAgICAgIGVycm9ySW5mby5kZXRhaWxzLFxuICAgICAgZXJyb3JJbmZvLm9yaWdpbmFsRXJyb3JcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGVycm9yIGlzIG9mIGEgc3BlY2lmaWMgY2F0ZWdvcnlcbiAgICovXG4gIHN0YXRpYyBpc0Vycm9yQ2F0ZWdvcnkoZXJyb3I6IHVua25vd24sIGNhdGVnb3J5OiBFcnJvckNhdGVnb3J5KTogYm9vbGVhbiB7XG4gICAgY29uc3QgZXJyb3JJbmZvID0gdGhpcy5leHRyYWN0RXJyb3JJbmZvKGVycm9yKTtcbiAgICByZXR1cm4gZXJyb3JJbmZvLmNhdGVnb3J5ID09PSBjYXRlZ29yeTtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JtYXQgZXJyb3IgZm9yIEFQSSByZXNwb25zZVxuICAgKi9cbiAgc3RhdGljIGZvcm1hdEZvclJlc3BvbnNlKGVycm9yOiB1bmtub3duKToge1xuICAgIHN1Y2Nlc3M6IGZhbHNlO1xuICAgIG1lc3NhZ2U6IHN0cmluZztcbiAgICBlcnJvcjogc3RyaW5nO1xuICAgIGRldGFpbHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgfSB7XG4gICAgY29uc3QgZXJyb3JJbmZvID0gdGhpcy5leHRyYWN0RXJyb3JJbmZvKGVycm9yKTtcbiAgICBjb25zdCB1c2VyTWVzc2FnZSA9IHRoaXMuZ2V0VXNlck1lc3NhZ2UoZXJyb3IpO1xuICAgIFxuICAgIHJldHVybiB7XG4gICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgIG1lc3NhZ2U6IHVzZXJNZXNzYWdlLFxuICAgICAgZXJyb3I6IGVycm9ySW5mby5jb2RlIHx8IGVycm9ySW5mby5jYXRlZ29yeSxcbiAgICAgIC8vIE9ubHkgaW5jbHVkZSBkZXRhaWxzIGluIGRldmVsb3BtZW50XG4gICAgICBkZXRhaWxzOiBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50JyA/IGVycm9ySW5mby5kZXRhaWxzIDogdW5kZWZpbmVkXG4gICAgfTtcbiAgfVxufSJdfQ==
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility class for efficient file discovery operations
|
|
3
|
+
* Provides optimized file search with caching and security
|
|
4
|
+
*
|
|
5
|
+
* IMPLEMENTATION (PR #503 - PR #496 Recommendation):
|
|
6
|
+
* 1. PERFORMANCE: Single readdir operation instead of multiple file checks
|
|
7
|
+
* 2. PERFORMANCE: 5-second cache TTL for repeated searches
|
|
8
|
+
* 3. SECURITY: Unicode normalization for all search inputs
|
|
9
|
+
* 4. MEMORY: Efficient cache management with 100 entry limit
|
|
10
|
+
*
|
|
11
|
+
* This addresses the PR #496 review recommendation to extract file discovery
|
|
12
|
+
* logic to a reusable utility class for better performance and maintainability.
|
|
13
|
+
*/
|
|
14
|
+
export interface FileSearchOptions {
|
|
15
|
+
extensions?: string[];
|
|
16
|
+
partialMatch?: boolean;
|
|
17
|
+
maxResults?: number;
|
|
18
|
+
cacheResults?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare class FileDiscoveryUtil {
|
|
21
|
+
private static readonly CACHE_TTL;
|
|
22
|
+
private static cache;
|
|
23
|
+
/**
|
|
24
|
+
* Find files in a directory with optimized search
|
|
25
|
+
* Uses single readdir operation and filters results
|
|
26
|
+
*/
|
|
27
|
+
static findFiles(directory: string, searchName: string, options?: FileSearchOptions): Promise<string[]>;
|
|
28
|
+
/**
|
|
29
|
+
* Build search patterns for different file extensions
|
|
30
|
+
*/
|
|
31
|
+
private static buildSearchPatterns;
|
|
32
|
+
/**
|
|
33
|
+
* Check if filename matches pattern
|
|
34
|
+
*/
|
|
35
|
+
private static matchesPattern;
|
|
36
|
+
/**
|
|
37
|
+
* Get cached results if still valid
|
|
38
|
+
*/
|
|
39
|
+
private static getCached;
|
|
40
|
+
/**
|
|
41
|
+
* Cache results with timestamp
|
|
42
|
+
*/
|
|
43
|
+
private static setCached;
|
|
44
|
+
/**
|
|
45
|
+
* Clear the cache
|
|
46
|
+
*/
|
|
47
|
+
static clearCache(): void;
|
|
48
|
+
/**
|
|
49
|
+
* Find a single file (convenience method)
|
|
50
|
+
*/
|
|
51
|
+
static findFile(directory: string, searchName: string, options?: FileSearchOptions): Promise<string | null>;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=FileDiscoveryUtil.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileDiscoveryUtil.d.ts","sourceRoot":"","sources":["../../src/utils/FileDiscoveryUtil.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAOD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAQ;IACzC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAiC;IAErD;;;OAGG;WACU,SAAS,CACpB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,EAAE,CAAC;IAkFpB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAoBlC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAO7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAaxB;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,SAAS;IAiBxB;;OAEG;IACH,MAAM,CAAC,UAAU,IAAI,IAAI;IAKzB;;OAEG;WACU,QAAQ,CACnB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAO1B"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility class for efficient file discovery operations
|
|
3
|
+
* Provides optimized file search with caching and security
|
|
4
|
+
*
|
|
5
|
+
* IMPLEMENTATION (PR #503 - PR #496 Recommendation):
|
|
6
|
+
* 1. PERFORMANCE: Single readdir operation instead of multiple file checks
|
|
7
|
+
* 2. PERFORMANCE: 5-second cache TTL for repeated searches
|
|
8
|
+
* 3. SECURITY: Unicode normalization for all search inputs
|
|
9
|
+
* 4. MEMORY: Efficient cache management with 100 entry limit
|
|
10
|
+
*
|
|
11
|
+
* This addresses the PR #496 review recommendation to extract file discovery
|
|
12
|
+
* logic to a reusable utility class for better performance and maintainability.
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from 'fs/promises';
|
|
15
|
+
import * as path from 'path';
|
|
16
|
+
import { logger } from './logger.js';
|
|
17
|
+
import { UnicodeValidator } from '../security/validators/unicodeValidator.js';
|
|
18
|
+
export class FileDiscoveryUtil {
|
|
19
|
+
static CACHE_TTL = 5000; // 5 seconds cache TTL
|
|
20
|
+
static cache = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* Find files in a directory with optimized search
|
|
23
|
+
* Uses single readdir operation and filters results
|
|
24
|
+
*/
|
|
25
|
+
static async findFiles(directory, searchName, options = {}) {
|
|
26
|
+
const { extensions = ['.json', '.yaml', '.yml', '.md'], partialMatch = true, maxResults = 10, cacheResults = true } = options;
|
|
27
|
+
// Normalize search name for security
|
|
28
|
+
const normalizedSearch = UnicodeValidator.normalize(searchName);
|
|
29
|
+
if (!normalizedSearch.isValid) {
|
|
30
|
+
logger.warn('Invalid Unicode in search name', {
|
|
31
|
+
issues: normalizedSearch.detectedIssues
|
|
32
|
+
});
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
const safeName = normalizedSearch.normalizedContent.toLowerCase();
|
|
36
|
+
// Check cache if enabled
|
|
37
|
+
const cacheKey = `${directory}:${safeName}:${JSON.stringify(options)}`;
|
|
38
|
+
if (cacheResults) {
|
|
39
|
+
const cached = this.getCached(cacheKey);
|
|
40
|
+
if (cached) {
|
|
41
|
+
logger.debug('File search cache hit', { directory, searchName });
|
|
42
|
+
return cached;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
// Single readdir operation for efficiency
|
|
47
|
+
const files = await fs.readdir(directory);
|
|
48
|
+
// Build search patterns
|
|
49
|
+
const searchPatterns = this.buildSearchPatterns(safeName, extensions);
|
|
50
|
+
// Filter files efficiently
|
|
51
|
+
const matches = [];
|
|
52
|
+
for (const file of files) {
|
|
53
|
+
const fileLower = file.toLowerCase();
|
|
54
|
+
// Check each pattern
|
|
55
|
+
for (const pattern of searchPatterns) {
|
|
56
|
+
if (this.matchesPattern(fileLower, pattern, partialMatch)) {
|
|
57
|
+
const fullPath = path.join(directory, file);
|
|
58
|
+
matches.push(fullPath);
|
|
59
|
+
if (matches.length >= maxResults) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (matches.length >= maxResults) {
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Cache results if enabled
|
|
69
|
+
if (cacheResults && matches.length > 0) {
|
|
70
|
+
this.setCached(cacheKey, matches);
|
|
71
|
+
}
|
|
72
|
+
// Log file discovery for monitoring
|
|
73
|
+
if (matches.length > 0) {
|
|
74
|
+
logger.debug('Files discovered', {
|
|
75
|
+
directory,
|
|
76
|
+
searchName,
|
|
77
|
+
count: matches.length
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return matches;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
logger.error('File discovery failed', {
|
|
84
|
+
directory,
|
|
85
|
+
searchName,
|
|
86
|
+
error: error instanceof Error ? error.message : String(error)
|
|
87
|
+
});
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build search patterns for different file extensions
|
|
93
|
+
*/
|
|
94
|
+
static buildSearchPatterns(baseName, extensions) {
|
|
95
|
+
const patterns = [baseName];
|
|
96
|
+
// Add extension variations
|
|
97
|
+
for (const ext of extensions) {
|
|
98
|
+
patterns.push(`${baseName}${ext}`);
|
|
99
|
+
}
|
|
100
|
+
// Add common variations
|
|
101
|
+
const nameWithoutExtension = baseName.replace(/\.[^.]+$/, '');
|
|
102
|
+
if (nameWithoutExtension !== baseName) {
|
|
103
|
+
patterns.push(nameWithoutExtension);
|
|
104
|
+
for (const ext of extensions) {
|
|
105
|
+
patterns.push(`${nameWithoutExtension}${ext}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return patterns;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check if filename matches pattern
|
|
112
|
+
*/
|
|
113
|
+
static matchesPattern(filename, pattern, partialMatch) {
|
|
114
|
+
if (partialMatch) {
|
|
115
|
+
return filename.includes(pattern);
|
|
116
|
+
}
|
|
117
|
+
return filename === pattern;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Get cached results if still valid
|
|
121
|
+
*/
|
|
122
|
+
static getCached(key) {
|
|
123
|
+
const entry = this.cache.get(key);
|
|
124
|
+
if (!entry)
|
|
125
|
+
return null;
|
|
126
|
+
const age = Date.now() - entry.timestamp;
|
|
127
|
+
if (age > this.CACHE_TTL) {
|
|
128
|
+
this.cache.delete(key);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
return entry.files;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Cache results with timestamp
|
|
135
|
+
*/
|
|
136
|
+
static setCached(key, files) {
|
|
137
|
+
// Limit cache size to prevent memory issues
|
|
138
|
+
if (this.cache.size > 100) {
|
|
139
|
+
// Remove oldest entries
|
|
140
|
+
const entries = Array.from(this.cache.entries());
|
|
141
|
+
entries.sort((a, b) => a[1].timestamp - b[1].timestamp);
|
|
142
|
+
for (let i = 0; i < 50; i++) {
|
|
143
|
+
this.cache.delete(entries[i][0]);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
this.cache.set(key, {
|
|
147
|
+
files,
|
|
148
|
+
timestamp: Date.now()
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Clear the cache
|
|
153
|
+
*/
|
|
154
|
+
static clearCache() {
|
|
155
|
+
this.cache.clear();
|
|
156
|
+
logger.debug('File discovery cache cleared');
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Find a single file (convenience method)
|
|
160
|
+
*/
|
|
161
|
+
static async findFile(directory, searchName, options) {
|
|
162
|
+
const files = await this.findFiles(directory, searchName, {
|
|
163
|
+
...options,
|
|
164
|
+
maxResults: 1
|
|
165
|
+
});
|
|
166
|
+
return files.length > 0 ? files[0] : null;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRmlsZURpc2NvdmVyeVV0aWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvRmlsZURpc2NvdmVyeVV0aWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7OztHQVlHO0FBRUgsT0FBTyxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQWU5RSxNQUFNLE9BQU8saUJBQWlCO0lBQ3BCLE1BQU0sQ0FBVSxTQUFTLEdBQUcsSUFBSSxDQUFDLENBQUMsc0JBQXNCO0lBQ3hELE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQXNCLENBQUM7SUFFckQ7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQ3BCLFNBQWlCLEVBQ2pCLFVBQWtCLEVBQ2xCLFVBQTZCLEVBQUU7UUFFL0IsTUFBTSxFQUNKLFVBQVUsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxFQUM5QyxZQUFZLEdBQUcsSUFBSSxFQUNuQixVQUFVLEdBQUcsRUFBRSxFQUNmLFlBQVksR0FBRyxJQUFJLEVBQ3BCLEdBQUcsT0FBTyxDQUFDO1FBRVoscUNBQXFDO1FBQ3JDLE1BQU0sZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2hFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUM5QixNQUFNLENBQUMsSUFBSSxDQUFDLGdDQUFnQyxFQUFFO2dCQUM1QyxNQUFNLEVBQUUsZ0JBQWdCLENBQUMsY0FBYzthQUN4QyxDQUFDLENBQUM7WUFDSCxPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUM7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QixFQUNqQixVQUFrQixFQUNsQixPQUEyQjtRQUUzQixNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRTtZQUN4RCxHQUFHLE9BQU87WUFDVixVQUFVLEVBQUUsQ0FBQztTQUNkLENBQUMsQ0FBQztRQUNILE9BQU8sS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzVDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFV0aWxpdHkgY2xhc3MgZm9yIGVmZmljaWVudCBmaWxlIGRpc2NvdmVyeSBvcGVyYXRpb25zXG4gKiBQcm92aWRlcyBvcHRpbWl6ZWQgZmlsZSBzZWFyY2ggd2l0aCBjYWNoaW5nIGFuZCBzZWN1cml0eVxuICogXG4gKiBJTVBMRU1FTlRBVElPTiAoUFIgIzUwMyAtIFBSICM0OTYgUmVjb21tZW5kYXRpb24pOlxuICogMS4gUEVSRk9STUFOQ0U6IFNpbmdsZSByZWFkZGlyIG9wZXJhdGlvbiBpbnN0ZWFkIG9mIG11bHRpcGxlIGZpbGUgY2hlY2tzXG4gKiAyLiBQRVJGT1JNQU5DRTogNS1zZWNvbmQgY2FjaGUgVFRMIGZvciByZXBlYXRlZCBzZWFyY2hlc1xuICogMy4gU0VDVVJJVFk6IFVuaWNvZGUgbm9ybWFsaXphdGlvbiBmb3IgYWxsIHNlYXJjaCBpbnB1dHNcbiAqIDQuIE1FTU9SWTogRWZmaWNpZW50IGNhY2hlIG1hbmFnZW1lbnQgd2l0aCAxMDAgZW50cnkgbGltaXRcbiAqIFxuICogVGhpcyBhZGRyZXNzZXMgdGhlIFBSICM0OTYgcmV2aWV3IHJlY29tbWVuZGF0aW9uIHRvIGV4dHJhY3QgZmlsZSBkaXNjb3ZlcnlcbiAqIGxvZ2ljIHRvIGEgcmV1c2FibGUgdXRpbGl0eSBjbGFzcyBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlIGFuZCBtYWludGFpbmFiaWxpdHkuXG4gKi9cblxuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMvcHJvbWlzZXMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gJy4vbG9nZ2VyLmpzJztcbmltcG9ydCB7IFVuaWNvZGVWYWxpZGF0b3IgfSBmcm9tICcuLi9zZWN1cml0eS92YWxpZGF0b3JzL3VuaWNvZGVWYWxpZGF0b3IuanMnO1xuaW1wb3J0IHsgU2VjdXJpdHlNb25pdG9yIH0gZnJvbSAnLi4vc2VjdXJpdHkvc2VjdXJpdHlNb25pdG9yLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBGaWxlU2VhcmNoT3B0aW9ucyB7XG4gIGV4dGVuc2lvbnM/OiBzdHJpbmdbXTtcbiAgcGFydGlhbE1hdGNoPzogYm9vbGVhbjtcbiAgbWF4UmVzdWx0cz86IG51bWJlcjtcbiAgY2FjaGVSZXN1bHRzPzogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIENhY2hlRW50cnkge1xuICBmaWxlczogc3RyaW5nW107XG4gIHRpbWVzdGFtcDogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgRmlsZURpc2NvdmVyeVV0aWwge1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBDQUNIRV9UVEwgPSA1MDAwOyAvLyA1IHNlY29uZHMgY2FjaGUgVFRMXG4gIHByaXZhdGUgc3RhdGljIGNhY2hlID0gbmV3IE1hcDxzdHJpbmcsIENhY2hlRW50cnk+KCk7XG4gIFxuICAvKipcbiAgICogRmluZCBmaWxlcyBpbiBhIGRpcmVjdG9yeSB3aXRoIG9wdGltaXplZCBzZWFyY2hcbiAgICogVXNlcyBzaW5nbGUgcmVhZGRpciBvcGVyYXRpb24gYW5kIGZpbHRlcnMgcmVzdWx0c1xuICAgKi9cbiAgc3RhdGljIGFzeW5jIGZpbmRGaWxlcyhcbiAgICBkaXJlY3Rvcnk6IHN0cmluZyxcbiAgICBzZWFyY2hOYW1lOiBzdHJpbmcsXG4gICAgb3B0aW9uczogRmlsZVNlYXJjaE9wdGlvbnMgPSB7fVxuICApOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gICAgY29uc3Qge1xuICAgICAgZXh0ZW5zaW9ucyA9IFsnLmpzb24nLCAnLnlhbWwnLCAnLnltbCcsICcubWQnXSxcbiAgICAgIHBhcnRpYWxNYXRjaCA9IHRydWUsXG4gICAgICBtYXhSZXN1bHRzID0gMTAsXG4gICAgICBjYWNoZVJlc3VsdHMgPSB0cnVlXG4gICAgfSA9IG9wdGlvbnM7XG4gICAgXG4gICAgLy8gTm9ybWFsaXplIHNlYXJjaCBuYW1lIGZvciBzZWN1cml0eVxuICAgIGNvbnN0IG5vcm1hbGl6ZWRTZWFyY2ggPSBVbmljb2RlVmFsaWRhdG9yLm5vcm1hbGl6ZShzZWFyY2hOYW1lKTtcbiAgICBpZiAoIW5vcm1hbGl6ZWRTZWFyY2guaXNWYWxpZCkge1xuICAgICAgbG9nZ2VyLndhcm4oJ0ludmFsaWQgVW5pY29kZSBpbiBzZWFyY2ggbmFtZScsIHtcbiAgICAgICAgaXNzdWVzOiBub3JtYWxpemVkU2VhcmNoLmRldGVjdGVkSXNzdWVzXG4gICAgICB9KTtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgY29uc3Qgc2FmZU5hbWUgPSBub3JtYWxpemVkU2VhcmNoLm5vcm1hbGl6ZWRDb250ZW50LnRvTG93ZXJDYXNlKCk7XG4gICAgXG4gICAgLy8gQ2hlY2sgY2FjaGUgaWYgZW5hYmxlZFxuICAgIGNvbnN0IGNhY2hlS2V5ID0gYCR7ZGlyZWN0b3J5fToke3NhZmVOYW1lfToke0pTT04uc3RyaW5naWZ5KG9wdGlvbnMpfWA7XG4gICAgaWYgKGNhY2hlUmVzdWx0cykge1xuICAgICAgY29uc3QgY2FjaGVkID0gdGhpcy5nZXRDYWNoZWQoY2FjaGVLZXkpO1xuICAgICAgaWYgKGNhY2hlZCkge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ0ZpbGUgc2VhcmNoIGNhY2hlIGhpdCcsIHsgZGlyZWN0b3J5LCBzZWFyY2hOYW1lIH0pO1xuICAgICAgICByZXR1cm4gY2FjaGVkO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICB0cnkge1xuICAgICAgLy8gU2luZ2xlIHJlYWRkaXIgb3BlcmF0aW9uIGZvciBlZmZpY2llbmN5XG4gICAgICBjb25zdCBmaWxlcyA9IGF3YWl0IGZzLnJlYWRkaXIoZGlyZWN0b3J5KTtcbiAgICAgIFxuICAgICAgLy8gQnVpbGQgc2VhcmNoIHBhdHRlcm5zXG4gICAgICBjb25zdCBzZWFyY2hQYXR0ZXJucyA9IHRoaXMuYnVpbGRTZWFyY2hQYXR0ZXJucyhzYWZlTmFtZSwgZXh0ZW5zaW9ucyk7XG4gICAgICBcbiAgICAgIC8vIEZpbHRlciBmaWxlcyBlZmZpY2llbnRseVxuICAgICAgY29uc3QgbWF0Y2hlczogc3RyaW5nW10gPSBbXTtcbiAgICAgIGZvciAoY29uc3QgZmlsZSBvZiBmaWxlcykge1xuICAgICAgICBjb25zdCBmaWxlTG93ZXIgPSBmaWxlLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIFxuICAgICAgICAvLyBDaGVjayBlYWNoIHBhdHRlcm5cbiAgICAgICAgZm9yIChjb25zdCBwYXR0ZXJuIG9mIHNlYXJjaFBhdHRlcm5zKSB7XG4gICAgICAgICAgaWYgKHRoaXMubWF0Y2hlc1BhdHRlcm4oZmlsZUxvd2VyLCBwYXR0ZXJuLCBwYXJ0aWFsTWF0Y2gpKSB7XG4gICAgICAgICAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbihkaXJlY3RvcnksIGZpbGUpO1xuICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKGZ1bGxQYXRoKTtcbiAgICAgICAgICAgIFxuICAgICAgICAgICAgaWYgKG1hdGNoZXMubGVuZ3RoID49IG1heFJlc3VsdHMpIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAobWF0Y2hlcy5sZW5ndGggPj0gbWF4UmVzdWx0cykge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBcbiAgICAgIC8vIENhY2hlIHJlc3VsdHMgaWYgZW5hYmxlZFxuICAgICAgaWYgKGNhY2hlUmVzdWx0cyAmJiBtYXRjaGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhpcy5zZXRDYWNoZWQoY2FjaGVLZXksIG1hdGNoZXMpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBMb2cgZmlsZSBkaXNjb3ZlcnkgZm9yIG1vbml0b3JpbmdcbiAgICAgIGlmIChtYXRjaGVzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdGaWxlcyBkaXNjb3ZlcmVkJywge1xuICAgICAgICAgIGRpcmVjdG9yeSxcbiAgICAgICAgICBzZWFyY2hOYW1lLFxuICAgICAgICAgIGNvdW50OiBtYXRjaGVzLmxlbmd0aFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgcmV0dXJuIG1hdGNoZXM7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGxvZ2dlci5lcnJvcignRmlsZSBkaXNjb3ZlcnkgZmFpbGVkJywge1xuICAgICAgICBkaXJlY3RvcnksXG4gICAgICAgIHNlYXJjaE5hbWUsXG4gICAgICAgIGVycm9yOiBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcilcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEJ1aWxkIHNlYXJjaCBwYXR0ZXJucyBmb3IgZGlmZmVyZW50IGZpbGUgZXh0ZW5zaW9uc1xuICAgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgYnVpbGRTZWFyY2hQYXR0ZXJucyhiYXNlTmFtZTogc3RyaW5nLCBleHRlbnNpb25zOiBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBwYXR0ZXJuczogc3RyaW5nW10gPSBbYmFzZU5hbWVdO1xuICAgIFxuICAgIC8vIEFkZCBleHRlbnNpb24gdmFyaWF0aW9uc1xuICAgIGZvciAoY29uc3QgZXh0IG9mIGV4dGVuc2lvbnMpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2goYCR7YmFzZU5hbWV9JHtleHR9YCk7XG4gICAgfVxuICAgIFxuICAgIC8vIEFkZCBjb21tb24gdmFyaWF0aW9uc1xuICAgIGNvbnN0IG5hbWVXaXRob3V0RXh0ZW5zaW9uID0gYmFzZU5hbWUucmVwbGFjZSgvXFwuW14uXSskLywgJycpO1xuICAgIGlmIChuYW1lV2l0aG91dEV4dGVuc2lvbiAhPT0gYmFzZU5hbWUpIHtcbiAgICAgIHBhdHRlcm5zLnB1c2gobmFtZVdpdGhvdXRFeHRlbnNpb24pO1xuICAgICAgZm9yIChjb25zdCBleHQgb2YgZXh0ZW5zaW9ucykge1xuICAgICAgICBwYXR0ZXJucy5wdXNoKGAke25hbWVXaXRob3V0RXh0ZW5zaW9ufSR7ZXh0fWApO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICByZXR1cm4gcGF0dGVybnM7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDaGVjayBpZiBmaWxlbmFtZSBtYXRjaGVzIHBhdHRlcm5cbiAgICovXG4gIHByaXZhdGUgc3RhdGljIG1hdGNoZXNQYXR0ZXJuKGZpbGVuYW1lOiBzdHJpbmcsIHBhdHRlcm46IHN0cmluZywgcGFydGlhbE1hdGNoOiBib29sZWFuKTogYm9vbGVhbiB7XG4gICAgaWYgKHBhcnRpYWxNYXRjaCkge1xuICAgICAgcmV0dXJuIGZpbGVuYW1lLmluY2x1ZGVzKHBhdHRlcm4pO1xuICAgIH1cbiAgICByZXR1cm4gZmlsZW5hbWUgPT09IHBhdHRlcm47XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgY2FjaGVkIHJlc3VsdHMgaWYgc3RpbGwgdmFsaWRcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIGdldENhY2hlZChrZXk6IHN0cmluZyk6IHN0cmluZ1tdIHwgbnVsbCB7XG4gICAgY29uc3QgZW50cnkgPSB0aGlzLmNhY2hlLmdldChrZXkpO1xuICAgIGlmICghZW50cnkpIHJldHVybiBudWxsO1xuICAgIFxuICAgIGNvbnN0IGFnZSA9IERhdGUubm93KCkgLSBlbnRyeS50aW1lc3RhbXA7XG4gICAgaWYgKGFnZSA+IHRoaXMuQ0FDSEVfVFRMKSB7XG4gICAgICB0aGlzLmNhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBlbnRyeS5maWxlcztcbiAgfVxuICBcbiAgLyoqXG4gICAqIENhY2hlIHJlc3VsdHMgd2l0aCB0aW1lc3RhbXBcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHNldENhY2hlZChrZXk6IHN0cmluZywgZmlsZXM6IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgLy8gTGltaXQgY2FjaGUgc2l6ZSB0byBwcmV2ZW50IG1lbW9yeSBpc3N1ZXNcbiAgICBpZiAodGhpcy5jYWNoZS5zaXplID4gMTAwKSB7XG4gICAgICAvLyBSZW1vdmUgb2xkZXN0IGVudHJpZXNcbiAgICAgIGNvbnN0IGVudHJpZXMgPSBBcnJheS5mcm9tKHRoaXMuY2FjaGUuZW50cmllcygpKTtcbiAgICAgIGVudHJpZXMuc29ydCgoYSwgYikgPT4gYVsxXS50aW1lc3RhbXAgLSBiWzFdLnRpbWVzdGFtcCk7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDUwOyBpKyspIHtcbiAgICAgICAgdGhpcy5jYWNoZS5kZWxldGUoZW50cmllc1tpXVswXSk7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIHRoaXMuY2FjaGUuc2V0KGtleSwge1xuICAgICAgZmlsZXMsXG4gICAgICB0aW1lc3RhbXA6IERhdGUubm93KClcbiAgICB9KTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIENsZWFyIHRoZSBjYWNoZVxuICAgKi9cbiAgc3RhdGljIGNsZWFyQ2FjaGUoKTogdm9pZCB7XG4gICAgdGhpcy5jYWNoZS5jbGVhcigpO1xuICAgIGxvZ2dlci5kZWJ1ZygnRmlsZSBkaXNjb3ZlcnkgY2FjaGUgY2xlYXJlZCcpO1xuICB9XG4gIFxuICAvKipcbiAgICogRmluZCBhIHNpbmdsZSBmaWxlIChjb252ZW5pZW5jZSBtZXRob2QpXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgZmluZEZpbGUoXG4gICAgZGlyZWN0b3J5OiBzdHJpbmcsXG4gICAgc2VhcmNoTmFtZTogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBGaWxlU2VhcmNoT3B0aW9uc1xuICApOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICBjb25zdCBmaWxlcyA9IGF3YWl0IHRoaXMuZmluZEZpbGVzKGRpcmVjdG9yeSwgc2VhcmNoTmFtZSwge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIG1heFJlc3VsdHM6IDFcbiAgICB9KTtcbiAgICByZXR1cm4gZmlsZXMubGVuZ3RoID4gMCA/IGZpbGVzWzBdIDogbnVsbDtcbiAgfVxufSJdfQ==
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHubRateLimiter - Specialized rate limiter for GitHub API calls
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Respects GitHub's authenticated (5000/hour) and unauthenticated (60/hour) limits
|
|
6
|
+
* - Client-side queuing when approaching limits
|
|
7
|
+
* - Request prioritization for critical operations
|
|
8
|
+
* - Comprehensive logging for quota management
|
|
9
|
+
* - Early termination when exact matches are found
|
|
10
|
+
*/
|
|
11
|
+
import { RateLimitStatus } from './RateLimiter.js';
|
|
12
|
+
export interface GitHubRateLimitInfo {
|
|
13
|
+
limit: number;
|
|
14
|
+
remaining: number;
|
|
15
|
+
reset: Date;
|
|
16
|
+
used: number;
|
|
17
|
+
}
|
|
18
|
+
export interface GitHubApiRequest {
|
|
19
|
+
id: string;
|
|
20
|
+
operation: string;
|
|
21
|
+
priority: 'high' | 'normal' | 'low';
|
|
22
|
+
timestamp: number;
|
|
23
|
+
resolve: (value: any) => void;
|
|
24
|
+
reject: (error: any) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface GitHubRateStatus extends RateLimitStatus {
|
|
27
|
+
queueLength: number;
|
|
28
|
+
currentLimit: number;
|
|
29
|
+
rateLimitInfo?: GitHubRateLimitInfo;
|
|
30
|
+
}
|
|
31
|
+
export declare class GitHubRateLimiter {
|
|
32
|
+
private rateLimiter;
|
|
33
|
+
private requestQueue;
|
|
34
|
+
private processing;
|
|
35
|
+
private lastRateLimitInfo?;
|
|
36
|
+
private isAuthenticated;
|
|
37
|
+
constructor();
|
|
38
|
+
/**
|
|
39
|
+
* Update rate limits based on current authentication status
|
|
40
|
+
*/
|
|
41
|
+
private updateLimitsForAuthStatus;
|
|
42
|
+
/**
|
|
43
|
+
* Setup periodic check for rate limit status
|
|
44
|
+
*/
|
|
45
|
+
private setupPeriodicStatusCheck;
|
|
46
|
+
/**
|
|
47
|
+
* Queue a GitHub API request with rate limiting
|
|
48
|
+
* @param operation Description of the operation
|
|
49
|
+
* @param apiCall Function that makes the actual API call
|
|
50
|
+
* @param priority Request priority (high, normal, low)
|
|
51
|
+
* @returns Promise that resolves with the API response
|
|
52
|
+
*/
|
|
53
|
+
queueRequest<T>(operation: string, apiCall: () => Promise<T>, priority?: 'high' | 'normal' | 'low'): Promise<T>;
|
|
54
|
+
/**
|
|
55
|
+
* Add request to queue with priority ordering
|
|
56
|
+
*/
|
|
57
|
+
private addToQueue;
|
|
58
|
+
/**
|
|
59
|
+
* Process the request queue
|
|
60
|
+
*/
|
|
61
|
+
private processQueue;
|
|
62
|
+
/**
|
|
63
|
+
* Get current rate limit status
|
|
64
|
+
*/
|
|
65
|
+
getStatus(): GitHubRateStatus;
|
|
66
|
+
/**
|
|
67
|
+
* Check if an error is a GitHub rate limit error
|
|
68
|
+
*/
|
|
69
|
+
private isGitHubRateLimitError;
|
|
70
|
+
/**
|
|
71
|
+
* Handle GitHub rate limit error response
|
|
72
|
+
*/
|
|
73
|
+
private handleGitHubRateLimit;
|
|
74
|
+
/**
|
|
75
|
+
* Log API usage for monitoring and diagnostics
|
|
76
|
+
*/
|
|
77
|
+
private logApiUsage;
|
|
78
|
+
/**
|
|
79
|
+
* Clear the request queue (for testing or emergency situations)
|
|
80
|
+
*/
|
|
81
|
+
clearQueue(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Reset the rate limiter (for testing)
|
|
84
|
+
*/
|
|
85
|
+
reset(): void;
|
|
86
|
+
}
|
|
87
|
+
export declare const githubRateLimiter: GitHubRateLimiter;
|
|
88
|
+
//# sourceMappingURL=GitHubRateLimiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitHubRateLimiter.d.ts","sourceRoot":"","sources":["../../src/utils/GitHubRateLimiter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAkC,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAOnF,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,IAAI,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,MAAM,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAAC,CAAsB;IAChD,OAAO,CAAC,eAAe,CAAS;;IAQhC;;OAEG;YACW,yBAAyB;IA2CvC;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAShC;;;;;;OAMG;IACG,YAAY,CAAC,CAAC,EAClB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,QAAQ,GAAE,MAAM,GAAG,QAAQ,GAAG,KAAgB,GAC7C,OAAO,CAAC,CAAC,CAAC;IAwDb;;OAEG;IACH,OAAO,CAAC,UAAU;IAuBlB;;OAEG;YACW,YAAY;IA0C1B;;OAEG;IACH,SAAS,IAAI,gBAAgB;IAa7B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAM9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA6C7B;;OAEG;IACH,OAAO,CAAC,WAAW;IA8BnB;;OAEG;IACH,UAAU,IAAI,IAAI;IAalB;;OAEG;IACH,KAAK,IAAI,IAAI;CAMd;AAGD,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|