vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1642
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/README.md +240 -0
- package/package.json +10 -2
- package/src/agents/Agent.js +300 -0
- package/src/agents/AgentAdditionService.js +311 -0
- package/src/agents/AgentCheckService.js +690 -0
- package/src/agents/AgentInstallationService.js +140 -0
- package/src/agents/AgentSetupService.js +467 -0
- package/src/agents/AgentStatus.js +183 -0
- package/src/agents/AgentVerificationService.js +634 -0
- package/src/agents/ConfigurationSchemaValidator.js +543 -0
- package/src/agents/EnvironmentConfigurationManager.js +602 -0
- package/src/agents/InstallationErrorHandler.js +372 -0
- package/src/agents/InstallationLog.js +363 -0
- package/src/agents/InstallationMethod.js +510 -0
- package/src/agents/InstallationOrchestrator.js +352 -0
- package/src/agents/InstallationProgressReporter.js +372 -0
- package/src/agents/InstallationRetryManager.js +322 -0
- package/src/agents/InstallationType.js +254 -0
- package/src/agents/OperationTypes.js +310 -0
- package/src/agents/PerformanceMetricsCollector.js +493 -0
- package/src/agents/SecurityValidationService.js +534 -0
- package/src/agents/VerificationTest.js +354 -0
- package/src/agents/VerificationType.js +226 -0
- package/src/agents/WindowsPermissionHandler.js +518 -0
- package/src/agents/config/AgentConfigManager.js +393 -0
- package/src/agents/config/AgentDefaultsRegistry.js +373 -0
- package/src/agents/config/ConfigValidator.js +281 -0
- package/src/agents/discovery/AgentDiscoveryService.js +707 -0
- package/src/agents/logging/AgentLogger.js +511 -0
- package/src/agents/status/AgentStatusManager.js +481 -0
- package/src/agents/storage/FileManager.js +454 -0
- package/src/agents/verification/AgentCommunicationTester.js +474 -0
- package/src/agents/verification/BaseVerifier.js +430 -0
- package/src/agents/verification/CommandVerifier.js +480 -0
- package/src/agents/verification/FileOperationVerifier.js +453 -0
- package/src/agents/verification/ResultAnalyzer.js +707 -0
- package/src/agents/verification/TestRequirementManager.js +495 -0
- package/src/agents/verification/VerificationRunner.js +433 -0
- package/src/agents/windows/BaseWindowsInstaller.js +441 -0
- package/src/agents/windows/ChocolateyInstaller.js +509 -0
- package/src/agents/windows/DirectInstaller.js +443 -0
- package/src/agents/windows/InstallerFactory.js +391 -0
- package/src/agents/windows/NpmInstaller.js +505 -0
- package/src/agents/windows/PowerShellInstaller.js +458 -0
- package/src/agents/windows/WinGetInstaller.js +390 -0
- package/src/analysis/analysis-reporter.js +132 -0
- package/src/analysis/boundary-detector.js +712 -0
- package/src/analysis/categorizer.js +340 -0
- package/src/analysis/codebase-scanner.js +384 -0
- package/src/analysis/line-counter.js +513 -0
- package/src/analysis/priority-calculator.js +679 -0
- package/src/analysis/report/analysis-report.js +250 -0
- package/src/analysis/report/package-analyzer.js +278 -0
- package/src/analysis/report/recommendation-generator.js +382 -0
- package/src/analysis/report/statistics-generator.js +515 -0
- package/src/analysis/reports/analysis-report-model.js +101 -0
- package/src/analysis/reports/recommendation-generator.js +283 -0
- package/src/analysis/reports/report-generators.js +191 -0
- package/src/analysis/reports/statistics-calculator.js +231 -0
- package/src/analysis/reports/trend-analyzer.js +219 -0
- package/src/analysis/strategy-generator.js +814 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
- package/src/config/refactoring-config.js +307 -0
- package/src/health-tracking/json-storage.js +38 -2
- package/src/ide-integration/applescript-manager-core.js +233 -0
- package/src/ide-integration/applescript-manager.cjs +357 -28
- package/src/ide-integration/applescript-manager.js +89 -3599
- package/src/ide-integration/cdp-manager.js +306 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
- package/src/ide-integration/continuation-handler.js +337 -0
- package/src/ide-integration/ide-status-checker.js +292 -0
- package/src/ide-integration/macos-ide-manager.js +627 -0
- package/src/ide-integration/macos-text-sender.js +528 -0
- package/src/ide-integration/response-reader.js +548 -0
- package/src/ide-integration/windows-automation-manager.js +121 -0
- package/src/ide-integration/windows-ide-manager.js +373 -0
- package/src/index.cjs +25 -3
- package/src/index.js +15 -1
- package/src/llm/direct-llm-manager.cjs +90 -2
- package/src/models/compliance-report.js +538 -0
- package/src/models/file-analysis.js +681 -0
- package/src/models/refactoring-plan.js +770 -0
- package/src/monitoring/alert-system.js +834 -0
- package/src/monitoring/compliance-progress-tracker.js +437 -0
- package/src/monitoring/continuous-scan-notifications.js +661 -0
- package/src/monitoring/continuous-scanner.js +279 -0
- package/src/monitoring/file-monitor/file-analyzer.js +262 -0
- package/src/monitoring/file-monitor/file-monitor.js +237 -0
- package/src/monitoring/file-monitor/watcher.js +194 -0
- package/src/monitoring/file-monitor.js +17 -0
- package/src/monitoring/notification-manager.js +437 -0
- package/src/monitoring/scanner-core.js +368 -0
- package/src/monitoring/scanner-events.js +214 -0
- package/src/monitoring/violation-notification-system.js +515 -0
- package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
- package/src/refactoring/boundaries/extraction-result.js +285 -0
- package/src/refactoring/boundaries/extraction-strategies.js +392 -0
- package/src/refactoring/boundaries/module-boundary.js +209 -0
- package/src/refactoring/boundary/boundary-detector.js +741 -0
- package/src/refactoring/boundary/boundary-types.js +405 -0
- package/src/refactoring/boundary/extraction-strategies.js +554 -0
- package/src/refactoring/boundary-extraction-result.js +77 -0
- package/src/refactoring/boundary-extraction-strategies.js +330 -0
- package/src/refactoring/boundary-extractor.js +384 -0
- package/src/refactoring/boundary-types.js +46 -0
- package/src/refactoring/circular/circular-dependency.js +88 -0
- package/src/refactoring/circular/cycle-detection.js +147 -0
- package/src/refactoring/circular/dependency-node.js +82 -0
- package/src/refactoring/circular/dependency-result.js +107 -0
- package/src/refactoring/circular/dependency-types.js +58 -0
- package/src/refactoring/circular/graph-builder.js +213 -0
- package/src/refactoring/circular/resolution-strategy.js +72 -0
- package/src/refactoring/circular/strategy-generator.js +229 -0
- package/src/refactoring/circular-dependency-resolver-original.js +809 -0
- package/src/refactoring/circular-dependency-resolver.js +200 -0
- package/src/refactoring/code-mover.js +761 -0
- package/src/refactoring/file-splitter.js +696 -0
- package/src/refactoring/functionality-validator.js +816 -0
- package/src/refactoring/import-manager.js +774 -0
- package/src/refactoring/module-boundary.js +107 -0
- package/src/refactoring/refactoring-executor.js +672 -0
- package/src/refactoring/refactoring-rollback.js +614 -0
- package/src/refactoring/test-validator.js +631 -0
- package/src/requirement-management/default-requirement-manager.js +321 -0
- package/src/requirement-management/requirement-file-parser.js +159 -0
- package/src/requirement-management/requirement-sequencer.js +221 -0
- package/src/rui/commands/AgentCommandParser.js +600 -0
- package/src/rui/commands/AgentCommands.js +487 -0
- package/src/rui/commands/AgentResponseFormatter.js +832 -0
- package/src/scripts/verify-full-compliance.js +269 -0
- package/src/sync/sync-engine-core.js +1 -0
- package/src/sync/sync-engine-remote-handlers.js +135 -0
- package/src/task-generation/automated-task-generator.js +351 -0
- package/src/task-generation/prioritizer.js +287 -0
- package/src/task-generation/task-list-updater.js +215 -0
- package/src/task-generation/task-management-integration.js +480 -0
- package/src/task-generation/task-manager-integration.js +270 -0
- package/src/task-generation/violation-task-generator.js +474 -0
- package/src/task-management/continuous-scan-integration.js +342 -0
- package/src/timeout-management/index.js +12 -3
- package/src/timeout-management/response-time-tracker.js +167 -0
- package/src/timeout-management/timeout-calculator.js +159 -0
- package/src/timeout-management/timeout-config-manager.js +172 -0
- package/src/utils/ast-analyzer.js +417 -0
- package/src/utils/current-requirement-manager.js +276 -0
- package/src/utils/current-requirement-operations.js +472 -0
- package/src/utils/dependency-mapper.js +456 -0
- package/src/utils/download-with-progress.js +4 -2
- package/src/utils/electron-update-checker.js +4 -1
- package/src/utils/file-size-analyzer.js +272 -0
- package/src/utils/import-updater.js +280 -0
- package/src/utils/refactoring-tools.js +512 -0
- package/src/utils/report-generator.js +569 -0
- package/src/utils/reports/report-analysis.js +218 -0
- package/src/utils/reports/report-types.js +55 -0
- package/src/utils/reports/summary-generators.js +102 -0
- package/src/utils/requirement-file-management.js +157 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
- package/src/utils/requirement-helpers/requirement-mover.js +414 -0
- package/src/utils/requirement-helpers/requirement-parser.js +326 -0
- package/src/utils/requirement-helpers/requirement-status.js +320 -0
- package/src/utils/requirement-helpers-new.js +55 -0
- package/src/utils/requirement-helpers-refactored.js +367 -0
- package/src/utils/requirement-helpers.js +291 -1191
- package/src/utils/requirement-movement-operations.js +450 -0
- package/src/utils/requirement-movement.js +312 -0
- package/src/utils/requirement-parsing-helpers.js +56 -0
- package/src/utils/requirement-statistics.js +200 -0
- package/src/utils/requirement-text-utils.js +58 -0
- package/src/utils/rollback/rollback-handlers.js +125 -0
- package/src/utils/rollback/rollback-operation.js +63 -0
- package/src/utils/rollback/rollback-recorder.js +166 -0
- package/src/utils/rollback/rollback-state-manager.js +175 -0
- package/src/utils/rollback/rollback-types.js +33 -0
- package/src/utils/rollback/rollback-utils.js +110 -0
- package/src/utils/rollback-manager-original.js +569 -0
- package/src/utils/rollback-manager.js +202 -0
- package/src/utils/smoke-test-cli.js +362 -0
- package/src/utils/smoke-test-gui.js +351 -0
- package/src/utils/smoke-test-orchestrator.js +321 -0
- package/src/utils/smoke-test-runner.js +60 -0
- package/src/utils/smoke-test-web.js +347 -0
- package/src/utils/specification-helpers.js +39 -13
- package/src/utils/specification-migration.js +97 -0
- package/src/utils/test-runner.js +579 -0
- package/src/utils/validation-framework.js +518 -0
- package/src/validation/compliance-analyzer.js +197 -0
- package/src/validation/compliance-report-generator.js +343 -0
- package/src/validation/compliance-reporter.js +711 -0
- package/src/validation/compliance-rules.js +127 -0
- package/src/validation/constitution-validator-new.js +196 -0
- package/src/validation/constitution-validator.js +17 -0
- package/src/validation/file-validators.js +170 -0
- package/src/validation/line-limit/file-analyzer.js +201 -0
- package/src/validation/line-limit/line-limit-validator.js +208 -0
- package/src/validation/line-limit/validation-result.js +144 -0
- package/src/validation/line-limit-core.js +225 -0
- package/src/validation/line-limit-reporter.js +134 -0
- package/src/validation/line-limit-result.js +125 -0
- package/src/validation/line-limit-validator.js +41 -0
- package/src/validation/metrics-calculator.js +660 -0
- package/src/sync/sync-engine-backup.js +0 -559
|
@@ -0,0 +1,774 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages import statement updates during refactoring operations.
|
|
5
|
+
* Handles import resolution, organization, and dependency tracking.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Import types
|
|
13
|
+
*/
|
|
14
|
+
const IMPORT_TYPES = {
|
|
15
|
+
ES6_IMPORT: 'es6_import',
|
|
16
|
+
COMMONJS_REQUIRE: 'commonjs_require',
|
|
17
|
+
DYNAMIC_IMPORT: 'dynamic_import',
|
|
18
|
+
TYPESCRIPT_IMPORT: 'typescript_import'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Import statement class
|
|
23
|
+
*/
|
|
24
|
+
class ImportStatement {
|
|
25
|
+
constructor(type, module, specifier = null, isDefault = false) {
|
|
26
|
+
this.type = type;
|
|
27
|
+
this.module = module;
|
|
28
|
+
this.specifier = specifier;
|
|
29
|
+
this.isDefault = isDefault;
|
|
30
|
+
this.isTypeOnly = false;
|
|
31
|
+
this.isRelative = this.isRelativeModule(module);
|
|
32
|
+
this.originalStatement = '';
|
|
33
|
+
this.lineNumber = 0;
|
|
34
|
+
this.metadata = {
|
|
35
|
+
createdAt: new Date().toISOString(),
|
|
36
|
+
used: false,
|
|
37
|
+
unused: false
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
isRelativeModule(module) {
|
|
42
|
+
return module.startsWith('./') || module.startsWith('../');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setOriginalStatement(statement) {
|
|
46
|
+
this.originalStatement = statement;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
setLineNumber(lineNumber) {
|
|
50
|
+
this.lineNumber = lineNumber;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
setTypeOnly(isTypeOnly) {
|
|
54
|
+
this.isTypeOnly = isTypeOnly;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
setUsed(used) {
|
|
58
|
+
this.metadata.used = used;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
setUnused(unused) {
|
|
62
|
+
this.metadata.unused = unused;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
generateStatement() {
|
|
66
|
+
switch (this.type) {
|
|
67
|
+
case IMPORT_TYPES.ES6_IMPORT:
|
|
68
|
+
if (this.isDefault) {
|
|
69
|
+
return `import ${this.specifier} from '${this.module}';`;
|
|
70
|
+
} else if (this.specifier) {
|
|
71
|
+
return `import { ${this.specifier} } from '${this.module}';`;
|
|
72
|
+
} else {
|
|
73
|
+
return `import '${this.module}';`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
case IMPORT_TYPES.COMMONJS_REQUIRE:
|
|
77
|
+
if (this.specifier) {
|
|
78
|
+
return `const ${this.specifier} = require('${this.module}');`;
|
|
79
|
+
} else {
|
|
80
|
+
return `require('${this.module}');`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
case IMPORT_TYPES.DYNAMIC_IMPORT:
|
|
84
|
+
return `import('${this.module}')`;
|
|
85
|
+
|
|
86
|
+
case IMPORT_TYPES.TYPESCRIPT_IMPORT:
|
|
87
|
+
const typePrefix = this.isTypeOnly ? 'type ' : '';
|
|
88
|
+
if (this.isDefault) {
|
|
89
|
+
return `import ${typePrefix}${this.specifier} from '${this.module}';`;
|
|
90
|
+
} else if (this.specifier) {
|
|
91
|
+
return `import ${typePrefix}{ ${this.specifier} } from '${this.module}';`;
|
|
92
|
+
} else {
|
|
93
|
+
return `import '${this.module}';`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
default:
|
|
97
|
+
return this.originalStatement;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
getSummary() {
|
|
102
|
+
return {
|
|
103
|
+
type: this.type,
|
|
104
|
+
module: this.module,
|
|
105
|
+
specifier: this.specifier,
|
|
106
|
+
isDefault: this.isDefault,
|
|
107
|
+
isRelative: this.isRelative,
|
|
108
|
+
isUsed: this.metadata.used,
|
|
109
|
+
isUnused: this.metadata.unused,
|
|
110
|
+
lineNumber: this.lineNumber
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Import manager result class
|
|
117
|
+
*/
|
|
118
|
+
class ImportManagerResult {
|
|
119
|
+
constructor(filePath) {
|
|
120
|
+
this.filePath = filePath;
|
|
121
|
+
this.originalImports = [];
|
|
122
|
+
this.updatedImports = [];
|
|
123
|
+
this.addedImports = [];
|
|
124
|
+
this.removedImports = [];
|
|
125
|
+
this.unusedImports = [];
|
|
126
|
+
this.success = false;
|
|
127
|
+
this.errors = [];
|
|
128
|
+
this.warnings = [];
|
|
129
|
+
this.metadata = {
|
|
130
|
+
processedAt: new Date().toISOString(),
|
|
131
|
+
importsAdded: 0,
|
|
132
|
+
importsRemoved: 0,
|
|
133
|
+
importsUpdated: 0
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
addOriginalImport(importStmt) {
|
|
138
|
+
this.originalImports.push(importStmt);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
addUpdatedImport(importStmt) {
|
|
142
|
+
this.updatedImports.push(importStmt);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
addAddedImport(importStmt) {
|
|
146
|
+
this.addedImports.push(importStmt);
|
|
147
|
+
this.metadata.importsAdded++;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
addRemovedImport(importStmt) {
|
|
151
|
+
this.removedImports.push(importStmt);
|
|
152
|
+
this.metadata.importsRemoved++;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
addUnusedImport(importStmt) {
|
|
156
|
+
this.unusedImports.push(importStmt);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
addError(error) {
|
|
160
|
+
this.errors.push({
|
|
161
|
+
message: error.message,
|
|
162
|
+
timestamp: new Date().toISOString()
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
addWarning(warning) {
|
|
167
|
+
this.warnings.push({
|
|
168
|
+
message: warning,
|
|
169
|
+
timestamp: new Date().toISOString()
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
setSuccess(success) {
|
|
174
|
+
this.success = success;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
getSummary() {
|
|
178
|
+
return {
|
|
179
|
+
filePath: this.filePath,
|
|
180
|
+
success: this.success,
|
|
181
|
+
originalImportCount: this.originalImports.length,
|
|
182
|
+
updatedImportCount: this.updatedImports.length,
|
|
183
|
+
addedImportCount: this.addedImports.length,
|
|
184
|
+
removedImportCount: this.removedImports.length,
|
|
185
|
+
unusedImportCount: this.unusedImports.length,
|
|
186
|
+
errorCount: this.errors.length,
|
|
187
|
+
warningCount: this.warnings.length
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Import manager class
|
|
194
|
+
*/
|
|
195
|
+
class ImportManager {
|
|
196
|
+
constructor(options = {}) {
|
|
197
|
+
this.options = {
|
|
198
|
+
organizeImports: true,
|
|
199
|
+
removeUnused: true,
|
|
200
|
+
sortImports: true,
|
|
201
|
+
groupImports: true,
|
|
202
|
+
preserveComments: true,
|
|
203
|
+
updateRelativePaths: true,
|
|
204
|
+
...options
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Update imports in a file after refactoring
|
|
210
|
+
*/
|
|
211
|
+
async updateImports(filePath, changes = []) {
|
|
212
|
+
const result = new ImportManagerResult(filePath);
|
|
213
|
+
|
|
214
|
+
try {
|
|
215
|
+
// Read file content
|
|
216
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
217
|
+
const lines = content.split('\n');
|
|
218
|
+
|
|
219
|
+
// Parse existing imports
|
|
220
|
+
const existingImports = this.parseImports(lines);
|
|
221
|
+
for (const imp of existingImports) {
|
|
222
|
+
result.addOriginalImport(imp);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Apply changes
|
|
226
|
+
const updatedImports = this.applyChanges(existingImports, changes);
|
|
227
|
+
|
|
228
|
+
// Detect unused imports
|
|
229
|
+
const unusedImports = this.detectUnusedImports(content, updatedImports);
|
|
230
|
+
for (const imp of unusedImports) {
|
|
231
|
+
result.addUnusedImport(imp);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Remove unused if enabled
|
|
235
|
+
let finalImports = updatedImports;
|
|
236
|
+
if (this.options.removeUnused) {
|
|
237
|
+
finalImports = updatedImports.filter(imp => !unusedImports.includes(imp));
|
|
238
|
+
for (const imp of unusedImports) {
|
|
239
|
+
result.addRemovedImport(imp);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Organize imports if enabled
|
|
244
|
+
if (this.options.organizeImports) {
|
|
245
|
+
finalImports = this.organizeImports(finalImports);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Generate updated content
|
|
249
|
+
const updatedContent = this.generateUpdatedContent(content, existingImports, finalImports);
|
|
250
|
+
|
|
251
|
+
// Write updated file
|
|
252
|
+
fs.writeFileSync(filePath, updatedContent, 'utf8');
|
|
253
|
+
|
|
254
|
+
// Set results
|
|
255
|
+
for (const imp of finalImports) {
|
|
256
|
+
result.addUpdatedImport(imp);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
result.setSuccess(true);
|
|
260
|
+
|
|
261
|
+
} catch (error) {
|
|
262
|
+
result.addError(error);
|
|
263
|
+
result.setSuccess(false);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return result;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Parse import statements from file lines
|
|
271
|
+
*/
|
|
272
|
+
parseImports(lines) {
|
|
273
|
+
const imports = [];
|
|
274
|
+
|
|
275
|
+
for (let i = 0; i < lines.length; i++) {
|
|
276
|
+
const line = lines[i].trim();
|
|
277
|
+
|
|
278
|
+
// ES6 imports
|
|
279
|
+
const es6Match = line.match(/^import\s+(.+?)\s+from\s+['"]([^'"]+)['"];?\s*$/);
|
|
280
|
+
if (es6Match) {
|
|
281
|
+
const importStmt = new ImportStatement(IMPORT_TYPES.ES6_IMPORT, es6Match[2]);
|
|
282
|
+
importStmt.setOriginalStatement(line);
|
|
283
|
+
importStmt.setLineNumber(i + 1);
|
|
284
|
+
|
|
285
|
+
// Parse specifier
|
|
286
|
+
const specifierPart = es6Match[1].trim();
|
|
287
|
+
if (specifierPart.startsWith('type ')) {
|
|
288
|
+
importStmt.setTypeOnly(true);
|
|
289
|
+
importStmt.type = IMPORT_TYPES.TYPESCRIPT_IMPORT;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (specifierPart === 'default' || !specifierPart.includes('{')) {
|
|
293
|
+
importStmt.isDefault = true;
|
|
294
|
+
importStmt.specifier = specifierPart.replace('type ', '').trim();
|
|
295
|
+
} else {
|
|
296
|
+
const namedMatch = specifierPart.match(/\{\s*(.+?)\s*\}/);
|
|
297
|
+
if (namedMatch) {
|
|
298
|
+
importStmt.specifier = namedMatch[1].trim();
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
imports.push(importStmt);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// CommonJS requires
|
|
307
|
+
const cjsMatch = line.match(/^const\s+(.+?)\s*=\s*require\s*\(\s*['"]([^'"]+)['"]\s*\);?\s*$/);
|
|
308
|
+
if (cjsMatch) {
|
|
309
|
+
const importStmt = new ImportStatement(IMPORT_TYPES.COMMONJS_REQUIRE, cjsMatch[2]);
|
|
310
|
+
importStmt.setOriginalStatement(line);
|
|
311
|
+
importStmt.setLineNumber(i + 1);
|
|
312
|
+
importStmt.specifier = cjsMatch[1].trim();
|
|
313
|
+
imports.push(importStmt);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Bare require
|
|
318
|
+
const bareRequireMatch = line.match(/^require\s*\(\s*['"]([^'"]+)['"]\s*\);?\s*$/);
|
|
319
|
+
if (bareRequireMatch) {
|
|
320
|
+
const importStmt = new ImportStatement(IMPORT_TYPES.COMMONJS_REQUIRE, bareRequireMatch[1]);
|
|
321
|
+
importStmt.setOriginalStatement(line);
|
|
322
|
+
importStmt.setLineNumber(i + 1);
|
|
323
|
+
imports.push(importStmt);
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Dynamic imports
|
|
328
|
+
const dynamicMatch = line.match(/import\s*\(\s*['"]([^'"]+)['"]\s*\)/);
|
|
329
|
+
if (dynamicMatch) {
|
|
330
|
+
const importStmt = new ImportStatement(IMPORT_TYPES.DYNAMIC_IMPORT, dynamicMatch[1]);
|
|
331
|
+
importStmt.setOriginalStatement(line);
|
|
332
|
+
importStmt.setLineNumber(i + 1);
|
|
333
|
+
imports.push(importStmt);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return imports;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Apply changes to imports
|
|
342
|
+
*/
|
|
343
|
+
applyChanges(existingImports, changes) {
|
|
344
|
+
let updatedImports = [...existingImports];
|
|
345
|
+
|
|
346
|
+
for (const change of changes) {
|
|
347
|
+
switch (change.type) {
|
|
348
|
+
case 'add':
|
|
349
|
+
const newImport = this.createImportFromChange(change);
|
|
350
|
+
if (newImport && !this.importExists(updatedImports, newImport)) {
|
|
351
|
+
updatedImports.push(newImport);
|
|
352
|
+
}
|
|
353
|
+
break;
|
|
354
|
+
|
|
355
|
+
case 'remove':
|
|
356
|
+
updatedImports = updatedImports.filter(imp =>
|
|
357
|
+
imp.module !== change.module &&
|
|
358
|
+
imp.specifier !== change.specifier
|
|
359
|
+
);
|
|
360
|
+
break;
|
|
361
|
+
|
|
362
|
+
case 'update':
|
|
363
|
+
updatedImports = updatedImports.map(imp => {
|
|
364
|
+
if (imp.module === change.oldModule && imp.specifier === change.oldSpecifier) {
|
|
365
|
+
const updatedImport = new ImportStatement(imp.type, change.newModule || imp.module, change.newSpecifier || imp.specifier, imp.isDefault);
|
|
366
|
+
updatedImport.setLineNumber(imp.lineNumber);
|
|
367
|
+
return updatedImport;
|
|
368
|
+
}
|
|
369
|
+
return imp;
|
|
370
|
+
});
|
|
371
|
+
break;
|
|
372
|
+
|
|
373
|
+
case 'move':
|
|
374
|
+
// Update relative paths for moved files
|
|
375
|
+
if (change.oldPath && change.newPath) {
|
|
376
|
+
updatedImports = updatedImports.map(imp => {
|
|
377
|
+
if (imp.isRelative && imp.module.includes(change.oldPath)) {
|
|
378
|
+
const updatedPath = this.updateRelativePath(imp.module, change.oldPath, change.newPath);
|
|
379
|
+
const updatedImport = new ImportStatement(imp.type, updatedPath, imp.specifier, imp.isDefault);
|
|
380
|
+
updatedImport.setLineNumber(imp.lineNumber);
|
|
381
|
+
return updatedImport;
|
|
382
|
+
}
|
|
383
|
+
return imp;
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return updatedImports;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Create import from change object
|
|
395
|
+
*/
|
|
396
|
+
createImportFromChange(change) {
|
|
397
|
+
const type = change.importType || IMPORT_TYPES.ES6_IMPORT;
|
|
398
|
+
const importStmt = new ImportStatement(type, change.module, change.specifier, change.isDefault);
|
|
399
|
+
|
|
400
|
+
if (change.isTypeOnly) {
|
|
401
|
+
importStmt.setTypeOnly(true);
|
|
402
|
+
if (type === IMPORT_TYPES.ES6_IMPORT) {
|
|
403
|
+
importStmt.type = IMPORT_TYPES.TYPESCRIPT_IMPORT;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return importStmt;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Check if import already exists
|
|
412
|
+
*/
|
|
413
|
+
importExists(imports, newImport) {
|
|
414
|
+
return imports.some(imp =>
|
|
415
|
+
imp.module === newImport.module &&
|
|
416
|
+
imp.specifier === newImport.specifier &&
|
|
417
|
+
imp.type === newImport.type
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Update relative path
|
|
423
|
+
*/
|
|
424
|
+
updateRelativePath(currentPath, oldBasePath, newBasePath) {
|
|
425
|
+
// Resolve the current path relative to old base
|
|
426
|
+
const absolutePath = path.resolve(path.dirname(oldBasePath), currentPath);
|
|
427
|
+
|
|
428
|
+
// Calculate new relative path
|
|
429
|
+
const newRelativePath = path.relative(path.dirname(newBasePath), absolutePath);
|
|
430
|
+
|
|
431
|
+
// Ensure forward slashes and add ./ if needed
|
|
432
|
+
const normalizedPath = newRelativePath.replace(/\\/g, '/');
|
|
433
|
+
return normalizedPath.startsWith('.') ? normalizedPath : `./${normalizedPath}`;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Detect unused imports
|
|
438
|
+
*/
|
|
439
|
+
detectUnusedImports(content, imports) {
|
|
440
|
+
const unused = [];
|
|
441
|
+
|
|
442
|
+
for (const imp of imports) {
|
|
443
|
+
if (!this.isImportUsed(content, imp)) {
|
|
444
|
+
imp.setUnused(true);
|
|
445
|
+
unused.push(imp);
|
|
446
|
+
} else {
|
|
447
|
+
imp.setUsed(true);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
return unused;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Check if import is used in content
|
|
456
|
+
*/
|
|
457
|
+
isImportUsed(content, importStmt) {
|
|
458
|
+
if (!importStmt.specifier) {
|
|
459
|
+
// Side-effect imports are always considered used
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// For default imports, check for the specifier name
|
|
464
|
+
if (importStmt.isDefault) {
|
|
465
|
+
const regex = new RegExp(`\\b${importStmt.specifier}\\b`, 'g');
|
|
466
|
+
return regex.test(content);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// For named imports, check each imported name
|
|
470
|
+
const names = importStmt.specifier.split(',').map(name => name.trim().split(' as ')[0]);
|
|
471
|
+
for (const name of names) {
|
|
472
|
+
const regex = new RegExp(`\\b${name}\\b`, 'g');
|
|
473
|
+
if (regex.test(content)) {
|
|
474
|
+
return true;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Organize imports
|
|
483
|
+
*/
|
|
484
|
+
organizeImports(imports) {
|
|
485
|
+
if (!this.options.sortImports && !this.options.groupImports) {
|
|
486
|
+
return imports;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Group imports by type and source
|
|
490
|
+
const groups = {
|
|
491
|
+
node_builtin: [],
|
|
492
|
+
third_party: [],
|
|
493
|
+
relative: [],
|
|
494
|
+
absolute: [],
|
|
495
|
+
type: [],
|
|
496
|
+
other: []
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
for (const imp of imports) {
|
|
500
|
+
const group = this.getImportGroup(imp);
|
|
501
|
+
groups[group].push(imp);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Sort within groups
|
|
505
|
+
if (this.options.sortImports) {
|
|
506
|
+
for (const group of Object.values(groups)) {
|
|
507
|
+
group.sort((a, b) => {
|
|
508
|
+
// Sort by module, then by specifier
|
|
509
|
+
if (a.module !== b.module) {
|
|
510
|
+
return a.module.localeCompare(b.module);
|
|
511
|
+
}
|
|
512
|
+
return (a.specifier || '').localeCompare(b.specifier || '');
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Flatten groups
|
|
518
|
+
const organized = [];
|
|
519
|
+
const groupOrder = ['node_builtin', 'third_party', 'absolute', 'relative', 'type', 'other'];
|
|
520
|
+
|
|
521
|
+
for (const groupName of groupOrder) {
|
|
522
|
+
if (groups[groupName].length > 0) {
|
|
523
|
+
organized.push(...groups[groupName]);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
return organized;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Get import group for an import
|
|
532
|
+
*/
|
|
533
|
+
getImportGroup(importStmt) {
|
|
534
|
+
if (importStmt.isTypeOnly) {
|
|
535
|
+
return 'type';
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (importStmt.isRelative) {
|
|
539
|
+
return 'relative';
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// Node.js built-in modules
|
|
543
|
+
const nodeBuiltins = [
|
|
544
|
+
'fs', 'path', 'http', 'https', 'url', 'querystring', 'util', 'events',
|
|
545
|
+
'stream', 'buffer', 'child_process', 'cluster', 'os', 'crypto', 'tls',
|
|
546
|
+
'net', 'dgram', 'dns', 'readline', 'repl', 'vm', 'zlib', 'console'
|
|
547
|
+
];
|
|
548
|
+
|
|
549
|
+
if (nodeBuiltins.includes(importStmt.module)) {
|
|
550
|
+
return 'node_builtin';
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Third-party (starts with @ or doesn't contain .)
|
|
554
|
+
if (importStmt.module.startsWith('@') || !importStmt.module.includes('.')) {
|
|
555
|
+
return 'third_party';
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Absolute paths
|
|
559
|
+
if (importStmt.module.startsWith('/')) {
|
|
560
|
+
return 'absolute';
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
return 'other';
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Generate updated content with new imports
|
|
568
|
+
*/
|
|
569
|
+
generateUpdatedContent(originalContent, originalImports, updatedImports) {
|
|
570
|
+
const lines = originalContent.split('\n');
|
|
571
|
+
|
|
572
|
+
// Find import section
|
|
573
|
+
const importSection = this.findImportSection(lines, originalImports);
|
|
574
|
+
|
|
575
|
+
if (importSection.start === -1) {
|
|
576
|
+
// No imports found, add at the beginning
|
|
577
|
+
const importLines = updatedImports.map(imp => imp.generateStatement());
|
|
578
|
+
return [...importLines, '', ...lines].join('\n');
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Replace import section
|
|
582
|
+
const beforeImports = lines.slice(0, importSection.start);
|
|
583
|
+
const afterImports = lines.slice(importSection.end + 1);
|
|
584
|
+
|
|
585
|
+
const importLines = updatedImports.map(imp => imp.generateStatement());
|
|
586
|
+
|
|
587
|
+
// Add empty lines around imports if they don't exist
|
|
588
|
+
if (importLines.length > 0) {
|
|
589
|
+
if (beforeImports.length > 0 && beforeImports[beforeImports.length - 1].trim() !== '') {
|
|
590
|
+
importLines.unshift('');
|
|
591
|
+
}
|
|
592
|
+
if (afterImports.length > 0 && afterImports[0].trim() !== '') {
|
|
593
|
+
importLines.push('');
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
return [...beforeImports, ...importLines, ...afterImports].join('\n');
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Find import section in lines
|
|
602
|
+
*/
|
|
603
|
+
findImportSection(lines, imports) {
|
|
604
|
+
if (imports.length === 0) {
|
|
605
|
+
return { start: -1, end: -1 };
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const start = Math.min(...imports.map(imp => imp.lineNumber - 1));
|
|
609
|
+
const end = Math.max(...imports.map(imp => imp.lineNumber - 1));
|
|
610
|
+
|
|
611
|
+
return { start, end };
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Update imports for multiple files
|
|
616
|
+
*/
|
|
617
|
+
async updateImportsInFiles(filePaths, changes) {
|
|
618
|
+
const results = [];
|
|
619
|
+
|
|
620
|
+
for (const filePath of filePaths) {
|
|
621
|
+
const result = await this.updateImports(filePath, changes);
|
|
622
|
+
results.push(result);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
return results;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Add import to file
|
|
630
|
+
*/
|
|
631
|
+
async addImport(filePath, module, specifier = null, options = {}) {
|
|
632
|
+
const change = {
|
|
633
|
+
type: 'add',
|
|
634
|
+
module,
|
|
635
|
+
specifier,
|
|
636
|
+
isDefault: options.isDefault || false,
|
|
637
|
+
isTypeOnly: options.isTypeOnly || false,
|
|
638
|
+
importType: options.importType || IMPORT_TYPES.ES6_IMPORT
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
return await this.updateImports(filePath, [change]);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Remove import from file
|
|
646
|
+
*/
|
|
647
|
+
async removeImport(filePath, module, specifier = null) {
|
|
648
|
+
const change = {
|
|
649
|
+
type: 'remove',
|
|
650
|
+
module,
|
|
651
|
+
specifier
|
|
652
|
+
};
|
|
653
|
+
|
|
654
|
+
return await this.updateImports(filePath, [change]);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Update import paths after file moves
|
|
659
|
+
*/
|
|
660
|
+
async updateImportPathsAfterMove(movedFiles) {
|
|
661
|
+
const results = [];
|
|
662
|
+
|
|
663
|
+
for (const movedFile of movedFiles) {
|
|
664
|
+
// Find files that might import the moved file
|
|
665
|
+
const dependentFiles = this.findDependentFiles(movedFile.oldPath);
|
|
666
|
+
|
|
667
|
+
for (const depFile of dependentFiles) {
|
|
668
|
+
const change = {
|
|
669
|
+
type: 'move',
|
|
670
|
+
oldPath: movedFile.oldPath,
|
|
671
|
+
newPath: movedFile.newPath
|
|
672
|
+
};
|
|
673
|
+
|
|
674
|
+
const result = await this.updateImports(depFile, [change]);
|
|
675
|
+
results.push(result);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
return results;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Find files that depend on a given file
|
|
684
|
+
*/
|
|
685
|
+
findDependentFiles(targetPath) {
|
|
686
|
+
// This would search the codebase for files that import from targetPath
|
|
687
|
+
// For now, return empty array as placeholder
|
|
688
|
+
return [];
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Get import statistics
|
|
693
|
+
*/
|
|
694
|
+
getStatistics(results) {
|
|
695
|
+
const stats = {
|
|
696
|
+
totalFiles: results.length,
|
|
697
|
+
successful: 0,
|
|
698
|
+
failed: 0,
|
|
699
|
+
totalImportsProcessed: 0,
|
|
700
|
+
totalImportsAdded: 0,
|
|
701
|
+
totalImportsRemoved: 0,
|
|
702
|
+
totalUnusedImports: 0,
|
|
703
|
+
errors: [],
|
|
704
|
+
warnings: []
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
for (const result of results) {
|
|
708
|
+
if (result.success) {
|
|
709
|
+
stats.successful++;
|
|
710
|
+
} else {
|
|
711
|
+
stats.failed++;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
stats.totalImportsProcessed += result.originalImports.length;
|
|
715
|
+
stats.totalImportsAdded += result.metadata.importsAdded;
|
|
716
|
+
stats.totalImportsRemoved += result.metadata.importsRemoved;
|
|
717
|
+
stats.totalUnusedImports += result.unusedImports.length;
|
|
718
|
+
|
|
719
|
+
stats.errors.push(...result.errors);
|
|
720
|
+
stats.warnings.push(...result.warnings);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
return stats;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Validate import statements
|
|
728
|
+
*/
|
|
729
|
+
validateImports(filePath) {
|
|
730
|
+
const result = new ImportManagerResult(filePath);
|
|
731
|
+
|
|
732
|
+
try {
|
|
733
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
734
|
+
const lines = content.split('\n');
|
|
735
|
+
const imports = this.parseImports(lines);
|
|
736
|
+
|
|
737
|
+
for (const imp of imports) {
|
|
738
|
+
// Check if module exists
|
|
739
|
+
if (imp.isRelative) {
|
|
740
|
+
const resolvedPath = path.resolve(path.dirname(filePath), imp.module);
|
|
741
|
+
if (!fs.existsSync(resolvedPath) && !fs.existsSync(resolvedPath + '.js')) {
|
|
742
|
+
result.addWarning(`Import module not found: ${imp.module}`);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// Check for duplicate imports
|
|
747
|
+
const duplicates = imports.filter(other =>
|
|
748
|
+
other !== imp &&
|
|
749
|
+
other.module === imp.module &&
|
|
750
|
+
other.specifier === imp.specifier
|
|
751
|
+
);
|
|
752
|
+
|
|
753
|
+
if (duplicates.length > 0) {
|
|
754
|
+
result.addWarning(`Duplicate import: ${imp.module} - ${imp.specifier}`);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
result.setSuccess(true);
|
|
759
|
+
|
|
760
|
+
} catch (error) {
|
|
761
|
+
result.addError(error);
|
|
762
|
+
result.setSuccess(false);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
return result;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
module.exports = {
|
|
770
|
+
ImportManager,
|
|
771
|
+
ImportStatement,
|
|
772
|
+
ImportManagerResult,
|
|
773
|
+
IMPORT_TYPES
|
|
774
|
+
};
|